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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -29,7 +29,7 @@ const ProxyPolicy = {
/** Always use a proxy */
ALWAYS: 'always',
/** Never use a proxy, skip a verification if a proxy is inevitable */
NEVER: 'never',
NEVER: 'never'
}
Object.freeze(ProxyPolicy)
@ -52,7 +52,7 @@ const Fetcher = {
/** HTTP request to Gitlab API */
GITLAB: 'gitlab',
/** HTTP request to Twitter API */
TWITTER: 'twitter',
TWITTER: 'twitter'
}
Object.freeze(Fetcher)
@ -69,7 +69,7 @@ const ProofAccess = {
/** HTTP requests must contain API or access tokens */
GRANTED: 2,
/** Not accessible by HTTP request, needs server software */
SERVER: 3,
SERVER: 3
}
Object.freeze(ProofAccess)
@ -82,7 +82,7 @@ const ProofFormat = {
/** JSON format */
JSON: 'json',
/** Plaintext format */
TEXT: 'text',
TEXT: 'text'
}
Object.freeze(ProofFormat)
@ -97,7 +97,7 @@ const ClaimFormat = {
/** `123123123` */
FINGERPRINT: 1,
/** `[Verifying my OpenPGP key: openpgp4fpr:123123123]` */
MESSAGE: 2,
MESSAGE: 2
}
Object.freeze(ClaimFormat)
@ -112,7 +112,7 @@ const ClaimRelation = {
/** Claim is equal to the JSON field's textual content */
EQUALS: 1,
/** Claim is equal to an element of the JSON field's array of strings */
ONEOF: 2,
ONEOF: 2
}
Object.freeze(ClaimRelation)
@ -127,7 +127,7 @@ const ClaimStatus = {
/** Claim has matched its URI to candidate claim definitions */
MATCHED: 'matched',
/** Claim has verified one or multiple candidate claim definitions */
VERIFIED: 'verified',
VERIFIED: 'verified'
}
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
limitations under the License.
*/
const jsEnv = require("browser-or-node")
const jsEnv = require('browser-or-node')
/**
* @module fetcher/dns
@ -55,8 +55,8 @@ if (jsEnv.isNode) {
resolve({
domain: data.domain,
records: {
txt: records,
},
txt: records
}
})
})
})
@ -68,4 +68,4 @@ if (jsEnv.isNode) {
}
} else {
module.exports.fn = null
}
}

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 resUser = await req(urlUser, null, { Accept: 'application/json' })
const jsonUser = await resUser.json()
// const resUser = await req(urlUser, null, { Accept: 'application/json' })
const res = req(urlUser, null, { Accept: 'application/json' })
.then(resUser => {
return resUser.json()
})
.then(jsonUser => {
return jsonUser.find((user) => user.username === data.username)
})
.then(user => {
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)
})
const user = jsonUser.find((user) => user.username === data.username)
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()
const project = jsonProject.find((proj) => proj.path === 'gitlab_proof')
if (!project) {
reject(`No project found`)
}
resolve(project)
resolve(res)
})
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) => {
if (!data.url) {
reject('No valid URI provided')
reject(new Error('No valid URI provided'))
return
}
@ -55,7 +55,7 @@ module.exports.fn = async (data, opts) => {
case E.ProofFormat.JSON:
req(data.url, null, {
Accept: 'application/json',
'User-Agent': `doipjs/${require('../../package.json').version}`,
'User-Agent': `doipjs/${require('../../package.json').version}`
})
.then(async (res) => {
return await res.json()
@ -80,7 +80,7 @@ module.exports.fn = async (data, opts) => {
})
break
default:
reject('No specified data format')
reject(new Error('No specified data format'))
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
limitations under the License.
*/
const jsEnv = require("browser-or-node")
const jsEnv = require('browser-or-node')
/**
* @module fetcher/irc
@ -28,7 +28,7 @@ module.exports.timeout = 20000
if (jsEnv.isNode) {
const irc = require('irc-upd')
const validator = require('validator')
/**
* Execute a fetch request
* @function
@ -48,14 +48,14 @@ if (jsEnv.isNode) {
data.fetcherTimeout ? data.fetcherTimeout : module.exports.timeout
)
})
const fetchPromise = new Promise((resolve, reject) => {
try {
validator.isAscii(opts.claims.irc.nick)
} catch (err) {
throw new Error(`IRC fetcher was not set up properly (${err.message})`)
}
try {
const client = new irc.Client(data.domain, opts.claims.irc.nick, {
port: 6697,
@ -64,10 +64,10 @@ if (jsEnv.isNode) {
showErrors: 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./
let keys = []
const keys = []
client.addListener('registered', (message) => {
client.send(`PRIVMSG NickServ TAXONOMY ${data.nick}`)
})
@ -85,7 +85,7 @@ if (jsEnv.isNode) {
reject(error)
}
})
return Promise.race([fetchPromise, timeoutPromise]).then((result) => {
clearTimeout(timeoutHandle)
return result

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}`
bentReq(url, null, {
Accept: 'application/json',
Accept: 'application/json'
})
.then(async (res) => {
return await res.json()

View file

@ -60,7 +60,7 @@ module.exports.fn = async (data, opts) => {
null,
{
Accept: 'application/json',
Authorization: `Bearer ${opts.claims.twitter.bearerToken}`,
Authorization: `Bearer ${opts.claims.twitter.bearerToken}`
}
)
.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
limitations under the License.
*/
const jsEnv = require("browser-or-node")
const jsEnv = require('browser-or-node')
/**
* @module fetcher/xmpp
@ -30,16 +30,16 @@ if (jsEnv.isNode) {
const { client, xml } = require('@xmpp/client')
const debug = require('@xmpp/debug')
const validator = require('validator')
let xmpp = null,
iqCaller = null
let xmpp = null
let iqCaller = null
const xmppStart = async (service, username, password) => {
return new Promise((resolve, reject) => {
const xmpp = client({
service: service,
username: username,
password: password,
password: password
})
if (process.env.NODE_ENV !== 'production') {
debug(xmpp, true)
@ -54,7 +54,7 @@ if (jsEnv.isNode) {
})
})
}
/**
* Execute a fetch request
* @function
@ -69,6 +69,32 @@ if (jsEnv.isNode) {
* @returns {object}
*/
module.exports.fn = async (data, opts) => {
try {
validator.isFQDN(opts.claims.xmpp.service)
validator.isAscii(opts.claims.xmpp.username)
validator.isAscii(opts.claims.xmpp.password)
} catch (err) {
throw new Error(`XMPP fetcher was not set up properly (${err.message})`)
}
if (!xmpp || xmpp.status !== 'online') {
const xmppStartRes = await xmppStart(
opts.claims.xmpp.service,
opts.claims.xmpp.username,
opts.claims.xmpp.password
)
xmpp = xmppStartRes.xmpp
iqCaller = xmppStartRes.iqCaller
}
const response = await iqCaller.request(
xml('iq', { type: 'get', to: data.id }, xml('vCard', 'vcard-temp')),
30 * 1000
)
const vcardRow = response.getChild('vCard', 'vcard-temp').toString()
const dom = new jsdom.JSDOM(vcardRow)
let timeoutHandle
const timeoutPromise = new Promise((resolve, reject) => {
timeoutHandle = setTimeout(
@ -76,37 +102,11 @@ if (jsEnv.isNode) {
data.fetcherTimeout ? data.fetcherTimeout : module.exports.timeout
)
})
const fetchPromise = new Promise(async (resolve, reject) => {
try {
validator.isFQDN(opts.claims.xmpp.service)
validator.isAscii(opts.claims.xmpp.username)
validator.isAscii(opts.claims.xmpp.password)
} catch (err) {
throw new Error(`XMPP fetcher was not set up properly (${err.message})`)
}
if (!xmpp || xmpp.status !== 'online') {
const xmppStartRes = await xmppStart(
opts.claims.xmpp.service,
opts.claims.xmpp.username,
opts.claims.xmpp.password
)
xmpp = xmppStartRes.xmpp
iqCaller = xmppStartRes.iqCaller
}
const response = await iqCaller.request(
xml('iq', { type: 'get', to: data.id }, xml('vCard', 'vcard-temp')),
30 * 1000
)
const vcardRow = response.getChild('vCard', 'vcard-temp').toString()
const dom = new jsdom.JSDOM(vcardRow)
const fetchPromise = new Promise((resolve, reject) => {
try {
let vcard
switch (data.field.toLowerCase()) {
case 'desc':
case 'note':
@ -120,7 +120,7 @@ if (jsEnv.isNode) {
throw new Error('No DESC or NOTE field found in vCard')
}
break
default:
vcard = dom.window.document.querySelector(data).textContent
break
@ -131,7 +131,7 @@ if (jsEnv.isNode) {
reject(error)
}
})
return Promise.race([fetchPromise, timeoutPromise]).then((result) => {
clearTimeout(timeoutHandle)
return result

View file

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

View file

@ -54,49 +54,37 @@ const handleBrowserRequests = (data, opts) => {
switch (opts.proxy.policy) {
case E.ProxyPolicy.ALWAYS:
return createProxyRequestPromise(data, opts)
break
case E.ProxyPolicy.NEVER:
switch (data.proof.request.access) {
case E.ProofAccess.GENERIC:
case E.ProofAccess.GRANTED:
return createDefaultRequestPromise(data, opts)
break
case E.ProofAccess.NOCORS:
case E.ProofAccess.SERVER:
throw new Error(
'Impossible to fetch proof (bad combination of service access and proxy policy)'
)
break
default:
throw new Error('Invalid proof access value')
break
}
break
case E.ProxyPolicy.ADAPTIVE:
switch (data.proof.request.access) {
case E.ProofAccess.GENERIC:
return createFallbackRequestPromise(data, opts)
break
case E.ProofAccess.NOCORS:
return createProxyRequestPromise(data, opts)
break
case E.ProofAccess.GRANTED:
return createFallbackRequestPromise(data, opts)
break
case E.ProofAccess.SERVER:
return createProxyRequestPromise(data, opts)
break
default:
throw new Error('Invalid proof access value')
break
}
break
default:
throw new Error('Invalid proxy policy')
break
}
}
@ -104,19 +92,15 @@ const handleNodeRequests = (data, opts) => {
switch (opts.proxy.policy) {
case E.ProxyPolicy.ALWAYS:
return createProxyRequestPromise(data, opts)
break
case E.ProxyPolicy.NEVER:
return createDefaultRequestPromise(data, opts)
break
case E.ProxyPolicy.ADAPTIVE:
return createFallbackRequestPromise(data, opts)
break
default:
throw new Error('Invalid proxy policy')
break
}
}
@ -129,7 +113,7 @@ const createDefaultRequestPromise = (data, opts) => {
fetcher: data.proof.request.fetcher,
data: data,
viaProxy: false,
result: res,
result: res
})
})
.catch((err) => {
@ -154,7 +138,7 @@ const createProxyRequestPromise = (data, opts) => {
const requestData = {
url: proxyUrl,
format: data.proof.request.format,
fetcherTimeout: fetcher[data.proof.request.fetcher].timeout,
fetcherTimeout: fetcher[data.proof.request.fetcher].timeout
}
fetcher.http
.fn(requestData, opts)
@ -163,7 +147,7 @@ const createProxyRequestPromise = (data, opts) => {
fetcher: 'http',
data: data,
viaProxy: true,
result: res,
result: res
})
})
.catch((err) => {
@ -184,7 +168,7 @@ const createFallbackRequestPromise = (data, opts) => {
return resolve(res)
})
.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')
require('dotenv').config()
const xmpp_service = process.env.XMPP_SERVICE || null
const xmpp_username = process.env.XMPP_USERNAME || null
const xmpp_password = process.env.XMPP_PASSWORD || null
const twitter_bearer_token = process.env.TWITTER_BEARER_TOKEN || null
const matrix_instance = process.env.MATRIX_INSTANCE || null
const matrix_access_token = process.env.MATRIX_ACCESS_TOKEN || null
const irc_nick = process.env.IRC_NICK || null
const xmppService = process.env.XMPP_SERVICE || null
const xmppUsername = process.env.XMPP_USERNAME || null
const xmppPassword = process.env.XMPP_PASSWORD || null
const twitterBearerToken = process.env.TWITTER_BEARER_TOKEN || null
const matrixInstance = process.env.MATRIX_INSTANCE || null
const matrixAccessToken = process.env.MATRIX_ACCESS_TOKEN || null
const ircNick = process.env.IRC_NICK || null
let xmpp = null,
iqCaller = null,
xmpp_enabled = true,
twitter_enabled = false,
matrix_enabled = false,
irc_enabled = false
let xmpp = null
let iqCaller = null
let xmppEnabled = true
let twitterEnabled = false
let matrixEnabled = false
let ircEnabled = false
if (!xmpp_service || !xmpp_username || !xmpp_password) {
xmpp_enabled = false
if (!xmppService || !xmppUsername || !xmppPassword) {
xmppEnabled = false
}
if (twitter_bearer_token) {
twitter_enabled = true
if (twitterBearerToken) {
twitterEnabled = true
}
if (matrix_instance && matrix_access_token) {
matrix_enabled = true
if (matrixInstance && matrixAccessToken) {
matrixEnabled = true
}
if (irc_nick) {
irc_enabled = true
if (ircNick) {
ircEnabled = true
}
const xmppStart = async (xmpp_service, xmpp_username, xmpp_password) => {
const xmppStart = async (xmppService, xmppUsername, xmppPassword) => {
return new Promise((resolve, reject) => {
const xmpp = client({
service: xmpp_service,
username: xmpp_username,
password: xmpp_password,
service: xmppService,
username: xmppUsername,
password: xmppPassword
})
if (process.env.NODE_ENV !== 'production') {
debug(xmpp, true)
@ -77,7 +77,7 @@ const xmppStart = async (xmpp_service, xmpp_username, xmpp_password) => {
router.get('/', async (req, res) => {
res.status(200).json({
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) => {
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()
} else {
return res.status(400).json({ message: 'XMPP_ID was not valid' })
@ -112,13 +112,13 @@ router.param('xmppdata', async (req, res, next, xmppdata) => {
'BDAY',
'NICKNAME',
'NOTE',
'DESC',
'DESC'
]
if (!allowedData.includes(req.params.xmppdata)) {
return res.status(400).json({
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) => {
bentReq(req.params.url, 'json', {
Accept: 'application/json',
Accept: 'application/json'
})
.then(async (result) => {
return await result.json()
@ -155,11 +155,14 @@ router.get('/get/text/:url', (req, res) => {
router.get('/get/dns/:hostname', async (req, res) => {
dns.resolveTxt(req.params.hostname, (err, records) => {
if (err) {
throw new Error(err)
}
const out = {
hostname: req.params.hostname,
records: {
txt: records,
},
txt: records
}
}
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) => {
if (!xmpp_enabled) {
if (!xmppEnabled) {
return res.status(500).json('XMPP not enabled on server')
}
if (!xmpp) {
const xmppStartRes = await xmppStart(
xmpp_service,
xmpp_username,
xmpp_password
xmppService,
xmppUsername,
xmppPassword
)
xmpp = xmppStartRes.xmpp
iqCaller = xmppStartRes.iqCaller
@ -231,7 +234,7 @@ router.get('/get/xmpp/:xmppid/:xmppdata', 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')
}
@ -240,7 +243,7 @@ router.get('/get/twitter/:tweetid', async (req, res) => {
null,
{
Accept: 'application/json',
Authorization: `Bearer ${twitter_bearer_token}`,
Authorization: `Bearer ${twitterBearerToken}`
}
)
.then(async (data) => {
@ -253,20 +256,20 @@ router.get('/get/twitter/:tweetid', async (req, res) => {
return res.status(error.statusCode || 400).json({
data: [],
message: 'Request could not be fulfilled',
error: error,
error: error
})
})
})
router.get('/get/matrix/:matrixroomid/:matrixeventid', async (req, res) => {
if (!matrix_enabled) {
if (!matrixEnabled) {
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, {
Accept: 'application/json',
Accept: 'application/json'
})
.then(async (data) => {
return await data.json()
@ -278,25 +281,25 @@ router.get('/get/matrix/:matrixroomid/:matrixeventid', async (req, res) => {
return res.status(error.statusCode || 400).json({
data: [],
message: 'Request could not be fulfilled',
error: error,
error: error
})
})
})
router.get('/get/irc/:ircserver/:ircnick', async (req, res) => {
if (!irc_enabled) {
if (!ircEnabled) {
return res.status(500).json('IRC not enabled on server')
}
try {
const client = new irc.Client(req.params.ircserver, irc_nick, {
const client = new irc.Client(req.params.ircserver, ircNick, {
port: 6697,
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./
let keys = []
const keys = []
client.addListener('registered', (message) => {
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({
data: [],
message: 'Request could not be fulfilled',
error: error,
error: error
})
}
})

View file

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

View file

@ -27,122 +27,116 @@ const keys = require('./keys')
* @param {string} signature - The plaintext signature to process
* @returns {Promise<object>}
*/
const process = (signature) => {
return new Promise(async (resolve, reject) => {
let sigData,
result = {
fingerprint: null,
users: [
{
userData: {},
claims: [],
},
],
primaryUserIndex: null,
key: {
data: null,
fetchMethod: null,
uri: null,
},
const process = async (signature) => {
let sigData
const result = {
fingerprint: null,
users: [
{
userData: {},
claims: []
}
],
primaryUserIndex: null,
key: {
data: null,
fetchMethod: null,
uri: null
}
}
try {
sigData = await openpgp.cleartext.readArmored(signature)
} catch (error) {
reject(new Error('invalid_signature'))
try {
sigData = await openpgp.cleartext.readArmored(signature)
} catch (error) {
throw new Error('invalid_signature')
}
const issuerKeyId = sigData.signature.packets[0].issuerKeyId.toHex()
const signersUserId = sigData.signature.packets[0].signersUserId
const preferredKeyServer =
sigData.signature.packets[0].preferredKeyServer ||
'https://keys.openpgp.org/'
const text = sigData.getText()
const sigKeys = []
text.split('\n').forEach((line, i) => {
const match = line.match(/^([a-zA-Z0-9]*)=(.*)$/i)
if (!match) {
return
}
switch (match[1].toLowerCase()) {
case 'key':
sigKeys.push(match[2])
break
const issuerKeyId = sigData.signature.packets[0].issuerKeyId.toHex()
const signersUserId = sigData.signature.packets[0].signersUserId
const preferredKeyServer =
sigData.signature.packets[0].preferredKeyServer ||
'https://keys.openpgp.org/'
const text = sigData.getText()
let sigKeys = []
case 'proof':
result.users[0].claims.push(new Claim(match[2]))
break
text.split('\n').forEach((line, i) => {
const match = line.match(/^([a-zA-Z0-9]*)\=(.*)$/i)
if (!match) {
return
}
switch (match[1].toLowerCase()) {
case 'key':
sigKeys.push(match[2])
break
case 'proof':
result.users[0].claims.push(new Claim(match[2]))
break
default:
break
}
})
// Try overruling key
if (sigKeys.length > 0) {
try {
result.key.uri = sigKeys[0]
result.key.data = await keys.fetchURI(result.key.uri)
result.key.fetchMethod = result.key.uri.split(':')[0]
} catch (e) {}
default:
break
}
// Try WKD
if (!result.key.data && signersUserId) {
try {
result.key.uri = `wkd:${signersUserId}`
result.key.data = await keys.fetchURI(result.key.uri)
result.key.fetchMethod = 'wkd'
} catch (e) {}
}
// Try HKP
if (!result.key.data) {
try {
const match = preferredKeyServer.match(/^(.*\:\/\/)?([^/]*)(?:\/)?$/i)
result.key.uri = `hkp:${match[2]}:${
issuerKeyId ? issuerKeyId : signersUserId
}`
result.key.data = await keys.fetchURI(result.key.uri)
result.key.fetchMethod = 'hkp'
} catch (e) {
reject(new Error('key_not_found'))
return
}
}
result.fingerprint = result.key.data.keyPacket.getFingerprint()
result.users[0].claims.forEach((claim) => {
claim.fingerprint = result.fingerprint
})
const primaryUserData = await result.key.data.getPrimaryUser()
let userData
if (signersUserId) {
result.key.data.users.forEach((user) => {
if (user.userId.email == signersUserId) {
userData = user
}
})
}
if (!userData) {
userData = primaryUserData.user
}
result.users[0].userData = {
id: userData.userId ? userData.userId.userid : null,
name: userData.userId ? userData.userId.name : null,
email: userData.userId ? userData.userId.email : null,
comment: userData.userId ? userData.userId.comment : null,
isPrimary: primaryUserData.user.userId.userid === userData.userId.userid,
}
result.primaryUserIndex = result.users[0].userData.isPrimary ? 0 : null
resolve(result)
})
// Try overruling key
if (sigKeys.length > 0) {
try {
result.key.uri = sigKeys[0]
result.key.data = await keys.fetchURI(result.key.uri)
result.key.fetchMethod = result.key.uri.split(':')[0]
} catch (e) {}
}
// Try WKD
if (!result.key.data && signersUserId) {
try {
result.key.uri = `wkd:${signersUserId}`
result.key.data = await keys.fetchURI(result.key.uri)
result.key.fetchMethod = 'wkd'
} catch (e) {}
}
// Try HKP
if (!result.key.data) {
try {
const match = preferredKeyServer.match(/^(.*:\/\/)?([^/]*)(?:\/)?$/i)
result.key.uri = `hkp:${match[2]}:${issuerKeyId || signersUserId}`
result.key.data = await keys.fetchURI(result.key.uri)
result.key.fetchMethod = 'hkp'
} catch (e) {
throw new Error('key_not_found')
}
}
result.fingerprint = result.key.data.keyPacket.getFingerprint()
result.users[0].claims.forEach((claim) => {
claim.fingerprint = result.fingerprint
})
const primaryUserData = await result.key.data.getPrimaryUser()
let userData
if (signersUserId) {
result.key.data.users.forEach((user) => {
if (user.userId.email === signersUserId) {
userData = user
}
})
}
if (!userData) {
userData = primaryUserData.user
}
result.users[0].userData = {
id: userData.userId ? userData.userId.userid : null,
name: userData.userId ? userData.userId.name : null,
email: userData.userId ? userData.userId.email : null,
comment: userData.userId ? userData.userId.comment : null,
isPrimary: primaryUserData.user.userId.userid === userData.userId.userid
}
result.primaryUserIndex = result.users[0].userData.isPrimary ? 0 : null
return result
}
exports.process = process

View file

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

View file

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