2023-04-27 06:17:20 +02:00
/*eslint no-undef:0*/
/*eslint-env browser*/
"use strict" ;
var apx = apx || { } ;
/ * *
* Js lib to interact with apxtrib backend
*
* html page must have apxlocal with at least headers key
* < script >
const apxlocal = {
headers : { xalias : "" , xhash : "" , xtribe : "smatchit" , xapp : "smatchapp" , xlang : "en" } ,
firstimeload : true ,
forceload : true ,
tpl : {
footer : "{{{msg}}}"
} ,
tpldata : {
footer : { msg : "<p>Made with love for people freedom, enjoy!</p>" }
} ,
objects : { }
} ;
* apx . generateKey ( params ) create a public / private key compatible with apXtrib backend and store it in apx . data
* apx . detachedSignature ( params ) generate a detachedSignature for a Message that backend can check with the publicKey of the alias
* apx . checkdetachedSignature ( params ) check a detachedSignature for a Message ( used on the backend as well )
* apx . ready ( callback ) equivalent of jquery Document . ready ( )
* apx . save ( ) save apx . data as xapp value in localStorage
* apx . update ( ) get localStorage up to date
* apx . loadfile ( { url : name } , dest , axiosoptions ) async that wait to load a list of relativ url and store it in a apx . data [ dest ]
* /
apx . generateKey = async ( alias , passphrase ) => {
/ * *
* @ param { string } alias a unique alias that identify an identity
* @ param { string } passphrase a string to cipher the publicKey ( can be empty , less secure but simpler )
* @ return { publicKey , privateKey } with userIds = [ { alias } ]
* /
const { privateKey , publicKey } = await openpgp . generateKey ( {
type : "ecc" , // Type of the key, defaults to ECC
curve : "curve25519" , // ECC curve name, defaults to curve25519
userIDs : [ { alias : alias } ] , // you can pass multiple user IDs
passphrase : passphrase , // protects the private key
format : "armored" , // output key format, defaults to 'armored' (other options: 'binary' or 'object')
} ) ;
// key start by '-----BEGIN PGP PRIVATE KEY BLOCK ... '
// get liste of alias:pubklickey await axios.get('api/v0/pagans')
// check alias does not exist
return { alias , privateKey , publicKey } ;
/ * d o c u m e n t . g e t E l e m e n t B y I d ( ' p r i v a t e k e y ' ) . i n n e r H T M L = p r i v a t e K e y ;
document . getElementById ( 'publickey' ) . innerHTML = publicKey ;
apx . data . pagans = { }
apx . data . pagans . privateKey = privateKey ;
apx . data . pagans . publicKey = publicKey ;
apx . save ( ) ;
console . log ( apx . data )
* /
} ;
apx . detachedSignature = async ( pubK , privK , passphrase , message ) => {
/ * *
* @ pubK { string } a text public key
* @ privK { string } a test priv key
* @ passphrase { string } used to read privK
* @ message { string } message to sign
* @ Return a detached Signature of the message
* /
const publicKey = await openpgp . readKey ( { armoredKey : pubK } ) ;
const privateKey = await openpgp . decryptKey ( {
privateKey : await openpgp . readPrivateKey ( { armoredKey : privK } ) ,
passphrase ,
} ) ;
const msg = await openpgp . createMessage ( { text : message } ) ;
return await openpgp . sign ( { msg , signinKeys : privK , detached : true } ) ;
} ;
apx . checkdetachedSignature = async (
alias ,
pubK ,
detachedSignature ,
message
) => {
/ * *
* @ alias { string } alias link to the publicKey
* @ pubK { string } publiKey text format
* @ detachedSignature { string } a detachedsignatured get from apx . detachedSignature
* @ message { string } the message signed
* @ return { boolean } true the message was signed by alias
* false the message was not signed by alias
* /
const publicKey = await openpgp . readKey ( { armoredKey : pubK } ) ;
const msg = await openpgp . createMessage ( { text : message } ) ;
const signature = await openpgp . readSignature ( {
armoredSignature : detachedSignature , // parse detached signature
} ) ;
const verificationResult = await openpgp . verify ( {
msg , // Message object
signature ,
2023-04-28 13:21:02 +02:00
verificationKeys : publicKey
2023-04-27 06:17:20 +02:00
} ) ;
const { verified , keyID } = verificationResult . signatures [ 0 ] ;
try {
await verified ; // throws on invalid signature
console . log ( "Signed by key id " + keyID . toHex ( ) ) ;
return KeyId . toHex ( ) . alias == alias ;
} catch ( e ) {
console . log ( "Signature could not be verified: " + e . message ) ;
return false ;
}
} ;
apx . ready = ( callback ) => {
/ * *
* Wait loading DOM , when ready run callback function
* /
if ( ! callback ) {
alert (
"You have an unknown callback pwa.state.ready(callback), you need to order your code callback = ()=>{} then pwa.state.ready(callback), boring but js rules ;-)"
) ;
}
if ( document . readyState != "loading" ) callback ( ) ;
// modern browsers
else if ( document . addEventListener )
document . addEventListener ( "DOMContentLoaded" , callback ) ;
// IE <= 8
else
document . attachEvent ( "onreadystatechange" , function ( ) {
if ( document . readyState == "complete" ) callback ( ) ;
} ) ;
} ;
apx . loadfile = async ( list , dest , axiosoptions ) => {
/ * *
* Load external file as tpl , tpldata ( temmplate and data ) , objects index of object
* @ param { object } list { name : url } it will run as promise all the requested url
* @ param { string } dest where to store it in apx . data ( tpl , tpldata , objectname , ... )
* @ param { object } axiosoptions alow to add headers any option to axios
* @ return { object } load into apx . data [ dest ] = { name : { object } } and localStorage . xapp [ dest ] = { name : { object } }
*
* @ example < caption > Load into apx . data . tpl . blocncol = "string" < / c a p t i o n >
* apx . loadfile ( { blocncol : "static/tpl/blocncol.mustache" } , "tpl" , { headers : apx . data . header } )
*
* /
const invertlist = { } ;
Object . keys ( list ) . forEach ( ( n ) => {
invertlist [ list [ n ] ] = n ;
} ) ;
//console.log( 'invertlist', invertlist )
if (
apx . data . forcereload ||
! apx . data [ dest ] ||
Object . keys ( apx . data [ dest ] ) . length == 0
) {
if ( ! apx . data [ dest ] ) apx . data [ dest ] = { } ;
const fetchURL = ( r , options ) => {
return axios . get ( r , options ) ;
} ;
const urls = Object . keys ( invertlist ) ;
if ( ! axiosoptions ) {
axiosoptions = { headers : apx . data . headers } ;
}
console . log ( 'axiosiptions' , axiosoptions )
const promiseArray = urls . map ( ( r ) => fetchURL ( r , axiosoptions ) ) ;
await Promise . all ( promiseArray )
. then ( ( data ) => {
console . log ( data )
for ( let pos = 0 ; pos < urls . length ; pos ++ ) {
//console.log( 'url', urls[ pos ] )
//console.log( data[ pos ] );
apx . data [ dest ] [ invertlist [ urls [ pos ] ] ] = data [ pos ] . data ;
console . log (
` store apx.data[ ${ dest } ][ invertlist[ ${ urls [ pos ] } ] ] `
) ;
apx . save ( ) ;
}
} )
. catch ( ( err ) => {
console . log ( "erreur de loading" , err ) ;
} ) ;
}
} ;
apx . save = ( ) => {
localStorage . setItem ( apx . data . headers . xapp , JSON . stringify ( apx . data ) ) ;
} ;
apx . update = async ( ) => {
if ( ! apxlocal ) {
console . log (
'Please add to the html page header, this line <script> const apxlocal={headers:{xalias:"",xhash:"",xtribe:"smatchit", xapp:"smatchapp", xlang:"en" }};</script> '
) ;
return ;
}
if ( document . querySelector ( "html" ) . getAttribute ( "lang" ) ) {
apxlocal . headers . xlang = document
. querySelector ( "html" )
. getAttribute ( "lang" ) ;
}
if ( localStorage . getItem ( apxlocal . headers . xapp ) ) {
apx . data = JSON . parse ( localStorage . getItem ( apxlocal . headers . xapp ) ) ;
if ( apx . data . headers . xtribe != apxlocal . headers . xtribe ) {
// if an app change of tribe
localStorage . removeItem ( apxlocal . headers . xapp ) ;
delete apx . data ;
}
}
if ( ! apx . data ) {
apx . data = apxlocal ;
}
console . log ( "apx.data" , apx . data ) ;
apx . save ( ) ;
} ;
apx . ready ( apx . update ) ;