const express = require("express"); const fs = require("fs-extra"); const dayjs=require('dayjs'); const path = require("path"); // Classes const Pagans = require("../models/Pagans.js"); const Odmdb = require("../models/Odmdb.js"); // Middlewares const checkHeaders = require("../middlewares/checkHeaders.js"); const isAuthenticated = require("../middlewares/isAuthenticated.js"); const conf = require(`../../../conf.json`); const currentmod = "pagans"; const log = conf.api.activelog.includes(currentmod); const router = express.Router(); /** * /api/models/Pagans.js * * Managed: /** * Alias exist then return public key or not * @api {get} adminapi/pagans/alias/:alias - alias Get * @apiName isalias * @apiGroup Pagans * @apiDescription If alias exist return its publickey * * @param {string} alias * * @apiError {json} aliasdoesnotexist * @apiErrorExample {json} * HTTP/1.1 404 Not Found {"status":404,"ref":"pagans","msg":"aliasdoesnotexist","data": { alias}} * * @apiSuccess {object} indexfile content * @apiSuccessExample {json} Success-Response: * HTTP/1.1 200 OK * {"status":200, ref:"pagans","msg":"aliasexist","data": { alias, publicKey }} * * **/ router.get("/alias/:alias", (req, res) => { const getalias = Pagans.getalias(req.params.alias); res.status(getalias.status).send(getalias); }); /** * @api {get} adminapi/pagans/logout - pagan Logout * @apiName Removetoken * @apiGroup Pagans * @apiDescription Remove server's token only the owner of the token (no one else can delete a token ) * * @apiSuccess {object} indexfile content * @apiSuccessExample {json} Success-Response: * HTTP/1.1 200 OK * {status: 200, ref: "Pagans", msg: "logout" * */ router.get("/logout", checkHeaders, isAuthenticated, (req, res) => { if (log) console.log(currentmod,"Logout:",req.session.header); const logout = Pagans.logout( req.session.header.xalias, req.session.header.xtribe, req.session.header.xdays, req.session.header.xhash ); res.status(logout.status).json(logout); }); /** * @api {get} adminapi/pagans/isauth - pagan isAuthenticated? * @apiName isAuth * @apiGroup Pagans * @apiDescription Check if pagan's token is still valid * * @apiError (400) missingheaders * @apiError (400) xaliasdoesnotexist * @apiError (400) signaturefailled * @apiError (401) aliasanonymous * @apiError (404) tribedoesnotexist * * @apiSuccess (200) valid * {object} data contains indexfile requested * */ router.get("/isauth", checkHeaders, isAuthenticated, (req, res) => { res.status(200).send({ status: 200, ref: "headers", msg: "authenticated", data: { xalias: req.session.header.xalias, xprofils: req.session.header.xprofils, }, }); }); // @a pi Body {object} schema:pagans /nationchains/schema/pagans.json /** * @api {post} adminapi/pagans - pagan Post * @apiName addpagan * @apiGroup Pagans * @apiDescription * Create a pagan account from alias, publickey, if trusted recovery => * If trustedtribe is true then create a person in xtribe/person/xalias.json with profil.auth={email,privatekey, passphrase}. * * Middleware isAuthenticated check that: * - xhash is well signed from private key linked to the publickey of alias * - check that alias does not already exist (if yes then verifiedsigne would be false) * Need to wait next block chain to be sure that alias is register in the blokchain * @apiBody {string} alias available (that does not already exist check get /api/alias/:alias that must return 404). * @apiBody {string} publickey * @apiBody {string} [email] if specified then an email is sent to it with public and privatekey * @apiBody {string} [privatekey] * @apiBody {string} [passphrase] if not specidied => passphrase="" * @apiBody {string} [trustedtribe] the tribename if not specified then the process will only create a pagan identity, else an item person is create for trustedtribe (that must exist with profil 'person'). To create a person with an existing pagan identity use put /api/person/:alias after authenticated you (headers). In case a person is created then we use all valid other apiBody respecting the persons schema (see put persons) * * @apiError {json} objectNotfound the file does not exist * @apiErrorExample {json} * HTTP/1.1 404 Not Found {"status":404,"ref":"Odmdb","msg":"pathnamedoesnotexist","data":{indexpath}} * * @apiSuccess {object} indexfile content * @apiSuccessExample {json} Success-Response: * HTTP/1.1 200 OK * {"status":200, "ref":"Odmdb", "msg":"indexexist", "data":{indexname,content:{index file}} * */ router.post("/", checkHeaders, isAuthenticated, async (req, res) => { if (log) console.log(currentmod,"post with", req.body); const role = { xalias: req.session.header.xalias, xprofils: req.session.header.xprofils, }; const emailregex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; if (!(req.body.trustedtribe && req.body.email && emailregex.test(req.body.email) )) { res.status(400).json({status:400,ref:"Pagans",msg:"emailerr", data:{email:req.body.email}}) return } const objpagan = { alias: req.body.alias, publickey: req.body.publickey }; console.log(path.resolve(`../objects/pagans`)) const newpagan = Odmdb.cud(`../objects/pagans`, "C", objpagan, role); const createprocess={status:200, ref:"Pagans", msg:"successfulcreate",data:{alias:req.body.alias}}; if (newpagan.status == 200) { if (req.body.email) { const emailsent = await Pagans.sendmailkey({ alias: req.body.alias, privatekey: req.body.privatekey, tribe: req.session.header.xtribe, passprhase: req.body.passphrase, publickey: req.body.publickey, email: req.body.email, lg: req.session.header.xlang } ); createprocess.data.emailsent = (emailsent.status == 200); createprocess.data.email=req.body.email createprocess.data.tribe=req.session.header.xtribe; if (emailsent.status!=200) { console.log("pagans err to send email emailsent: ",emailsent) createprocess.data.emailerror = emailsent.data.err; } } if (req.body.trustedtribe) { const persondata = { alias: req.body.alias, owner: req.body.alias, profils: ["pagans", "persons"], recoveryauth: { email: req.body.email, privatekey: req.body.privatekey, publickey: req.body.publickey, passphrase: req.body.passphrase, }, }; const personup = Odmdb.cud(`../../${req.body.trustedtribe}/objects/persons`, "C", persondata, {xprofils:["pagan"],xalias:req.body.alias}); if (log) console.log(currentmod,'person create',personup) if (personup.status==200){ createprocess.data.createperson=true; }else{ createprocess.data.createperson=false; createprocess.data.errorperson=true; createprocess.data.errpersonup=personup.data; if (log) console.log(currentmod,"Warning pagan created but person not created and no recovery registration", personup); } res.status(createprocess.status).json(createprocess); }else{ res.status(newpagan.status).json(newpagan); } } else { //error to create pagan certaily already exist res.status(newpagan.status).json(newpagan); } }); /** * @api {delete} adminapi/pagans/alias/:alias - pagan Delete * @apiName deletepagan * @apiGroup Pagans * @apiDescription * Delete an alias and his publickey, this mean that publickey disapear as well as alias. We set dt_delete * */ router.delete("/alias/:alias", checkHeaders, isAuthenticated, (req, res) => { const personpath=`../objects/pagans`; const role = { xalias: req.session.header.xalias, xprofils: req.session.header.xprofils, }; req.session.header.role const delperson = Odmdb.cud(personpath,"U",{alias:req.params.alias,dt_delete:dayjs().toISOString()},role,true); if (log) console.log(currentmod,`DELETE person ${personpath}/${req.params.alias}.json `); if (log) console.log(delperson) res.status(delperson.status).json(delperson); if (log) console.log(`DELETE pagans adminapi/objects/pagans/${req.params.alias}.json`); const result = Pagans.delete(req.params.alias, req.session.header); res.status(result.status).send(result); }); /** * @api {delete} adminapi/pagans/person/:tribe/:alias - person Delete * @apiName deleteperson * @apiGroup Pagans * @apiDescription * Unsubscribe a person to a tribe => remove a person item and all data link to this alias. An asynchrone process turn each day to clean data in tribe, if a persons does not exist anymore in the tribe. Pagans alias is still existing as it is autonomous. It is possible to delete pagans see "pagan Delete". * @apiHeader {array} xprofils list of profil of authenticated user * @apiHeader {string} xalias current user * @apiParam {string} tribe where person alias exist * @apiParam {string} alias to delete as person * */ router.delete("/person/:tribe/:alias", checkHeaders, isAuthenticated, (req, res) => { const personpath=`../../${req.params.tribe}/objects/persons`; const role = { xalias: req.session.header.xalias, xprofils: req.session.header.xprofils, }; req.session.header.role const delperson = Odmdb.cud(personpath,"D",{alias:req.params.alias},role,true); if (log) console.log(currentmod,`DELETE person ${personpath}/${req.params.alias}.json `); if (log) console.log(currentmod,"delete person ",delperson) res.status(delperson.status).json(delperson); }); /** * @api {get} adminapi/pagans/person/:alias - person Get * @apiName getpersondata * @apiDescription Get person information from his alias for a xtribe (data and profils per apps) * @apiGroup Pagans * * @apiParam {string} alias * * @apiSuccess (200) personExist * @apiSuccessExample {json} * {status:200, ref:"pagans",msg:"personexist",data: { person } } * * @apiError (404) Notfound * @apiErrorExample {json} * {status: 404, ref:"pagans",msg:"persondoesnotexist",data: { person } } * * @todo check accessright for req.session.header.xalias to see if jhe can get person data * if req.param.alias == req.session.header.xalias => Owner * else need accessright to on person set at R * */ router.get("/person/:alias", checkHeaders, isAuthenticated, (req, res) => { console.log(path.resolve(`../../${req.session.header.xtribe}/objects/persons`)) const getperson=Odmdb.r( `../../${req.session.header.xtribe}/objects/persons`,req.params.alias,{ xprofils: req.session.header.xprofils, xalias: req.session.header.xalias }) res.status(getperson.status).send(getperson); }); /** * @api {put} adminapi/pagans/person/:tribe - person Put * @apiName updateperson * @apiGroup Pagans * @apiDescription add or update a person = alias in tribe. xalias authenticated (in header) must have a profil with accessright into schema person to create a person. * @apiHeader {string} xhash authenthicate hash with current user keys * @apiHeader {string} xalias current user * @apiHeader {string} xprofils profil list * @apiParam {object} schema:persons https://dnstribe/tribe/schema/persons.json * */ router.put("/person/:tribe", checkHeaders, isAuthenticated, (req, res) => { //console.log(req.body); const pathobj=`../../${req.params.tribe}/objects/persons`; const action = (fs.existsSync(`${pathobj}/itm/${req.body.alias}.json`))? "U":"C"; //set req.body to be in line with schema if (!req.body.profils){ req.body.profils=["anonymous","pagans","persons"] } const personup = Odmdb.cud(pathobj, action, req.body, {xprofils:req.session.header.xprofils, xalias:req.session.header.xalias}); if (log) console.log(currentmod,' personupdate or create:',personup) res.status(personup.status).json(personup); }); /** * @api {post} adminapi/pagans/keyrecovery - recovery keys * @apiName recoveryKey * @apiGroup Pagans * @apiDescription Send mails with all registers identities (one per alias where recoveryauth.email is register). Search can be request by email or by alias for a tribe. It is looking for in person.recoveryauth.email to send keys. One mail is sent by alias. So if n alias has the same recoveryaut.email then it will send n email. * @apiBody {string} emailalias type of search (email or alias) * @apiBody {string} tribe tribename into looking for * @apiBody {string} search an email or an alias * * @apiSuccess {object} send recovery email * @apiSuccessExample {json} Success-Response: * HTTP/1.1 200 OK * {"status":200, "ref":"Pagans", "msg":"recoveryemailsent", "data":{email,tribe,numberemailsent'}} * * @apiError (404) {string} recoveryemailnotfound email does not exist for this tribe * @apiErrorExample {json} * {status: 404, ref:"pagans",msg:"recoveryemailnotfound",data: { tribe,email } } * */ router.post("/keyrecovery", checkHeaders, (req, res) => { let emailist=[] let alias =req.body.search; if (req.body.emailalias=="email"){ req.body.search=req.body.search.toLowerCase(); const idxreco=`../../${req.body.tribe}/objects/persons/idx/emailrecovery_alias.json`; if (fs.existsSync(idxreco)){ const emailreco = fs.readJSONSync(idxreco); const listalias = (emailreco[req.body.search])? emailreco[req.body.search]: []; listalias.forEach(a=>{ emailist.push({alias:a,tribe:req.body.tribe,lg:req.session.header.xlang}) }) } }else if (req.body.emailalias=="alias"){ const falias= `../../${req.body.tribe}/objects/persons/itm/${req.body.search}.json`; if (fs.existsSync(falias)){ emailist.push({alias:req.body.search,tribe:req.body.tribe,lg:req.session.header.xlang}) } }else{ //console later } emailist.forEach(e => { console.log(e) const ret= Pagans.sendmailkey(e) }) if (emailist.length>0) { res.status(200).json({status:200,ref:"Pagans",msg:"recoveryemailsent",data:{numberemailsent:emailist.length}}); }else{ res.status(404).json({status:404,ref:"Pagans",msg:"recoveryemailnotfound",data:{tribe:req.body.tribe}}); } }); module.exports = router;