This commit is contained in:
philc 2023-06-12 05:28:19 +00:00
commit 51159b1d05
5 changed files with 97 additions and 223 deletions

View File

@ -2,11 +2,15 @@ server {
server_name {{#dns}} {{.}} {{/dns}};
access_log {{{nginx.logs}}}.access.log main;
location ~* /nationchains/(schema|blocks|pagans|towns|nations)/ {
location ~* /nationchains/(blocks|pagans|towns|nations)/ {
# Warning: never add tribes for keeping it private
root {{{dirapi}}}/;
}
location ~* /nationchains/schema/ {
#outside of nationchains for git purpose
rewrite /nationchains/schema/(.*$) /$1 break;
root {{{dirapi}}}/adminapi/www/adminapx/schema/;
}
# /plugins/pluginame/components/xxx?plugin=pluginname&pluginkey=key
# acess if exist pluginkey
location /plugins/ {
@ -34,10 +38,11 @@ proxy_pass http://localhost:{{{api.port}}};
proxy_redirect off;
include proxy_params;
}
#to add htpasswd install apache2-utils => sudo htpasswd -c dirtown/tribes/tribeId/.htpasswd loginname passwd see man for option
#to add htpasswd install apache2-utils => sudo htpasswd -c dirtown/tribes/tribeId/.htpasswd loginname passwd see man for
option
location / {
{{#nginx.private}}
{{#nginx.private}}
auth_basic "Mot de passe {{nginx.privatelogin}}";
auth_basic_user_file {{dirtown}}/tribes/{{tribeId}}/.htpasswd;
{{/nginx.private}}

View File

@ -1,6 +1,6 @@
{
"$schema":"http://json-schema.org/schema#",
"$id":"nationchains/socialworld/objects/schema/nations",
"$id":"schema/nations",
"title": "Nation definition",
"description": "A nation from apXtrib world",
"$comment":"see ./lg/nations_lg.json for description in your languange lg",

View File

@ -1,9 +1,9 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "nationchains/schema/person",
"$id": "/schema/person",
"title": "Person minimum definition to link a person to a pagan identity",
"description": "A person is a human with a apxtrib identity (Public Private Key. Information stored (not cipher) for a person are only visible from the town's Mayor and the tribe's Druid. You need at least trus the druid that trust the mayor (for sensitive data Mayor and Druid can be the same apx Identity.) Only a pagan that have the privateKey can read cipher data. The purpose of this sschema is to link a person to a tribe and manage basic activities, profil will be a tribe object if need more personnal information",
"type": "objects",
"type": "object",
"properties": {
"alias": {
"type": "string",
@ -25,12 +25,13 @@
"privatekey": { "type": "string", "format": "eccCorve25519armored" }
}
},
"recoveryauth":{"type":"object","$ref":""},
"biography": {
"type": "string",
"pattern": "^.{O,150}$"
},
"imgavatar": {
"type": "string",
"type": "string"
},
"accessrights": {
"type": "object",

View File

@ -20,6 +20,12 @@ const conf = require(`${process.env.dirtown}/conf.json`);
const Pagans = {};
Pagans.getalias = (alias) => {
/**
* @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} }
*
**/
console.log(`${conf.dirapi}/nationchains/pagans/itm/${alias}.json`);
if (fs.existsSync(`${conf.dirapi}/nationchains/pagans/itm/${alias}.json`)) {
return {
@ -41,12 +47,20 @@ Pagans.getalias = (alias) => {
};
Pagans.getperson = (alias, tribeid) => {
/**
* @param {string} alias that exist
* @param {string} tribeId that exist with a person alias
* @return {object} { status: 200, ref:"pagans",msg:"personexist",data: { person } }
* { status: 404, ref:"pagans",msg:"persondoesnotexist",data: { person } }
*
**/
if (
fs.existsSync(`${conf.dirtown}/tribes/${tribeid}/person/itm/${alias}.json`)
) {
const person = fs.readJsonSync(
`${conf.dirtown}/tribes/${tribeid}/person/itm/${alias}.json`
);
delete person.auth;
return {
status: 200,
ref: "Pagans",
@ -171,4 +185,15 @@ Pagans.authenticatedetachedSignature = async (
}
};
Pagans.keyrecovery = (tribeid, email) => {
glob
.GlobSync(`${conf.dirtown}/tribes/${tribeId}/Person/*.json`)
.forEach((f) => {
const person = fs.readJsonSync(f);
if (person.recoveryauth && person.recoveryauth.email) {
// send email (alias publickey privatekey )
}
});
return { status: 200, ref: "Pagans", msg: "todo" };
};
module.exports = Pagans;

View File

@ -48,29 +48,46 @@ Owner means it can be Write/Delete if field OWNER contain the UUID that try to a
*/
router.get("/alias/:alias", (req, res) => {
/**
* @api {get} /pagans/alias/:alias
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @param {string} alias a alias that exist or not
* @apiSuccess (200) {object} {ref:"pagans",msg:"aliasexist",data: { alias, publicKey } }
* @apiError (404) {object} {ref:"pagans",msg:"aliasdoesnotexist",data: { alias} }
*
**/
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
router.get("/person/:alias", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {get} /pagans/person:alias
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @apiUse apxHeader
* @param {string} alias that exist
* @param {string} tribeId that exist with a person alias
* @apiSuccess (200) {ref:"pagans",msg:"personexist",data: { person } }
* @apiError (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
* */
res.send(Pagans.getperson(req.params.alias, req.session.header.xtribe));
});
router.get("/isauth", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {get} /pagans/isregister
* @api {get} /pagans/isauth
* @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
*
*/
@ -85,6 +102,11 @@ router.get("/isauth", checkHeaders, isAuthenticated, (req, res) => {
});
router.post("/", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {post} /pagans
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @apiUse apxHeader
*
* 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:
@ -136,6 +158,11 @@ router.post("/", checkHeaders, isAuthenticated, (req, res) => {
});
router.put("/person", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {put} /pagans/person
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @apiUse apxHeader
*
* add/update a person = alias + tribe with specific accessright and specific schema link to tribe
* @todo add tribe/schema/person.json
*/
@ -145,215 +172,31 @@ router.put("/person", checkHeaders, isAuthenticated, (req, res) => {
);
});
router.delete("/:alias", checkHeaders, isAuthenticated, (req, res) => {
/**
* @api {delete} /pagans/:alias
* @apiName Is register check xalias and xhash
* @apiGroup Pagans
* @apiUse apxHeader
* */
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("/keyrecovery/:tribeid/:email", checkHeaders, (req, res) => {
/**
* @api {get} /pagans/keyrecovery/tribe/email
* @apiName apxtrib
* @apiGroup Pagans
*
*
*
* @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(Pagans.keyrecovery(req.params.tribeId, req.params.email));
});
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;