diff --git a/src/index.js b/src/index.js index a0cb6cf..ff7fdec 100644 --- a/src/index.js +++ b/src/index.js @@ -40,11 +40,11 @@ const verify = async (uri, fingerprint, opts) => { res = null if (spData.customRequestHandler instanceof Function) { - proofData = spData.customRequestHandler(spData, opts) + proofData = await spData.customRequestHandler(spData, opts) } else if (!spData.proof.useProxy || 'useProxyWhenNeeded' in opts && !opts.useProxyWhenNeeded) { - proofData = serviceproviders.directRequestHandler(spData) + proofData = await serviceproviders.directRequestHandler(spData) } else { - proofData = serviceproviders.proxyRequestHandler(spData) + proofData = await serviceproviders.proxyRequestHandler(spData) } claimHasBeenVerified = claimVerification.run(proofData, spData) diff --git a/src/serviceproviders.js b/src/serviceproviders.js index fe869ff..fa66930 100644 --- a/src/serviceproviders.js +++ b/src/serviceproviders.js @@ -25,6 +25,7 @@ const list = [ 'lobsters', 'devto', 'gitea', + 'gitlab', 'github', ] @@ -37,6 +38,7 @@ const data = { lobsters: require('./serviceproviders/lobsters'), devto: require('./serviceproviders/devto'), gitea: require('./serviceproviders/gitea'), + gitlab: require('./serviceproviders/gitlab'), github: require('./serviceproviders/github'), } @@ -55,7 +57,7 @@ const match = (uri, opts) => { const directRequestHandler = async (spData) => { const res = await req(spData.proof.fetch ? spData.proof.fetch : spData.proof.uri) - + switch (spData.proof.format) { case 'json': return await res.json() @@ -69,7 +71,7 @@ const directRequestHandler = async (spData) => { } } -const proxyRequestHandler = (spData) => { +const proxyRequestHandler = async (spData) => { return null } diff --git a/src/serviceproviders/gitlab.js b/src/serviceproviders/gitlab.js new file mode 100644 index 0000000..83ee8e2 --- /dev/null +++ b/src/serviceproviders/gitlab.js @@ -0,0 +1,92 @@ +/* +Copyright 2020 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. +*/ +const bent = require('bent') +const req = bent('GET') + +const reURI = /^https:\/\/(.*)\/(.*)\/gitlab_proof\/?/ + +const customRequestHandler = async (spData, opts) => { + const match = spData.proof.uri.match(reURI) + + const urlUser = `https://${match[1]}/api/v4/users?username=${match[2]}` + const resUser = await req(urlUser, {}, { Accept: 'application/json' }) + const jsonUser = await resUser.json() + + const user = jsonUser.find(user => user.username === match[2]) + if (!user) { + throw new Error(`No user with username ${match[2]}`); + } + + const urlProject = `https://${match[1]}/api/v4/users/${user.id}/projects` + const resProject = await req(urlProject, {}, { Accept: 'application/json' }) + const jsonProject = await resProject.json() + + const project = jsonProject.find(proj => proj.path === 'gitlab_proof') + if (!project) { + throw new Error(`No project at ${spData.proof.uri}`); + } + + return project +} + +const processURI = (uri, opts) => { + if (!opts) { opts = {} } + const match = uri.match(reURI) + + return { + serviceprovider: { + type: 'web', + name: 'gitlab' + }, + profile: { + display: `${match[2]}@${match[1]}`, + uri: `https://${match[1]}/${match[2]}` + }, + proof: { + uri: uri, + fetch: null, + useProxy: false, + format: 'json' + }, + claim: { + fingerprint: null, + format: 'message', + path: ['description'], + relation: 'contains' + }, + qr: null, + customRequestHandler: customRequestHandler + } +} + +const tests = [ + { + uri: 'https://gist.github.com/Alice/123456789', + shouldMatch: true + }, + { + uri: 'https://gist.github.com/Alice/123456789/', + shouldMatch: true + }, + { + uri: 'https://domain.org/Alice/123456789', + shouldMatch: false + } +] + +exports.reURI = reURI +exports.processURI = processURI +exports.tests = tests