diff --git a/src/asp.js b/src/asp.js index 655163e..7868fb4 100644 --- a/src/asp.js +++ b/src/asp.js @@ -33,9 +33,9 @@ const SupportedCryptoAlg = ['EdDSA', 'ES256', 'ES256K', 'ES384', 'ES512'] * Fetch a public key using Web Key Directory * @function * @param {string} uri - ASPE URI - * @returns {Promise} + * @returns {Promise} The fetched profile * @example - * const key = doip.aspe.fetchASPE('aspe:domain.tld:1234567890'); + * const key = await doip.aspe.fetchASPE('aspe:domain.example:1234567890'); */ export async function fetchASPE (uri) { const re = /aspe:(.*):(.*)/ @@ -77,13 +77,13 @@ export async function fetchASPE (uri) { } /** - * Fetch a public key using Web Key Directory + * Parse a JWS and extract the profile it contains * @function * @param {string} profileJws - Compact-Serialized profile JWS - * @param {string} uri - The ASPE URI associated with the profile - * @returns {Promise} + * @param {string} uri - The ASPE URI associated with the profile + * @returns {Promise} The extracted profile * @example - * const key = doip.aspe.parseProfileJws('...'); + * const key = await doip.aspe.parseProfileJws('...'); */ export async function parseProfileJws (profileJws, uri) { const matches = uri.match(/aspe:(.*):(.*)/) @@ -172,8 +172,8 @@ export async function parseProfileJws (profileJws, uri) { /** * Compute the fingerprint for JWK keys * @function - * @param {joseMod.JWK} key - * @returns {Promise} + * @param {joseMod.JWK} key - The JWK public key for which to compute the fingerprint + * @returns {Promise} The computed fingerprint */ export async function computeJwkFingerprint (key) { const thumbprint = await calculateJwkThumbprint(key, 'sha512') diff --git a/src/claim.js b/src/claim.js index fe3e0f2..b757b2a 100644 --- a/src/claim.js +++ b/src/claim.js @@ -18,11 +18,11 @@ import { isUri } from 'valid-url' import mergeOptions from 'merge-options' import { fetch } from './proofs.js' import { run } from './verifications.js' -import * as verificationsMod from './verifications.js' import { list, data as _data } from './serviceProviders/index.js' import { opts as _opts } from './defaults.js' import { ClaimStatus } from './enums.js' import { ServiceProvider } from './serviceProvider.js' +import * as Types from './types.js' /** * @class @@ -31,17 +31,16 @@ import { ServiceProvider } from './serviceProvider.js' * @property {string} fingerprint - The fingerprint to verify the claim against * @property {number} status - The current status code of the claim * @property {Array} matches - The claim definitions matched against the URI + * @example + * const claim = doip.Claim(); + * const claim = doip.Claim('dns:domain.tld?type=TXT'); + * const claim = doip.Claim('dns:domain.tld?type=TXT', '123abc123abc'); */ export class Claim { /** * Initialize a Claim object - * @constructor * @param {string} [uri] - The URI of the identity claim * @param {string} [fingerprint] - The fingerprint of the OpenPGP key - * @example - * const claim = doip.Claim(); - * const claim = doip.Claim('dns:domain.tld?type=TXT'); - * const claim = doip.Claim('dns:domain.tld?type=TXT', '123abc123abc'); */ constructor (uri, fingerprint) { // Verify validity of URI @@ -79,8 +78,8 @@ export class Claim { /** * @function - * @param {object} claimObject - * @returns {Claim | Error} + * @param {object} claimObject - JSON representation of a claim + * @returns {Claim | Error} Parsed claim * @example * doip.Claim.fromJSON(JSON.stringify(claim)); */ @@ -218,7 +217,7 @@ export class Claim { * regardless of the result. * @async * @function - * @param {object} [opts] - Options for proxy, fetchers + * @param {Types.VerificationConfig} [opts] - Options for proxy, fetchers */ async verify (opts) { if (this._status === ClaimStatus.INIT) { @@ -246,7 +245,7 @@ export class Claim { let claimData = this._matches[index] - /** @type {verificationsMod.VerificationResult} */ + /** @type {Types.VerificationResult} */ let verificationResult = null let proofData = null let proofFetchError @@ -312,7 +311,7 @@ export class Claim { * of the candidates is unambiguous. An ambiguous claim should never be * displayed in an user interface when its result is negative. * @function - * @returns {boolean} + * @returns {boolean} Whether the claim is ambiguous */ isAmbiguous () { if (this._status < ClaimStatus.MATCHED) { @@ -329,7 +328,7 @@ export class Claim { * Get a JSON representation of the Claim object. Useful when transferring * data between instances/machines. * @function - * @returns {object} + * @returns {object} JSON reprentation of the claim */ toJSON () { let displayProfileName = this._uri @@ -364,8 +363,8 @@ export class Claim { } /** - * @param {object} claimObject - * @returns {Claim | Error} + * @param {object} claimObject - JSON representation of a claim + * @returns {Claim | Error} Parsed claim */ function importJsonClaimVersion1 (claimObject) { if (!('claimVersion' in claimObject && claimObject.claimVersion === 1)) { @@ -405,8 +404,8 @@ function importJsonClaimVersion1 (claimObject) { } /** - * @param {object} claimObject - * @returns {Claim | Error} + * @param {object} claimObject - JSON representation of a claim + * @returns {Claim | Error} Parsed claim */ function importJsonClaimVersion2 (claimObject) { if (!('claimVersion' in claimObject && claimObject.claimVersion === 2)) { diff --git a/src/defaults.js b/src/defaults.js index 024cc19..710f9cc 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -14,6 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ import { ProxyPolicy } from './enums.js' +import * as Types from './types.js' /** * Contains default values @@ -21,26 +22,9 @@ import { ProxyPolicy } from './enums.js' */ /** - * The default options used throughout the library - * @constant {object} - * @property {object} proxy - Options related to the proxy - * @property {string|null} proxy.hostname - The hostname of the proxy - * @property {string} proxy.policy - The policy that defines when to use a proxy ({@link module:enums~ProxyPolicy|here}) - * @property {object} claims - Options related to claim verification - * @property {object} claims.activitypub - Options related to the verification of activitypub claims - * @property {string|null} claims.activitypub.url - The URL of the verifier account - * @property {string|null} claims.activitypub.privateKey - The private key to sign the request - * @property {object} claims.irc - Options related to the verification of IRC claims - * @property {string|null} claims.irc.nick - The nick that the library uses to connect to the IRC server - * @property {object} claims.matrix - Options related to the verification of Matrix claims - * @property {string|null} claims.matrix.instance - The server hostname on which the library can log in - * @property {string|null} claims.matrix.accessToken - The access token required to identify the library ({@link https://www.matrix.org/docs/guides/client-server-api|Matrix docs}) - * @property {object} claims.telegram - Options related to the verification of Telegram claims - * @property {string|null} claims.telegram.token - The Telegram API's token ({@link https://core.telegram.org/bots/api#authorizing-your-bot|Telegram docs}) - * @property {object} claims.xmpp - Options related to the verification of XMPP claims - * @property {string|null} claims.xmpp.service - The server hostname on which the library can log in - * @property {string|null} claims.xmpp.username - The username used to log in - * @property {string|null} claims.xmpp.password - The password used to log in + * The default claim verification config used throughout the library + * @constant + * @type {Types.VerificationConfig} */ export const opts = { proxy: { diff --git a/src/enums.js b/src/enums.js index dac0b30..cc1e098 100644 --- a/src/enums.js +++ b/src/enums.js @@ -115,7 +115,7 @@ export const ClaimFormat = { } /** - * How to find the claim inside the proof's JSON data + * How to find the proof inside the fetched data * @readonly * @enum {string} */ diff --git a/src/fetcher/activitypub.js b/src/fetcher/activitypub.js index 7a470f4..551a75e 100644 --- a/src/fetcher/activitypub.js +++ b/src/fetcher/activitypub.js @@ -18,22 +18,24 @@ import isURL from 'validator/lib/isURL.js' import { isNode } from 'browser-or-node' import crypto from 'crypto' import { version } from '../constants.js' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 5000 /** * Execute a fetch request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.url - The URL of the account to verify - * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @param {object} opts - Options used to enable the request - * @param {object} opts.claims - * @param {object} opts.claims.activitypub - * @param {string} opts.claims.activitypub.url - The URL of the verifier account - * @param {string} opts.claims.activitypub.privateKey - The private key to sign the request - * @returns {Promise} + * @param {object} data - Data used in the request + * @param {string} data.url - The URL of the account to verify + * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise} The fetched ActivityPub object */ export async function fn (data, opts) { let timeoutHandle diff --git a/src/fetcher/aspe.js b/src/fetcher/aspe.js index 7668c78..e425f5f 100644 --- a/src/fetcher/aspe.js +++ b/src/fetcher/aspe.js @@ -17,7 +17,13 @@ import axios from 'axios' import isFQDN from 'validator/lib/isFQDN.js' import { version } from '../constants.js' import { parseProfileJws } from '../asp.js' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 5000 const reURI = /^aspe:([a-zA-Z0-9.\-_]*):([a-zA-Z0-9]*)/ @@ -26,10 +32,11 @@ const reURI = /^aspe:([a-zA-Z0-9.\-_]*):([a-zA-Z0-9]*)/ * Execute a fetch request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.aspeUri - ASPE URI of the targeted profile - * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @returns {Promise} + * @param {object} data - Data used in the request + * @param {string} data.aspeUri - ASPE URI of the targeted profile + * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise} The fetched claims from an ASP profile */ export async function fn (data, opts) { let timeoutHandle diff --git a/src/fetcher/dns.js b/src/fetcher/dns.js index 2c5eecd..05ddd21 100644 --- a/src/fetcher/dns.js +++ b/src/fetcher/dns.js @@ -15,17 +15,24 @@ limitations under the License. */ import { isBrowser } from 'browser-or-node' import dns from 'dns' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 5000 /** * Execute a fetch request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.domain - The targeted domain - * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @returns {Promise} + * @param {object} data - Data used in the request + * @param {string} data.domain - The targeted domain + * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise} The fetched DNS records */ export async function fn (data, opts) { if (isBrowser) { diff --git a/src/fetcher/graphql.js b/src/fetcher/graphql.js index 15d544f..c6458b3 100644 --- a/src/fetcher/graphql.js +++ b/src/fetcher/graphql.js @@ -15,18 +15,25 @@ limitations under the License. */ import axios from 'axios' import { version } from '../constants.js' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 5000 /** * Execute a GraphQL query via HTTP request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.url - The URL pointing at the GraphQL HTTP endpoint - * @param {string} data.query - The GraphQL query to fetch the data containing the proof - * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @returns {Promise} + * @param {object} data - Data used in the request + * @param {string} data.url - The URL pointing at the GraphQL HTTP endpoint + * @param {string} data.query - The GraphQL query to fetch the data containing the proof + * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise} The fetched GraphQL object */ export async function fn (data, opts) { let timeoutHandle diff --git a/src/fetcher/http.js b/src/fetcher/http.js index 0421772..41fcc6c 100644 --- a/src/fetcher/http.js +++ b/src/fetcher/http.js @@ -16,18 +16,25 @@ limitations under the License. import axios from 'axios' import { ProofFormat } from '../enums.js' import { version } from '../constants.js' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 5000 /** * Execute a fetch request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.url - The URL pointing at targeted content - * @param {string} data.format - The format of the targeted content - * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @returns {Promise} + * @param {object} data - Data used in the request + * @param {string} data.url - The URL pointing at targeted content + * @param {string} data.format - The format of the targeted content + * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise} The fetched JSON object or text */ export async function fn (data, opts) { let timeoutHandle diff --git a/src/fetcher/irc.js b/src/fetcher/irc.js index fa55200..2dd061f 100644 --- a/src/fetcher/irc.js +++ b/src/fetcher/irc.js @@ -15,22 +15,25 @@ limitations under the License. */ import irc from 'irc-upd' import isAscii from 'validator/lib/isAscii.js' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 20000 /** * Execute a fetch request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.nick - The nick of the targeted account - * @param {string} data.domain - The domain on which the targeted account is registered + * @param {object} data - Data used in the request + * @param {string} data.nick - The nick of the targeted account + * @param {string} data.domain - The domain on which the targeted account is registered * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @param {object} opts - Options used to enable the request - * @param {object} opts.claims - * @param {object} opts.claims.irc - * @param {string} opts.claims.irc.nick - The nick to be used by the library to log in - * @returns {Promise} + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise} The fetched proofs from an IRC account */ export async function fn (data, opts) { let timeoutHandle diff --git a/src/fetcher/matrix.js b/src/fetcher/matrix.js index 0baf11d..a4fa6d8 100644 --- a/src/fetcher/matrix.js +++ b/src/fetcher/matrix.js @@ -17,23 +17,25 @@ import axios from 'axios' import isFQDN from 'validator/lib/isFQDN.js' import isAscii from 'validator/lib/isAscii.js' import { version } from '../constants.js' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 5000 /** * Execute a fetch request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.eventId - The identifier of the targeted post - * @param {string} data.roomId - The identifier of the room containing the targeted post - * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @param {object} opts - Options used to enable the request - * @param {object} opts.claims - * @param {object} opts.claims.matrix - * @param {string} opts.claims.matrix.instance - The server hostname on which the library can log in - * @param {string} opts.claims.matrix.accessToken - The access token required to identify the library ({@link https://www.matrix.org/docs/guides/client-server-api|Matrix docs}) - * @returns {Promise} + * @param {object} data - Data used in the request + * @param {string} data.eventId - The identifier of the targeted post + * @param {string} data.roomId - The identifier of the room containing the targeted post + * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise} The fetched Matrix object */ export async function fn (data, opts) { let timeoutHandle diff --git a/src/fetcher/openpgp.js b/src/fetcher/openpgp.js index 982a477..b828194 100644 --- a/src/fetcher/openpgp.js +++ b/src/fetcher/openpgp.js @@ -18,18 +18,25 @@ import { readKey } from 'openpgp' import { OpenPgpQueryProtocol } from '../enums.js' import { version } from '../constants.js' import { parsePublicKey } from '../openpgp.js' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 5000 /** * Execute a fetch request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.url - The URL pointing at targeted content - * @param {OpenPgpQueryProtocol} data.protocol - The protocol used to access the targeted content - * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @returns {Promise} + * @param {object} data - Data used in the request + * @param {string} data.url - The URL pointing at targeted content + * @param {OpenPgpQueryProtocol} data.protocol - The protocol used to access the targeted content + * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise} The fetched notations from an OpenPGP key */ export async function fn (data, opts) { let timeoutHandle diff --git a/src/fetcher/telegram.js b/src/fetcher/telegram.js index 00fe7f1..87ac7cc 100644 --- a/src/fetcher/telegram.js +++ b/src/fetcher/telegram.js @@ -16,22 +16,25 @@ limitations under the License. import axios from 'axios' import isAscii from 'validator/lib/isAscii.js' import { version } from '../constants.js' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 5000 /** * Execute a fetch request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.chat - Telegram public chat username - * @param {string} data.user - Telegram user username - * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @param {object} opts - Options used to enable the request - * @param {object} opts.claims - * @param {object} opts.claims.telegram - * @param {string} opts.claims.telegram.token - The Telegram Bot API token - * @returns {Promise} + * @param {object} data - Data used in the request + * @param {string} data.chat - Telegram public chat username + * @param {string} data.user - Telegram user username + * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise} The fetched Telegram object */ export async function fn (data, opts) { let timeoutHandle diff --git a/src/fetcher/xmpp.js b/src/fetcher/xmpp.js index 88a0d2d..fca93ad 100644 --- a/src/fetcher/xmpp.js +++ b/src/fetcher/xmpp.js @@ -17,18 +17,31 @@ import { client, xml } from '@xmpp/client' import debug from '@xmpp/debug' import isFQDN from 'validator/lib/isFQDN.js' import isAscii from 'validator/lib/isAscii.js' +import * as Types from '../types.js' +/** + * Timeout after which the fetch is aborted + * @constant + * @type {number} + */ export const timeout = 5000 let xmpp = null let iqCaller = null -const xmppStart = async (service, username, password) => { +/** + * Start the XMPP client + * @function + * @async + * @param {Types.XmppClaimVerificationConfig} params - XMPP claim verification config + * @returns {Promise} The fetched proofs from an XMPP account + */ +const xmppStart = async (params) => { return new Promise((resolve, reject) => { const xmpp = client({ - service, - username, - password + service: params.service, + username: params.username, + password: params.password }) if (process.env.NODE_ENV !== 'production') { debug(xmpp, true) @@ -48,16 +61,11 @@ const xmppStart = async (service, username, password) => { * Execute a fetch request * @function * @async - * @param {object} data - Data used in the request - * @param {string} data.id - The identifier of the targeted account - * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher - * @param {object} opts - Options used to enable the request - * @param {object} opts.claims - * @param {object} opts.claims.xmpp - * @param {string} opts.claims.xmpp.service - The server hostname on which the library can log in - * @param {string} opts.claims.xmpp.username - The username used to log in - * @param {string} opts.claims.xmpp.password - The password used to log in - * @returns {Promise} + * @param {object} data - Data used in the request + * @param {string} data.id - The identifier of the targeted account + * @param {number} [data.fetcherTimeout] - Optional timeout for the fetcher + * @param {Types.VerificationConfig} [opts] - Options used to enable the request + * @returns {Promise>} The fetched proofs from an XMPP account */ export async function fn (data, opts) { try { @@ -69,11 +77,7 @@ export async function fn (data, opts) { } if (!xmpp || xmpp.status !== 'online') { - const xmppStartRes = await xmppStart( - opts.claims.xmpp.service, - opts.claims.xmpp.username, - opts.claims.xmpp.password - ) + const xmppStartRes = await xmppStart(opts.claims.xmpp) xmpp = xmppStartRes.xmpp iqCaller = xmppStartRes.iqCaller } diff --git a/src/index.js b/src/index.js index b932e51..5ddb0b4 100644 --- a/src/index.js +++ b/src/index.js @@ -28,3 +28,4 @@ export * as utils from './utils.js' export * as verifications from './verifications.js' export * as schemas from './schemas.js' export * as fetcher from './fetcher/index.js' +export * as types from './types.js' diff --git a/src/openpgp.js b/src/openpgp.js index 5ea0392..4dbcc7e 100644 --- a/src/openpgp.js +++ b/src/openpgp.js @@ -31,17 +31,16 @@ import { Persona } from './persona.js' /** * Fetch a public key using keyservers * @function - * @param {string} identifier - Fingerprint or email address - * @param {string} [keyserverDomain=keys.openpgp.org] - Domain of the keyserver - * @returns {Promise} + * @param {string} identifier - Fingerprint or email address + * @param {string} [keyserverDomain] - Domain of the keyserver + * @returns {Promise} The profile from the fetched OpenPGP key * @example * const key1 = doip.keys.fetchHKP('alice@domain.tld'); * const key2 = doip.keys.fetchHKP('123abc123abc'); + * const key3 = doip.keys.fetchHKP('123abc123abc', 'pgpkeys.eu'); */ -export async function fetchHKP (identifier, keyserverDomain) { - const keyserverBaseUrl = keyserverDomain - ? `https://${keyserverDomain}` - : 'https://keys.openpgp.org' +export async function fetchHKP (identifier, keyserverDomain = 'keys.openpgp.org') { + const keyserverBaseUrl = `https://${keyserverDomain ?? 'keys.openpgp.org'}` const hkp = new HKP(keyserverBaseUrl) const lookupOpts = { @@ -76,7 +75,7 @@ export async function fetchHKP (identifier, keyserverDomain) { * Fetch a public key using Web Key Directory * @function * @param {string} identifier - Identifier of format 'username@domain.tld` - * @returns {Promise} + * @returns {Promise} The profile from the fetched OpenPGP key * @example * const key = doip.keys.fetchWKD('alice@domain.tld'); */ @@ -113,9 +112,9 @@ export async function fetchWKD (identifier) { /** * Fetch a public key from Keybase * @function - * @param {string} username - Keybase username - * @param {string} fingerprint - Fingerprint of key - * @returns {Promise} + * @param {string} username - Keybase username + * @param {string} fingerprint - Fingerprint of key + * @returns {Promise} The profile from the fetched OpenPGP key * @example * const key = doip.keys.fetchKeybase('alice', '123abc123abc'); */ @@ -155,10 +154,10 @@ export async function fetchKeybase (username, fingerprint) { } /** - * Get a public key from plaintext data + * Get a public key from armored public key text data * @function * @param {string} rawKeyContent - Plaintext ASCII-formatted public key data - * @returns {Promise} + * @returns {Promise} The profile from the armored public key * @example * const plainkey = `-----BEGIN PGP PUBLIC KEY BLOCK----- * @@ -185,7 +184,7 @@ export async function fetchPlaintext (rawKeyContent) { * Fetch a public key using an URI * @function * @param {string} uri - URI that defines the location of the key - * @returns {Promise} + * @returns {Promise} The profile from the fetched OpenPGP key * @example * const key1 = doip.keys.fetchURI('hkp:alice@domain.tld'); * const key2 = doip.keys.fetchURI('hkp:123abc123abc'); @@ -231,7 +230,7 @@ export async function fetchURI (uri) { * This function will also try and parse the input as a plaintext key * @function * @param {string} identifier - URI that defines the location of the key - * @returns {Promise} + * @returns {Promise} The profile from the fetched OpenPGP key * @example * const key1 = doip.keys.fetch('alice@domain.tld'); * const key2 = doip.keys.fetch('123abc123abc'); @@ -273,7 +272,7 @@ export async function fetch (identifier) { * Process a public key to get a profile * @function * @param {PublicKey} publicKey - The public key to parse - * @returns {Promise} + * @returns {Promise} The profile from the processed OpenPGP key * @example * const key = doip.keys.fetchURI('hkp:alice@domain.tld'); * const profile = doip.keys.parsePublicKey(key); diff --git a/src/persona.js b/src/persona.js index 5c14a95..7daeb91 100644 --- a/src/persona.js +++ b/src/persona.js @@ -16,9 +16,8 @@ limitations under the License. import { Claim } from './claim.js' /** - * A persona with identity claims * @class - * @constructor + * @classdesc A persona with identity claims * @public * @example * const claim = Claim('https://alice.tld', '123'); @@ -26,8 +25,8 @@ import { Claim } from './claim.js' */ export class Persona { /** - * @param {string} name - * @param {Claim[]} claims + * @param {string} name - Name of the persona + * @param {Claim[]} claims - Claims of the persona */ constructor (name, claims) { /** @@ -81,10 +80,11 @@ export class Persona { } /** + * Parse a JSON object and convert it into a persona * @function - * @param {object} personaObject - * @param {number} profileVersion - * @returns {Persona | Error} + * @param {object} personaObject - JSON representation of a persona + * @param {number} profileVersion - Version of the Profile containing the persona + * @returns {Persona | Error} Parsed persona * @example * doip.Persona.fromJSON(JSON.stringify(persona), 2); */ @@ -112,46 +112,52 @@ export class Persona { } /** + * Set the persona's identifier * @function - * @param {string} identifier + * @param {string} identifier - Identifier of the persona */ setIdentifier (identifier) { this.identifier = identifier } /** + * Set the persona's description * @function - * @param {string} description + * @param {string} description - Description of the persona */ setDescription (description) { this.description = description } /** + * Set the persona's email address * @function - * @param {string} email + * @param {string} email - Email address of the persona */ setEmailAddress (email) { this.email = email } /** + * Set the URL to the persona's avatar * @function - * @param {string} avatarUrl + * @param {string} avatarUrl - URL to the persona's avatar */ setAvatarUrl (avatarUrl) { this.avatarUrl = avatarUrl } /** + * Add a claim * @function - * @param {Claim} claim + * @param {Claim} claim - Claim to add */ addClaim (claim) { this.claims.push(claim) } /** + * Revoke the persona * @function */ revoke () { @@ -159,9 +165,9 @@ export class Persona { } /** - * Get a JSON representation of the Profile object + * Get a JSON representation of the persona * @function - * @returns {object} + * @returns {object} JSON representation of the persona */ toJSON () { return { @@ -178,8 +184,8 @@ export class Persona { } /** - * @param {object} personaObject - * @returns {Persona | Error} + * @param {object} personaObject - JSON representation of a persona + * @returns {Persona | Error} Parsed persona */ function importJsonPersonaVersion2 (personaObject) { const claims = personaObject.claims.map(x => Claim.fromJSON(x)) diff --git a/src/profile.js b/src/profile.js index e4906a8..7ac74d3 100644 --- a/src/profile.js +++ b/src/profile.js @@ -13,22 +13,14 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { PublicKey } from 'openpgp' -import * as joseMod from 'jose' import { PublicKeyFetchMethod, PublicKeyEncoding, PublicKeyType, ProfileType } from './enums.js' import { Persona } from './persona.js' +import * as Types from './types.js' /** - * The online verifier instance of identity profiles like Keyoxide's web interface - * @typedef {Object} ProfileVerifier - * @property {string} name - Name of the profile verifier - * @property {string} url - URL to the profile verifier - */ - -/** - * A profile of personas with identity claims - * @function - * @param {Array} personas + * @class [Types.Profile] + * @classdesc A profile of personas with identity claims + * @param {Array} personas - Personas of the profile * @public * @example * const claim = Claim('https://alice.tld', '123'); @@ -39,17 +31,12 @@ export class Profile { /** * Create a new profile * @function - * @param {ProfileType} profileType - * @param {string} identifier - * @param {Array} personas + * @param {ProfileType} profileType - Type of profile (ASP, OpenPGP, etc.) + * @param {string} identifier - Profile identifier (fingerprint, URI, etc.) + * @param {Array} personas - Personas of the profile * @public */ constructor (profileType, identifier, personas) { - /** - * Profile version - * @type {number} - * @public - */ this.profileVersion = 2 /** * Profile version @@ -77,78 +64,34 @@ export class Profile { this.primaryPersonaIndex = personas.length > 0 ? 0 : -1 /** * The cryptographic key associated with the profile - * @property {object} + * @type {Types.ProfilePublicKey} * @public */ this.publicKey = { - /** - * The type of cryptographic key - * @type {PublicKeyType} - * @public - */ keyType: PublicKeyType.NONE, - /** - * The fingerprint of the cryptographic key - * @type {string | null} - * @public - */ fingerprint: null, - /** - * The encoding of the cryptographic key - * @type {PublicKeyEncoding} - * @public - */ encoding: PublicKeyEncoding.NONE, - /** - * The encoded cryptographic key - * @type {string | null} - * @public - */ encodedKey: null, - /** - * The raw cryptographic key as object (to be removed during toJSON()) - * @type {PublicKey | joseMod.JWK | null} - * @public - */ key: null, - /** - * Details on how to fetch the public key - * @property {object} - * @public - */ fetch: { - /** - * The method to fetch the key - * @type {PublicKeyFetchMethod} - * @public - */ method: PublicKeyFetchMethod.NONE, - /** - * The query to fetch the key - * @type {string | null} - * @public - */ query: null, - /** - * The URL the method eventually resolved to - * @type {string | null} - * @public - */ resolvedUrl: null } } /** * List of verifier URLs - * @type {ProfileVerifier[]} + * @type {Types.ProfileVerifier[]} * @public */ this.verifiers = [] } /** + * Parse a JSON object and convert it into a profile * @function - * @param {object} profileObject - * @returns {Profile | Error} + * @param {object} profileObject - JSON representation of a profile + * @returns {Profile | Error} Parsed profile * @example * doip.Profile.fromJSON(JSON.stringify(profile)); */ @@ -176,18 +119,19 @@ export class Profile { } /** + * Add profile verifier to the profile * @function - * @param {string} name - * @param {string} url + * @param {string} name - Name of the verifier + * @param {string} url - URL of the verifier */ addVerifier (name, url) { this.verifiers.push({ name, url }) } /** - * Get a JSON representation of the Profile object + * Get a JSON representation of the profile * @function - * @returns {object} + * @returns {object} JSON representation of the profile */ toJSON () { return { @@ -213,8 +157,8 @@ export class Profile { } /** - * @param {object} profileObject - * @returns {Profile | Error} + * @param {object} profileObject - JSON representation of the profile + * @returns {Profile | Error} Parsed profile */ function importJsonProfileVersion2 (profileObject) { if (!('profileVersion' in profileObject && profileObject.profileVersion === 2)) { diff --git a/src/proofs.js b/src/proofs.js index b77bc49..c5a199d 100644 --- a/src/proofs.js +++ b/src/proofs.js @@ -18,6 +18,7 @@ import { fetcher } from './index.js' import { generateProxyURL } from './utils.js' import { ProxyPolicy, ProofAccessRestriction } from './enums.js' import { ServiceProvider } from './serviceProvider.js' +import * as Types from './types.js' /** * @module proofs @@ -31,8 +32,8 @@ import { ServiceProvider } from './serviceProvider.js' * approach is possible. * @async * @param {ServiceProvider} data - Data from a claim definition - * @param {object} opts - Options to enable the request - * @returns {Promise} + * @param {Types.VerificationConfig} opts - Options to enable the request + * @returns {Promise} Fetched proof data */ export async function fetch (data, opts) { if (isNode) { @@ -45,7 +46,7 @@ export async function fetch (data, opts) { /** * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request - * @returns {Promise} + * @returns {Promise} Fetched proof data */ const handleBrowserRequests = (data, opts) => { switch (opts.proxy.policy) { @@ -88,7 +89,7 @@ const handleBrowserRequests = (data, opts) => { /** * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request - * @returns {Promise} + * @returns {Promise} Fetched proof data */ const handleNodeRequests = (data, opts) => { switch (opts.proxy.policy) { @@ -109,7 +110,7 @@ const handleNodeRequests = (data, opts) => { /** * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request - * @returns {Promise} + * @returns {Promise} Fetched proof data */ const createDefaultRequestPromise = (data, opts) => { return new Promise((resolve, reject) => { @@ -135,7 +136,7 @@ const createDefaultRequestPromise = (data, opts) => { /** * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request - * @returns {Promise} + * @returns {Promise} Fetched proof data */ const createProxyRequestPromise = (data, opts) => { return new Promise((resolve, reject) => { @@ -174,7 +175,7 @@ const createProxyRequestPromise = (data, opts) => { /** * @param {ServiceProvider} data - Data from a claim definition * @param {object} opts - Options to enable the request - * @returns {Promise} + * @returns {Promise} Fetched proof data */ const createFallbackRequestPromise = (data, opts) => { return new Promise((resolve, reject) => { diff --git a/src/serviceProvider.js b/src/serviceProvider.js index aca19f1..059153d 100644 --- a/src/serviceProvider.js +++ b/src/serviceProvider.js @@ -13,140 +13,44 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -import { ClaimFormat, ClaimRelation, EntityEncodingFormat, ProofAccessRestriction, ProofFormat } from "./enums" - -/** - * The method to find the proof inside the response data - * @typedef {Object} ProofTarget - * @property {ClaimFormat} format - How the response data is formatted - * @property {EntityEncodingFormat} encoding - How the response data is encoded - * @property {ClaimRelation} relation - How the proof is related to the response data - * @property {string[]} path - Path to the proof inside the response data object - */ +import * as Types from './types.js' /** * A service provider matched to an identity claim * @class - * @constructor * @public */ export class ServiceProvider { /** - * @param {object} spObj + * @param {Types.ServiceProviderObject} serviceProviderObject - JSON representation of a {@link ServiceProvider} */ - constructor (spObj) { + constructor (serviceProviderObject) { /** * Details about the service provider - * @property {object} + * @type {Types.ServiceProviderAbout} */ - this.about = { - /** - * Identifier of the service provider (no whitespace or symbols, lowercase) - * @type {string} - */ - id: spObj.about.id, - /** - * Full name of the service provider - * @type {string} - */ - name: spObj.about.name, - /** - * URL to the homepage of the service provider - * @type {string | null} - */ - homepage: spObj.about.homepage || null - } + this.about = serviceProviderObject.about /** - * What the profile would look like if the match is correct - * @property {object} + * What the profile would look like if a claim matches this service provider + * @type {Types.ServiceProviderProfile} */ - this.profile = { - /** - * Profile name to be displayed - * @type {string} - */ - display: spObj.profile.display, - /** - * URI or URL for public access to the profile - * @type {string} - */ - uri: spObj.profile.uri, - /** - * URI or URL associated with the profile usually served as a QR code - * @type {string | null} - */ - qr: spObj.profile.qr || null - } + this.profile = serviceProviderObject.profile /** - * Details from the claim matching process - * @property {object} + * Information about the claim matching process + * @type {Types.ServiceProviderClaim} */ - this.claim = { - /** - * Regular expression used to parse the URI - * @type {string} - */ - uriRegularExpression: spObj.claim.uriRegularExpression, - /** - * Whether this match automatically excludes other matches - * @type {boolean} - */ - uriIsAmbiguous: spObj.claim.uriIsAmbiguous - } + this.claim = serviceProviderObject.claim /** * Information for the proof verification process - * @property {object} + * @type {Types.ServiceProviderProof} */ - this.proof = { - /** - * Details to request the potential proof - * @property {object} - */ - request: { - /** - * Location of the proof - * @type {string | null} - */ - uri: spObj.proof.request.uri, - /** - * Fetcher to be used to request the proof - * @type {string} - */ - fetcher: spObj.proof.request.fetcher, - /** - * Type of access restriction - * @type {ProofAccessRestriction} - */ - accessRestriction: spObj.proof.request.accessRestriction, - /** - * Data needed by the fetcher or proxy to request the proof - * @type {object} - */ - data: spObj.proof.request.data - }, - /** - * Details about the expected response - * @property {object} - */ - response: { - /** - * Expected format of the proof - * @type {ProofFormat} - */ - format: spObj.proof.response.format - }, - /** - * Details about the target located in the response - * @type {ProofTarget[]} - */ - target: spObj.proof.target - } + this.proof = serviceProviderObject.proof } /** - * Get a JSON representation of the ServiceProvider object + * Get a JSON representation of the {@link ServiceProvider} * @function - * @returns {object} + * @returns {Types.ServiceProviderObject} JSON representation of a {@link ServiceProvider} */ toJSON () { return { diff --git a/src/serviceProviders/activitypub.js b/src/serviceProviders/activitypub.js index 68362cd..d16d133 100644 --- a/src/serviceProviders/activitypub.js +++ b/src/serviceProviders/activitypub.js @@ -21,8 +21,8 @@ export const reURI = /^https:\/\/(.*)\/?/ /** * @function - * @param {string} uri - * @returns {ServiceProvider} + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { return new ServiceProvider({ diff --git a/src/serviceProviders/aspe.js b/src/serviceProviders/aspe.js index b6a0ccb..f4412bb 100644 --- a/src/serviceProviders/aspe.js +++ b/src/serviceProviders/aspe.js @@ -21,7 +21,8 @@ export const reURI = /^aspe:([a-zA-Z0-9.\-_]*):([a-zA-Z0-9]*)/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/discourse.js b/src/serviceProviders/discourse.js index 3a30f77..1d2d01a 100644 --- a/src/serviceProviders/discourse.js +++ b/src/serviceProviders/discourse.js @@ -20,8 +20,8 @@ export const reURI = /^https:\/\/(.*)\/u\/(.*)\/?/ /** * @function - * @param {string} uri - * @returns {ServiceProvider} + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/dns.js b/src/serviceProviders/dns.js index fb9cde7..06c81ec 100644 --- a/src/serviceProviders/dns.js +++ b/src/serviceProviders/dns.js @@ -20,7 +20,8 @@ export const reURI = /^dns:([a-zA-Z0-9.\-_]*)(?:\?(.*))?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/forem.js b/src/serviceProviders/forem.js index de75630..a49ec68 100644 --- a/src/serviceProviders/forem.js +++ b/src/serviceProviders/forem.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/(.*)\/(.*)\/(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/forgejo.js b/src/serviceProviders/forgejo.js index 97b0b80..f1a14f6 100644 --- a/src/serviceProviders/forgejo.js +++ b/src/serviceProviders/forgejo.js @@ -21,7 +21,8 @@ export const reURI = /^https:\/\/(.*)\/(.*)\/(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/gitea.js b/src/serviceProviders/gitea.js index 38841cc..0cd2d72 100644 --- a/src/serviceProviders/gitea.js +++ b/src/serviceProviders/gitea.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/(.*)\/(.*)\/(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/github.js b/src/serviceProviders/github.js index bbe4653..d0c36f8 100644 --- a/src/serviceProviders/github.js +++ b/src/serviceProviders/github.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/gist\.github\.com\/(.*)\/(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/gitlab.js b/src/serviceProviders/gitlab.js index 1c568b0..7e5c8ae 100644 --- a/src/serviceProviders/gitlab.js +++ b/src/serviceProviders/gitlab.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/(.*)\/(.*)\/gitlab_proof\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) @@ -41,7 +42,6 @@ export function processURI (uri) { uriIsAmbiguous: true }, proof: { - uri, request: { fetcher: E.Fetcher.HTTP, accessRestriction: E.ProofAccessRestriction.NONE, diff --git a/src/serviceProviders/hackernews.js b/src/serviceProviders/hackernews.js index 2f3a6cb..0c22b6b 100644 --- a/src/serviceProviders/hackernews.js +++ b/src/serviceProviders/hackernews.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/news\.ycombinator\.com\/user\?id=(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/irc.js b/src/serviceProviders/irc.js index dddfd98..3992220 100644 --- a/src/serviceProviders/irc.js +++ b/src/serviceProviders/irc.js @@ -20,7 +20,8 @@ export const reURI = /^irc:\/\/(.*)\/([a-zA-Z0-9\-[\]\\`_^{|}]*)/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/keybase.js b/src/serviceProviders/keybase.js index 934a246..4773f4b 100644 --- a/src/serviceProviders/keybase.js +++ b/src/serviceProviders/keybase.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/keybase.io\/(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/liberapay.js b/src/serviceProviders/liberapay.js index c44e223..b18eea0 100644 --- a/src/serviceProviders/liberapay.js +++ b/src/serviceProviders/liberapay.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/liberapay\.com\/(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/lichess.js b/src/serviceProviders/lichess.js index 22e0b4f..57e6dc1 100644 --- a/src/serviceProviders/lichess.js +++ b/src/serviceProviders/lichess.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/lichess\.org\/@\/(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/lobsters.js b/src/serviceProviders/lobsters.js index 9e72985..a988f98 100644 --- a/src/serviceProviders/lobsters.js +++ b/src/serviceProviders/lobsters.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/lobste\.rs\/(?:~|u\/)(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/matrix.js b/src/serviceProviders/matrix.js index eeb6153..884f2a8 100644 --- a/src/serviceProviders/matrix.js +++ b/src/serviceProviders/matrix.js @@ -20,7 +20,8 @@ export const reURI = /^matrix:u\/(?:@)?([^@:]*:[^?]*)(\?.*)?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/opencollective.js b/src/serviceProviders/opencollective.js index fe38845..b5847e4 100644 --- a/src/serviceProviders/opencollective.js +++ b/src/serviceProviders/opencollective.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/opencollective\.com\/(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/openpgp.js b/src/serviceProviders/openpgp.js index beddbc2..048d3db 100644 --- a/src/serviceProviders/openpgp.js +++ b/src/serviceProviders/openpgp.js @@ -24,7 +24,8 @@ const reURIWkdAdvanced = /^https:\/\/(openpgpkey.*)\/.well-known\/openpgpkey\/(. /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { let reURI = null diff --git a/src/serviceProviders/orcid.js b/src/serviceProviders/orcid.js index 55e1263..0f6f478 100644 --- a/src/serviceProviders/orcid.js +++ b/src/serviceProviders/orcid.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/orcid\.org\/(.*)\/?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/owncast.js b/src/serviceProviders/owncast.js index 6abf042..454f520 100644 --- a/src/serviceProviders/owncast.js +++ b/src/serviceProviders/owncast.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/(.*)/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/reddit.js b/src/serviceProviders/reddit.js index 15f61cf..c92f857 100644 --- a/src/serviceProviders/reddit.js +++ b/src/serviceProviders/reddit.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/(?:www\.)?reddit\.com\/user\/(.*)\/comments\/(. /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/stackexchange.js b/src/serviceProviders/stackexchange.js index 16eec02..34bb9a3 100644 --- a/src/serviceProviders/stackexchange.js +++ b/src/serviceProviders/stackexchange.js @@ -21,7 +21,8 @@ const reStackExchange = /\.stackexchange$/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const [, domain, id] = uri.match(reURI) diff --git a/src/serviceProviders/telegram.js b/src/serviceProviders/telegram.js index 8bc0c2f..d15f8d4 100644 --- a/src/serviceProviders/telegram.js +++ b/src/serviceProviders/telegram.js @@ -20,7 +20,8 @@ export const reURI = /https:\/\/t.me\/([A-Za-z0-9_]{5,32})\?proof=([A-Za-z0-9_]{ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/twitter.js b/src/serviceProviders/twitter.js index aba21a4..14d81fe 100644 --- a/src/serviceProviders/twitter.js +++ b/src/serviceProviders/twitter.js @@ -20,7 +20,8 @@ export const reURI = /^https:\/\/twitter\.com\/(.*)\/status\/([0-9]*)(?:\?.*)?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/serviceProviders/xmpp.js b/src/serviceProviders/xmpp.js index 56d55f8..8fc9c8f 100644 --- a/src/serviceProviders/xmpp.js +++ b/src/serviceProviders/xmpp.js @@ -20,7 +20,8 @@ export const reURI = /^xmpp:([a-zA-Z0-9.\-_]*)@([a-zA-Z0-9.\-_]*)(?:\?(.*))?/ /** * @function - * @param {string} uri + * @param {string} uri - Claim URI to process + * @returns {ServiceProvider} The service provider information based on the claim URI */ export function processURI (uri) { const match = uri.match(reURI) diff --git a/src/signatures.js b/src/signatures.js index 114dceb..654a33e 100644 --- a/src/signatures.js +++ b/src/signatures.js @@ -28,7 +28,7 @@ import { Persona } from './persona.js' * Extract the profile from a signature and fetch the associated key * @async * @param {string} signature - The plaintext signature to parse - * @returns {Promise} + * @returns {Promise} The profile obtained from the signature */ export async function parse (signature) { /** @type {CleartextMessage} */ diff --git a/src/types.js b/src/types.js new file mode 100644 index 0000000..19d989d --- /dev/null +++ b/src/types.js @@ -0,0 +1,199 @@ +/* +Copyright 2024 Yarmo Mackenbach + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +/** + * Contains various types + * @module types + */ + +import { PublicKey } from 'openpgp' +import * as joseMod from 'jose' +import { ClaimFormat, ClaimRelation, EntityEncodingFormat, ProofAccessRestriction, ProofFormat, ProxyPolicy, PublicKeyEncoding, PublicKeyFetchMethod, PublicKeyType } from './enums.js' + +/** + * Service provider + * @typedef {object} ServiceProviderObject + * @property {ServiceProviderAbout} about - Details about the service provider + * @property {ServiceProviderProfile} profile - What the profile would look like if a claim matches this service provider + * @property {ServiceProviderClaim} claim - Details from the claim matching process + * @property {ServiceProviderProof} proof - Information for the proof verification process + */ + +/** + * Details about the service provider + * @typedef {object} ServiceProviderAbout + * @property {string} id - Identifier of the service provider (no whitespace or symbols, lowercase) + * @property {string} name - Full name of the service provider + * @property {string} [homepage] - URL to the homepage of the service provider + */ + +/** + * What the profile would look like if a claim matches this service provider + * @typedef {object} ServiceProviderProfile + * @property {string} display - Profile name to be displayed + * @property {string} uri - URI or URL for public access to the profile + * @property {string} [qr] -URI or URL associated with the profile usually served as a QR code + */ + +/** + * Information about the claim matching process + * @typedef {object} ServiceProviderClaim + * @property {string} uriRegularExpression - Regular expression used to parse the URI + * @property {boolean} uriIsAmbiguous - Whether this match automatically excludes other matches + */ + +/** + * Information for the proof verification process + * @typedef {object} ServiceProviderProof + * @property {ServiceProviderProofRequest} request - Details to request the potential proof + * @property {ServiceProviderProofResponse} response - Details about the expected response + * @property {ProofTarget[]} target - Details about the target located in the response + */ + +/** + * Details to request the potential proof + * @typedef {object} ServiceProviderProofRequest + * @property {string} [uri] - Location of the proof + * @property {string} fetcher - Fetcher to be used to request the proof + * @property {ProofAccessRestriction} accessRestriction - Type of access restriction + * @property {object} data - Data needed by the fetcher or proxy to request the proof + */ + +/** + * Details about the expected response + * @typedef {object} ServiceProviderProofResponse + * @property {ProofFormat} format - Expected format of the proof + */ + +/** + * Public key for a profile + * @typedef {object} ProfilePublicKey + * @property {PublicKeyType} keyType - The type of cryptographic key + * @property {PublicKeyEncoding} encoding - The encoding of the cryptographic key + * @property {string} [fingerprint] - The fingerprint of the cryptographic key + * @property {string} [encodedKey] - The encoded cryptographic key + * @property {PublicKey | joseMod.JWK} [key] - The raw cryptographic key as object (to be removed during toJSON()) + * @property {ProfilePublicKeyFetch} fetch - Details on how to fetch the public key + */ + +/** + * Details on how to fetch the public key + * @typedef {object} ProfilePublicKeyFetch + * @property {PublicKeyFetchMethod} method - The method to fetch the key + * @property {string} [query] - The query to fetch the key + * @property {string} [resolvedUrl] - The URL the method eventually resolved to + */ + +/** + * Config used for the claim verification + * @typedef {object} VerificationConfig + * @property {ProxyVerificationConfig} [proxy] - Options related to the use of proxy servers + * @property {ClaimVerificationConfig} [claims] - Config related to the verification of supported claims + */ + +/** + * Config related to the use of proxy servers + * @typedef {object} ProxyVerificationConfig + * @property {string} [scheme] - The scheme to use for proxy requests + * @property {string} [hostname] - The hostname of the proxy + * @property {ProxyPolicy} policy - The policy that defines when to use a proxy ({@link module:enums~ProxyPolicy|here}) + */ + +/** + * Config related to the verification of supported claims + * @typedef {object} ClaimVerificationConfig + * @property {ActivityPubClaimVerificationConfig} [activitypub] - Config related to the verification of ActivityPub claims + * @property {IrcClaimVerificationConfig} [irc] - Config related to the verification of IRC claims + * @property {MatrixClaimVerificationConfig} [matrix] - Config related to the verification of Matrix claims + * @property {TelegramClaimVerificationConfig} [telegram] - Config related to the verification of Telegram claims + * @property {XmppClaimVerificationConfig} [xmpp] - Config related to the verification of XMPP claims + */ + +/** + * Config related to the verification of ActivityPub claims + * @typedef {object} ActivityPubClaimVerificationConfig + * @property {string} url - The URL of the verifier account + * @property {string} privateKey - The private key to sign the request + */ + +/** + * Config related to the verification of IRC claims + * @typedef {object} IrcClaimVerificationConfig + * @property {string} nick - The nick that the library uses to connect to the IRC server + */ + +/** + * Config related to the verification of Matrix claims + * @typedef {object} MatrixClaimVerificationConfig + * @property {string} instance - The server hostname on which the library can log in + * @property {string} accessToken - The access token required to identify the library ({@link https://www.matrix.org/docs/guides/client-server-api|Matrix docs}) + */ + +/** + * Config related to the verification of Telegram claims + * @typedef {object} TelegramClaimVerificationConfig + * @property {string} token - The Telegram API's token ({@link https://core.telegram.org/bots/api#authorizing-your-bot|Telegram docs}) + */ + +/** + * Config related to the verification of XMPP claims + * @typedef {object} XmppClaimVerificationConfig + * @property {string} service - The server hostname on which the library can log in + * @property {string} username - The username used to log in + * @property {string} password - The password used to log in + */ + +/** + * The online verifier instance of identity profiles like Keyoxide's web interface + * @typedef {object} ProfileVerifier + * @property {string} name - Name of the profile verifier + * @property {string} url - URL to the profile verifier + */ + +/** + * Parameters needed to perform the proof verification + * @typedef {object} VerificationParams + * @property {string} target - Proof to search + * @property {ClaimFormat} claimFormat - Format of the claim + * @property {EntityEncodingFormat} proofEncodingFormat - Encoding of the data containing the proof + * @property {ClaimRelation} [claimRelation] - How to find the proof inside the JSON data + */ + +/** + * Result of the proof verification + * @typedef {object} VerificationResult + * @property {boolean} result - Whether the proof was found and the claim verified + * @property {boolean} completed - Whether the verification process completed without errors + * @property {VerificationResultProof} [proof] - Details about the proof and how it was fetched + * @property {any[]} errors - Errors that ocurred during the verification process + */ + +/** + * Information about the proof in the proof verification result + * @typedef {object} VerificationResultProof + * @property {string} fetcher - Which fetcher was used to obtain the data containing the proof + * @property {boolean} viaProxy - Whether a proxy was used to obtain the data containing the proof + */ + +/** + * The method to find the proof inside the response data + * @typedef {object} ProofTarget + * @property {ClaimFormat} format - How the response data is formatted + * @property {EntityEncodingFormat} encoding - How the response data is encoded + * @property {ClaimRelation} relation - How the proof is related to the response data + * @property {string[]} path - Path to the proof inside the response data object + */ + +export const Types = {} diff --git a/src/utils.js b/src/utils.js index e6f7387..30bdada 100644 --- a/src/utils.js +++ b/src/utils.js @@ -15,6 +15,7 @@ limitations under the License. */ import isFQDN from 'validator/lib/isFQDN.js' import { ClaimFormat } from './enums.js' +import * as Types from './types.js' /** * @module utils @@ -22,13 +23,10 @@ import { ClaimFormat } from './enums.js' /** * Generate an URL to request data from a proxy server - * @param {string} type - The name of the fetcher the proxy must use - * @param {object} data - The data the proxy must provide to the fetcher - * @param {object} opts - Options to enable the request - * @param {object} opts.proxy - Proxy related options - * @param {object} opts.proxy.scheme - The scheme used by the proxy server - * @param {object} opts.proxy.hostname - The hostname of the proxy server - * @returns {string} + * @param {string} type - The name of the fetcher the proxy must use + * @param {object} data - The data the proxy must provide to the fetcher + * @param {Types.VerificationConfig} opts - Options to enable the request + * @returns {string} Generated proxy URL */ export function generateProxyURL (type, data, opts) { try { @@ -43,7 +41,7 @@ export function generateProxyURL (type, data, opts) { queryStrings.push(`${key}=${encodeURIComponent(data[key])}`) }) - const scheme = opts.proxy.scheme ? opts.proxy.scheme : 'https' + const scheme = opts.proxy.scheme ?? 'https' return `${scheme}://${opts.proxy.hostname}/api/3/get/${type}?${queryStrings.join( '&' @@ -52,9 +50,9 @@ export function generateProxyURL (type, data, opts) { /** * Generate the string that must be found in the proof to verify a claim - * @param {string} fingerprint - The fingerprint of the claim - * @param {string} format - The claim's format (see {@link module:enums~ClaimFormat|enums.ClaimFormat}) - * @returns {string} + * @param {string} fingerprint - The fingerprint of the claim + * @param {ClaimFormat} format - The claim's format (see {@link ClaimFormat}) + * @returns {string} Generate claim */ export function generateClaim (fingerprint, format) { switch (format) { @@ -72,8 +70,8 @@ export function generateClaim (fingerprint, format) { /** * Get the URIs from a string and return them as an array - * @param {string} text - The text that may contain URIs - * @returns {Array} + * @param {string} text - The text that may contain URIs + * @returns {Array} List of URIs extracted from input */ export function getUriFromString (text) { const re = /((([A-Za-z0-9]+:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www\.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w\-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[.!/\\\w]*))?)/gi diff --git a/src/verifications.js b/src/verifications.js index f7f329a..1103345 100644 --- a/src/verifications.js +++ b/src/verifications.js @@ -18,6 +18,7 @@ import { ClaimFormat, EntityEncodingFormat, ClaimRelation, ProofFormat } from '. import { bcryptVerify, argon2Verify } from 'hash-wasm' import { decodeHTML, decodeXML } from 'entities' import { ServiceProvider } from './serviceProvider.js' +import * as Types from './types.js' /** * @module verifications @@ -25,35 +26,11 @@ import { ServiceProvider } from './serviceProvider.js' */ /** - * Parameters needed to perform the proof verification - * @typedef {object} VerificationParams - * @property {string} target - * @property {ClaimFormat} claimFormat - * @property {EntityEncodingFormat} proofEncodingFormat - * @property {ClaimRelation} [claimRelation] - */ - -/** - * Result of the proof verification - * @typedef {Object} VerificationResult - * @property {boolean} result - * @property {boolean} completed - * @property {VerificationResultProof} [proof] - * @property {any[]} errors - */ - -/** - * Information about the proof in the proof verification result - * @typedef {Object} VerificationResultProof - * @property {string} fetcher - * @property {boolean} viaProxy - */ - -/** + * Check if string contains the proof * @function - * @param {string} data - * @param {VerificationParams} params - * @returns {Promise} + * @param {string} data - Data potentially containing the proof + * @param {Types.VerificationParams} params - Verification parameters + * @returns {Promise} Whether the proof was found in the string */ const containsProof = async (data, params) => { const fingerprintFormatted = generateClaim(params.target, params.claimFormat) @@ -237,11 +214,12 @@ const containsProof = async (data, params) => { } /** + * Run a JSON object through the verification process * @function - * @param {any} proofData - * @param {string[]} checkPath - * @param {VerificationParams} params - * @returns {Promise} + * @param {any} proofData - Data potentially containing the proof + * @param {string[]} checkPath - Paths to check for proof + * @param {Types.VerificationParams} params - Verification parameters + * @returns {Promise} Whether the proof was found in the object */ const runJSON = async (proofData, checkPath, params) => { if (!proofData) { @@ -288,15 +266,15 @@ const runJSON = async (proofData, checkPath, params) => { } /** - * Run the verification by finding the formatted fingerprint in the proof + * Run the verification by searching for the proof in the fetched data * @async - * @param {object} proofData - The proof data - * @param {ServiceProvider} claimData - The claim data - * @param {string} fingerprint - The fingerprint - * @returns {Promise} + * @param {object} proofData - The proof data + * @param {ServiceProvider} claimData - The claim data + * @param {string} fingerprint - The fingerprint + * @returns {Promise} Result of the verification */ export async function run (proofData, claimData, fingerprint) { - /** @type {VerificationResult} */ + /** @type {Types.VerificationResult} */ const res = { result: false, completed: false, diff --git a/test/openpgp.test.js b/test/openpgp.test.js index 6ac43fd..f2517e6 100644 --- a/test/openpgp.test.js +++ b/test/openpgp.test.js @@ -129,9 +129,9 @@ describe('openpgp.fetchURI', () => { }) describe('openpgp.fetchHKP', () => { - it('should be a function (2 arguments)', () => { + it('should be a function (1 required argument, 1 optional argument)', () => { expect(openpgp.fetchHKP).to.be.a('function') - expect(openpgp.fetchHKP).to.have.length(2) + expect(openpgp.fetchHKP).to.have.length(1) }) it('should return a Key object when provided a valid fingerprint', async () => { expect(await openpgp.fetchHKP(pubKeyFingerprint)).to.be.instanceOf(