Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 130x 130x 194x 109x 2x 1x 1x 127x 127x 1x 72x 55x 19x 184x 1x 56x 53x 19x 34x 34x 53x 1x 129x 2x 2x 1x 126x | import { request } from '@blockcerts/explorer-lookup';
import { VerifierError } from '../../../models';
import { getText } from '../../i18n/useCases';
import type { Issuer } from '../../../models/Issuer';
import domain from '../../../domain';
import type { IDidDocument } from '../../../models/DidDocument';
// TODO: move these functions to url helper
function isValidUrl (url: string): boolean {
// https://stackoverflow.com/a/15734347/4064775
const regex = /^(ftp|http|https):\/\/[^ "]+$/;
return regex.test(url);
}
export function isDidUri (url: string): boolean {
return url.startsWith('did:', 0);
}
export function isDidKey (url: string): boolean {
return url.startsWith('did:key:', 0);
}
function isValidV1Profile (profile: Issuer): boolean {
const { issuer_key, revocation_key, issuerKeys, revocationKeys } = profile;
if (!!issuer_key && !!revocation_key) {
// https://github.com/blockchain-certificates/cert-schema/blob/master/cert_schema/1.1/issuer-schema-v1-1.json
return true;
}
if (issuerKeys && revocationKeys) {
// https://github.com/blockchain-certificates/cert-schema/blob/master/cert_schema/1.2/issuer-id-1.2.json
return true;
}
return false;
}
function isValidProfile (profile: Issuer): boolean {
const validTypes: string[] = ['issuer', 'profile', 'blockcertsissuerprofile']; // https://w3id.org/openbadges#Profile
const { type } = profile;
if (!type) {
return false;
}
if (Array.isArray(type)) {
return type.some(type => validTypes.includes(type.toLowerCase()));
}
return validTypes.includes(type.toLowerCase());
}
function createIssuerProfileFromDidKey (didDocument: IDidDocument): Issuer {
return {
'@context': [
'https://w3id.org/openbadges/v2',
'https://w3id.org/blockcerts/3.0'
],
publicKey: [
{
created: new Date().toISOString(),
id: didDocument.id.split(':').pop()
}
]
};
}
export default async function getIssuerProfile (issuerAddress: Issuer | string): Promise<Issuer> {
const errorMessage = getText('errors', 'getIssuerProfile');
if (!issuerAddress) {
throw new VerifierError('getIssuerProfile', `${errorMessage} - ${getText('errors', 'issuerProfileNotSet')}`);
}
if (typeof issuerAddress === 'object') {
issuerAddress = issuerAddress.id;
}
let issuerProfile: Issuer;
if (isDidUri(issuerAddress)) {
// TODO: it could be that the issuer profile is embedded, or that it is distant,
// but we found a did document so the rest of the function does not apply
try {
const didDocument: IDidDocument = await domain.did.resolve(issuerAddress);
if (isDidKey(issuerAddress)) {
issuerProfile = createIssuerProfileFromDidKey(didDocument);
} else {
const issuerProfileUrl = domain.did.getIssuerProfileUrl(didDocument);
if (issuerProfileUrl) {
issuerProfile = await getIssuerProfile(issuerProfileUrl);
}
}
return {
didDocument,
...issuerProfile
};
} catch (e) {
console.error(e);
throw new VerifierError('getIssuerProfile', `${errorMessage} - ${e as string}`);
}
} else if (!isValidUrl(issuerAddress)) {
throw new VerifierError('getIssuerProfile', `${errorMessage} - ${getText('errors', 'issuerProfileNotSet')}`);
}
issuerProfile = JSON.parse(await request({ url: issuerAddress }).catch((error) => {
console.error(error);
throw new VerifierError('getIssuerProfile', errorMessage);
}));
if (!isValidProfile(issuerProfile) && !isValidV1Profile(issuerProfile)) {
throw new VerifierError('getIssuerProfile', `${errorMessage} - ${getText('errors', 'issuerProfileInvalid')}`);
}
return issuerProfile;
}
|