1
0
forked from apxtri/apxtri
This commit is contained in:
philc 2024-04-12 12:49:48 +02:00
parent 4c959380b6
commit 52fcf0d9aa
9 changed files with 221 additions and 187 deletions

View File

@ -18,37 +18,40 @@ See [apxtri web site](https://apxtri.crabdance.com) how to create a new social w
All actors will have the same target to respect contracts and are free to leave or to stay into a nation, a town or a tribe. If a contract is not fair, then a nation, tribe, will be empty mean not creating value mean die. Only fair rules will survive but any try will rewards actor with XTRIB coin. All actors will have the same target to respect contracts and are free to leave or to stay into a nation, a town or a tribe. If a contract is not fair, then a nation, tribe, will be empty mean not creating value mean die. Only fair rules will survive but any try will rewards actor with XTRIB coin.
```plaintext ```plaintext
/town-nation/ /town-nation/ tribe sapce
/conf.json town conf express.js /conf.json town conf express.js
/tmp/tokens temporary files /tmp/tokens temporary files
/tribes/ tribe's space /adminapi/ Space to manage tribes
/idx/ /apxtri/ core system that manage used tribe adminapi referential endepoint https://.../api/routeName/...
/itm/admin.json tribe conf are store
tribeName.json
/adminapi/ Allow apxtribe management
/apxtri/ core system that manage used tribe adminapi referential endepoint https://.../api/routeName/...
/middlewares
/models
/routes endpoint that return {status,ref,msg,data}
apxtri.js starting point
package.json
/nginx/adminapi_adminapx.conf nginx conf per website
/schema/ list of schema for ObjectName.json title description coments are in english
/lg list of schema ObjectName_lg.json per language data (same structure than ObjectName.json but in language lg)
/objects/objectName/idx/ list of indexName.json
/itm/ list of object content store by apxid.json (unique key to identify an ite in a collection of items object
/pagans Unique numeric ID shared accross all node (towns)
/towns Unique town name shared accross all node by domain name + IP
/
/www/cdn/ web public access file
/share/apxtriVx.tar derniere version apxTri pour installation
/adminapx/index_lg.html administration webapp
/website/
/tribeName/
/apxtri/routes Specific web service https://.../api/tribename/routeName/endpoint
/middlewares /middlewares
/models /models
/nginx/tribe_website.conf nginx conf per website /routes endpoint that return {status,ref,msg,data}
apxtri.js starting point
package.json
/nginx/adminapi_adminapx.conf nginx conf per website
/schema/ list of schema for ObjectName.json title description coments are in english
/lg list of schema ObjectName_lg.json per language data (same structure than ObjectName.json but in language lg)
/objects/objectName/
/idx/ list of indexName.json
/itm/ list of object content store by apxid.json (unique key to identify an ite in a collection of items object
/conf.json Version list and schema link that define this object
some key objects
/pagans/ Unique numeric ID shared accross all node (towns)
/towns/ Unique town name shared accross all node by domain name + IP
/...
/wwws/ Webspace that can be served with nginx
cdn/ web public access file
/adminapx/index_lg.html administration webapp
/website/
/idx/
/itm/adminapi.json tribe conf admin
tribeName.json tribeName conf
/tribeName/
/apxtri/routes Specific web service https://.../api/tribename/routeName/endpoint
/middlewares
/models
/nginx/tribe_website.conf nginx conf per website
/schema/ /schema/
/objects/ /objects/
/www/ /www/

View File

@ -2,54 +2,20 @@
api documentation for routes and middleware has to respect apidoc's rules [https://apidocjs.com/](https://apidocjs.com)  api documentation for routes and middleware has to respect apidoc's rules [https://apidocjs.com/](https://apidocjs.com) 
To update this doc accessible in [https://wal-ants.ndda.fr/cdn/apidoc](https://wal-ants.ndda.fr/cdn/apidoc) : To update this doc accessible in [https://wal-ants.ndda.fr/apidoc](https://wal-ants.ndda.fr/cdn/apidoc) :
`yarn apidoc`   `$ tribe=adminapi yarn apidoc` 
For api tribe's doc  accessible in [https://smatchit.io/cdn/apidoc](https://smatchit.io/cdn/apidoc) [:](https://smatchit.io/cdn/apidoc:)  For api tribe's doc  accessible in [https://admin.smatchit.io/apidoc](https://smatchit.io/cdn/apidoc) [:](https://smatchit.io/cdn/apidoc:) 
`yarn apidoctribename` `$ tribe=smatchit yarn apidoc`
A special tribe call adminapi is replicated in any towns (node), it works the same than all the other tribe except that all their data are synchronize with a blockchain  To get overview check README.md project and the package.json [https://gitea.ndda.fr/apxtri/apxtri](https://gitea.ndda.fr/apxtri/apxtri)
A special tribe call adminapi in any towns (node), it works the same than all the other tribe except that all their data are synchronize with a blockchain 
Objects manage by adminapi are: pagans (numerique id =alias/public key / private key), notifications (cypher message betxeen alias) , nations (rules apply to all towns belonging to a nations), towns ( a server that host IT ressources disk space, ram, bandwith and rules aplly to all tribe belonging to a town), tribes (( a sharing space to store data as well as api with rules to any person that use it), wwws (web space, dns) Objects manage by adminapi are: pagans (numerique id =alias/public key / private key), notifications (cypher message betxeen alias) , nations (rules apply to all towns belonging to a nations), towns ( a server that host IT ressources disk space, ram, bandwith and rules aplly to all tribe belonging to a town), tribes (( a sharing space to store data as well as api with rules to any person that use it), wwws (web space, dns)
All others object are managed by spécifics tribe. 
```plaintext
/townName_nationName/
/conf/nginx/tribename_appname.conf # nginx conf
/conf/apidoc # apidoc conf
/conf/townconf.json # town settings contain all glabl parameter
/tribes/idx/triebid_all.json # A global file {tribename:{conf}
/itm/tribename.json # Config file of a tribe
/adminapi # Tribes synchronize with all town
/apxtri # git yarn/npm project package.json entry point apxtri.js
/routes/
/models/
/middlewares/
/logs/nginx # nginx log related to /conf/nginx/apxtri_adminapi.conf
/api
/objects/objectname/idx/ # list of index to search objectname items
/itms/ # 1 json per items name apxid.json where apxid is a unique key
/wwws/idx/
/itm/
appname.json # website appname conf
cdn.json
/appname/ # website files
/cdn/ # cached files to optimize nginx static file delivery
/schema/conf.json # list of schema and version
/objectname.json # schema title and escription are in english
/lg/objectname_lg.json # title and description in lg
/tribename/ # same than adminapi for a specific trib,
# we only have 1 node process that manage 1 town that manage many tribes api
```
API Endpoint url: **/api/{tribename}/{routename}/xxx**
Domaine name can be a adminapi donaim name aswell any tribe's domain  name. Check nginx conf in /conf/nginx 
## Object management (Odmdb) ## Object management (Odmdb)
An object has a name and is defined by a schema that contain properties key. An object has a name and is defined by a schema that contain properties key.
@ -57,34 +23,57 @@ An object has a name and is defined by a schema that contain properties key.
A propertie has a name and a list of caracteristics (type, pattern,format,...) that have to be validate to be accepted. A propertie has a name and a list of caracteristics (type, pattern,format,...) that have to be validate to be accepted.
All properties respect the rules [https://json-schema.org/draft/2020-12/schema,](https://json-schema.org/draft/2020-12/schema,) some extra"format" can be add to mutualise recurrent regex pattern All properties respect the rules [https://json-schema.org/draft/2020-12/schema,](https://json-schema.org/draft/2020-12/schema,) some extra"format" can be add to mutualise recurrent regex pattern
To access a schema [https://wall-ants.ndda.fr/nationchains/schema/nations.json](https://wall-ants.ndda.fr/nationchains/schema/nations.json) and language specifique [https//:wall-ants.ndda.fr/nationchains/schema/lg/nations\_fr.json](https//:wall-ants.ndda.fr/nationchains/schema/lg/nations_fr.json) To access a schema [https://wall-ants.ndda.fr/api/adminapi/schema/tribename/schamname.json](https://wall-ants.ndda.fr/nationchains/schema/nations.json) and language is set by the header in xlang
A checkjson.js is available to manage all specific format [https://wall-ants.ndda.fr/Checkjson.js](https://wall-ants.ndda.fr/Checkjson.js) see **Odmdb - schema Checkjson** A checkjson.js is available to manage all specific format [https://wall-ants.ndda.fr/Checkjson.js](https://wall-ants.ndda.fr/Checkjson.js) see **Odmdb - schema Checkjson**
**Additional properties that not exist in 2020-12/schema :**
**required**: an array of required properties **required**: an array of required properties
**Additional properties that not exist in 2020-12/schema :**
**apxid**: the propertie used as an unique id **apxid**: the propertie used as an unique id
**apxuniquekey**: array of unique properties **apxuniquekey**: array of unique properties
**apxidx** : array of index **apxidx** : array of index definition
**apxaccessrights**: object with key profilname and accessrights on properties {profilname:{C:\[properties array\],R:\[properties array\],U:\[\],D:\[\]}} **apxaccessrights**: object with key profilname and accessrights on properties {profilname:{C:\[properties array\],R:\[properties array\],U:\[\],D:\[\]}}
Items of an object are store in files into :   Items of an object are store in files into :  
```plaintext ```plaintext
/objectnames/idx/keyval_objkey.json tribename/objectnames/idx/keyval_objkey.json
/objectnames/itm/uniqueid.json tribename//objectnames/itm/uniqueid.json
```
## Accessrights:
An alias is just an identity, to access a tribe, a person must exist with an authenticated alias into /tribes/{tribename}/objects/persons/itm/{alias}.json
A person has a property profils with a list of profilename, common profiles are : anonymous (no identity) / pagan (an identity)  / person (an identity with access right into a tribe) / druid (the administrator of a tribe) / mayor (administrator of a town/server)/ and any profil can be define for a tribe
Each object has an apxaccessrights that is a list of profil and CRUD access per object key.
Example: owner on this object cab create delete an item is own, can read a list of propertie and update only some.
```plaintext
"owner": {
"C" : [],
"D": [],
"R": ["alias","owner","profils","firstname","lastname","dt_birth"],
"U": ["firstname","lastname","dt_birth"]
}
``` ```
## api pre-request ## api pre-request
API Endpoint url: **/api/{tribename}/{routename}/xxx**
Domaine name can be a adminapi donaim name aswell any tribe's domain  name. Check nginx conf in /tribename/nginx 
**Valid header see Middlewares** **Valid header see Middlewares**
App use openpgp.js lib to sign xdays\_xalias with a privatekey and store it in xhash. App use openpgp.js lib to sign xalias\_xdays  (xdays a timestamp integer in miilisecond from Unix Epoch) with a privatekey and store it in xhash.
/middlewares/isAuthenticated.js check if (xhash) is a valid signature of the public key a xhash is valid for 24 hours /middlewares/isAuthenticated.js check if (xhash) is a valid signature of the public key a xhash is valid for 24 hours
@ -108,17 +97,9 @@ C - a json multi answer **{status,multimsg:\[{ref,msg,data}\]}**
To show feedback context message in a language lg => get /api/adminapi/objects/tplstrings/{{model}}\_{{lg}}.json To show feedback context message in a language lg => get /api/adminapi/objects/tplstrings/{{model}}\_{{lg}}.json
This contain a json {msg:"mustache template string to render with data"}   This contain a json {msg:"mustache template string to render with data"}  
## Accessrights:
An alias is just an identity, to access a tribe, a person must exist with an authenticated alias into /tribes/{tribename}/objects/persons/itm/{alias}.json
A person has a property profils with a list of profilename, common profiles are : anonymous (no identity) / pagan (an identity)  / person (an identity with access right into a tribe) / druid (the administrator of a tribe) / mayor (administrator of a town/server)
Each object has an apxaccessrights that is a list of profil and CRUD access per object key .
## Add tribe's api: ## Add tribe's api:
Accessible with https://dns/api/tribename/routes Accessible with https://dns/api/tribename/routename/
```plaintext ```plaintext
/tribes/tribename/apxtri/routes /tribes/tribename/apxtri/routes

View File

@ -52,6 +52,8 @@ const isAuthenticated = async (req, res, next) => {
glob.sync(`../../tmp/tokens/*.json`).forEach((f) => { glob.sync(`../../tmp/tokens/*.json`).forEach((f) => {
const fsplit = f.split("_"); const fsplit = f.split("_");
const elapse = tsday - parseInt(fsplit[2]); const elapse = tsday - parseInt(fsplit[2]);
console.log("##############################")
console.log(fsplit,"--",fsplit[2])
//24h 86400000 milliseconde 15mn 900000 //24h 86400000 milliseconde 15mn 900000
if (elapse && elapse > 86400000) { if (elapse && elapse > 86400000) {
fs.remove(f); fs.remove(f);

View File

@ -94,6 +94,7 @@ Checkjson.schema.properties.format = {
"idn-email": / /, "idn-email": / /,
uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/, uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
uri: / /, uri: / /,
url: /^(?:(?:https?|ftp):\/\/)(?:\w+(?::\w+)?@)?(?:(?:[a-z0-9-\.]+\.[a-z]{2,})(?:[-a-z0-9+\._\%\!\\[\]\(\)\,\*\?\&\=\:]*){1,})|(?:(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[0-1]?[0-9][0-9]?))(?:[:\/#][^#]*)?$/,
"uri-reference": / /, "uri-reference": / /,
iri: / /, iri: / /,
hostname: / /, hostname: / /,

View File

@ -32,21 +32,23 @@ Notifications.get = (alias, tribeId) => {
*/ */
Notifications.statmaillist=(tribe)=>{ Notifications.statmaillist=(tribe)=>{
const statinfo={} const statinfo={}
let csv="email/phone;name;srckey\n"
const src=`../../${tribe}/objects/maillinglists/*.json` const src=`../../${tribe}/objects/maillinglists/*.json`
console.log(path.resolve(src)) console.log(path.resolve(src))
glob.sync(src).forEach(f=>{ glob.sync(src).forEach(f=>{
const name=path.basename(f,".json"); const name=path.basename(f,".json");
const mlst=fs.readJSONSync(f) const mlst=fs.readJSONSync(f)
Object.keys(mlst).forEach(c=>{ Object.keys(mlst).forEach(c=>{
csv+=`"${c}";"${name}";"${mlst[c].srckeys.join('-')}"\n`
mlst[c].srckeys.forEach(s=>{ mlst[c].srckeys.forEach(s=>{
if (!statinfo[s]) statinfo[s]={} if (!statinfo[s]) statinfo[s]={}
if (!statinfo[s][name]) statinfo[s][name]=0 if (!statinfo[s][name]) statinfo[s][name]=0
statinfo[s][name]++ statinfo[s][name]++
}) })
//console.log(c) recupere les contact tel ou email
}) })
}) })
// fichier csv stocker en local en attendant d'avoir un back pour stocker la reponse dans data.csv
fs.outputFileSync(`../../${tribe}/mailinglst.csv`,csv,"utf-8");
return {status:200,ref:"Notifications",msg:"statistics",data:statinfo} return {status:200,ref:"Notifications",msg:"statistics",data:statinfo}
} }

View File

@ -156,113 +156,162 @@ Odmdb.updateObject = (objectPathname, meta) => {};
* @lg language you want to get schema * @lg language you want to get schema
* @return {status:200,data:{conf:"schemaconf",schema:"schemacontent"} } * @return {status:200,data:{conf:"schemaconf",schema:"schemacontent"} }
*/ */
Odmdb.Schema = (objectPathname, validschema, lg="en") => { Odmdb.Schema = (objectPathname, validschema, lg = "en") => {
const replacelg = (data) => {
const replacelg = (data)=>{
// data.en version schema de base, data.fr version schema traduite // data.en version schema de base, data.fr version schema traduite
Object.keys(data.lg).forEach(k=>{ Object.keys(data.lg).forEach((k) => {
console.log(k) console.log(k);
if (data.lg[k].title) data.en[k].title = data.lg[k].title if (data.lg[k].title) data.en[k].title = data.lg[k].title;
if (data.lg[k].description) data.en[k].description = data.lg[k].description if (data.lg[k].description)
if (data.lg.properties){ data.en[k].description = data.lg[k].description;
console.log('properties') if (data.lg.properties) {
console.log(data.en.properties) console.log("properties");
console.log(data.lg.properties) console.log(data.en.properties);
const res = replacelg({en:data.en.properties,lg:data.lg.properties}) console.log(data.lg.properties);
data.lg.properties=res.lg const res = replacelg({
data.en.properties=res.en en: data.en.properties,
lg: data.lg.properties,
});
data.lg.properties = res.lg;
data.en.properties = res.en;
} }
}) });
return data return data;
} };
const getschemalg = (schemaPath,lg) => { const getschemalg = (schemaPath, lg) => {
if (schemaPath.slice(-5) != ".json") schemaPath += ".json"; if (schemaPath.slice(-5) != ".json") schemaPath += ".json";
if (schemaPath.substring(0, 4) == "http") { if (schemaPath.substring(0, 4) == "http") {
// lance requete http pour recuperer le schema avec un await axios // lance requete http pour recuperer le schema avec un await axios
} else { } else {
schemaPath = `../../${schemaPath}`; schemaPath = `../../${schemaPath}`;
if (log) console.log(currentmod,"resolve path schemaPath:",path.resolve(schemaPath)) if (log)
console.log(
currentmod,
"resolve path schemaPath:",
path.resolve(schemaPath)
);
if (!fs.existsSync(schemaPath)) { if (!fs.existsSync(schemaPath)) {
return {}; return {};
} else { } else {
let schemalg = fs.readJsonSync(schemaPath); let schemalg = fs.readJsonSync(schemaPath);
if (lg!="en"){ if (lg != "en") {
let lgtrans={} let lgtrans = {};
try{ try {
lgtrans=fs.readJsonSync(schemaPath.replace('/schema/','/schema/lg/').replace('.json',`_${lg}.json`)); lgtrans = fs.readJsonSync(
const res= replacelg({en:schemalg,lg:lgtrans}) schemaPath
//console.log(res.en.title,res.lg.title) .replace("/schema/", "/schema/lg/")
schemalg=res.en .replace(".json", `_${lg}.json`)
}catch(err){ );
const res = replacelg({ en: schemalg, lg: lgtrans });
//console.log(res.en.title,res.lg.title)
schemalg = res.en;
} catch (err) {
// console.log('Err',err) // console.log('Err',err)
// no translation file deliver en by default // no translation file deliver en by default
} }
} }
return schemalg return schemalg;
} }
} }
}; };
if (log) console.log(currentmod,`${objectPathname}/conf.json`); const convoptionstoenum=(propertie,lg)=>{
const res = { if (!propertie.options) return propertie;
status: 200, if (!(propertie.options["$ref"])){
ref: "Odmdb", propertie.msg="missingref"
msg: "getschema", return propertie
data: {}, }
}; let optionsfile;
let optionstype;
if (propertie.options["$ref"].includes("/options/")) {
optionstype = "options";
optionsfile = path.resolve(
`../../${propertie.options["$ref"]}_${lg}.json`
);
}
if (propertie.options["$ref"].includes("/idx/")) {
optionstype = "idx";
optionsfile = path.resolve(
`../../${propertie.options["$ref"]}.json`
);
}
if (log) console.log(currentmod, "Lien vers options:", optionsfile);
if (!fs.existsSync(optionsfile)) {
propertie.msg = "missingref";
return propertie;
} else {
delete propertie.options
if (optionstype == "options") {
propertie.enum =
fs.readJSONSync(optionsfile).lst_idx;
}
if (optionstype == "idx") {
propertie.enum = fs.readJSONSync(optionsfile);
}
}
return propertie
}
if (log) console.log(currentmod, `${objectPathname}/conf.json`);
const res = {
status: 200,
ref: "Odmdb",
msg: "getschema",
data: {},
};
if (fs.existsSync(`${objectPathname}/conf.json`)) { if (fs.existsSync(`${objectPathname}/conf.json`)) {
res.data.conf=fs.readJsonSync(`${objectPathname}/conf.json`); res.data.conf = fs.readJsonSync(`${objectPathname}/conf.json`);
res.data.schema = getschemalg(res.data.conf.schema,lg) res.data.schema = getschemalg(res.data.conf.schema, lg);
}else{ } else {
res.data.conf={} res.data.conf = {};
} }
if (!res.data.schema || Object.keys(res.data.schema).length == 0 ) { if (!res.data.schema || Object.keys(res.data.schema).length == 0) {
return { return {
status: 404, status: 404,
ref: "Odmdb", ref: "Odmdb",
msg: "schemanotfound", msg: "schemanotfound",
data: { objectPathname:path.resolve(objectPathname), schema: {} }, data: { objectPathname: path.resolve(objectPathname), schema: {} },
}; };
} }
// get $ref from $def
//@todo only 1 level $ref if multi level need to rewrite with recursive call if (res.data.schema["$defs"]){
Object.keys(res.data.schema["$defs"]).forEach(ss=>{
Object.keys(res.data.schema["$defs"][ss].properties).forEach(pp=>{
res.data.schema["$defs"][ss].properties[pp]=convoptionstoenum(res.data.schema["$defs"][ss].properties[pp],lg)
})
})
}
Object.keys(res.data.schema.properties).forEach((p) => { Object.keys(res.data.schema.properties).forEach((p) => {
//looking for type:object with $ref to load and replace by ref content (ref must be adminapi/ or tribeid/)
if ( if (
res.data.schema.properties[p].type == "object" && res.data.schema.properties[p].type == "object" &&
res.data.schema.properties[p]["$ref"] res.data.schema.properties[p]["$ref"]
) { ) {
const subschema = path.resolve(`../../${res.data.schema.properties[p]["$ref"]}.json`); let subschema
if (Object.keys(res.data.schema).length == 0) { const localdef=res.data.schema.properties[p]["$ref"].includes("#/")
if (
localdef &&
!(res.data.schema["$defs"] && res.data.schema["$defs"][propertie["$ref"]])
) {
res.status = 404; res.status = 404;
res.msg = "missingref"; res.msg = "missinglocalref";
res.data.missingref = res.data.schema.properties[p]["$ref"]; res.data.missingref = propertie;
return res; return res;
} else { }
subschema.description += ` from external schema: ${res.data.schema.properties[p]["$ref"]}`; if (localdef) {
res.data.schema.properties[p] = subschema; res.data.schema.properties[p]=res.data.schema["$defs"][res.data.schema.properties[p]["$ref"]]
}else{
subschema = Odmdb.Schema(path.resolve(res.data.schema.properties[p]["$ref"]), validschema, lg)
if(subschema.status==200){
res.data.schema.properties[p]=subschema.data.schema;
}else{
subschema.data.originschemaproperty=p
return subschema
}
} }
} }
//`../../${req.session.header.xtribe}/objects/persons` if (res.data.schema.properties[p].options){
//looking for options:{"$ref":"../objects/options/xxx.json"} //remplace options par enum:[]
//to add enum:[] = content of options available in res.data.schema.properties[p]=convoptionstoenum(res.data.schema.properties[p],lg)
if (
res.data.schema.properties[p].options &&
res.data.schema.properties[p].options["$ref"]
) {
const optionsfile = path.resolve(`../../${res.data.schema.properties[p].options["$ref"]}_${lg}.json`)
if (log) console.log(currentmod,"Lien vers options:", optionsfile)
if (!fs.existsSync(optionsfile)){
res.status = 404;
res.msg = "missingref";
res.data.missingref = res.data.schema.properties[p].options["$ref"];
return res;
}else{
if (!res.data.schema.apxref) {res.data.schema.apxref=[]}
if (!res.data.schema.apxref.includes(res.data.schema.properties[p].options["$ref"]))
res.data.schema.apxref.push(res.data.schema.properties[p].options["$ref"])
res.data.schema.properties[p].enum=fs.readJSONSync(optionsfile).lst_idx
}
} }
}); });
@ -487,7 +536,7 @@ Odmdb.cud = (objectPathname, crud, itm, role, runindex = true) => {
const existid = fs.existsSync( const existid = fs.existsSync(
`${objectPathname}/itm/${itm[getschema.data.schema.apxid]}.json` `${objectPathname}/itm/${itm[getschema.data.schema.apxid]}.json`
); );
if (log) console.log(currentmod,"Pass schema itm existid = ", existid) if (log) console.log(currentmod, "Pass schema itm existid = ", existid);
/*const pathindex = `${objectPathname}/idx/lst_${getschema.data.schema.apxid}.json`; /*const pathindex = `${objectPathname}/idx/lst_${getschema.data.schema.apxid}.json`;
if (!fs.existsSync(pathindex)) { if (!fs.existsSync(pathindex)) {
fs.outputJSONSync(pathindex, []); fs.outputJSONSync(pathindex, []);
@ -545,7 +594,7 @@ Odmdb.cud = (objectPathname, crud, itm, role, runindex = true) => {
(crud == "D" && !accessright.D) || (crud == "D" && !accessright.D) ||
(crud == "U" && !accessright.U) (crud == "U" && !accessright.U)
) { ) {
if (log) console.log(currentmod,"Forbidden accessright:", accessright); if (log) console.log(currentmod, "Forbidden accessright:", accessright);
return { return {
status: 403, status: 403,
ref: "Odmdb", ref: "Odmdb",
@ -581,14 +630,18 @@ Odmdb.cud = (objectPathname, crud, itm, role, runindex = true) => {
false false
); );
if (chkdata.status != 200) { if (chkdata.status != 200) {
if (log) console.log(currentmod,"Unconsistency data", chkdata); if (log) console.log(currentmod, "Unconsistency data", chkdata);
return chkdata; return chkdata;
} }
if (log) console.log(currentmod,"Data compliance with schema"); if (log) console.log(currentmod, "Data compliance with schema");
if (!getschema.data.schema.apxuniquekey) if (!getschema.data.schema.apxuniquekey)
getschema.data.schema.apxuniquekey = []; getschema.data.schema.apxuniquekey = [];
if (log) console.log(currentmod,`${objectPathname}/itm/${chkdata.data.apxid}.json`); if (log)
if (log) console.log(currentmod,chkdata.data.itm); console.log(
currentmod,
`${objectPathname}/itm/${chkdata.data.apxid}.json`
);
if (log) console.log(currentmod, chkdata.data.itm);
fs.outputJSONSync( fs.outputJSONSync(
`${objectPathname}/itm/${chkdata.data.apxid}.json`, `${objectPathname}/itm/${chkdata.data.apxid}.json`,
chkdata.data.itm chkdata.data.itm
@ -596,7 +649,7 @@ Odmdb.cud = (objectPathname, crud, itm, role, runindex = true) => {
} }
//if (log) console.log(currentmod,"getschema", getschema); //if (log) console.log(currentmod,"getschema", getschema);
//rebuild index if requested //rebuild index if requested
if (log) console.log(currentmod,"runidx", runindex); if (log) console.log(currentmod, "runidx", runindex);
if (runindex) Odmdb.runidx(objectPathname, getschema.data.schema); if (runindex) Odmdb.runidx(objectPathname, getschema.data.schema);
getschema.data.conf.lastupdatedata = dayjs().toISOString(); getschema.data.conf.lastupdatedata = dayjs().toISOString();
fs.outputJSONSync(`${objectPathname}/conf.json`, getschema.data.conf); fs.outputJSONSync(`${objectPathname}/conf.json`, getschema.data.conf);
@ -619,7 +672,7 @@ Odmdb.cud = (objectPathname, crud, itm, role, runindex = true) => {
* *
*/ */
Odmdb.runidx = (objectPathname, schema) => { Odmdb.runidx = (objectPathname, schema) => {
if (log) console.log(currentmod,`idx for ${objectPathname}`); if (log) console.log(currentmod, `idx for ${objectPathname}`);
if (!schema || !schema.apxid) { if (!schema || !schema.apxid) {
const getschema = Odmdb.Schema(objectPathname, true); const getschema = Odmdb.Schema(objectPathname, true);
if (getschema.status != 200) return getschema; if (getschema.status != 200) return getschema;
@ -701,8 +754,8 @@ Odmdb.runidx = (objectPathname, schema) => {
itm[ventil[n].keyval.split(".")[0]] itm[ventil[n].keyval.split(".")[0]]
) { ) {
let itmval = JSON.parse(JSON.stringify(itm)); let itmval = JSON.parse(JSON.stringify(itm));
if (log) console.log(currentmod,ventil[n].keyval); if (log) console.log(currentmod, ventil[n].keyval);
if (log) console.log(currentmod,itmval); if (log) console.log(currentmod, itmval);
ventil[n].keyval ventil[n].keyval
.split(".") .split(".")
.forEach((i) => (itmval = itmval[i] ? itmval[i] : null)); .forEach((i) => (itmval = itmval[i] ? itmval[i] : null));
@ -752,15 +805,16 @@ Odmdb.ASUPidxfromitm = (
idxs = [], idxs = [],
schema schema
) => { ) => {
if (log) console.log(currentmod,`idxfromitem for ${objectPathname} action:${crud}`); if (log)
console.log(currentmod, `idxfromitem for ${objectPathname} action:${crud}`);
if (!schema || !schema.apxid) { if (!schema || !schema.apxid) {
const getschema = Odmdb.Schema(objectPathname, true); const getschema = Odmdb.Schema(objectPathname, true);
if (getschema.status != 200) return getschema; if (getschema.status != 200) return getschema;
schema = getschema.data.schema; schema = getschema.data.schema;
} }
if (log) console.log(currentmod,schema.apxuniquekey); if (log) console.log(currentmod, schema.apxuniquekey);
const itms = crud == "I" ? glob.sync(`${objectPathname}/itm/*.json`) : [itm]; const itms = crud == "I" ? glob.sync(`${objectPathname}/itm/*.json`) : [itm];
if (log) console.log(currentmod,itms); if (log) console.log(currentmod, itms);
if (crud == "I") { if (crud == "I") {
//reinit all idx //reinit all idx
idxs.forEach((idx) => { idxs.forEach((idx) => {
@ -787,8 +841,8 @@ Odmdb.ASUPidxfromitm = (
idxtoreindex.push(idx); //@todo idxtoreindex.push(idx); //@todo
} }
} }
if (log) console.log(currentmod,idx.keyval); if (log) console.log(currentmod, idx.keyval);
if (log) console.log(currentmod,itm[idx.keyval]); if (log) console.log(currentmod, itm[idx.keyval]);
if ( if (
["C", "U", "I"].includes(crud) && ["C", "U", "I"].includes(crud) &&

View File

@ -32,16 +32,6 @@ At each reboot run a process to analyse /apxtri/routes and api/models whre only
4 to delete a user sudo userdel smatchit (this keep folder smatchit to remove folder smatchit => sudo userdel --remove smacthit) 4 to delete a user sudo userdel smatchit (this keep folder smatchit to remove folder smatchit => sudo userdel --remove smacthit)
/tribes/tribeid /tribes/tribeid
Manage a tribeid space Manage a tribeid space
* create * create

View File

@ -302,16 +302,14 @@ router.get(
* @apiParam {String} objectname name Mandatory if in conf.nationObjects then file is into nationchains/ else in /tribes/xtribe/objectname * @apiParam {String} objectname name Mandatory if in conf.nationObjects then file is into nationchains/ else in /tribes/xtribe/objectname
* @apiParam {String} primaryindex the unique id where item is store * @apiParam {String} primaryindex the unique id where item is store
* *
* @apiError {json} objectNotfound the file item does not exist * @apiError {json} objectfiledoesnotexist the file item does not exist
* @apiErrorExample {json} * @apiErrorExample {json}
* HTTP/1.1 404 Not Found * HTTP/1.1 404 Not Found
* {"status":404,"ref":"Odmdb","msg":"doesnotexist","data":{"objectname":"objectname","key":"apxid","val":"primaryindex"}} * {status:404,ref: "Odmdb",msg: "objectfiledoesnotexist",data: { objectpath }}
*
* @apiSuccess {object} indexfile content * @apiSuccess {object} indexfile content
* @apiSuccessExample {json} Success-Response: * @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK * HTTP/1.1 200 OK
* {"status":200, "ref":"Odmdb", "msg":"indexexist", "data":{"indexname","content":{itm file}} * {status:200,ref:"Odmdb",msg:"itmfound", data:{itm:{} }} *
*
* *
*/ */
// indexname = objectname_key_value.json // indexname = objectname_key_value.json
@ -323,9 +321,10 @@ router.get(
const objectpath = `../../${req.params.tribe}/objects/${req.params.objectname}/itm/${req.params.primaryindex}.json`; const objectpath = `../../${req.params.tribe}/objects/${req.params.objectname}/itm/${req.params.primaryindex}.json`;
if (fs.existsSync(objectpath)) { if (fs.existsSync(objectpath)) {
res.status(200).json({ data: fs.readJsonSync(objectpath) }); res.status(200).json({status:200,ref:"Odmdb",msg:"itmfound", data:{itm: fs.readJsonSync(objectpath) }});
} else { } else {
res.status(404).json({ res.status(404).json({
status:404,
ref: "Odmdb", ref: "Odmdb",
msg: "objectfiledoesnotexist", msg: "objectfiledoesnotexist",
data: { objectpath }, data: { objectpath },

View File

@ -234,6 +234,8 @@ router.post( '/downloadls', checkHeaders, isAuthenticated, ( req, res ) => {
.send( 'Forbidden access' ) .send( 'Forbidden access' )
} }
} ); } );
router.post( '/upfilepond', checkHeaders, isAuthenticated, ( req, res ) => { router.post( '/upfilepond', checkHeaders, isAuthenticated, ( req, res ) => {
console.log( 'post adminapi/tribes/uploadfilepond' ); console.log( 'post adminapi/tribes/uploadfilepond' );
// Store file and return a unique id to save button // Store file and return a unique id to save button