diff --git a/src/api/v0/index.js b/src/api/v0/index.js
deleted file mode 100644
index 32c7764..0000000
--- a/src/api/v0/index.js
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
-Copyright (C) 2021 Yarmo Mackenbach
-
-This program is free software: you can redistribute it and/or modify it under
-the terms of the GNU Affero General Public License as published by the Free
-Software Foundation, either version 3 of the License, or (at your option)
-any later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-details.
-
-You should have received a copy of the GNU Affero General Public License along
-with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
-If your software can interact with users remotely through a computer network,
-you should also make sure that it provides a way for users to get its source.
-For example, if your program is a web application, its interface could display
-a "Source" link that leads users to an archive of the code. There are many
-ways you could offer source, and different solutions will be better for different
-programs; see section 13 for the specific requirements.
-
-You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary. For
-more information on this, and how to apply and follow the GNU AGPL, see .
-*/
-import express from 'express'
-import { check, validationResult } from 'express-validator'
-import Ajv from 'ajv'
-import { generateWKDProfile, generateHKPProfile, generateAutoProfile } from '../../server/index.js'
-import * as dotenv from 'dotenv'
-dotenv.config()
-
-const router = express.Router()
-const ajv = new Ajv({ coerceTypes: true })
-
-const apiProfileSchema = {
- type: 'object',
- properties: {
- keyData: {
- type: 'object',
- properties: {
- fingerprint: {
- type: 'string'
- },
- openpgp4fpr: {
- type: 'string'
- },
- users: {
- type: 'array',
- items: {
- type: 'object',
- properties: {
- userData: {
- type: 'object',
- properties: {
- id: { type: 'string' },
- name: { type: 'string' },
- email: { type: 'string' },
- comment: { type: 'string' },
- isPrimary: { type: 'boolean' },
- isRevoked: { type: 'boolean' }
- }
- },
- claims: {
- type: 'array',
- items: {
- type: 'object',
- properties: {
- claimVersion: { type: 'integer' },
- uri: { type: 'string' },
- fingerprint: { type: 'string' },
- status: { type: 'string' },
- matches: {
- type: 'array',
- items: {
- type: 'object',
- properties: {
- serviceProvider: {
- type: 'object',
- properties: {
- type: { type: 'string' },
- name: { type: 'string' }
- }
- },
- match: {
- type: 'object',
- properties: {
- regularExpression: { type: 'object' },
- isAmbiguous: { type: 'boolean' }
- }
- },
- profile: {
- type: 'object',
- properties: {
- display: { type: 'string' },
- uri: { type: 'string' },
- qr: { type: 'string' }
- }
- },
- proof: {
- type: 'object',
- properties: {
- uri: { type: 'string' },
- request: {
- type: 'object',
- properties: {
- fetcher: { type: 'string' },
- access: { type: 'string' },
- format: { type: 'string' },
- data: { type: 'object' }
- }
- }
- }
- },
- claim: {
- type: 'object',
- properties: {
- format: { type: 'string' },
- relation: { type: 'string' },
- path: {
- type: 'array',
- items: {
- type: 'string'
- }
- }
- }
- }
- }
- }
- },
- verification: {
- type: 'object'
- },
- summary: {
- type: 'object',
- properties: {
- profileName: { type: 'string' },
- profileURL: { type: 'string' },
- serviceProviderName: { type: 'string' },
- isVerificationDone: { type: 'boolean' },
- isVerified: { type: 'boolean' }
- }
- }
- }
- }
- }
- }
- }
- },
- primaryUserIndex: {
- type: 'integer'
- },
- key: {
- type: 'object',
- properties: {
- data: { type: 'object' },
- fetchMethod: { type: 'string' },
- uri: { type: 'string' }
- }
- }
- }
- },
- keyoxide: {
- type: 'object',
- properties: {
- url: { type: 'string' }
- }
- },
- extra: {
- type: 'object',
- properties: {
- avatarURL: { type: 'string' }
- }
- },
- errors: {
- type: 'array'
- }
- },
- required: ['keyData', 'keyoxide', 'extra', 'errors'],
- additionalProperties: false
-}
-
-const apiProfileValidate = ajv.compile(apiProfileSchema)
-
-const doVerification = async (data) => {
- const promises = []
- const results = []
- const verificationOptions = {
- proxy: {
- hostname: process.env.PROXY_HOSTNAME,
- policy: (process.env.PROXY_HOSTNAME !== '') ? 'adaptive' : 'never'
- }
- }
-
- // Return early if no users in key
- if (!data.keyData.users) {
- return data
- }
-
- for (let iUser = 0; iUser < data.keyData.users.length; iUser++) {
- const user = data.keyData.users[iUser]
-
- for (let iClaim = 0; iClaim < user.claims.length; iClaim++) {
- const claim = user.claims[iClaim]
-
- promises.push(
- new Promise((resolve, reject) => {
- (async () => {
- await claim.verify(verificationOptions)
- results.push([iUser, iClaim, claim])
- resolve()
- })()
- })
- )
- }
- }
- await Promise.all(promises)
-
- results.forEach(result => {
- data.keyData.users[result[0]].claims[result[1]] = result[2]
- })
-
- return data
-}
-
-const sanitize = (data) => {
- const dataClone = JSON.parse(JSON.stringify(data))
-
- if (dataClone.keyData.users) {
- for (let iUser = 0; iUser < dataClone.keyData.users.length; iUser++) {
- const user = dataClone.keyData.users[iUser]
-
- for (let iClaim = 0; iClaim < user.claims.length; iClaim++) {
- const claim = user.claims[iClaim]
-
- // TODO Fix upstream
- for (let iMatch = 0; iMatch < claim.matches.length; iMatch++) {
- const match = claim.matches[iMatch]
- if (Array.isArray(match.claim)) {
- match.claim = match.claim[0]
- }
- }
- // TODO Fix upstream
- if (!claim.verification) {
- claim.verification = {}
- }
- // TODO Fix upstream
- claim.matches.forEach(match => {
- match.proof.request.access = ['generic', 'nocors', 'granted', 'server'][match.proof.request.access]
- match.claim.format = ['uri', 'fingerprint', 'message'][match.claim.format]
- match.claim.relation = ['contains', 'equals', 'oneof'][match.claim.relation]
- })
-
- data.keyData.users[iUser].claims[iClaim] = claim
- }
- }
- }
-
- const valid = apiProfileValidate(data)
- if (!valid) {
- throw new Error('Profile data sanitization error')
- }
-
- return data
-}
-
-const addSummaryToClaims = (data) => {
- // Return early if no users in key
- if (!data.keyData.users) {
- return data
- }
-
- // To be removed when data is added by DOIP library
- for (let userIndex = 0; userIndex < data.keyData.users.length; userIndex++) {
- const user = data.keyData.users[userIndex]
-
- for (let claimIndex = 0; claimIndex < user.claims.length; claimIndex++) {
- const claim = user.claims[claimIndex]
-
- const isVerificationDone = claim.status === 'verified'
- const isVerified = isVerificationDone ? claim.verification.result : false
- const isAmbiguous = isVerified
- ? false
- : claim.matches.length > 1 || claim.matches[0].match.isAmbiguous
-
- data.keyData.users[userIndex].claims[claimIndex].summary = {
- profileName: !isAmbiguous ? claim.matches[0].profile.display : claim.uri,
- profileURL: !isAmbiguous ? claim.matches[0].profile.uri : '',
- serviceProviderName: !isAmbiguous ? claim.matches[0].serviceprovider.name : '',
- isVerificationDone,
- isVerified
- }
- }
- }
-
- return data
-}
-
-router.get('/profile/fetch',
- check('query').exists(),
- check('protocol').optional().toLowerCase().isIn(['hkp', 'wkd']),
- check('doVerification').default(false).isBoolean().toBoolean(),
- check('returnPublicKey').default(false).isBoolean().toBoolean(),
- async (req, res) => {
- const valRes = validationResult(req)
- if (!valRes.isEmpty()) {
- res.status(400).send(valRes)
- return
- }
-
- // Generate profile
- let data
- switch (req.query.protocol) {
- case 'wkd':
- data = await generateWKDProfile(req.query.query)
- break
- case 'hkp':
- data = await generateHKPProfile(req.query.query)
- break
- default:
- data = await generateAutoProfile(req.query.query)
- break
- }
-
- if (data.errors.length > 0) {
- data.key = undefined
- res.status(500).send(data)
- }
-
- // Return public key
- if (req.query.returnPublicKey) {
- data.keyData.key.data = data.key.publicKey
- }
- data.key = undefined
-
- // Do verification
- if (req.query.doVerification) {
- data = await doVerification(data)
- }
-
- try {
- // Sanitize JSON
- data = sanitize(data)
- } catch (error) {
- data.keyData = {}
- data.extra = {}
- data.errors = [error.message]
- }
-
- // Add missing data
- data = addSummaryToClaims(data)
-
- let statusCode = 200
- if (data.errors.length > 0) {
- statusCode = 500
- }
-
- res.status(statusCode).send(data)
- }
-)
-
-router.get('/profile/verify',
- check('data').exists().isJSON(),
- async (req, res) => {
- const valRes = validationResult(req)
- if (!valRes.isEmpty()) {
- res.status(400).send(valRes)
- return
- }
-
- // Do verification
- let data = await doVerification(req.query.data)
-
- try {
- // Sanitize JSON
- data = sanitize(data)
- } catch (error) {
- data.keyData = {}
- data.extra = {}
- data.errors = [error.message]
- }
-
- // Add missing data
- data = addSummaryToClaims(data)
-
- let statusCode = 200
- if (data.errors.length > 0) {
- statusCode = 500
- }
-
- res.status(statusCode).send(data)
- }
-)
-
-export default router
diff --git a/src/api/v1/index.js b/src/api/v1/index.js
deleted file mode 100644
index c61d247..0000000
--- a/src/api/v1/index.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-Copyright 2022 Yarmo Mackenbach
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-import express from 'express'
-const router = express.Router()
-
-router.get('*', (req, res) => {
- return res.status(501).send('Proxy v1 API endpoint is no longer supported, please migrate to proxy v2 API endpoint')
-})
-
-export default router
diff --git a/src/api/v2/keyoxide_profile.js b/src/api/v2/keyoxide_profile.js
deleted file mode 100644
index f13a7c2..0000000
--- a/src/api/v2/keyoxide_profile.js
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
-Copyright (C) 2022 Yarmo Mackenbach
-
-This program is free software: you can redistribute it and/or modify it under
-the terms of the GNU Affero General Public License as published by the Free
-Software Foundation, either version 3 of the License, or (at your option)
-any later version.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-details.
-
-You should have received a copy of the GNU Affero General Public License along
-with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
-If your software can interact with users remotely through a computer network,
-you should also make sure that it provides a way for users to get its source.
-For example, if your program is a web application, its interface could display
-a "Source" link that leads users to an archive of the code. There are many
-ways you could offer source, and different solutions will be better for different
-programs; see section 13 for the specific requirements.
-
-You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary. For
-more information on this, and how to apply and follow the GNU AGPL, see .
-*/
-import express from 'express'
-import { check, validationResult } from 'express-validator'
-import Ajv from 'ajv'
-import { generateWKDProfile, generateHKPProfile, generateAutoProfile } from '../../server/index.js'
-import * as dotenv from 'dotenv'
-dotenv.config()
-
-const router = express.Router()
-const ajv = new Ajv({ coerceTypes: true })
-
-const apiProfileSchema = {
- type: 'object',
- properties: {
- keyData: {
- type: 'object',
- properties: {
- fingerprint: {
- type: 'string'
- },
- openpgp4fpr: {
- type: 'string'
- },
- users: {
- type: 'array',
- items: {
- type: 'object',
- properties: {
- userData: {
- type: 'object',
- properties: {
- id: { type: 'string' },
- name: { type: 'string' },
- email: { type: 'string' },
- comment: { type: 'string' },
- isPrimary: { type: 'boolean' },
- isRevoked: { type: 'boolean' }
- }
- },
- claims: {
- type: 'array',
- items: {
- type: 'object',
- properties: {
- claimVersion: { type: 'integer' },
- uri: { type: 'string' },
- fingerprint: { type: 'string' },
- status: { type: 'string' },
- matches: {
- type: 'array',
- items: {
- type: 'object',
- properties: {
- serviceProvider: {
- type: 'object',
- properties: {
- type: { type: 'string' },
- name: { type: 'string' }
- }
- },
- match: {
- type: 'object',
- properties: {
- regularExpression: { type: 'object' },
- isAmbiguous: { type: 'boolean' }
- }
- },
- profile: {
- type: 'object',
- properties: {
- display: { type: 'string' },
- uri: { type: 'string' },
- qr: { type: 'string' }
- }
- },
- proof: {
- type: 'object',
- properties: {
- uri: { type: 'string' },
- request: {
- type: 'object',
- properties: {
- fetcher: { type: 'string' },
- access: { type: 'string' },
- format: { type: 'string' },
- data: { type: 'object' }
- }
- }
- }
- },
- claim: {
- type: 'array',
- items: {
- type: 'object',
- properties: {
- format: { type: 'string' },
- relation: { type: 'string' },
- path: {
- type: 'array',
- items: {
- type: 'string'
- }
- }
- }
- }
- }
- }
- }
- },
- verification: {
- type: 'object'
- },
- summary: {
- type: 'object',
- properties: {
- profileName: { type: 'string' },
- profileURL: { type: 'string' },
- serviceProviderName: { type: 'string' },
- isVerificationDone: { type: 'boolean' },
- isVerified: { type: 'boolean' }
- }
- }
- }
- }
- }
- }
- }
- },
- primaryUserIndex: {
- type: 'integer'
- },
- key: {
- type: 'object',
- properties: {
- data: { type: 'object' },
- fetchMethod: { type: 'string' },
- uri: { type: 'string' }
- }
- }
- }
- },
- keyoxide: {
- type: 'object',
- properties: {
- url: { type: 'string' }
- }
- },
- extra: {
- type: 'object',
- properties: {
- avatarURL: { type: 'string' }
- }
- },
- errors: {
- type: 'array'
- }
- },
- required: ['keyData', 'keyoxide', 'extra', 'errors'],
- additionalProperties: false
-}
-
-const apiProfileValidate = ajv.compile(apiProfileSchema)
-
-const doVerification = async (data) => {
- const promises = []
- const results = []
- const verificationOptions = {
- proxy: {
- hostname: process.env.PROXY_HOSTNAME,
- policy: (process.env.PROXY_HOSTNAME !== '') ? 'adaptive' : 'never'
- }
- }
-
- // Return early if no users in key
- if (!data.keyData.users) {
- return data
- }
-
- for (let iUser = 0; iUser < data.keyData.users.length; iUser++) {
- const user = data.keyData.users[iUser]
-
- for (let iClaim = 0; iClaim < user.claims.length; iClaim++) {
- const claim = user.claims[iClaim]
-
- promises.push(
- new Promise((resolve, reject) => {
- (async () => {
- await claim.verify(verificationOptions)
- results.push([iUser, iClaim, claim])
- resolve()
- })()
- })
- )
- }
- }
- await Promise.all(promises)
-
- results.forEach(result => {
- data.keyData.users[result[0]].claims[result[1]] = result[2]
- })
-
- return data
-}
-
-const sanitize = (data) => {
- const valid = apiProfileValidate(data)
- if (!valid) {
- throw new Error('Profile data sanitization error')
- }
-
- return data
-}
-
-const addSummaryToClaims = (data) => {
- // Return early if no users in key
- if (!data.keyData.users) {
- return data
- }
-
- // To be removed when data is added by DOIP library
- for (let userIndex = 0; userIndex < data.keyData.users.length; userIndex++) {
- const user = data.keyData.users[userIndex]
-
- for (let claimIndex = 0; claimIndex < user.claims.length; claimIndex++) {
- const claim = user.claims[claimIndex]
-
- const isVerificationDone = claim.status === 'verified'
- const isVerified = isVerificationDone ? claim.verification.result : false
- const isAmbiguous = isVerified
- ? false
- : claim.matches.length > 1 || claim.matches[0].match.isAmbiguous
-
- data.keyData.users[userIndex].claims[claimIndex].summary = {
- profileName: !isAmbiguous ? claim.matches[0].profile.display : claim.uri,
- profileURL: !isAmbiguous ? claim.matches[0].profile.uri : '',
- serviceProviderName: !isAmbiguous ? claim.matches[0].serviceprovider.name : '',
- isVerificationDone,
- isVerified
- }
- }
- }
-
- return data
-}
-
-router.get('/fetch',
- check('query').exists(),
- check('protocol').optional().toLowerCase().isIn(['hkp', 'wkd']),
- check('doVerification').default(false).isBoolean().toBoolean(),
- check('returnPublicKey').default(false).isBoolean().toBoolean(),
- async (req, res) => {
- const valRes = validationResult(req)
- if (!valRes.isEmpty()) {
- res.status(400).send(valRes)
- return
- }
-
- // Generate profile
- let data
- switch (req.query.protocol) {
- case 'wkd':
- data = await generateWKDProfile(req.query.query)
- break
- case 'hkp':
- data = await generateHKPProfile(req.query.query)
- break
- default:
- data = await generateAutoProfile(req.query.query)
- break
- }
-
- if (data.errors.length > 0) {
- data.key = undefined
- res.status(500).send(data)
- }
-
- // Return public key
- if (req.query.returnPublicKey) {
- data.keyData.key.data = data.key.publicKey
- }
- data.key = undefined
-
- // Do verification
- if (req.query.doVerification) {
- data = await doVerification(data)
- }
-
- try {
- // Sanitize JSON
- data = sanitize(data)
- } catch (error) {
- data.keyData = {}
- data.extra = {}
- data.errors = [error.message]
- }
-
- // Add missing data
- data = addSummaryToClaims(data)
-
- let statusCode = 200
- if (data.errors.length > 0) {
- statusCode = 500
- }
-
- res.status(statusCode).send(data)
- }
-)
-
-router.get('/verify',
- check('data').exists().isJSON(),
- async (req, res) => {
- const valRes = validationResult(req)
- if (!valRes.isEmpty()) {
- res.status(400).send(valRes)
- return
- }
-
- // Do verification
- let data = await doVerification(req.query.data)
-
- try {
- // Sanitize JSON
- data = sanitize(data)
- } catch (error) {
- data.keyData = {}
- data.extra = {}
- data.errors = [error.message]
- }
-
- // Add missing data
- data = addSummaryToClaims(data)
-
- let statusCode = 200
- if (data.errors.length > 0) {
- statusCode = 500
- }
-
- res.status(statusCode).send(data)
- }
-)
-
-export default router
diff --git a/src/api/v2/index.js b/src/api/v3/index.js
similarity index 98%
rename from src/api/v2/index.js
rename to src/api/v3/index.js
index 1b17e75..80a0d28 100644
--- a/src/api/v2/index.js
+++ b/src/api/v3/index.js
@@ -1,5 +1,5 @@
/*
-Copyright (C) 2022 Yarmo Mackenbach
+Copyright (C) 2023 Yarmo Mackenbach
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
diff --git a/src/api/v3/keyoxide_profile.js b/src/api/v3/keyoxide_profile.js
new file mode 100644
index 0000000..b1ba960
--- /dev/null
+++ b/src/api/v3/keyoxide_profile.js
@@ -0,0 +1,185 @@
+/*
+Copyright (C) 2023 Yarmo Mackenbach
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU Affero General Public License as published by the Free
+Software Foundation, either version 3 of the License, or (at your option)
+any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+details.
+
+You should have received a copy of the GNU Affero General Public License along
+with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+If your software can interact with users remotely through a computer network,
+you should also make sure that it provides a way for users to get its source.
+For example, if your program is a web application, its interface could display
+a "Source" link that leads users to an archive of the code. There are many
+ways you could offer source, and different solutions will be better for different
+programs; see section 13 for the specific requirements.
+
+You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary. For
+more information on this, and how to apply and follow the GNU AGPL, see .
+*/
+import express from 'express'
+import { check, validationResult } from 'express-validator'
+import Ajv from 'ajv/dist/2020.js'
+import * as dotenv from 'dotenv'
+import { Claim } from 'doipjs'
+import { generateAspeProfile, generateWKDProfile, generateHKPProfile, generateAutoProfile } from '../../server/index.js'
+import { claimSchema, personaSchema, profileSchema, serviceProviderSchema } from '../../schemas.js'
+dotenv.config()
+
+const router = express.Router()
+const ajv = new Ajv({
+ schemas: [profileSchema, personaSchema, claimSchema, serviceProviderSchema]
+})
+
+const apiProfileValidate = ajv.compile(profileSchema)
+
+const doVerification = async (profile) => {
+ const promises = []
+ const results = []
+ const verificationOptions = {
+ proxy: {
+ hostname: process.env.PROXY_HOSTNAME,
+ policy: (process.env.PROXY_HOSTNAME !== '') ? 'adaptive' : 'never'
+ }
+ }
+
+ // Return early if no users in key
+ if (!profile.personas) {
+ return profile
+ }
+
+ for (let iUser = 0; iUser < profile.personas.length; iUser++) {
+ const user = profile.personas[iUser]
+
+ for (let iClaim = 0; iClaim < user.claims.length; iClaim++) {
+ const claim = user.claims[iClaim]
+
+ promises.push(
+ new Promise((resolve, reject) => {
+ (async () => {
+ await claim.verify(verificationOptions)
+ results.push([iUser, iClaim, claim])
+ resolve()
+ })()
+ })
+ )
+ }
+ }
+ await Promise.all(promises)
+
+ results.forEach(result => {
+ profile.personas[result[0]].claims[result[1]] = result[2]
+ })
+
+ return profile
+}
+
+const validate = (profile) => {
+ const valid = apiProfileValidate(profile)
+ if (!valid) {
+ throw new Error(`Profile data validation error: ${apiProfileValidate.errors.map(x => x.message).join(', ')}`)
+ }
+}
+
+router.get('/fetch',
+ check('query').exists(),
+ check('protocol').optional().toLowerCase().isIn(['aspe', 'hkp', 'wkd']),
+ check('doVerification').default(false).isBoolean().toBoolean(),
+ async (req, res) => {
+ const valRes = validationResult(req)
+ if (!valRes.isEmpty()) {
+ res.status(400).send(valRes)
+ return
+ }
+
+ // Generate profile
+ let data
+ switch (req.query.protocol) {
+ case 'aspe':
+ data = await generateAspeProfile(req.query.query)
+ break
+ case 'wkd':
+ data = await generateWKDProfile(req.query.query)
+ break
+ case 'hkp':
+ data = await generateHKPProfile(req.query.query)
+ break
+ default:
+ data = await generateAutoProfile(req.query.query)
+ break
+ }
+
+ if ('errors' in data && data.errors.length > 0) {
+ res.status(500).send(data)
+ }
+
+ // Do verification
+ if (req.query.doVerification) {
+ data = await doVerification(data)
+ }
+
+ data = data.toJSON()
+
+ try {
+ // Validate JSON
+ validate(data)
+ } catch (error) {
+ data = {
+ errors: [error.message]
+ }
+ }
+
+ let statusCode = 200
+ if ('errors' in data && data.errors.length > 0) {
+ statusCode = 500
+ }
+
+ res.status(statusCode).send(data)
+ }
+)
+
+router.get('/verify',
+ check('data').exists().isJSON(),
+ async (req, res) => {
+ const valRes = validationResult(req)
+ if (!valRes.isEmpty()) {
+ res.status(400).send(valRes)
+ return
+ }
+
+ let profile = Claim.fromJson(req.query.data)
+
+ // Do verification
+ let data = await doVerification(profile)
+
+ data = data.toJSON()
+
+ try {
+ // Validate JSON
+ validate(data)
+ } catch (error) {
+ data = {
+ errors: [error.message]
+ }
+ }
+
+ let statusCode = 200
+ if ('errors' in data) {
+ statusCode = 500
+ }
+
+ res.status(statusCode).send(data)
+ }
+)
+
+export default router
diff --git a/src/api/v2/proxy_get.js b/src/api/v3/proxy_get.js
similarity index 92%
rename from src/api/v2/proxy_get.js
rename to src/api/v3/proxy_get.js
index 5cacfa6..a766735 100644
--- a/src/api/v2/proxy_get.js
+++ b/src/api/v3/proxy_get.js
@@ -51,9 +51,6 @@ const opts = {
telegram: {
token: process.env.TELEGRAM_TOKEN || null
},
- twitter: {
- bearerToken: process.env.TWITTER_BEARER_TOKEN || null
- },
xmpp: {
service: process.env.XMPP_SERVICE || null,
username: process.env.XMPP_USERNAME || null,
@@ -138,26 +135,6 @@ router.get(
}
)
-// Twitter route
-router.get('/twitter', query('tweetId').isInt(), async (req, res) => {
- if (!opts.claims.twitter.bearerToken) {
- return res.status(501).json({ errors: 'Twitter not enabled on server' })
- }
- const errors = validationResult(req)
- if (!errors.isEmpty()) {
- return res.status(400).json({ errors: errors.array() })
- }
-
- fetcher.twitter
- .fn(req.query, opts)
- .then((data) => {
- return res.status(200).send(data)
- })
- .catch((err) => {
- return res.status(400).json({ errors: err.message ? err.message : err })
- })
-})
-
// Matrix route
router.get(
'/matrix',