const glob = require("glob"); const path = require("path"); const dayjs = require("dayjs"); const fs = require("fs-extra"); const axios = require("axios"); const Mustache = require("mustache"); const openpgp = require("openpgp"); const Notifications = require("./Notifications.js"); const Odmdb = require("./Odmdb.js"); const conf = require(`../../../conf.json`); const currentmod = "Pagans"; const log = conf.api.activelog.includes(currentmod); /** * Pagan Management numeric Identity and Person (Person = Pagan Id + tribe) * * * */ const Pagans = {}; /** * Remove authentification token after a logout * @param {string} alias * @param {string} tribe * @param {integer} xdays * @param {string} xhash * @returns {status:200, ref:"Pagans",msg:"logout"} * tmpfs name file has to be on line with the tmpfs create by isAuthenticated * tmpfs contain profils name for a tribe/ */ Pagans.logout = (alias, tribe, xdays, xhash) => { //console.log(alias, tribe, xdays, xhash); // inline with middleware isAuthenticated.js let tmpfs = `../../tmp/tokens/${alias}_${tribe}_${xdays}`; //max filename in ext4: 255 characters tmpfs += `_${xhash.substring(150, 150 + tmpfs.length - 249)}.json`; fs.remove(tmpfs); if (log) console.log(currentmod, "logout token", tmpfs); return { status: 200, ref: "Pagans", msg: "logout" }; }; /** * @param {string} alias a alias that exist or not * @return {object} { status: 200, ref:"pagans",msg:"aliasexist",data: { alias, publicKey } } * { status: 404, ref:"pagans",msg:"aliasdoesnotexist",data: { alias} } * **/ Pagans.getalias = (alias) => { //bypass Odmdb cause all is public save ressources console.log(path.resolve(`../objects/pagans/itm/${alias}.json`)); if (fs.existsSync(`../objects/pagans/itm/${alias}.json`)) { return { status: 200, ref: "Pagans", msg: "aliasexist", data: fs.readJSONSync(`../objects/pagans/itm/${alias}.json`), }; } else { return { status: 404, ref: "Pagans", msg: "aliasdoesnotexist", data: { alias }, }; } }; /** * Send email with alias's keys to email or person alias person.recovery.email * * If email or pubkey is undefined then get data from tribe/person(alias) * Send email with keys * @param {object} data * @param {string} data.alias * @param {pgpPrivate} [data.privatekey] * @param {string} [data.passphrase] * @param {string} data.tribe * @param {pgpPublic} [data.publickey] * @param {string} [data.email] * @param {string} data.lg */ Pagans.sendmailkey = (data) => { if (log) console.log( currentmod, data.alias, "-", data.privatekey ? data.privatekey.substring(0, 10) : "", "-", data.tribe, "-", data.passphrase, "-", data.publickey ? data.publickey.substring(0, 10) : "", "-", data.email, "-", data.lg ); const person = { alias: data.alias, privatekey: data.privatekey, tribe: data.tribe, }; if (!data.publickey || !data.email || !data.privatekey) { const personfile = `../../${data.tribe}/objects/persons/itm/${data.alias}.json`; if (!fs.existsSync(personfile)) { return { status: 404, ref: "Pagans", msg: "persondoesnotexist", data: { alias: data.alias, tribe: data.tribe }, }; } const persondata = fs.readJsonSync(personfile); if (!persondata.recoveryauth) { return { status: 404, ref: "Pagans", msg: "personhasnorecoveryauth", data: { alias: data.alias, tribe: data.tribe, email: data.email }, }; } person.email = persondata.recoveryauth.email; person.publickey = persondata.recoveryauth.publickey; person.privatekey = persondata.recoveryauth.privatekey; person.passphrase = persondata.recoveryauth.passphrase; } else { person.email = data.email; person.passphrase = data.passphrase; person.publickey = data.publickey; } person.avecpassphrase = person.passphrase != ""; let tplfile = `../../${data.tribe}/template/createidentity_${data.lg}.js`; if (!fs.existsSync(tplfile)) { tplfile = `../template/createidentity_${data.lg}.js`; if (!fs.existsSync(tplfile)) { return { status: 406, ref: "Pagans", msg: "templatedoesnotexist", data: { tplfile }, }; } } const tplemail = require(path.resolve(tplfile)); /* Remove from attachments for less user confusing { filename:`${person.alias}_publickey.txt`, content: person.publickey, contentType:"text/plain" }, */ const maildata = { from: tplemail.sender, to: person.email, subject: Mustache.render(tplemail.subject, person), html: Mustache.render(tplemail.html, person), text: Mustache.render(tplemail.text, person), attachments: [ { filename: `${person.alias}_privatekey.txt`, content: person.privatekey, contentType: "text/plain", }, ], }; return Notifications.sendmail(maildata, data.tribe); }; Pagans.authenticatedetachedSignature = async ( alias, pubK, detachedSignature, message ) => { /** * Check that a message was signed with a privateKey from a publicKey * This is not necessary if isAuthenticated, but can be usefull to double check * @TODO finish it and implement it also in /apxpagan.js for browser * @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, verificationKeys: publicKey, }); const { verified, keyID } = verificationResult.signatures[0]; try { await verified; // throws on invalid signature if (log) console.log(currentmod, "Signed by key id " + keyID.toHex()); return KeyId.toHex().alias == alias; } catch (e) { if (log) console.log(currentmod, "Signature could not be verified: " + e.message); return false; } }; module.exports = Pagans;