Fix JavaScript Standard Style issues

This commit is contained in:
Yarmo Mackenbach 2021-07-09 23:44:52 +02:00
parent 5b7bdcad76
commit 3676023df1
No known key found for this signature in database
GPG key ID: 37367F4AF4087AD1
35 changed files with 665 additions and 704 deletions

View file

@ -43,7 +43,7 @@ class Claim {
* const claim = doip.Claim('dns:domain.tld?type=TXT', '123abc123abc'); * const claim = doip.Claim('dns:domain.tld?type=TXT', '123abc123abc');
* const claimAlt = doip.Claim(JSON.stringify(claim)); * const claimAlt = doip.Claim(JSON.stringify(claim));
*/ */
constructor(uri, fingerprint) { constructor (uri, fingerprint) {
// Import JSON // Import JSON
if (typeof uri === 'object' && 'claimVersion' in uri) { if (typeof uri === 'object' && 'claimVersion' in uri) {
const data = uri const data = uri
@ -58,7 +58,6 @@ class Claim {
default: default:
throw new Error('Invalid claim version') throw new Error('Invalid claim version')
break
} }
return return
} }
@ -73,44 +72,44 @@ class Claim {
try { try {
validator.isAlphanumeric(fingerprint) validator.isAlphanumeric(fingerprint)
} catch (err) { } catch (err) {
throw new Error(`Invalid fingerprint`) throw new Error('Invalid fingerprint')
} }
} }
this._uri = uri ? uri : null this._uri = uri || null
this._fingerprint = fingerprint ? fingerprint : null this._fingerprint = fingerprint || null
this._status = E.ClaimStatus.INIT this._status = E.ClaimStatus.INIT
this._matches = null this._matches = null
this._verification = null this._verification = null
} }
get uri() { get uri () {
return this._uri return this._uri
} }
get fingerprint() { get fingerprint () {
return this._fingerprint return this._fingerprint
} }
get status() { get status () {
return this._status return this._status
} }
get matches() { get matches () {
if (this._status === E.ClaimStatus.INIT) { if (this._status === E.ClaimStatus.INIT) {
throw new Error('This claim has not yet been matched') throw new Error('This claim has not yet been matched')
} }
return this._matches return this._matches
} }
get verification() { get verification () {
if (this._status !== E.ClaimStatus.VERIFIED) { if (this._status !== E.ClaimStatus.VERIFIED) {
throw new Error('This claim has not yet been verified') throw new Error('This claim has not yet been verified')
} }
return this._verification return this._verification
} }
set uri(uri) { set uri (uri) {
if (this._status !== E.ClaimStatus.INIT) { if (this._status !== E.ClaimStatus.INIT) {
throw new Error( throw new Error(
'Cannot change the URI, this claim has already been matched' 'Cannot change the URI, this claim has already been matched'
@ -126,7 +125,7 @@ class Claim {
this._uri = uri this._uri = uri
} }
set fingerprint(fingerprint) { set fingerprint (fingerprint) {
if (this._status === E.ClaimStatus.VERIFIED) { if (this._status === E.ClaimStatus.VERIFIED) {
throw new Error( throw new Error(
'Cannot change the fingerprint, this claim has already been verified' 'Cannot change the fingerprint, this claim has already been verified'
@ -135,15 +134,15 @@ class Claim {
this._fingerprint = fingerprint this._fingerprint = fingerprint
} }
set status(anything) { set status (anything) {
throw new Error("Cannot change a claim's status") throw new Error("Cannot change a claim's status")
} }
set matches(anything) { set matches (anything) {
throw new Error("Cannot change a claim's matches") throw new Error("Cannot change a claim's matches")
} }
set verification(anything) { set verification (anything) {
throw new Error("Cannot change a claim's verification result") throw new Error("Cannot change a claim's verification result")
} }
@ -151,7 +150,7 @@ class Claim {
* Match the claim's URI to candidate definitions * Match the claim's URI to candidate definitions
* @function * @function
*/ */
match() { match () {
if (this._status !== E.ClaimStatus.INIT) { if (this._status !== E.ClaimStatus.INIT) {
throw new Error('This claim was already matched') throw new Error('This claim was already matched')
} }
@ -195,7 +194,7 @@ class Claim {
* @function * @function
* @param {object} [opts] - Options for proxy, fetchers * @param {object} [opts] - Options for proxy, fetchers
*/ */
async verify(opts) { async verify (opts) {
if (this._status === E.ClaimStatus.INIT) { if (this._status === E.ClaimStatus.INIT) {
throw new Error('This claim has not yet been matched') throw new Error('This claim has not yet been matched')
} }
@ -207,7 +206,7 @@ class Claim {
} }
// Handle options // Handle options
opts = mergeOptions(defaults.opts, opts ? opts : {}) opts = mergeOptions(defaults.opts, opts || {})
// If there are no matches // If there are no matches
if (this._matches.length === 0) { if (this._matches.length === 0) {
@ -215,7 +214,7 @@ class Claim {
result: false, result: false,
completed: true, completed: true,
proof: {}, proof: {},
errors: ['No matches for claim'], errors: ['No matches for claim']
} }
} }
@ -223,9 +222,9 @@ class Claim {
for (let index = 0; index < this._matches.length; index++) { for (let index = 0; index < this._matches.length; index++) {
const claimData = this._matches[index] const claimData = this._matches[index]
let verificationResult = null, let verificationResult = null
proofData = null, let proofData = null
proofFetchError let proofFetchError
try { try {
proofData = await proofs.fetch(claimData, opts) proofData = await proofs.fetch(claimData, opts)
@ -242,15 +241,15 @@ class Claim {
) )
verificationResult.proof = { verificationResult.proof = {
fetcher: proofData.fetcher, fetcher: proofData.fetcher,
viaProxy: proofData.viaProxy, viaProxy: proofData.viaProxy
} }
} else { } else {
// Consider the proof completed but with a negative result // Consider the proof completed but with a negative result
verificationResult = verificationResult ? verificationResult : { verificationResult = verificationResult || {
result: false, result: false,
completed: true, completed: true,
proof: {}, proof: {},
errors: [proofFetchError], errors: [proofFetchError]
} }
if (this.isAmbiguous()) { if (this.isAmbiguous()) {
@ -268,11 +267,13 @@ class Claim {
} }
// Fail safe verification result // Fail safe verification result
this._verification = this._verification ? this._verification : { this._verification = this._verification
? this._verification
: {
result: false, result: false,
completed: true, completed: true,
proof: {}, proof: {},
errors: ['Unknown error'], errors: ['Unknown error']
} }
this._status = E.ClaimStatus.VERIFIED this._status = E.ClaimStatus.VERIFIED
@ -285,16 +286,14 @@ class Claim {
* @function * @function
* @returns {boolean} * @returns {boolean}
*/ */
isAmbiguous() { isAmbiguous () {
if (this._status === E.ClaimStatus.INIT) { if (this._status === E.ClaimStatus.INIT) {
throw new Error('The claim has not been matched yet') throw new Error('The claim has not been matched yet')
} }
if (this._matches.length === 0) { if (this._matches.length === 0) {
throw new Error('The claim has no matches') throw new Error('The claim has no matches')
} }
return ( return this._matches.length > 1 || this._matches[0].match.isAmbiguous
this._matches.length > 1 || this._matches[0].match.isAmbiguous
)
} }
/** /**
@ -303,14 +302,14 @@ class Claim {
* @function * @function
* @returns {object} * @returns {object}
*/ */
toJSON() { toJSON () {
return { return {
claimVersion: 1, claimVersion: 1,
uri: this._uri, uri: this._uri,
fingerprint: this._fingerprint, fingerprint: this._fingerprint,
status: this._status, status: this._status,
matches: this._matches, matches: this._matches,
verification: this._verification, verification: this._verification
} }
} }
} }

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'devto', name: 'devto'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: match[1], display: match[1],
uri: `https://dev.to/${match[1]}`, uri: `https://dev.to/${match[1]}`,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: `https://dev.to/api/articles/${match[1]}/${match[2]}`, url: `https://dev.to/api/articles/${match[1]}/${match[2]}`,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['body_markdown'], path: ['body_markdown']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://dev.to/alice/post', uri: 'https://dev.to/alice/post',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://dev.to/alice/post/', uri: 'https://dev.to/alice/post/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/alice/post', uri: 'https://domain.org/alice/post',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'discourse', name: 'discourse'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: true, isAmbiguous: true
}, },
profile: { profile: {
display: `${match[2]}@${match[1]}`, display: `${match[2]}@${match[1]}`,
uri: uri, uri: uri,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: `https://${match[1]}/u/${match[2]}.json`, url: `https://${match[1]}/u/${match[2]}.json`,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['user', 'bio_raw'], path: ['user', 'bio_raw']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://domain.org/u/alice', uri: 'https://domain.org/u/alice',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/u/alice/', uri: 'https://domain.org/u/alice/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/alice', uri: 'https://domain.org/alice',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
const E = require('../enums') const E = require('../enums')
const reURI = /^dns:([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/ const reURI = /^dns:([a-zA-Z0-9.\-_]*)(?:\?(.*))?/
const processURI = (uri) => { const processURI = (uri) => {
const match = uri.match(reURI) const match = uri.match(reURI)
@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'dns', name: 'dns'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: match[1], display: match[1],
uri: `https://${match[1]}`, uri: `https://${match[1]}`,
qr: null, qr: null
}, },
proof: { proof: {
uri: null, uri: null,
@ -41,31 +41,31 @@ const processURI = (uri) => {
access: E.ProofAccess.SERVER, access: E.ProofAccess.SERVER,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
domain: match[1], domain: match[1]
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.URI, format: E.ClaimFormat.URI,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['records', 'txt'], path: ['records', 'txt']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'dns:domain.org', uri: 'dns:domain.org',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'dns:domain.org?type=TXT', uri: 'dns:domain.org?type=TXT',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org', uri: 'https://domain.org',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'fediverse', name: 'fediverse'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: true, isAmbiguous: true
}, },
profile: { profile: {
display: `@${match[2]}@${match[1]}`, display: `@${match[2]}@${match[1]}`,
uri: uri, uri: uri,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: uri, url: uri,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.FINGERPRINT, format: E.ClaimFormat.FINGERPRINT,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['summary'], path: ['summary']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://domain.org/users/alice', uri: 'https://domain.org/users/alice',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/users/alice/', uri: 'https://domain.org/users/alice/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/alice', uri: 'https://domain.org/alice',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'gitea', name: 'gitea'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: true, isAmbiguous: true
}, },
profile: { profile: {
display: `${match[2]}@${match[1]}`, display: `${match[2]}@${match[1]}`,
uri: `https://${match[1]}/${match[2]}`, uri: `https://${match[1]}/${match[2]}`,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: `https://${match[1]}/api/v1/repos/${match[2]}/gitea_proof`, url: `https://${match[1]}/api/v1/repos/${match[2]}/gitea_proof`,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.EQUALS, relation: E.ClaimRelation.EQUALS,
path: ['description'], path: ['description']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://domain.org/alice/gitea_proof', uri: 'https://domain.org/alice/gitea_proof',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/alice/gitea_proof/', uri: 'https://domain.org/alice/gitea_proof/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/alice/other_proof', uri: 'https://domain.org/alice/other_proof',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'github', name: 'github'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: match[1], display: match[1],
uri: `https://github.com/${match[1]}`, uri: `https://github.com/${match[1]}`,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: `https://api.github.com/gists/${match[2]}`, url: `https://api.github.com/gists/${match[2]}`,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['files', 'openpgp.md', 'content'], path: ['files', 'openpgp.md', 'content']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://gist.github.com/Alice/123456789', uri: 'https://gist.github.com/Alice/123456789',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://gist.github.com/Alice/123456789/', uri: 'https://gist.github.com/Alice/123456789/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/Alice/123456789', uri: 'https://domain.org/Alice/123456789',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'gitlab', name: 'gitlab'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: true, isAmbiguous: true
}, },
profile: { profile: {
display: `${match[2]}@${match[1]}`, display: `${match[2]}@${match[1]}`,
uri: `https://${match[1]}/${match[2]}`, uri: `https://${match[1]}/${match[2]}`,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
domain: match[1], domain: match[1],
username: match[2], username: match[2]
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.EQUALS, relation: E.ClaimRelation.EQUALS,
path: ['description'], path: ['description']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://gitlab.domain.org/alice/gitlab_proof', uri: 'https://gitlab.domain.org/alice/gitlab_proof',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://gitlab.domain.org/alice/gitlab_proof/', uri: 'https://gitlab.domain.org/alice/gitlab_proof/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/alice/other_proof', uri: 'https://domain.org/alice/other_proof',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'hackernews', name: 'hackernews'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: match[1], display: match[1],
uri: uri, uri: uri,
qr: null, qr: null
}, },
proof: { proof: {
uri: `https://hacker-news.firebaseio.com/v0/user/${match[1]}.json`, uri: `https://hacker-news.firebaseio.com/v0/user/${match[1]}.json`,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: `https://hacker-news.firebaseio.com/v0/user/${match[1]}.json`, url: `https://hacker-news.firebaseio.com/v0/user/${match[1]}.json`,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.URI, format: E.ClaimFormat.URI,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['about'], path: ['about']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://news.ycombinator.com/user?id=Alice', uri: 'https://news.ycombinator.com/user?id=Alice',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://news.ycombinator.com/user?id=Alice/', uri: 'https://news.ycombinator.com/user?id=Alice/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/user?id=Alice', uri: 'https://domain.org/user?id=Alice',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -30,7 +30,7 @@ const list = [
'mastodon', 'mastodon',
'fediverse', 'fediverse',
'discourse', 'discourse',
'owncast', 'owncast'
] ]
const data = { const data = {
@ -50,7 +50,7 @@ const data = {
mastodon: require('./mastodon'), mastodon: require('./mastodon'),
fediverse: require('./fediverse'), fediverse: require('./fediverse'),
discourse: require('./discourse'), discourse: require('./discourse'),
owncast: require('./owncast'), owncast: require('./owncast')
} }
exports.list = list exports.list = list

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
const E = require('../enums') const E = require('../enums')
const reURI = /^irc\:\/\/(.*)\/([a-zA-Z0-9\-\[\]\\\`\_\^\{\|\}]*)/ const reURI = /^irc:\/\/(.*)\/([a-zA-Z0-9\-[\]\\`_^{|}]*)/
const processURI = (uri) => { const processURI = (uri) => {
const match = uri.match(reURI) const match = uri.match(reURI)
@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'communication', type: 'communication',
name: 'irc', name: 'irc'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: `irc://${match[1]}/${match[2]}`, display: `irc://${match[1]}/${match[2]}`,
uri: uri, uri: uri,
qr: null, qr: null
}, },
proof: { proof: {
uri: null, uri: null,
@ -42,35 +42,35 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
domain: match[1], domain: match[1],
nick: match[2], nick: match[2]
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.URI, format: E.ClaimFormat.URI,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: [], path: []
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'irc://chat.ircserver.org/Alice1', uri: 'irc://chat.ircserver.org/Alice1',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'irc://chat.ircserver.org/alice?param=123', uri: 'irc://chat.ircserver.org/alice?param=123',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'irc://chat.ircserver.org/alice_bob', uri: 'irc://chat.ircserver.org/alice_bob',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://chat.ircserver.org/alice', uri: 'https://chat.ircserver.org/alice',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'liberapay', name: 'liberapay'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: match[1], display: match[1],
uri: uri, uri: uri,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: `https://liberapay.com/${match[1]}/public.json`, url: `https://liberapay.com/${match[1]}/public.json`,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['statements', 'content'], path: ['statements', 'content']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://liberapay.com/alice', uri: 'https://liberapay.com/alice',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://liberapay.com/alice/', uri: 'https://liberapay.com/alice/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/alice', uri: 'https://domain.org/alice',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'lobsters', name: 'lobsters'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: match[1], display: match[1],
uri: uri, uri: uri,
qr: null, qr: null
}, },
proof: { proof: {
uri: `https://lobste.rs/u/${match[1]}.json`, uri: `https://lobste.rs/u/${match[1]}.json`,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: `https://lobste.rs/u/${match[1]}.json`, url: `https://lobste.rs/u/${match[1]}.json`,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['about'], path: ['about']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://lobste.rs/u/Alice', uri: 'https://lobste.rs/u/Alice',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://lobste.rs/u/Alice/', uri: 'https://lobste.rs/u/Alice/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/u/Alice', uri: 'https://domain.org/u/Alice',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'mastodon', name: 'mastodon'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: true, isAmbiguous: true
}, },
profile: { profile: {
display: `@${match[2]}@${match[1]}`, display: `@${match[2]}@${match[1]}`,
uri: uri, uri: uri,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: uri, url: uri,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.FINGERPRINT, format: E.ClaimFormat.FINGERPRINT,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['attachment', 'value'], path: ['attachment', 'value']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://domain.org/@alice', uri: 'https://domain.org/@alice',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/@alice/', uri: 'https://domain.org/@alice/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/alice', uri: 'https://domain.org/alice',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -16,7 +16,7 @@ limitations under the License.
const E = require('../enums') const E = require('../enums')
const queryString = require('query-string') const queryString = require('query-string')
const reURI = /^matrix\:u\/(?:\@)?([^@:]*\:[^?]*)(\?.*)?/ const reURI = /^matrix:u\/(?:@)?([^@:]*:[^?]*)(\?.*)?/
const processURI = (uri) => { const processURI = (uri) => {
const match = uri.match(reURI) const match = uri.match(reURI)
@ -37,16 +37,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'communication', type: 'communication',
name: 'matrix', name: 'matrix'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: `@${match[1]}`, display: `@${match[1]}`,
uri: profileUrl, uri: profileUrl,
qr: null, qr: null
}, },
proof: { proof: {
uri: eventUrl, uri: eventUrl,
@ -56,15 +56,15 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
eventId: params['org.keyoxide.e'], eventId: params['org.keyoxide.e'],
roomId: params['org.keyoxide.r'], roomId: params['org.keyoxide.r']
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['content', 'body'], path: ['content', 'body']
}, }
} }
} }
@ -72,20 +72,20 @@ const tests = [
{ {
uri: uri:
'matrix:u/alice:matrix.domain.org?org.keyoxide.r=!123:domain.org&org.keyoxide.e=$123', 'matrix:u/alice:matrix.domain.org?org.keyoxide.r=!123:domain.org&org.keyoxide.e=$123',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'matrix:u/alice:matrix.domain.org', uri: 'matrix:u/alice:matrix.domain.org',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'xmpp:alice@domain.org', uri: 'xmpp:alice@domain.org',
shouldMatch: false, shouldMatch: false
}, },
{ {
uri: 'https://domain.org/@alice', uri: 'https://domain.org/@alice',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'owncast', name: 'owncast'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: true, isAmbiguous: true
}, },
profile: { profile: {
display: match[1], display: match[1],
uri: uri, uri: uri,
qr: null, qr: null
}, },
proof: { proof: {
uri: `${uri}/api/config`, uri: `${uri}/api/config`,
@ -42,35 +42,35 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: `${uri}/api/config`, url: `${uri}/api/config`,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.FINGERPRINT, format: E.ClaimFormat.FINGERPRINT,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['socialHandles', 'url'], path: ['socialHandles', 'url']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://live.domain.org', uri: 'https://live.domain.org',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://live.domain.org/', uri: 'https://live.domain.org/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/live', uri: 'https://domain.org/live',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/live/', uri: 'https://domain.org/live/',
shouldMatch: true, shouldMatch: true
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'reddit', name: 'reddit'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: match[1], display: match[1],
uri: `https://www.reddit.com/user/${match[1]}`, uri: `https://www.reddit.com/user/${match[1]}`,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -42,39 +42,39 @@ const processURI = (uri) => {
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON,
data: { data: {
url: `https://www.reddit.com/user/${match[1]}/comments/${match[2]}.json`, url: `https://www.reddit.com/user/${match[1]}/comments/${match[2]}.json`,
format: E.ProofFormat.JSON, format: E.ProofFormat.JSON
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: ['data', 'children', 'data', 'selftext'], path: ['data', 'children', 'data', 'selftext']
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://www.reddit.com/user/Alice/comments/123456/post', uri: 'https://www.reddit.com/user/Alice/comments/123456/post',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://www.reddit.com/user/Alice/comments/123456/post/', uri: 'https://www.reddit.com/user/Alice/comments/123456/post/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://reddit.com/user/Alice/comments/123456/post', uri: 'https://reddit.com/user/Alice/comments/123456/post',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://reddit.com/user/Alice/comments/123456/post/', uri: 'https://reddit.com/user/Alice/comments/123456/post/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/user/Alice/comments/123456/post', uri: 'https://domain.org/user/Alice/comments/123456/post',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'web', type: 'web',
name: 'twitter', name: 'twitter'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: `@${match[1]}`, display: `@${match[1]}`,
uri: `https://twitter.com/${match[1]}`, uri: `https://twitter.com/${match[1]}`,
qr: null, qr: null
}, },
proof: { proof: {
uri: uri, uri: uri,
@ -41,31 +41,31 @@ const processURI = (uri) => {
access: E.ProofAccess.GRANTED, access: E.ProofAccess.GRANTED,
format: E.ProofFormat.TEXT, format: E.ProofFormat.TEXT,
data: { data: {
tweetId: match[2], tweetId: match[2]
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: [], path: []
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'https://twitter.com/alice/status/1234567890123456789', uri: 'https://twitter.com/alice/status/1234567890123456789',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://twitter.com/alice/status/1234567890123456789/', uri: 'https://twitter.com/alice/status/1234567890123456789/',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org/alice/status/1234567890123456789', uri: 'https://domain.org/alice/status/1234567890123456789',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
const E = require('../enums') const E = require('../enums')
const reURI = /^xmpp:([a-zA-Z0-9\.\-\_]*)@([a-zA-Z0-9\.\-\_]*)(?:\?(.*))?/ const reURI = /^xmpp:([a-zA-Z0-9.\-_]*)@([a-zA-Z0-9.\-_]*)(?:\?(.*))?/
const processURI = (uri) => { const processURI = (uri) => {
const match = uri.match(reURI) const match = uri.match(reURI)
@ -23,16 +23,16 @@ const processURI = (uri) => {
return { return {
serviceprovider: { serviceprovider: {
type: 'communication', type: 'communication',
name: 'xmpp', name: 'xmpp'
}, },
match: { match: {
regularExpression: reURI, regularExpression: reURI,
isAmbiguous: false, isAmbiguous: false
}, },
profile: { profile: {
display: `${match[1]}@${match[2]}`, display: `${match[1]}@${match[2]}`,
uri: uri, uri: uri,
qr: uri, qr: uri
}, },
proof: { proof: {
uri: null, uri: null,
@ -42,31 +42,31 @@ const processURI = (uri) => {
format: E.ProofFormat.TEXT, format: E.ProofFormat.TEXT,
data: { data: {
id: `${match[1]}@${match[2]}`, id: `${match[1]}@${match[2]}`,
field: 'note', field: 'note'
}, }
}, }
}, },
claim: { claim: {
format: E.ClaimFormat.MESSAGE, format: E.ClaimFormat.MESSAGE,
relation: E.ClaimRelation.CONTAINS, relation: E.ClaimRelation.CONTAINS,
path: [], path: []
}, }
} }
} }
const tests = [ const tests = [
{ {
uri: 'xmpp:alice@domain.org', uri: 'xmpp:alice@domain.org',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'xmpp:alice@domain.org?omemo-sid-123456789=A1B2C3D4E5F6G7H8I9', uri: 'xmpp:alice@domain.org?omemo-sid-123456789=A1B2C3D4E5F6G7H8I9',
shouldMatch: true, shouldMatch: true
}, },
{ {
uri: 'https://domain.org', uri: 'https://domain.org',
shouldMatch: false, shouldMatch: false
}, }
] ]
exports.reURI = reURI exports.reURI = reURI

View file

@ -42,25 +42,25 @@ const E = require('./enums')
const opts = { const opts = {
proxy: { proxy: {
hostname: null, hostname: null,
policy: E.ProxyPolicy.NEVER, policy: E.ProxyPolicy.NEVER
}, },
claims: { claims: {
irc: { irc: {
nick: null, nick: null
}, },
matrix: { matrix: {
instance: null, instance: null,
accessToken: null, accessToken: null
}, },
xmpp: { xmpp: {
service: null, service: null,
username: null, username: null,
password: null, password: null
}, },
twitter: { twitter: {
bearerToken: null, bearerToken: null
}, }
}, }
} }
exports.opts = opts exports.opts = opts

View file

@ -29,7 +29,7 @@ const ProxyPolicy = {
/** Always use a proxy */ /** Always use a proxy */
ALWAYS: 'always', ALWAYS: 'always',
/** Never use a proxy, skip a verification if a proxy is inevitable */ /** Never use a proxy, skip a verification if a proxy is inevitable */
NEVER: 'never', NEVER: 'never'
} }
Object.freeze(ProxyPolicy) Object.freeze(ProxyPolicy)
@ -52,7 +52,7 @@ const Fetcher = {
/** HTTP request to Gitlab API */ /** HTTP request to Gitlab API */
GITLAB: 'gitlab', GITLAB: 'gitlab',
/** HTTP request to Twitter API */ /** HTTP request to Twitter API */
TWITTER: 'twitter', TWITTER: 'twitter'
} }
Object.freeze(Fetcher) Object.freeze(Fetcher)
@ -69,7 +69,7 @@ const ProofAccess = {
/** HTTP requests must contain API or access tokens */ /** HTTP requests must contain API or access tokens */
GRANTED: 2, GRANTED: 2,
/** Not accessible by HTTP request, needs server software */ /** Not accessible by HTTP request, needs server software */
SERVER: 3, SERVER: 3
} }
Object.freeze(ProofAccess) Object.freeze(ProofAccess)
@ -82,7 +82,7 @@ const ProofFormat = {
/** JSON format */ /** JSON format */
JSON: 'json', JSON: 'json',
/** Plaintext format */ /** Plaintext format */
TEXT: 'text', TEXT: 'text'
} }
Object.freeze(ProofFormat) Object.freeze(ProofFormat)
@ -97,7 +97,7 @@ const ClaimFormat = {
/** `123123123` */ /** `123123123` */
FINGERPRINT: 1, FINGERPRINT: 1,
/** `[Verifying my OpenPGP key: openpgp4fpr:123123123]` */ /** `[Verifying my OpenPGP key: openpgp4fpr:123123123]` */
MESSAGE: 2, MESSAGE: 2
} }
Object.freeze(ClaimFormat) Object.freeze(ClaimFormat)
@ -112,7 +112,7 @@ const ClaimRelation = {
/** Claim is equal to the JSON field's textual content */ /** Claim is equal to the JSON field's textual content */
EQUALS: 1, EQUALS: 1,
/** Claim is equal to an element of the JSON field's array of strings */ /** Claim is equal to an element of the JSON field's array of strings */
ONEOF: 2, ONEOF: 2
} }
Object.freeze(ClaimRelation) Object.freeze(ClaimRelation)
@ -127,7 +127,7 @@ const ClaimStatus = {
/** Claim has matched its URI to candidate claim definitions */ /** Claim has matched its URI to candidate claim definitions */
MATCHED: 'matched', MATCHED: 'matched',
/** Claim has verified one or multiple candidate claim definitions */ /** Claim has verified one or multiple candidate claim definitions */
VERIFIED: 'verified', VERIFIED: 'verified'
} }
Object.freeze(ClaimStatus) Object.freeze(ClaimStatus)

View file

@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
const jsEnv = require("browser-or-node") const jsEnv = require('browser-or-node')
/** /**
* @module fetcher/dns * @module fetcher/dns
@ -55,8 +55,8 @@ if (jsEnv.isNode) {
resolve({ resolve({
domain: data.domain, domain: data.domain,
records: { records: {
txt: records, txt: records
}, }
}) })
}) })
}) })

View file

@ -44,28 +44,45 @@ module.exports.fn = async (data, opts) => {
) )
}) })
const fetchPromise = new Promise(async (resolve, reject) => { const fetchPromise = new Promise((resolve, reject) => {
const urlUser = `https://${data.domain}/api/v4/users?username=${data.username}` const urlUser = `https://${data.domain}/api/v4/users?username=${data.username}`
const resUser = await req(urlUser, null, { Accept: 'application/json' }) // const resUser = await req(urlUser, null, { Accept: 'application/json' })
const jsonUser = await resUser.json() const res = req(urlUser, null, { Accept: 'application/json' })
.then(resUser => {
const user = jsonUser.find((user) => user.username === data.username) return resUser.json()
if (!user) {
reject(`No user with username ${data.username}`)
}
const urlProject = `https://${data.domain}/api/v4/users/${user.id}/projects`
const resProject = await req(urlProject, null, {
Accept: 'application/json',
}) })
const jsonProject = await resProject.json() .then(jsonUser => {
return jsonUser.find((user) => user.username === data.username)
const project = jsonProject.find((proj) => proj.path === 'gitlab_proof') })
if (!project) { .then(user => {
reject(`No project found`) if (!user) {
throw new Error(`No user with username ${data.username}`)
} }
return user
})
.then(user => {
const urlProject = `https://${data.domain}/api/v4/users/${user.id}/projects`
return req(urlProject, null, {
Accept: 'application/json'
})
})
.then(resProject => {
return resProject.json()
})
.then(jsonProject => {
return jsonProject.find((proj) => proj.path === 'gitlab_proof')
})
.then(project => {
if (!project) {
throw new Error('No project found')
}
return project
})
.catch(error => {
reject(error)
})
resolve(project) resolve(res)
}) })
return Promise.race([fetchPromise, timeoutPromise]).then((result) => { return Promise.race([fetchPromise, timeoutPromise]).then((result) => {

View file

@ -47,7 +47,7 @@ module.exports.fn = async (data, opts) => {
const fetchPromise = new Promise((resolve, reject) => { const fetchPromise = new Promise((resolve, reject) => {
if (!data.url) { if (!data.url) {
reject('No valid URI provided') reject(new Error('No valid URI provided'))
return return
} }
@ -55,7 +55,7 @@ module.exports.fn = async (data, opts) => {
case E.ProofFormat.JSON: case E.ProofFormat.JSON:
req(data.url, null, { req(data.url, null, {
Accept: 'application/json', Accept: 'application/json',
'User-Agent': `doipjs/${require('../../package.json').version}`, 'User-Agent': `doipjs/${require('../../package.json').version}`
}) })
.then(async (res) => { .then(async (res) => {
return await res.json() return await res.json()
@ -80,7 +80,7 @@ module.exports.fn = async (data, opts) => {
}) })
break break
default: default:
reject('No specified data format') reject(new Error('No specified data format'))
break break
} }
}) })

View file

@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
const jsEnv = require("browser-or-node") const jsEnv = require('browser-or-node')
/** /**
* @module fetcher/irc * @module fetcher/irc
@ -64,9 +64,9 @@ if (jsEnv.isNode) {
showErrors: false, showErrors: false,
debug: false debug: false
}) })
const reKey = /[a-zA-Z0-9\-\_]+\s+:\s(openpgp4fpr\:.*)/ const reKey = /[a-zA-Z0-9\-_]+\s+:\s(openpgp4fpr:.*)/
const reEnd = /End\sof\s.*\staxonomy./ const reEnd = /End\sof\s.*\staxonomy./
let keys = [] const keys = []
client.addListener('registered', (message) => { client.addListener('registered', (message) => {
client.send(`PRIVMSG NickServ TAXONOMY ${data.nick}`) client.send(`PRIVMSG NickServ TAXONOMY ${data.nick}`)

View file

@ -58,7 +58,7 @@ module.exports.fn = async (data, opts) => {
const url = `https://${opts.claims.matrix.instance}/_matrix/client/r0/rooms/${data.roomId}/event/${data.eventId}?access_token=${opts.claims.matrix.accessToken}` const url = `https://${opts.claims.matrix.instance}/_matrix/client/r0/rooms/${data.roomId}/event/${data.eventId}?access_token=${opts.claims.matrix.accessToken}`
bentReq(url, null, { bentReq(url, null, {
Accept: 'application/json', Accept: 'application/json'
}) })
.then(async (res) => { .then(async (res) => {
return await res.json() return await res.json()

View file

@ -60,7 +60,7 @@ module.exports.fn = async (data, opts) => {
null, null,
{ {
Accept: 'application/json', Accept: 'application/json',
Authorization: `Bearer ${opts.claims.twitter.bearerToken}`, Authorization: `Bearer ${opts.claims.twitter.bearerToken}`
} }
) )
.then(async (data) => { .then(async (data) => {

View file

@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
const jsEnv = require("browser-or-node") const jsEnv = require('browser-or-node')
/** /**
* @module fetcher/xmpp * @module fetcher/xmpp
@ -31,15 +31,15 @@ if (jsEnv.isNode) {
const debug = require('@xmpp/debug') const debug = require('@xmpp/debug')
const validator = require('validator') const validator = require('validator')
let xmpp = null, let xmpp = null
iqCaller = null let iqCaller = null
const xmppStart = async (service, username, password) => { const xmppStart = async (service, username, password) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const xmpp = client({ const xmpp = client({
service: service, service: service,
username: username, username: username,
password: password, password: password
}) })
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
debug(xmpp, true) debug(xmpp, true)
@ -69,15 +69,6 @@ if (jsEnv.isNode) {
* @returns {object} * @returns {object}
*/ */
module.exports.fn = async (data, opts) => { module.exports.fn = async (data, opts) => {
let timeoutHandle
const timeoutPromise = new Promise((resolve, reject) => {
timeoutHandle = setTimeout(
() => reject(new Error('Request was timed out')),
data.fetcherTimeout ? data.fetcherTimeout : module.exports.timeout
)
})
const fetchPromise = new Promise(async (resolve, reject) => {
try { try {
validator.isFQDN(opts.claims.xmpp.service) validator.isFQDN(opts.claims.xmpp.service)
validator.isAscii(opts.claims.xmpp.username) validator.isAscii(opts.claims.xmpp.username)
@ -104,6 +95,15 @@ if (jsEnv.isNode) {
const vcardRow = response.getChild('vCard', 'vcard-temp').toString() const vcardRow = response.getChild('vCard', 'vcard-temp').toString()
const dom = new jsdom.JSDOM(vcardRow) const dom = new jsdom.JSDOM(vcardRow)
let timeoutHandle
const timeoutPromise = new Promise((resolve, reject) => {
timeoutHandle = setTimeout(
() => reject(new Error('Request was timed out')),
data.fetcherTimeout ? data.fetcherTimeout : module.exports.timeout
)
})
const fetchPromise = new Promise((resolve, reject) => {
try { try {
let vcard let vcard

View file

@ -34,35 +34,31 @@ const Claim = require('./claim')
* const key1 = doip.keys.fetchHKP('alice@domain.tld'); * const key1 = doip.keys.fetchHKP('alice@domain.tld');
* const key2 = doip.keys.fetchHKP('123abc123abc'); * const key2 = doip.keys.fetchHKP('123abc123abc');
*/ */
exports.fetchHKP = (identifier, keyserverDomain) => { exports.fetchHKP = async (identifier, keyserverDomain) => {
return new Promise(async (resolve, reject) => {
const keyserverBaseUrl = keyserverDomain const keyserverBaseUrl = keyserverDomain
? `https://${keyserverDomain}` ? `https://${keyserverDomain}`
: 'https://keys.openpgp.org' : 'https://keys.openpgp.org'
const hkp = new openpgp.HKP(keyserverBaseUrl) const hkp = new openpgp.HKP(keyserverBaseUrl)
const lookupOpts = { const lookupOpts = {
query: identifier, query: identifier
} }
let publicKey = await hkp.lookup(lookupOpts).catch((error) => { const publicKey = await hkp.lookup(lookupOpts).catch((error) => {
reject('Key does not exist or could not be fetched') throw new Error(`Key does not exist or could not be fetched (${error})`)
}) })
publicKey = await openpgp.key if (!publicKey) {
throw new Error('Key does not exist or could not be fetched')
}
return await openpgp.key
.readArmored(publicKey) .readArmored(publicKey)
.then((result) => { .then((result) => {
return result.keys[0] return result.keys[0]
}) })
.catch((error) => { .catch((error) => {
return null throw new Error(`Key does not exist or could not be fetched (${error})`)
})
if (publicKey) {
resolve(publicKey)
} else {
reject('Key does not exist or could not be fetched')
}
}) })
} }
@ -74,27 +70,19 @@ exports.fetchHKP = (identifier, keyserverDomain) => {
* @example * @example
* const key = doip.keys.fetchWKD('alice@domain.tld'); * const key = doip.keys.fetchWKD('alice@domain.tld');
*/ */
exports.fetchWKD = (identifier) => { exports.fetchWKD = async (identifier) => {
return new Promise(async (resolve, reject) => {
const wkd = new openpgp.WKD() const wkd = new openpgp.WKD()
const lookupOpts = { const lookupOpts = {
email: identifier, email: identifier
} }
const publicKey = await wkd return await wkd
.lookup(lookupOpts) .lookup(lookupOpts)
.then((result) => { .then((result) => {
return result.keys[0] return result.keys[0]
}) })
.catch((error) => { .catch((error) => {
return null throw new Error(`Key does not exist or could not be fetched (${error})`)
})
if (publicKey) {
resolve(publicKey)
} else {
reject('Key does not exist or could not be fetched')
}
}) })
} }
@ -107,8 +95,7 @@ exports.fetchWKD = (identifier) => {
* @example * @example
* const key = doip.keys.fetchKeybase('alice', '123abc123abc'); * const key = doip.keys.fetchKeybase('alice', '123abc123abc');
*/ */
exports.fetchKeybase = (username, fingerprint) => { exports.fetchKeybase = async (username, fingerprint) => {
return new Promise(async (resolve, reject) => {
const keyLink = `https://keybase.io/${username}/pgp_keys.asc?fingerprint=${fingerprint}` const keyLink = `https://keybase.io/${username}/pgp_keys.asc?fingerprint=${fingerprint}`
let rawKeyContent let rawKeyContent
try { try {
@ -120,23 +107,16 @@ exports.fetchKeybase = (username, fingerprint) => {
}) })
.then((response) => response.text()) .then((response) => response.text())
} catch (e) { } catch (e) {
reject(`Error fetching Keybase key: ${e.message}`) throw new Error(`Error fetching Keybase key: ${e.message}`)
} }
const publicKey = await openpgp.key return await openpgp.key
.readArmored(rawKeyContent) .readArmored(rawKeyContent)
.then((result) => { .then((result) => {
return result.keys[0] return result.keys[0]
}) })
.catch((error) => { .catch((error) => {
return null throw new Error(`Key does not exist or could not be fetched (${error})`)
})
if (publicKey) {
resolve(publicKey)
} else {
reject('Key does not exist or could not be fetched')
}
}) })
} }
@ -154,12 +134,9 @@ exports.fetchKeybase = (username, fingerprint) => {
* -----END PGP PUBLIC KEY BLOCK-----` * -----END PGP PUBLIC KEY BLOCK-----`
* const key = doip.keys.fetchPlaintext(plainkey); * const key = doip.keys.fetchPlaintext(plainkey);
*/ */
exports.fetchPlaintext = (rawKeyContent) => { exports.fetchPlaintext = async (rawKeyContent) => {
return new Promise(async (resolve, reject) => {
const publicKey = (await openpgp.key.readArmored(rawKeyContent)).keys[0] const publicKey = (await openpgp.key.readArmored(rawKeyContent)).keys[0]
return publicKey
resolve(publicKey)
})
} }
/** /**
@ -172,41 +149,34 @@ exports.fetchPlaintext = (rawKeyContent) => {
* const key2 = doip.keys.fetchURI('hkp:123abc123abc'); * const key2 = doip.keys.fetchURI('hkp:123abc123abc');
* const key3 = doip.keys.fetchURI('wkd:alice@domain.tld'); * const key3 = doip.keys.fetchURI('wkd:alice@domain.tld');
*/ */
exports.fetchURI = (uri) => { exports.fetchURI = async (uri) => {
return new Promise(async (resolve, reject) => {
if (!validUrl.isUri(uri)) { if (!validUrl.isUri(uri)) {
reject('Invalid URI') throw new Error('Invalid URI')
} }
const re = /([a-zA-Z0-9]*):([a-zA-Z0-9@._=+\-]*)(?:\:([a-zA-Z0-9@._=+\-]*))?/ const re = /([a-zA-Z0-9]*):([a-zA-Z0-9@._=+-]*)(?::([a-zA-Z0-9@._=+-]*))?/
const match = uri.match(re) const match = uri.match(re)
if (!match[1]) { if (!match[1]) {
reject('Invalid URI') throw new Error('Invalid URI')
} }
switch (match[1]) { switch (match[1]) {
case 'hkp': case 'hkp':
resolve( return exports.fetchHKP(
exports.fetchHKP(
match[3] ? match[3] : match[2], match[3] ? match[3] : match[2],
match[3] ? match[2] : null match[3] ? match[2] : null
) )
)
break
case 'wkd': case 'wkd':
resolve(exports.fetchWKD(match[2])) return exports.fetchWKD(match[2])
break
case 'kb': case 'kb':
resolve( return exports.fetchKeybase(match[2], match.length >= 4 ? match[3] : null)
exports.fetchKeybase(match[2], match.length >= 4 ? match[3] : null)
)
break
default: default:
reject('Invalid URI protocol') throw new Error('Invalid URI protocol')
break
} }
})
} }
/** /**
@ -221,16 +191,15 @@ exports.fetchURI = (uri) => {
* console.log(claim.uri); * console.log(claim.uri);
* }); * });
*/ */
exports.process = (publicKey) => { exports.process = async (publicKey) => {
return new Promise(async (resolve, reject) => {
if (!publicKey || !(publicKey instanceof openpgp.key.Key)) { if (!publicKey || !(publicKey instanceof openpgp.key.Key)) {
reject('Invalid public key') throw new Error('Invalid public key')
} }
const fingerprint = await publicKey.primaryKey.getFingerprint() const fingerprint = await publicKey.primaryKey.getFingerprint()
const primaryUser = await publicKey.getPrimaryUser() const primaryUser = await publicKey.getPrimaryUser()
const users = publicKey.users const users = publicKey.users
let usersOutput = [] const usersOutput = []
users.forEach((user, i) => { users.forEach((user, i) => {
usersOutput[i] = { usersOutput[i] = {
@ -240,9 +209,9 @@ exports.process = (publicKey) => {
email: user.userId ? user.userId.email : null, email: user.userId ? user.userId.email : null,
comment: user.userId ? user.userId.comment : null, comment: user.userId ? user.userId.comment : null,
isPrimary: primaryUser.index === i, isPrimary: primaryUser.index === i,
isRevoked: false, isRevoked: false
}, },
claims: [], claims: []
} }
if ('selfCertifications' in user && user.selfCertifications.length > 0) { if ('selfCertifications' in user && user.selfCertifications.length > 0) {
@ -250,22 +219,27 @@ exports.process = (publicKey) => {
const notations = selfCertification.rawNotations const notations = selfCertification.rawNotations
usersOutput[i].claims = notations usersOutput[i].claims = notations
.filter(({ name, humanReadable }) => humanReadable && name === 'proof@metacode.biz') .filter(
.map(({ value }) => new Claim(openpgp.util.decode_utf8(value), fingerprint)) ({ name, humanReadable }) =>
humanReadable && name === 'proof@metacode.biz'
)
.map(
({ value }) =>
new Claim(openpgp.util.decode_utf8(value), fingerprint)
)
usersOutput[i].userData.isRevoked = selfCertification.revoked usersOutput[i].userData.isRevoked = selfCertification.revoked
} }
}) })
resolve({ return {
fingerprint: fingerprint, fingerprint: fingerprint,
users: usersOutput, users: usersOutput,
primaryUserIndex: primaryUser.index, primaryUserIndex: primaryUser.index,
key: { key: {
data: publicKey, data: publicKey,
fetchMethod: null, fetchMethod: null,
uri: null, uri: null
}, }
}) }
})
} }

View file

@ -54,49 +54,37 @@ const handleBrowserRequests = (data, opts) => {
switch (opts.proxy.policy) { switch (opts.proxy.policy) {
case E.ProxyPolicy.ALWAYS: case E.ProxyPolicy.ALWAYS:
return createProxyRequestPromise(data, opts) return createProxyRequestPromise(data, opts)
break
case E.ProxyPolicy.NEVER: case E.ProxyPolicy.NEVER:
switch (data.proof.request.access) { switch (data.proof.request.access) {
case E.ProofAccess.GENERIC: case E.ProofAccess.GENERIC:
case E.ProofAccess.GRANTED: case E.ProofAccess.GRANTED:
return createDefaultRequestPromise(data, opts) return createDefaultRequestPromise(data, opts)
break
case E.ProofAccess.NOCORS: case E.ProofAccess.NOCORS:
case E.ProofAccess.SERVER: case E.ProofAccess.SERVER:
throw new Error( throw new Error(
'Impossible to fetch proof (bad combination of service access and proxy policy)' 'Impossible to fetch proof (bad combination of service access and proxy policy)'
) )
break
default: default:
throw new Error('Invalid proof access value') throw new Error('Invalid proof access value')
break
} }
break
case E.ProxyPolicy.ADAPTIVE: case E.ProxyPolicy.ADAPTIVE:
switch (data.proof.request.access) { switch (data.proof.request.access) {
case E.ProofAccess.GENERIC: case E.ProofAccess.GENERIC:
return createFallbackRequestPromise(data, opts) return createFallbackRequestPromise(data, opts)
break
case E.ProofAccess.NOCORS: case E.ProofAccess.NOCORS:
return createProxyRequestPromise(data, opts) return createProxyRequestPromise(data, opts)
break
case E.ProofAccess.GRANTED: case E.ProofAccess.GRANTED:
return createFallbackRequestPromise(data, opts) return createFallbackRequestPromise(data, opts)
break
case E.ProofAccess.SERVER: case E.ProofAccess.SERVER:
return createProxyRequestPromise(data, opts) return createProxyRequestPromise(data, opts)
break
default: default:
throw new Error('Invalid proof access value') throw new Error('Invalid proof access value')
break
} }
break
default: default:
throw new Error('Invalid proxy policy') throw new Error('Invalid proxy policy')
break
} }
} }
@ -104,19 +92,15 @@ const handleNodeRequests = (data, opts) => {
switch (opts.proxy.policy) { switch (opts.proxy.policy) {
case E.ProxyPolicy.ALWAYS: case E.ProxyPolicy.ALWAYS:
return createProxyRequestPromise(data, opts) return createProxyRequestPromise(data, opts)
break
case E.ProxyPolicy.NEVER: case E.ProxyPolicy.NEVER:
return createDefaultRequestPromise(data, opts) return createDefaultRequestPromise(data, opts)
break
case E.ProxyPolicy.ADAPTIVE: case E.ProxyPolicy.ADAPTIVE:
return createFallbackRequestPromise(data, opts) return createFallbackRequestPromise(data, opts)
break
default: default:
throw new Error('Invalid proxy policy') throw new Error('Invalid proxy policy')
break
} }
} }
@ -129,7 +113,7 @@ const createDefaultRequestPromise = (data, opts) => {
fetcher: data.proof.request.fetcher, fetcher: data.proof.request.fetcher,
data: data, data: data,
viaProxy: false, viaProxy: false,
result: res, result: res
}) })
}) })
.catch((err) => { .catch((err) => {
@ -154,7 +138,7 @@ const createProxyRequestPromise = (data, opts) => {
const requestData = { const requestData = {
url: proxyUrl, url: proxyUrl,
format: data.proof.request.format, format: data.proof.request.format,
fetcherTimeout: fetcher[data.proof.request.fetcher].timeout, fetcherTimeout: fetcher[data.proof.request.fetcher].timeout
} }
fetcher.http fetcher.http
.fn(requestData, opts) .fn(requestData, opts)
@ -163,7 +147,7 @@ const createProxyRequestPromise = (data, opts) => {
fetcher: 'http', fetcher: 'http',
data: data, data: data,
viaProxy: true, viaProxy: true,
result: res, result: res
}) })
}) })
.catch((err) => { .catch((err) => {
@ -184,7 +168,7 @@ const createFallbackRequestPromise = (data, opts) => {
return resolve(res) return resolve(res)
}) })
.catch((err2) => { .catch((err2) => {
return reject([err1, err2]) return reject(err2)
}) })
}) })
}) })

View file

@ -24,40 +24,40 @@ const debug = require('@xmpp/debug')
const irc = require('irc-upd') const irc = require('irc-upd')
require('dotenv').config() require('dotenv').config()
const xmpp_service = process.env.XMPP_SERVICE || null const xmppService = process.env.XMPP_SERVICE || null
const xmpp_username = process.env.XMPP_USERNAME || null const xmppUsername = process.env.XMPP_USERNAME || null
const xmpp_password = process.env.XMPP_PASSWORD || null const xmppPassword = process.env.XMPP_PASSWORD || null
const twitter_bearer_token = process.env.TWITTER_BEARER_TOKEN || null const twitterBearerToken = process.env.TWITTER_BEARER_TOKEN || null
const matrix_instance = process.env.MATRIX_INSTANCE || null const matrixInstance = process.env.MATRIX_INSTANCE || null
const matrix_access_token = process.env.MATRIX_ACCESS_TOKEN || null const matrixAccessToken = process.env.MATRIX_ACCESS_TOKEN || null
const irc_nick = process.env.IRC_NICK || null const ircNick = process.env.IRC_NICK || null
let xmpp = null, let xmpp = null
iqCaller = null, let iqCaller = null
xmpp_enabled = true, let xmppEnabled = true
twitter_enabled = false, let twitterEnabled = false
matrix_enabled = false, let matrixEnabled = false
irc_enabled = false let ircEnabled = false
if (!xmpp_service || !xmpp_username || !xmpp_password) { if (!xmppService || !xmppUsername || !xmppPassword) {
xmpp_enabled = false xmppEnabled = false
} }
if (twitter_bearer_token) { if (twitterBearerToken) {
twitter_enabled = true twitterEnabled = true
} }
if (matrix_instance && matrix_access_token) { if (matrixInstance && matrixAccessToken) {
matrix_enabled = true matrixEnabled = true
} }
if (irc_nick) { if (ircNick) {
irc_enabled = true ircEnabled = true
} }
const xmppStart = async (xmpp_service, xmpp_username, xmpp_password) => { const xmppStart = async (xmppService, xmppUsername, xmppPassword) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const xmpp = client({ const xmpp = client({
service: xmpp_service, service: xmppService,
username: xmpp_username, username: xmppUsername,
password: xmpp_password, password: xmppPassword
}) })
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
debug(xmpp, true) debug(xmpp, true)
@ -77,7 +77,7 @@ const xmppStart = async (xmpp_service, xmpp_username, xmpp_password) => {
router.get('/', async (req, res) => { router.get('/', async (req, res) => {
res.status(200).json({ res.status(200).json({
message: message:
'Available endpoints: /json/:url, /text/:url, /dns/:hostname, /xmpp/:xmppid, /twitter/:tweetid, /matrix/:roomid/:eventid, /irc/:ircserver/:ircnick', 'Available endpoints: /json/:url, /text/:url, /dns/:hostname, /xmpp/:xmppid, /twitter/:tweetid, /matrix/:roomid/:eventid, /irc/:ircserver/:ircnick'
}) })
}) })
@ -94,7 +94,7 @@ router.param('url', async (req, res, next, url) => {
router.param('xmppid', async (req, res, next, xmppid) => { router.param('xmppid', async (req, res, next, xmppid) => {
req.params.xmppid = xmppid req.params.xmppid = xmppid
if (/^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,})+$/.test(req.params.xmppid)) { if (/^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,})+$/.test(req.params.xmppid)) {
next() next()
} else { } else {
return res.status(400).json({ message: 'XMPP_ID was not valid' }) return res.status(400).json({ message: 'XMPP_ID was not valid' })
@ -112,13 +112,13 @@ router.param('xmppdata', async (req, res, next, xmppdata) => {
'BDAY', 'BDAY',
'NICKNAME', 'NICKNAME',
'NOTE', 'NOTE',
'DESC', 'DESC'
] ]
if (!allowedData.includes(req.params.xmppdata)) { if (!allowedData.includes(req.params.xmppdata)) {
return res.status(400).json({ return res.status(400).json({
message: message:
'Allowed data are: FN, NUMBER, USERID, URL, BDAY, NICKNAME, NOTE, DESC', 'Allowed data are: FN, NUMBER, USERID, URL, BDAY, NICKNAME, NOTE, DESC'
}) })
} }
@ -127,7 +127,7 @@ router.param('xmppdata', async (req, res, next, xmppdata) => {
router.get('/get/json/:url', (req, res) => { router.get('/get/json/:url', (req, res) => {
bentReq(req.params.url, 'json', { bentReq(req.params.url, 'json', {
Accept: 'application/json', Accept: 'application/json'
}) })
.then(async (result) => { .then(async (result) => {
return await result.json() return await result.json()
@ -155,11 +155,14 @@ router.get('/get/text/:url', (req, res) => {
router.get('/get/dns/:hostname', async (req, res) => { router.get('/get/dns/:hostname', async (req, res) => {
dns.resolveTxt(req.params.hostname, (err, records) => { dns.resolveTxt(req.params.hostname, (err, records) => {
if (err) {
throw new Error(err)
}
const out = { const out = {
hostname: req.params.hostname, hostname: req.params.hostname,
records: { records: {
txt: records, txt: records
}, }
} }
return res.status(200).json(out) return res.status(200).json(out)
}) })
@ -174,14 +177,14 @@ router.get('/get/xmpp/:xmppid', async (req, res) => {
}) })
router.get('/get/xmpp/:xmppid/:xmppdata', async (req, res) => { router.get('/get/xmpp/:xmppid/:xmppdata', async (req, res) => {
if (!xmpp_enabled) { if (!xmppEnabled) {
return res.status(500).json('XMPP not enabled on server') return res.status(500).json('XMPP not enabled on server')
} }
if (!xmpp) { if (!xmpp) {
const xmppStartRes = await xmppStart( const xmppStartRes = await xmppStart(
xmpp_service, xmppService,
xmpp_username, xmppUsername,
xmpp_password xmppPassword
) )
xmpp = xmppStartRes.xmpp xmpp = xmppStartRes.xmpp
iqCaller = xmppStartRes.iqCaller iqCaller = xmppStartRes.iqCaller
@ -231,7 +234,7 @@ router.get('/get/xmpp/:xmppid/:xmppdata', async (req, res) => {
}) })
router.get('/get/twitter/:tweetid', async (req, res) => { router.get('/get/twitter/:tweetid', async (req, res) => {
if (!twitter_enabled) { if (!twitterEnabled) {
return res.status(500).json('Twitter not enabled on server') return res.status(500).json('Twitter not enabled on server')
} }
@ -240,7 +243,7 @@ router.get('/get/twitter/:tweetid', async (req, res) => {
null, null,
{ {
Accept: 'application/json', Accept: 'application/json',
Authorization: `Bearer ${twitter_bearer_token}`, Authorization: `Bearer ${twitterBearerToken}`
} }
) )
.then(async (data) => { .then(async (data) => {
@ -253,20 +256,20 @@ router.get('/get/twitter/:tweetid', async (req, res) => {
return res.status(error.statusCode || 400).json({ return res.status(error.statusCode || 400).json({
data: [], data: [],
message: 'Request could not be fulfilled', message: 'Request could not be fulfilled',
error: error, error: error
}) })
}) })
}) })
router.get('/get/matrix/:matrixroomid/:matrixeventid', async (req, res) => { router.get('/get/matrix/:matrixroomid/:matrixeventid', async (req, res) => {
if (!matrix_enabled) { if (!matrixEnabled) {
return res.status(500).json('Matrix not enabled on server') return res.status(500).json('Matrix not enabled on server')
} }
const url = `https://${matrix_instance}/_matrix/client/r0/rooms/${req.params.matrixroomid}/event/${req.params.matrixeventid}?access_token=${matrix_access_token}` const url = `https://${matrixInstance}/_matrix/client/r0/rooms/${req.params.matrixroomid}/event/${req.params.matrixeventid}?access_token=${matrixAccessToken}`
bentReq(url, null, { bentReq(url, null, {
Accept: 'application/json', Accept: 'application/json'
}) })
.then(async (data) => { .then(async (data) => {
return await data.json() return await data.json()
@ -278,25 +281,25 @@ router.get('/get/matrix/:matrixroomid/:matrixeventid', async (req, res) => {
return res.status(error.statusCode || 400).json({ return res.status(error.statusCode || 400).json({
data: [], data: [],
message: 'Request could not be fulfilled', message: 'Request could not be fulfilled',
error: error, error: error
}) })
}) })
}) })
router.get('/get/irc/:ircserver/:ircnick', async (req, res) => { router.get('/get/irc/:ircserver/:ircnick', async (req, res) => {
if (!irc_enabled) { if (!ircEnabled) {
return res.status(500).json('IRC not enabled on server') return res.status(500).json('IRC not enabled on server')
} }
try { try {
const client = new irc.Client(req.params.ircserver, irc_nick, { const client = new irc.Client(req.params.ircserver, ircNick, {
port: 6697, port: 6697,
secure: true, secure: true,
channels: [], channels: []
}) })
const reKey = /[a-zA-Z0-9\-\_]+\s+:\s(openpgp4fpr\:.*)/ const reKey = /[a-zA-Z0-9\-_]+\s+:\s(openpgp4fpr:.*)/
const reEnd = /End\sof\s.*\staxonomy./ const reEnd = /End\sof\s.*\staxonomy./
let keys = [] const keys = []
client.addListener('registered', (message) => { client.addListener('registered', (message) => {
client.send(`PRIVMSG NickServ :TAXONOMY ${req.params.ircnick}`) client.send(`PRIVMSG NickServ :TAXONOMY ${req.params.ircnick}`)
@ -317,7 +320,7 @@ router.get('/get/irc/:ircserver/:ircnick', async (req, res) => {
return res.status(400).json({ return res.status(400).json({
data: [], data: [],
message: 'Request could not be fulfilled', message: 'Request could not be fulfilled',
error: error, error: error
}) })
} }
}) })

View file

@ -22,21 +22,21 @@ require('dotenv').config()
const opts = { const opts = {
claims: { claims: {
irc: { irc: {
nick: process.env.IRC_NICK || null, nick: process.env.IRC_NICK || null
}, },
matrix: { matrix: {
instance: process.env.MATRIX_INSTANCE || null, instance: process.env.MATRIX_INSTANCE || null,
accessToken: process.env.MATRIX_ACCESS_TOKEN || null, accessToken: process.env.MATRIX_ACCESS_TOKEN || null
}, },
xmpp: { xmpp: {
service: process.env.XMPP_SERVICE || null, service: process.env.XMPP_SERVICE || null,
username: process.env.XMPP_USERNAME || null, username: process.env.XMPP_USERNAME || null,
password: process.env.XMPP_PASSWORD || null, password: process.env.XMPP_PASSWORD || null
}, },
twitter: { twitter: {
bearerToken: process.env.TWITTER_BEARER_TOKEN || null, bearerToken: process.env.TWITTER_BEARER_TOKEN || null
}, }
}, }
} }
// Root route // Root route
@ -61,11 +61,9 @@ router.get(
switch (req.query.format) { switch (req.query.format) {
case E.ProofFormat.JSON: case E.ProofFormat.JSON:
return res.status(200).json(result) return res.status(200).json(result)
break
case E.ProofFormat.TEXT: case E.ProofFormat.TEXT:
return res.status(200).send(result) return res.status(200).send(result)
break
} }
}) })
.catch((err) => { .catch((err) => {
@ -103,7 +101,7 @@ router.get(
'bday', 'bday',
'nickname', 'nickname',
'note', 'note',
'desc', 'desc'
]), ]),
async (req, res) => { async (req, res) => {
if ( if (

View file

@ -27,30 +27,28 @@ const keys = require('./keys')
* @param {string} signature - The plaintext signature to process * @param {string} signature - The plaintext signature to process
* @returns {Promise<object>} * @returns {Promise<object>}
*/ */
const process = (signature) => { const process = async (signature) => {
return new Promise(async (resolve, reject) => { let sigData
let sigData, const result = {
result = {
fingerprint: null, fingerprint: null,
users: [ users: [
{ {
userData: {}, userData: {},
claims: [], claims: []
}, }
], ],
primaryUserIndex: null, primaryUserIndex: null,
key: { key: {
data: null, data: null,
fetchMethod: null, fetchMethod: null,
uri: null, uri: null
}, }
} }
try { try {
sigData = await openpgp.cleartext.readArmored(signature) sigData = await openpgp.cleartext.readArmored(signature)
} catch (error) { } catch (error) {
reject(new Error('invalid_signature')) throw new Error('invalid_signature')
return
} }
const issuerKeyId = sigData.signature.packets[0].issuerKeyId.toHex() const issuerKeyId = sigData.signature.packets[0].issuerKeyId.toHex()
@ -59,10 +57,10 @@ const process = (signature) => {
sigData.signature.packets[0].preferredKeyServer || sigData.signature.packets[0].preferredKeyServer ||
'https://keys.openpgp.org/' 'https://keys.openpgp.org/'
const text = sigData.getText() const text = sigData.getText()
let sigKeys = [] const sigKeys = []
text.split('\n').forEach((line, i) => { text.split('\n').forEach((line, i) => {
const match = line.match(/^([a-zA-Z0-9]*)\=(.*)$/i) const match = line.match(/^([a-zA-Z0-9]*)=(.*)$/i)
if (!match) { if (!match) {
return return
} }
@ -99,15 +97,12 @@ const process = (signature) => {
// Try HKP // Try HKP
if (!result.key.data) { if (!result.key.data) {
try { try {
const match = preferredKeyServer.match(/^(.*\:\/\/)?([^/]*)(?:\/)?$/i) const match = preferredKeyServer.match(/^(.*:\/\/)?([^/]*)(?:\/)?$/i)
result.key.uri = `hkp:${match[2]}:${ result.key.uri = `hkp:${match[2]}:${issuerKeyId || signersUserId}`
issuerKeyId ? issuerKeyId : signersUserId
}`
result.key.data = await keys.fetchURI(result.key.uri) result.key.data = await keys.fetchURI(result.key.uri)
result.key.fetchMethod = 'hkp' result.key.fetchMethod = 'hkp'
} catch (e) { } catch (e) {
reject(new Error('key_not_found')) throw new Error('key_not_found')
return
} }
} }
@ -122,7 +117,7 @@ const process = (signature) => {
if (signersUserId) { if (signersUserId) {
result.key.data.users.forEach((user) => { result.key.data.users.forEach((user) => {
if (user.userId.email == signersUserId) { if (user.userId.email === signersUserId) {
userData = user userData = user
} }
}) })
@ -136,13 +131,12 @@ const process = (signature) => {
name: userData.userId ? userData.userId.name : null, name: userData.userId ? userData.userId.name : null,
email: userData.userId ? userData.userId.email : null, email: userData.userId ? userData.userId.email : null,
comment: userData.userId ? userData.userId.comment : null, comment: userData.userId ? userData.userId.comment : null,
isPrimary: primaryUserData.user.userId.userid === userData.userId.userid, isPrimary: primaryUserData.user.userId.userid === userData.userId.userid
} }
result.primaryUserIndex = result.users[0].userData.isPrimary ? 0 : null result.primaryUserIndex = result.users[0].userData.isPrimary ? 0 : null
resolve(result) return result
})
} }
exports.process = process exports.process = process

View file

@ -32,10 +32,10 @@ const generateProxyURL = (type, data, opts) => {
try { try {
validator.isFQDN(opts.proxy.hostname) validator.isFQDN(opts.proxy.hostname)
} catch (err) { } catch (err) {
throw new Error(`Invalid proxy hostname`) throw new Error('Invalid proxy hostname')
} }
let queryStrings = [] const queryStrings = []
Object.keys(data).forEach((key) => { Object.keys(data).forEach((key) => {
queryStrings.push(`${key}=${encodeURIComponent(data[key])}`) queryStrings.push(`${key}=${encodeURIComponent(data[key])}`)
@ -56,13 +56,10 @@ const generateClaim = (fingerprint, format) => {
switch (format) { switch (format) {
case E.ClaimFormat.URI: case E.ClaimFormat.URI:
return `openpgp4fpr:${fingerprint}` return `openpgp4fpr:${fingerprint}`
break
case E.ClaimFormat.MESSAGE: case E.ClaimFormat.MESSAGE:
return `[Verifying my OpenPGP key: openpgp4fpr:${fingerprint}]` return `[Verifying my OpenPGP key: openpgp4fpr:${fingerprint}]`
break
case E.ClaimFormat.FINGERPRINT: case E.ClaimFormat.FINGERPRINT:
return fingerprint return fingerprint
break
default: default:
throw new Error('No valid claim format') throw new Error('No valid claim format')
} }

View file

@ -39,31 +39,26 @@ const runJSON = (proofData, checkPath, checkClaim, checkRelation) => {
return result return result
} }
if (checkPath.length == 0) { if (checkPath.length === 0) {
switch (checkRelation) { switch (checkRelation) {
default:
case E.ClaimRelation.CONTAINS:
re = new RegExp(checkClaim, 'gi')
return re.test(proofData.replace(/\r?\n|\r|\\/g, ''))
break
case E.ClaimRelation.EQUALS: case E.ClaimRelation.EQUALS:
return ( return (
proofData.replace(/\r?\n|\r|\\/g, '').toLowerCase() == proofData.replace(/\r?\n|\r|\\/g, '').toLowerCase() ===
checkClaim.toLowerCase() checkClaim.toLowerCase()
) )
break
case E.ClaimRelation.ONEOF: case E.ClaimRelation.ONEOF:
re = new RegExp(checkClaim, 'gi') re = new RegExp(checkClaim, 'gi')
return re.test(proofData.join('|')) return re.test(proofData.join('|'))
break
case E.ClaimRelation.CONTAINS:
default:
re = new RegExp(checkClaim, 'gi')
return re.test(proofData.replace(/\r?\n|\r|\\/g, ''))
} }
} }
try { if (!(checkPath[0] in proofData)) {
checkPath[0] in proofData
} catch (e) {
throw new Error('err_json_structure_incorrect') throw new Error('err_json_structure_incorrect')
} }
@ -83,10 +78,10 @@ const runJSON = (proofData, checkPath, checkClaim, checkRelation) => {
* @returns {object} * @returns {object}
*/ */
const run = (proofData, claimData, fingerprint) => { const run = (proofData, claimData, fingerprint) => {
let res = { const res = {
result: false, result: false,
completed: false, completed: false,
errors: [], errors: []
} }
switch (claimData.proof.request.format) { switch (claimData.proof.request.format) {