const express = require("express"); const path = require("path"); // Classes const Pagans = require("../models/Pagans.js"); const Notifications = require("../models/Notifications.js"); // Middlewares const checkHeaders = require("../middlewares/checkHeaders"); const isAuthenticated = require("../middlewares/isAuthenticated"); const hasAccessrighton = require("../middlewares/hasAccessrighton"); const router = express.Router(); /* models/Pagans.js Managed: /data/tribee/client-Id/users/uuid.json /searchindex/emails.json {email:uuid} /login.json {login:uuid} /uids.json {uuid;[[ login, email, encrypted psw, accessrights]} ACCESSRIGHTS = { app:{"tribeid:appname":"profil"}, data:{"tribeid":{object:"CRUDO"}} } ACCESSRIGHTS is store into the token and is load into req.session.header.accessrights by hasAccessrighton() middleware appname is a website space object /sitewebsrc/appname website live is strored into /dist source in /src This can be managed by maildigitcreator or not. apxtrib/sitewebs/webapp is the webinterface of apxtrib profil: admin / manager / user are key word to give specific access to data into model. Any kind of other profil can exist. It is usefull to manage specific menu in an app. It is also possible to authorize update a field's object depending of rule into dataManagement/object/ { field:X nouserupdate: "!(['admin','manager'].includes(contexte.profil))", } data allow a user to access tribeid with Create Read Update Delete Own (CRUDO) on each object of a tribeid independantly of any app. Create allow to create a new object respecting rules defined into /referentials/dataManagement/object/name.json Update idem Delete idem Owner means it can be Write/Delete if field OWNER contain the UUID that try to act on this object. Usefull to allow someone to fully manage its objects. */ router.get("/alias/:alias", (req, res) => { res.send(Pagans.getalias(req.params.alias)); }); router.get("/person/:alias", (req, res) => { // 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 res.send(Pagans.getperson(req.params.alias, req.session.header.xtribe)); }); router.get("/isauth", checkHeaders, isAuthenticated, (req, res) => { /** * @api {get} /pagans/isregister * @apiName Is register check xalias and xhash * @apiGroup Pagans * * @apiUse apxHeader * * @apiError (400) {object} status missingheaders / xalias does not exist / signaturefailled * @apiError (401) {object} alias anonymous (not authenticated) * @apiError (404) {string} tribe does not exist * * * * @apiSuccess (200) {object} data contains indexfile requested * */ res.send({ status: 200, ref: "headers", msg: "authenticated", data: { xalias: req.session.header.xalias, }, }); }); router.post("/", checkHeaders, isAuthenticated, (req, res) => { /** * Create a pagan account from alias, publickey, if trusted recovery => * 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 */ console.log("pass ici", req.body); const feedback = { alias: req.body.alias, publickey: req.body.publickey }; const newpagan = Pagans.create(req.body.alias, req.body.publickey); if (newpagan.status == 200) { if (req.body.email) { feedback.withemail = true; feedback.email = req.body.email; feedback.privatekey = req.body.privatekey; feedback.passphrase = req.body.passphrase; Notifications.send({ type: "email", from: "", dest: [req.body.email], tpl: "registeremail", tribe: req.session.header.xtribe, data: feedback, }); } if (req.body.trustedtribe) { if (req.app.locals.tribeids.includes(req.body.trustedtribe)) { delete feedback.withemail; const persondata = { recovery: feedback }; res.send( Pagans.personupdate(req.body.alias, req.body.trustedtribe, persondata) ); } else { res.send({ status: 404, ref: "Pagans", msg: "tribedoesnotexist", data: { tribe: req.body.trustedtribe }, }); } } else { newpagan.data = feedback; res.send(newpagan); } } else { //error to create pagan res.send(newpagan); } }); router.put("/person", checkHeaders, isAuthenticated, (req, res) => { /** * add/update a person = alias + tribe with specific accessright and specific schema link to tribe * @todo add tribe/schema/person.json */ console.log(req.body); res.send( Pagans.personupdate(req.body.alias, req.session.header.xtribe, req.body) ); }); router.delete("/:alias", checkHeaders, isAuthenticated, (req, res) => { console.log(`DELETE pagans nationchains/pagans/${req.params.alias}.json`); const result = Pagans.delete(req.params.id, req.session.header); res.status(result.status).send(result.data); }); /*router.get("/isauth", checkHeaders, isAuthenticated, (req, res) => { if (req.session.header.xpseudo == "1") { return res.status(401).send({ info: "not authenticate" }); } else return res.status(200).send({ info: "well authenticated" }); });*/ router.post("/login", checkHeaders, async (req, res) => { // console.log('POST /users/login with: ', req.app.locals.header); /* Check un mot de passe pour un login pour obtenir un token d'authentification valable 1 hour, 1 day @header @body.LOGIN @body.PASSWORD @checkpsw = true check si les 2 mot de passe cryptés correspondent false bypass le contrôle et permet de générer un token utile le temps de reinitialisé son mot de passe. @return */ console.log("login for ", req.body, "in", req.session.header); const log = await Pagans.loginUser(req.session.header, req.body, true); console.log("log user login", log); if (log.status == 200) { // update req.app.locals.tokens for this uuid just after login success then next isAuth will be valid req.app.locals.tokens[log.data.user.UUID] = { TOKEN: log.data.user.TOKEN, ACCESSRIGHTS: log.data.user.ACCESSRIGHTS, }; console.log(req.app.locals); } return res.status(log.status).send(log.data); }); router.get("/getlinkwithoutpsw/:email", checkHeaders, async (req, res) => { /* Permet pour un email existant de renvoyer un email avec un lien valable 1h @email est le compte pour lequel on demande un accès Réponse: Si email n'existe pas on n'envoie pas d'email Si email existe on envoie un email avec un lien dont le token est valable 1h @return {status:200 ou erreur , payload:{ info:[list de key to appear in correct requester langue], model:'Pagans', moreinfo: 'texte pour log ' } } */ console.log( `GET /users/getlinkwithoutpsw for email: ${ req.params.email } tribeid :${req.header("X-Client-Id")}` ); if (!req.params.email) { return res.status(404).send({ info: ["emailmissing"], model: "Pagans", }); } else { try { const getlink = await Pagans.getlinkwithoutpsw( req.params.email, req.session.header ); console.log("getlink", getlink); //met à jour le token créer pour le uuid req.app.locals.tokens[getlink.data.info.xuuid] = getlink.data.info.token; // attention si on relance le serveur le token temporaire est perdu return res.status(getlink.status).send(getlink.data); } catch (err) { console.log(err); } } }); router.post("/register", checkHeaders, async (req, res) => { console.log(`POST /users for ${req.session.header.xtribe}`); if (req.session.header.xjwt == "123123") { // Creation d'un utilisateur avec information de base aucun droit // On modifie le contenu du form pour n egarder que login/email et psw // pour le client_id permet de traiter un user en attente de validation console.log("req du post", req); } }); router.get( "/info/:listindex", checkHeaders, isAuthenticated, hasAccessrighton("users", "R"), async (req, res) => { console.log( `get users info on tribeid ${req.session.header.xworkon} for ${req.params.listindex} with accessright`, req.session.header.accessrights.data ); const result = await Pagans.getinfoPagans( req.session.header.xpresworkon, req.session.header.accessrights, req.params.listindex ); res.status(result.status).send(result.data); } ); router.get( "/list/:filter/:field", checkHeaders, isAuthenticated, hasAccessrighton("users", "R"), async (req, res) => { console.log( "GET /users/list/filtre/champs list for " + req.session.header.xworkon ); if ( ["admin", "manager"].includes( req.session.header.decodetoken[ "apps" + req.session.header.xworkon + "profil" ] ) ) { try { const userslist = await Pagans.getUserlist( req.session.header, req.params.filter, req.params.field ); console.log("userslist", userslist); if (userslist.status == 200) { return res.status(userslist.status).send(userslist.data); } } catch (err) { console.log(err); return res.status(400).send({ info: "erreur" }); } } else { res.status(403).send({ info: ["forbiddenAccess"], model: "Pagans", }); } } ); router.get( "/uuid/:id", checkHeaders, isAuthenticated, hasAccessrighton("users", "R"), async (req, res) => { console.log(`GET /users/uuid/${req.params.id}`); //console.log('req.app.locals: ', req.app.locals); //console.log('req.session', req.session); const result = await Pagans.getUser( req.params.id, req.session.header.xworkon, req.session.header.accessrights ); res.status(result.status).send(result.data); } ); router.put("/chgpsw/:id", checkHeaders, isAuthenticated, async (req, res) => { console.log(`PUT update /users/chgpsw/${req.params.id}`); try { const majpsw = await Pagans.updateUserpassword( req.params.id, req.session.header, req.body ); res.status(majpsw.status).send(majpsw.data); } catch ({ status, data }) { res.status(status).send(data); } }); router.post( "/uuid", checkHeaders, isAuthenticated, hasAccessrighton("users", "C"), async (req, res) => { console.log( "POST /users create for " + req.session.header.xworkon, req.body ); const usercreate = await Pagans.createUser(req.session.header, req.body); return res.status(usercreate.status).send(usercreate.data); } ); router.put( "/uuid/:id", checkHeaders, isAuthenticated, hasAccessrighton("users", "U"), async (req, res) => { console.log(`PUT update /users/${req.params.id}`); // console.log('req.app.locals: ', req.app.locals); // console.log('req.session', req.session); try { const majUser = await Pagans.updateUser( req.params.id, req.session.header, req.body ); res.status(majUser.status).send(majUser.data); } catch ({ status, data }) { res.status(status).send(data); } } ); module.exports = router;