2022-02-25 11:18:46 -07:00
/ *
Copyright ( C ) 2021 Yarmo Mackenbach
This program is free software : you can redistribute it and / or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation , either version 3 of the License , or ( at your option )
any later version .
This program is distributed in the hope that it will be useful , but WITHOUT
ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE . See the GNU Affero General Public License for more
details .
You should have received a copy of the GNU Affero General Public License along
with this program . If not , see < https : //www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail .
If your software can interact with users remotely through a computer network ,
you should also make sure that it provides a way for users to get its source .
For example , if your program is a web application , its interface could display
a "Source" link that leads users to an archive of the code . There are many
ways you could offer source , and different solutions will be better for different
programs ; see section 13 for the specific requirements .
You should also get your employer ( if you work as a programmer ) or school ,
if any , to sign a "copyright disclaimer" for the program , if necessary . For
more information on this , and how to apply and follow the GNU AGPL , see < https : //www.gnu.org/licenses/>.
* /
2022-02-27 14:59:17 -07:00
import * as doipjs from 'doipjs' ;
2022-02-25 11:18:46 -07:00
export class Claim extends HTMLElement {
// Specify the attributes to observe
static get observedAttributes ( ) {
return [ 'data-claim' ] ;
}
constructor ( ) {
// Call super
super ( ) ;
}
attributeChangedCallback ( name , oldValue , newValue ) {
this . updateContent ( newValue ) ;
}
async verify ( ) {
2023-09-21 07:30:35 -06:00
const claim = doipjs . Claim . fromJSON ( JSON . parse ( this . getAttribute ( 'data-claim' ) ) ) ;
2022-02-25 11:18:46 -07:00
await claim . verify ( {
proxy : {
policy : 'adaptive' ,
2023-06-11 22:41:33 -06:00
hostname : 'PLACEHOLDER__PROXY_HOSTNAME' ,
scheme : 'PLACEHOLDER__PROXY_SCHEME'
2022-02-25 11:18:46 -07:00
}
} ) ;
this . setAttribute ( 'data-claim' , JSON . stringify ( claim ) ) ;
}
updateContent ( value ) {
const root = this ;
2023-09-15 06:24:54 -06:00
const claimJson = JSON . parse ( value ) ;
2023-09-21 07:30:35 -06:00
const claim = doipjs . Claim . fromJSON ( claimJson ) ;
2023-07-13 03:11:16 -06:00
2023-09-15 06:24:54 -06:00
root . querySelector ( '.info .title' ) . innerText = claimJson . display . name ;
root . querySelector ( '.info .subtitle' ) . innerText = claimJson . display . serviceProviderName ? ?
( claim . status < 300 ? '???' : '---' ) ;
2023-09-25 08:12:20 -06:00
root . querySelector ( '.info img' ) . setAttribute ( 'src' , ` https://design.keyoxide.org/brands/service-providers/ ${ claimJson . display . serviceProviderName . toLowerCase ( ) || '_' } /icon.svg ` ) ;
2022-02-25 11:18:46 -07:00
try {
2023-07-13 03:11:16 -06:00
if ( claim . status >= 200 ) {
2023-09-15 06:24:54 -06:00
root . setAttribute ( 'data-status' , claim . status < 300 ? 'success' : 'failed' ) ;
2022-02-25 11:18:46 -07:00
} else {
2023-09-15 06:24:54 -06:00
root . setAttribute ( 'data-status' , 'running' ) ;
2022-02-25 11:18:46 -07:00
}
} catch ( error ) {
2023-09-15 06:24:54 -06:00
root . setAttribute ( 'data-status' , 'failed' ) ;
2022-02-25 11:18:46 -07:00
}
const elContent = root . querySelector ( '.content' ) ;
elContent . innerHTML = ` ` ;
// Handle failed ambiguous claim
2023-07-13 03:11:16 -06:00
if ( claim . status >= 300 && claim . isAmbiguous ( ) ) {
2022-02-25 11:18:46 -07:00
root . querySelector ( '.info .subtitle' ) . innerText = '---' ;
const subsection _alert = elContent . appendChild ( document . createElement ( 'div' ) ) ;
subsection _alert . setAttribute ( 'class' , 'subsection' ) ;
const subsection _alert _icon = subsection _alert . appendChild ( document . createElement ( 'img' ) ) ;
2023-03-05 04:07:03 -07:00
subsection _alert _icon . setAttribute ( 'src' , '/static/img/alert-decagram.svg' ) ;
2022-02-25 11:18:46 -07:00
subsection _alert _icon . setAttribute ( 'alt' , '' ) ;
subsection _alert _icon . setAttribute ( 'aria-hidden' , 'true' ) ;
const subsection _alert _text = subsection _alert . appendChild ( document . createElement ( 'div' ) ) ;
const message = subsection _alert _text . appendChild ( document . createElement ( 'p' ) ) ;
message . innerHTML = ` None of the matched service providers could be verified. Keyoxide was not able to determine which was the correct service provider or why the verification process failed. ` ;
return ;
}
// Links to profile and proof
const subsection _links = elContent . appendChild ( document . createElement ( 'div' ) ) ;
subsection _links . setAttribute ( 'class' , 'subsection' ) ;
const subsection _links _icon = subsection _links . appendChild ( document . createElement ( 'img' ) ) ;
2023-03-05 04:07:03 -07:00
subsection _links _icon . setAttribute ( 'src' , '/static/img/link.svg' ) ;
2022-02-25 11:18:46 -07:00
subsection _links _icon . setAttribute ( 'alt' , '' ) ;
subsection _links _icon . setAttribute ( 'aria-hidden' , 'true' ) ;
const subsection _links _text = subsection _links . appendChild ( document . createElement ( 'div' ) ) ;
const profile _link = subsection _links _text . appendChild ( document . createElement ( 'p' ) ) ;
if ( claim . matches [ 0 ] . profile . uri ) {
profile _link . innerHTML = ` Profile link: <a rel="me" href=" ${ claim . matches [ 0 ] . profile . uri } " aria-label="link to profile"> ${ claim . matches [ 0 ] . profile . uri } </a> ` ;
} else {
profile _link . innerHTML = ` Profile link: not accessible from browser ` ;
}
const proof _link = subsection _links _text . appendChild ( document . createElement ( 'p' ) ) ;
2023-07-13 03:11:16 -06:00
if ( claim . matches [ 0 ] . proof . request . uri ) {
proof _link . innerHTML = ` Proof link: <a href=" ${ claim . matches [ 0 ] . proof . request . uri } " aria-label="link to profile"> ${ claim . matches [ 0 ] . proof . request . uri } </a> ` ;
2022-02-25 11:18:46 -07:00
} else {
proof _link . innerHTML = ` Proof link: not accessible from browser ` ;
}
// QR Code
if ( claim . matches [ 0 ] . profile . qr ) {
elContent . appendChild ( document . createElement ( 'hr' ) ) ;
const subsection _qr = elContent . appendChild ( document . createElement ( 'div' ) ) ;
subsection _qr . setAttribute ( 'class' , 'subsection' ) ;
const subsection _qr _icon = subsection _qr . appendChild ( document . createElement ( 'img' ) ) ;
2023-03-05 04:07:03 -07:00
subsection _qr _icon . setAttribute ( 'src' , '/static/img/qrcode.svg' ) ;
2022-02-25 11:18:46 -07:00
subsection _qr _icon . setAttribute ( 'alt' , '' ) ;
subsection _qr _icon . setAttribute ( 'aria-hidden' , 'true' ) ;
const subsection _qr _text = subsection _qr . appendChild ( document . createElement ( 'div' ) ) ;
const button _profileQR = subsection _qr _text . appendChild ( document . createElement ( 'button' ) ) ;
button _profileQR . innerText = ` Show profile QR ` ;
button _profileQR . setAttribute ( 'onClick' , ` window.showQR(' ${ claim . matches [ 0 ] . profile . qr } ', 'url') ` ) ;
button _profileQR . setAttribute ( 'aria-label' , ` Show QR code linking to profile ` ) ;
}
elContent . appendChild ( document . createElement ( 'hr' ) ) ;
// Claim verification status
const subsection _status = elContent . appendChild ( document . createElement ( 'div' ) ) ;
subsection _status . setAttribute ( 'class' , 'subsection' ) ;
const subsection _status _icon = subsection _status . appendChild ( document . createElement ( 'img' ) ) ;
2023-03-05 04:07:03 -07:00
subsection _status _icon . setAttribute ( 'src' , '/static/img/decagram.svg' ) ;
2022-02-25 11:18:46 -07:00
subsection _status _icon . setAttribute ( 'alt' , '' ) ;
subsection _status _icon . setAttribute ( 'aria-hidden' , 'true' ) ;
const subsection _status _text = subsection _status . appendChild ( document . createElement ( 'div' ) ) ;
const verification = subsection _status _text . appendChild ( document . createElement ( 'p' ) ) ;
2023-07-13 03:11:16 -06:00
if ( claim . status >= 200 ) {
2022-02-25 11:18:46 -07:00
verification . innerHTML = ` Claim verification has completed. ` ;
2023-03-05 04:07:03 -07:00
subsection _status _icon . setAttribute ( 'src' , '/static/img/check-decagram.svg' ) ;
2022-02-25 11:18:46 -07:00
subsection _status _icon . setAttribute ( 'alt' , '' ) ;
subsection _status _icon . setAttribute ( 'aria-hidden' , 'true' ) ;
} else {
verification . innerHTML = ` Claim verification is in progress… ` ;
return ;
}
elContent . appendChild ( document . createElement ( 'hr' ) ) ;
// Result of claim verification
const subsection _result = elContent . appendChild ( document . createElement ( 'div' ) ) ;
subsection _result . setAttribute ( 'class' , 'subsection' ) ;
const subsection _result _icon = subsection _result . appendChild ( document . createElement ( 'img' ) ) ;
2023-03-05 04:07:03 -07:00
subsection _result _icon . setAttribute ( 'src' , '/static/img/shield-search.svg' ) ;
2022-02-25 11:18:46 -07:00
subsection _result _icon . setAttribute ( 'alt' , '' ) ;
subsection _result _icon . setAttribute ( 'aria-hidden' , 'true' ) ;
const subsection _result _text = subsection _result . appendChild ( document . createElement ( 'div' ) ) ;
const result = subsection _result _text . appendChild ( document . createElement ( 'p' ) ) ;
2023-07-13 03:11:16 -06:00
result . innerHTML = ` The claim <strong> ${ claim . status >= 200 && claim . status < 300 ? 'HAS BEEN' : 'COULD NOT BE' } </strong> verified by the proof. ` ;
2022-02-25 11:18:46 -07:00
// Additional info
2023-07-13 03:11:16 -06:00
if ( claim . status === 201 ) {
2022-02-25 11:18:46 -07:00
elContent . appendChild ( document . createElement ( 'hr' ) ) ;
const subsection _info = elContent . appendChild ( document . createElement ( 'div' ) ) ;
subsection _info . setAttribute ( 'class' , 'subsection' ) ;
const subsection _info _icon = subsection _info . appendChild ( document . createElement ( 'img' ) ) ;
2023-03-05 04:07:03 -07:00
subsection _info _icon . setAttribute ( 'src' , '/static/img/information.svg' ) ;
2022-02-25 11:18:46 -07:00
subsection _info _icon . setAttribute ( 'alt' , '' ) ;
subsection _info _icon . setAttribute ( 'aria-hidden' , 'true' ) ;
const subsection _info _text = subsection _info . appendChild ( document . createElement ( 'div' ) ) ;
const result _proxyUsed = subsection _info _text . appendChild ( document . createElement ( 'p' ) ) ;
2023-06-11 22:41:33 -06:00
result _proxyUsed . innerHTML = ` A proxy was used to fetch the proof: <a href="PLACEHOLDER__PROXY_SCHEME://PLACEHOLDER__PROXY_HOSTNAME" aria-label="Link to proxy server">PLACEHOLDER__PROXY_HOSTNAME</a> ` ;
2022-02-25 11:18:46 -07:00
}
// TODO Display errors
// if (claim.verification.errors.length > 0) {
// console.log(claim.verification);
// elContent.appendChild(document.createElement('hr'));
// const subsection_errors = elContent.appendChild(document.createElement('div'));
// subsection_errors.setAttribute('class', 'subsection');
// const subsection_errors_icon = subsection_errors.appendChild(document.createElement('img'));
2023-03-05 04:07:03 -07:00
// subsection_errors_icon.setAttribute('src', '/static/img/alert-circle.svg');
2022-02-25 11:18:46 -07:00
// const subsection_errors_text = subsection_errors.appendChild(document.createElement('div'));
// claim.verification.errors.forEach(message => {
// const error = subsection_errors_text.appendChild(document.createElement('p'));
// if (message instanceof Error) {
// error.innerText = message.message;
// } else {
// error.innerText = message;
// }
// });
// }
}
2023-06-11 22:41:33 -06:00
}