update checkdata.js

This commit is contained in:
philc 2023-03-27 07:52:21 +02:00
parent a03e35c9e2
commit d0a3b10cfe
83 changed files with 1608 additions and 825 deletions

View File

@ -1,14 +0,0 @@
{
"folders": [
{
"path": "."
},
{
"path": "../apxtrib.wiki"
},
{
"path": "../apxtribautoeval"
}
],
"settings": {}
}

View File

@ -5,27 +5,32 @@ const express = require( 'express' );
/******************************************* /*******************************************
SEE http://gitlab.ndda.fr/philc/apixtribe/-/wikis/HOWTOoverview SEE https://gitea.ndda.fr/apxtrib/apxtrib/wiki/Devrules
To have a quick understanding before doing deeply in source code To have a quick understanding and convention before doing deeply in source code
*********************************************/ *********************************************/
// to make absolute path with `${__base}relativepath`
global.__base = __dirname +'/';
// check setup // check setup
if( !fs.existsSync( '/etc/nginx/nginx.conf' ) ) { if( !fs.existsSync( '/etc/nginx/nginx.conf' ) ) {
console.log( '\x1b[31m Check documentation, nginx have to be installed on this server first, no /etc/nginx/nginx.conf available, install then rerun yarn command.' ); console.log( '\x1b[31m Check documentation, nginx have to be installed on this server first, no /etc/nginx/nginx.conf available, install then rerun yarn command.' );
process.exit(); process.exit();
} }
if( !fs.existsSync( './tribes/townconf.js' ) ) { if( !fs.existsSync( './tribes/townconf.js' ) ) {
console.log( `\x1b[42m####################################\nWellcome into apixtribe, you need to init your town by "yarn setup" the first time . \nCheck README's project to learn more. more.\n #####################################\x1b[0m` ); console.log( `\x1b[42m#########################################################################\x1b[0m\n\x1b[42mWellcome into apxtrib, init your town and first tribe by 'yarn setup'. \x1b[0m \n\x1b[42mThen 'yarn dev' or 'yarn startpm2'. Check README's project to learn more.\x1b[0m\n\x1b[42m#########################################################################\x1b[0m` );
process.exit(); process.exit();
} }
// config.js exist in any case from Setup.checkinit(); // config.js exist in any case from Setup.checkinit();
const config = require( './tribes/townconf.js' ); const config = require( './tribes/townconf.js' );
// Tribes allow to get local apixtribe instance context // Tribes allow to get local apxtrib instance context
// dataclient .tribeids [] .DOMs [] .routes (plugins {url:name route:path}) .appname {tribeid:[website]} // dataclient .tribeids [] .DOMs [] .routes (plugins {url:name route:path}) .appname {tribeid:[website]}
const dataclient = require( './models/Tribes' ) const dataclient = require( './models/Tribes' )
.init(); .init();
console.log( 'allowed DOMs to access to this apixtribe server: ', dataclient.DOMs ) console.log( 'allowed DOMs to access to this apxtrib server: ', dataclient.DOMs )
const app = express(); const app = express();
Object.keys(config.appset).forEach(p=>{
app.set(p,config.appset[p])
})
app.set( 'trust proxy', true ); app.set( 'trust proxy', true );
// To set depending of data form or get size to send // To set depending of data form or get size to send
app.use( bodyParser.urlencoded( config.bodyparse.urlencoded ) ); app.use( bodyParser.urlencoded( config.bodyparse.urlencoded ) );
@ -79,10 +84,10 @@ app.use( express.static( `${__dirname}/tribes/${config.mayorId}/www/cdn/public`,
dotfiles: 'allow' dotfiles: 'allow'
} ) ); } ) );
//Allow to public access a space dev delivered by apixtribe //Allow to public access a space dev delivered by apxtrib
// this is just a static open route for dev purpose, // this is just a static open route for dev purpose,
// for production, we'll use a nginx static set to /www/app/appname // for production, we'll use a nginx static set to /www/app/appname
/*console.log( `${config.dnsapixtribe}/space/tribeid/website`, dataclient.appname ); /*console.log( `${config.dnsapxtrib}/space/tribeid/website`, dataclient.appname );
Object.keys( dataclient.appname ) Object.keys( dataclient.appname )
.forEach( cid => { .forEach( cid => {
dataclient.appname[ cid ].forEach( website => { dataclient.appname[ cid ].forEach( website => {
@ -91,9 +96,9 @@ Object.keys( dataclient.appname )
} ); } );
*/ */
// Routers add any routes from /routes and /plugins // Routers add any routes from /routes and /plugins
console.log( 'Routes available on this apixtribe instance' ); console.log( 'Routes available on this apxtrib instance' );
console.log( dataclient.routes ); console.log( dataclient.routes );
// prefix only use for dev purpose in production a proxy nginx redirect /app/ to node apixtribe // prefix only use for dev purpose in production a proxy nginx redirect /app/ to node apxtrib
dataclient.routes.forEach( r => { dataclient.routes.forEach( r => {
try { try {
@ -103,17 +108,8 @@ dataclient.routes.forEach( r => {
console.log( 'raise err-:', err ); console.log( 'raise err-:', err );
} }
} ) } )
// Listen web server from config profil (dev prod, other)
app.listen( config.porthttp, () => { app.listen( config.porthttp, () => {
console.log( `check in your browser that api works http://${config.dnsapixtribe}:${config.porthttp}` ); console.log( `check in your browser that api works http://${config.dnsapxtrib}:${config.porthttp}` );
} ); } );
/*httpServer.setTimeout( config.settimeout );
if( config.withssl == "YES" ) {
const httpsServer = https.createServer( config.SSLCredentials, app );
httpsServer.listen( config.port.https, () => {
console.log( `check in your browser that api works https://${config.dnsapixtribe}:${config.port.https}` );
} );
httpsServer.setTimeout( config.settimeout );
};*/
console.log( "\x1b[42m\x1b[37m", "Made with love for people's freedom, enjoy !!!", "\x1b[0m" ); console.log( "\x1b[42m\x1b[37m", "Made with love for people's freedom, enjoy !!!", "\x1b[0m" );

View File

@ -85,7 +85,7 @@ Contracts.initActiontodo = async ( envoie ) => {
const actiondone = await Contracts[ todo.action ]( todo, envoie ); const actiondone = await Contracts[ todo.action ]( todo, envoie );
todo.datesRun.push( moment( new Date() ) todo.datesRun.push( moment( new Date() )
.format( 'YYYYMMDD HH:mm:ss' ) ); .format( 'YYYYMMDD HH:mm:ss' ) );
//console.log("actiondone", actio jsonfile.writeFileSyncndone); //console.log("actiondone"
log.actionlist += "STATUS:" + actiondone.status + " -- " + listaction[ action ] + "\n"; log.actionlist += "STATUS:" + actiondone.status + " -- " + listaction[ action ] + "\n";
if( actiondone.status == 200 ) { if( actiondone.status == 200 ) {
todo.error = ""; todo.error = "";

View File

@ -12,11 +12,11 @@ const config = require( '../tribes/townconf.js' );
const checkdata = require( `../nationchains/socialworld/contracts/checkdata.js`); const checkdata = require( `../nationchains/socialworld/contracts/checkdata.js`);
/* /*
Message manager Message manager
* Manage apixtribe message at different level * Manage apxtrib message at different level
* this means that an object (most often a user or a contact) want to send a question to an other user. * this means that an object (most often a user or a contact) want to send a question to an other user.
To know more http://gitlab.ndda.fr/philc/apixtribe/-/wikis/HOWTONotification To know more http://gitlab.ndda.fr/philc/apxtrib/-/wikis/HOWTONotification
*/ */
const Messages = {}; const Messages = {};
@ -35,7 +35,7 @@ Messages.byEmailwithmailjet = ( tribeid, msg ) => {
TextPart:"texte content", TextPart:"texte content",
HTMLPart:"html content" HTMLPart:"html content"
}] }]
If tribeid has a mailjet account it use it if not then it use the apixtribe @mailjetconf = {apikeypub:, apikeypriv:, From:{Email:,Name:}} If tribeid has a mailjet account it use it if not then it use the apxtrib @mailjetconf = {apikeypub:, apikeypriv:, From:{Email:,Name:}}
This send a bunch of messages check the mailjet account used This send a bunch of messages check the mailjet account used
FYI: Basic account is 200 email /days 6000 /month FYI: Basic account is 200 email /days 6000 /month
Log is stored into Log is stored into
@ -48,12 +48,12 @@ Messages.byEmailwithmailjet = ( tribeid, msg ) => {
if( confclient.smtp && confclient.smtp.mailjet ) { if( confclient.smtp && confclient.smtp.mailjet ) {
mailjetconf = confclient.smtp.mailjet; mailjetconf = confclient.smtp.mailjet;
} else { } else {
const confapixtribe = fs.readJsonSync( `${config.tribes}/${config.mayorId}/clientconf.json` ); const confapxtrib = fs.readJsonSync( `${config.tribes}/${config.mayorId}/clientconf.json` );
if( !( confapixtribe.smtp && confapixtribe.smtp.mailjet ) ) { if( !( confapxtrib.smtp && confapxtrib.smtp.mailjet ) ) {
return { status: 403, data: { models: "Messages", info: [ "nosmtpmailjet" ], moreinfo: "missing smtpmailjet parameter in apixtribe contact your admin to activate an mailjet account on this server." } } return { status: 403, data: { models: "Messages", info: [ "nosmtpmailjet" ], moreinfo: "missing smtpmailjet parameter in apxtrib contact your admin to activate an mailjet account on this server." } }
} }
tribeidsender = "apixtribe"; tribeidsender = "apxtrib";
mailjetconf = confapixtribe.smtp.mailjet; mailjetconf = confapxtrib.smtp.mailjet;
} }
//add from from setings account //add from from setings account
const MSG = msg.map( m => { m.From = mailjetconf.From; return m; } ); const MSG = msg.map( m => { m.From = mailjetconf.From; return m; } );
@ -79,7 +79,7 @@ Messages.byEmailwithmailjet = ( tribeid, msg ) => {
}; };
Messages.buildemail = ( tribeid, tplmessage, data ) => { Messages.buildemail = ( tribeid, tplmessage, data ) => {
/* @tribeid => client concerned by sending email get info from clientconf.json (customization, useradmin:{ EMAIL,LOGIN} , ...) /* @tribeid => client concerned by sending email get info from clientconf.json (customization, useradmin:{ EMAIL,LOGIN} , ...)
@tplmessage => folder where template is available (ex: apixtribe/referentials/dataManagement/template/order) @tplmessage => folder where template is available (ex: apxtrib/referentials/dataManagement/template/order)
@data { destemail = email to @data { destemail = email to
if destuuid => then it get user EMAIL if exiat if destuuid => then it get user EMAIL if exiat
subject = mail subject subject = mail subject
@ -279,7 +279,7 @@ Messages.notification = ( data, header ) => {
}; };
} }
//by default store in tmp/notification this is only for sysadmin //by default store in tmp/notification this is only for sysadmin
// user adminapixtribe // user adminapxtrib
let notdest = `${config.tmp}`; let notdest = `${config.tmp}`;
if( data.app ) { if( data.app ) {

View File

@ -1,18 +1,14 @@
const bcrypt = require( 'bcrypt' ); const bcrypt = require("bcrypt");
const fs = require( 'fs-extra' ); const fs = require("fs-extra");
const path = require( 'path' ); const glob = require("glob");
const jsonfile = require( 'jsonfile' ); const jwt = require("jwt-simple");
const glob = require( 'glob' ); const axios = require("axios");
const jwt = require( 'jwt-simple' ); const config = require("../tribes/townconf.js");
const moment = require( 'moment' ); const Odmdb = require('../models/Odmdb.js');
const axios = require( 'axios' );
const UUID = require( 'uuid' );
const Outputs = require( './Outputs.js' );
const config = require( '../tribes/townconf.js' );
const checkdata = require( `../nationchains/socialworld/contracts/checkdata.js`);
/* /*
Blockchain manager Blockchain manager
* Manage network directory * Manage network directory of nations and towns
* read Blockchain and search, * read Blockchain and search,
* submit a transaction (now) or contract (futur) to store from userA.pubkey to userB.pubkey a number of AXESS * submit a transaction (now) or contract (futur) to store from userA.pubkey to userB.pubkey a number of AXESS
* mine to be able to register a block and create AXESS * mine to be able to register a block and create AXESS
@ -21,85 +17,146 @@ Blockchain manager
*/ */
const Nationchains = {}; const Nationchains = {};
Nationchains.init = () => { Nationchains.init = () => {
console.group( 'init Nationchains' ); console.group("init Nationchains");
} };
Nationchains.synchronize = () => { Nationchains.synchronize = () => {
/* /*
Run process to communicate with a list of apixtribe instance to update transaction and earn AXP Run process to communicate with a list of apxtrib instance to update transaction and earn AXP
To creation of a new tribeid or a new login To creation of a new tribeid or a new login
*/ */
//update himself then send to other information //update himself then send to other information
if( process.env.NODE_ENV != "prod" ) { if (process.env.NODE_ENV != "prod") {
// Not concerned // Not concerned
return {} return {};
} }
const initcurrentinstance = { const initcurrentinstance = {
"fixedIP": "", fixedIP: "",
"lastblocknumber": 0, lastblocknumber: 0,
"firsttimeupdate": 0, firsttimeupdate: 0,
"lastimeupdate": 0, lastimeupdate: 0,
"positifupdate": 0, positifupdate: 0,
"negatifupdate": 0, negatifupdate: 0,
"pubkeyadmin": "", pubkeyadmin: "",
"tribeids": [], tribeids: [],
"logins": [], logins: [],
"knowninstance": [] knowninstance: [],
}; };
let currentinstance = initcurrentinstance; let currentinstance = initcurrentinstance;
try { try {
currentinstance = fs.readFileSync( `${config.tribes}/${config.mayorId}/nationchains/nodes/${config.rootURL}`, 'utf-8' ) currentinstance = fs.readFileSync(
} catch ( err ) { `${config.tribes}/${config.mayorId}/nationchains/nodes/${config.rootURL}`,
console.log( 'first init' ) "utf-8"
} );
const loginsglob = fs.readJsonSync( `${config.tmp}/loginsglob.json`, 'utf-8' ); } catch (err) {
currentinstance.logins = Object.keys( loginsglob ); console.log("first init");
currentinstance.tribeids = [ ...new Set( Object.values( loginsglob ) ) ]; }
currentinstance.instanceknown = glob.Sync( `${config.tribes}/${config.mayorId}/nationchains/nodes/*` ); const loginsglob = fs.readJsonSync(`${config.tmp}/loginsglob.json`, "utf-8");
//Save it currentinstance.logins = Object.keys(loginsglob);
fs.outputJsonSync( `${config.tribes}/${config.mayorId}/nationchains/nodes/${config.rootURL}`, currentinstance ); currentinstance.tribeids = [...new Set(Object.values(loginsglob))];
// proof of work currentinstance.instanceknown = glob.Sync(
// try to find a key based on last block with difficulty `${config.tribes}/${config.mayorId}/nationchains/nodes/*`
// if find then send to all for update and try to get token );
// in any case rerun Nationchains.synchronize() //Save it
currentinstance.instanceknown.forEach( u => { fs.outputJsonSync(
if( u != config.rootURL ) { `${config.tribes}/${config.mayorId}/nationchains/nodes/${config.rootURL}`,
//send currentinstance info and get back state of currentinstance
axios.post( `https://${u}/nationchains/push`, currentinstance ) );
.then( rep => { // proof of work
newdata = rep.payload.moreinfo // try to find a key based on last block with difficulty
//Available update info // if find then send to all for update and try to get token
fs.readJson( `${config.tribes}/${config.mayorId}/nationchains/nodes/${u}`, ( err, data ) => { // in any case rerun Nationchains.synchronize()
if( err ) { currentinstance.instanceknown.forEach((u) => {
data.negatifupdate += 1; if (u != config.rootURL) {
data.lasttimeupdate = Date.now(); //send currentinstance info and get back state of
} else { axios
data.positifupdate += 1; .post(`https://${u}/nationchains/push`, currentinstance)
data.lastimeupdate = Date.now(); .then((rep) => {
data.tribeids = newdata.tribeids; newdata = rep.payload.moreinfo;
data.logins = newdata.logins; //Available update info
data.lastblocknumber = newdata.lastblocknumber; fs.readJson(
newdata.knowninstance.forEach( k => { `${config.tribes}/${config.mayorId}/nationchains/nodes/${u}`,
if( !data.knowninstance.includes( k ) ) { (err, data) => {
data.knowninstance.push( k ); if (err) {
//init the domain for next update data.negatifupdate += 1;
initcurrentinstance.firsttimeupdate = Date.now(); data.lasttimeupdate = Date.now();
fs.outputJson( `${config.tribes}/${config.mayorId}/nationchains/nodes/${k}`, initcurrentinstance, 'utf-8' ) } else {
} data.positifupdate += 1;
} ) data.lastimeupdate = Date.now();
} data.tribeids = newdata.tribeids;
//save with info data.logins = newdata.logins;
fs.outputJson( `${config.tribes}/${config.mayorId}/nationchains/nodes/${u}`, data ); data.lastblocknumber = newdata.lastblocknumber;
} ) newdata.knowninstance.forEach((k) => {
} ) if (!data.knowninstance.includes(k)) {
.catch( err => { data.knowninstance.push(k);
//Not available //init the domain for next update
data.negatifupdate += 1; initcurrentinstance.firsttimeupdate = Date.now();
data.lasttimeupdate = Date.now(); fs.outputJson(
fs.outputJson( `${config.tribes}/${config.mayorId}/nationchains/nodes/${u}`, data ); `${config.tribes}/${config.mayorId}/nationchains/nodes/${k}`,
} ); initcurrentinstance,
} "utf-8"
} ); );
}
});
}
//save with info
fs.outputJson(
`${config.tribes}/${config.mayorId}/nationchains/nodes/${u}`,
data
);
}
);
})
.catch((err) => {
//Not available
data.negatifupdate += 1;
data.lasttimeupdate = Date.now();
fs.outputJson(
`${config.tribes}/${config.mayorId}/nationchains/nodes/${u}`,
data
);
});
}
});
}; };
Nationchains.create = (conf) => {
/*
@conf from a nationchains/socialworld/setup/townSetup {object, nationName, townName, dns}
@return
*/
const res = {};
if (conf.object=="town"){
Odmdb.create("nationchains/socialworld/objects","town",conf);
}
const nation_town = fs.readJsonSync(
"./nationchains/socialworld/objects/towns/searchindex/towns_nationId_townId.json"
);
if (!ObjectKeys(nation_town).includes(conf.nationName)) {
res.status = 404;
res.info = `your nationName ${conf.nationName} does not exist you have to choose an existing one`;
return res;
}
if (nation_town[conf.nationName].includes(conf.townName)) {
res.status = 409;
res.info = `This conf.townName already exist you have to find a unique town name per nation`;
return res;
}
const towndata = {
uuid: conf.townName,
nationid: conf.nationName,
url: `${conf.townName}.${conf.nationName}.${conf.dns}`,
status: (conf.dns=="unchain")? "unchain" : "tochain",
};
const metatown=fs.readJsonSync('./nationchains/socialworld/metaobject/towns.json');
Odmdb.add(objectpath, towns, metatown,towndata)
fs.outputJsonSync(
`./nationchains/socialworld/objects/towns/${townName}.json`,
towndata
);
res.status=200
res.info=`${townName} create for ${nationName} nation`;
return res
};
module.exports = Nationchains; module.exports = Nationchains;

View File

@ -1,10 +1,16 @@
const glob = require( 'glob' ); const glob = require("glob");
const path = require( 'path' ); const path = require("path");
const fs = require( 'fs-extra' ); const fs = require("fs-extra");
const config = require( '../tribes/townconf.js' ); //const config = require( '../tribes/townconf.js' );
const check = require(`../nationchains/socialworld/contracts/checkdata.js`);
/* This manage Objects for indexing and check and act to CRUD
objectpath/objects/schema/objectName.json
/objectNames/searchindes/objectName_valueofkey_uuildlist.json
/objectNames/uuid.json
*/
const Odmdb = {}; const Odmdb = {};
/* /*
Input: metaobject => data mapper of Key: Value Input: metaobject => data mapper of Key: Value
@ -13,5 +19,127 @@ Input: metaobject => data mapper of Key: Value
objname + action index => update /searcindex of objects concern objname + action index => update /searcindex of objects concern
*/ */
Odmdb.schema = (objectPath, objectName) => {
// Return schema if exist and objectpath contain objectName { status:200;data:schema}
if (!fs.existsSync(`${objectPath}/${objectName}`))
return {
status: 404,
info: "|odmdb|objectpathnamedoesnotexist",
moreinfo: `${objectPath}/${objectName}`,
};
if (!fs.existsSync(`${objectPath}/schema/${objectName}.json`)) {
return {
status: 404,
info: `|odmdb|schemanotfound`,
moreinfo: `file not found ${objectPath}/schema/${objectName}.json`,
};
} else {
return {
status: 200,
data: fs.readJsonSync(`${objectPath}/schema/${objectName}.json`),
};
}
};
Odmdb.check = (objectPath, objectName, data) => {
/*
@objectPath path to the folder that contain /objects/objectName/ /objectsInfo/objectName_lg.json /objectsMeta/objectName.json
@objectName name of object
@data data to check based on objectsMeta definition
*/
const schema = Odmdb.schema(objectPath, objectName);
if (schema.status != 200) return schema;
console.log("SCHEMA for checking:");
console.log(schema.data);
console.log("DATA to check:");
console.log(data);
const validate = checkdata.schema.data(schema.data,data)
/*const ajv = new Ajv({strict:"log"});
const validate = ajv.compile(schema.data);
const valid = validate(data)
console.log("valid:",valid)
*/
};
Odmdb.search = (objectPath, objectName, search) => {
/*
@search= {
txt: string,
algo: match | pattern | fuzzy
fieldstring:[list of field],
indexfilter:{index1:[val1,val2 | ] }
}
Return data:[uuids]
example: search exact match hill in townId
heavy search={txt:"hill",algo:"match",fieldstring:"toxnId"}
light search={txt:"hill", algo:"match", indexfilter:{"key":"townId","value":[]}}
light search={txt:"hill", algo:"match", indexfilter:{"key":"nationId","value":"ants"}}
*/
const schema = Odmdb.schema(objectPath, objectName);
if (schema.status != 200) return schema;
};
Odmdb.get = (objectPath, objectName, uuidprimarykeyList, fieldList) => {
/*
@uuidprimarykeyList list of uuid requested
@fieldList key to return for each object
Return objectName {status:200; data:{found:[{primarykey,field}],notfound:[uuid]}
if all primarykey exist then data.notfound does not exist
if all primarykey does not exist data.found does not exist
*/
const res = { status: 200, data: {} };
uuidprimarykeyList.forEach((id) => {
if (fs.existsSync(`${objectPath}/${objectName}/${id}.json`)) {
if (!res.data.found) res.data.found = [];
const objectdata = fs.readJsonSync(
`${objectPath}/${objectName}/${id}.json`
);
if (!fieldList) {
res.data.found.push(objectdata);
} else {
const objinfo = {};
fieldlList.forEach((k) => {
if (objectdata[k]) objinfo[k] = objectdata[k];
});
res.data.found.push(objinfo);
}
} else {
if (!res.data.notfound) res.data.notfound = [];
}
});
return res;
};
Odmdb.create = (objectPath, objectName, data) => {
/*
Create an objects data into objectName
@objectPath path to the folder that contain /objects/objectName/ /objectsInfo/objectName_lg.json /objectsMeta/objectName.json
@objectName name of object
@data data to check based on objectsMeta definition
*/
};
Odmdb.update = (objectPath, objectName, data) => {
/*
Create an objects data into objectName
@objectPath path to the folder that contain /objects/objectName/ /objectsInfo/objectName_lg.json /objectsMeta/objectName.json
@objectName name of object
@data data to check based on objectsMeta definition
*/
};
Odmdb.delete = (objectPath, objectName, data) => {
/*
Create an objects data into objectName
@objectPath path to the folder that contain /objects/objectName/ /objectsInfo/objectName_lg.json /objectsMeta/objectName.json
@objectName name of object
@data data to check based on objectsMeta definition
*/
};
console.log("test Odmdb");
console.log(
Odmdb.check(
"/media/phil/usbfarm/apxtrib/nationchains/socialworld/objects",
"nations",
{ nationId: "123", status: "unchain" }
)
);
module.exports = Odmdb; module.exports = Odmdb;

View File

@ -435,7 +435,7 @@ Outputs.addjson = function ( data, header ) {
try { try {
fs.outputJsonSync( header.destinationfile + '/' + header.filename, data.jsonp ); fs.outputJsonSync( header.destinationfile + '/' + header.filename, data.jsonp );
if( data.callback ) { if( data.callback ) {
const execCB = require( `${config.mainDir}/models/tribeid/${header.xworkon const execCB = require( `${__base}/models/tribeid/${header.xworkon
}` ); }` );
execCB[ data.callback ](); execCB[ data.callback ]();
} }

View File

@ -350,7 +350,7 @@ Outputs.addjson = function ( data, header ) {
try { try {
fs.outputJsonSync( header.destinationfile + '/' + header.filename, data.jsonp ); fs.outputJsonSync( header.destinationfile + '/' + header.filename, data.jsonp );
if( data.callback ) { if( data.callback ) {
const execCB = require( `${config.mainDir}/models/tribeid/${header.xworkon const execCB = require( `${__base}/models/tribeid/${header.xworkon
}` ); }` );
execCB[ data.callback ](); execCB[ data.callback ]();
} }

View File

@ -1,6 +1,5 @@
const bcrypt = require( 'bcrypt' ); const bcrypt = require( 'bcrypt' );
const fs = require( 'fs-extra' ); const fs = require( 'fs-extra' );
const jsonfile = require( 'jsonfile' );
const glob = require( 'glob' ); const glob = require( 'glob' );
const moment = require( 'moment' ); const moment = require( 'moment' );
const jwt = require( 'jwt-simple' ); const jwt = require( 'jwt-simple' );

View File

@ -239,7 +239,7 @@ Referentials.update = ( tribeid, source, name ) => {
} }
} }
}; };
//console.log( Referentials.update( 'apixtribe', "object", "user" ) ) //console.log( Referentials.update( 'apxtrib', "object", "user" ) )
Referentials.genereobjet = ( tribeid, destination, tplmustache, objet, filtre ) => { Referentials.genereobjet = ( tribeid, destination, tplmustache, objet, filtre ) => {
/* @TODO /* @TODO

View File

@ -204,7 +204,7 @@ Referentials.update = ( tribeid, source, name ) => {
} }
} }
}; };
//console.log( Referentials.update( 'apixtribe', "object", "user" ) ) //console.log( Referentials.update( 'apxtrib', "object", "user" ) )
Referentials.genereobjet = ( tribeid, destination, tplmustache, objet, filtre ) => { Referentials.genereobjet = ( tribeid, destination, tplmustache, objet, filtre ) => {
/* @TODO /* @TODO

View File

@ -2,6 +2,7 @@ const fs = require( 'fs-extra' );
const path = require( 'path' ); const path = require( 'path' );
const dnsSync = require( 'dns-sync' ); const dnsSync = require( 'dns-sync' );
const Mustache = require( 'mustache' ); const Mustache = require( 'mustache' );
const Odmdb= require('./Odmdb.js');
const Setup = {}; const Setup = {};
@ -9,11 +10,11 @@ if( !fs.existsSync( '/etc/nginx/nginx.conf' ) ) {
console.log( '\x1b[31m Check documentation, nginx have to be installed on this server first, no /etc/nginx/nginx.conf available' ); console.log( '\x1b[31m Check documentation, nginx have to be installed on this server first, no /etc/nginx/nginx.conf available' );
process.exit(); process.exit();
} }
if( !fs.existsSync( '../config.js' ) ) { if( !fs.existsSync( `./tribes/townconf.json` ) ) {
console.log( `\x1b[42m####################################\nWellcome into apixtribe, this is a first install.\nWe need to make this server accessible from internet subdomain.domain to current IP. This setup will create your unique tribeid, with an admin login user to let you connect to the parameter interface.\nCheck README's project to learn more. more.\n#####################################\x1b[0m` ); console.log( `\x1b[42m####################################\nWellcome into apxtrib, this is a first install.\nWe need to make this server accessible from internet subdomain.domain to current IP. This setup will create your unique tribeid, with an admin login user to let you connect to the parameter interface.\nCheck README's project to learn more. more.\n#####################################\x1b[0m` );
const confdata = fs.readJsonSync( path.normalize( `${__dirname}/../setup/configsetup.json` ) ); const townSetup = fs.readJsonSync( './nationchains/socialworld/setup/townSetup.json') ;
console.log( 'Current setup conf from :\n' + path.normalize( `${__dirname}/../setup/configsetup.json` + '\nChange with relevant setup data and rerun yarn setup' ) ); console.log( `Current setup conf from :./nationchains/socialworld/setup/townSetup.json\nChange with relevant setup data and rerun yarn setup` ) ;
console.log( confdata ) console.log( townSetup )
const readline = require( 'readline' ); const readline = require( 'readline' );
const rl = readline.createInterface( { const rl = readline.createInterface( {
input: process.stdin, input: process.stdin,
@ -21,16 +22,26 @@ if( !fs.existsSync( '../config.js' ) ) {
} ); } );
rl.question( 'This is the data from setup/configsetup.json used, is it correct to use as first install (Yes/no)?', function ( rep1 ) { rl.question( 'This is the data from setup/configsetup.json used, is it correct to use as first install (Yes/no)?', function ( rep1 ) {
let quest = `This is a production install, please check that ${confdata.subdomain}.${confdata.domain} IP is well redirect to tour server`; let quest = `This is a production install, please check that ${townSetup.townName}.${townSetup.nationName}.${townSetup.dns} IP is well redirect to tour server`;
if( rep1 !== "Yes" ) process.exit( 0 ); if( rep1 !== "Yes" ) process.exit( 0 );
if( confdata.domain == 'local.fr' ) { if( townSetup.dns == 'unchain' ) {
quest = `This is a development installation, please add in your /etc/hosts "127.0.0.1 ${confdata.subdomain}.${confdata.domain} " `; quest = `This is a development installation, please add in your /etc/hosts 127.0.0.1 ${townSetup.townName}.${townSetup.nationName}.${townSetup.dns} `;
} }
rl.question( quest + '\nAre you sure to set this? (Yes/no)', function ( rep2 ) { rl.question( quest + '\nAre you sure to set this? (Yes/no)', function ( rep2 ) {
if( rep2 == "Yes" ) { if( rep2 == "Yes" ) {
const check = Setup.checkdata( confdata ); const check = Setup.check( townSetup );
if( check == "" ) { if( check == "" ) {
Setup.config( confdata ); const townconf=fs.readJsonSync('./nationchains/socialworld/setup/townSetup.json')
// create tribes folder with townconf.json
fs.outputJsonSync(`./tribes/townconf.json`,{...townSetup,...townconf},{spaces:2})
const Nationchains = require('./Nationchains');
const Tribes = require('./Tribes');
const Pagans = require('./Pagans');
townSetup.object="town"
Nationschains.create(townSetup);
Tribes.create(townSetup);
Pagans.create(townSetup);
//Setup.config( townSetup );
} else { } else {
console.log( check ); console.log( check );
} }
@ -48,93 +59,100 @@ if( !fs.existsSync( '../config.js' ) ) {
console.log( 'Carefull you have already a config.js that is running. If you want to change remove config.js file and run again yarn setup' ); console.log( 'Carefull you have already a config.js that is running. If you want to change remove config.js file and run again yarn setup' );
} }
Setup.checkdata = conf => { Setup.check = conf => {
let rep = ""; var rep = "";
if( ![ 'dev', 'prod' ].includes( conf.mode ) ) { const nation_town=fs.readJsonSync('./nationchains/socialworld/objects/towns/searchindex/towns_nation_uuid.json');
rep += "mode have to be 'dev' or 'prod' currently it's " + conf.mode + "\n"; if (!ObjectKeys(nation_town).includes(conf.nationName)){
rep+=`your nationName ${conf.nationName} does not exist you have to choose an existing one`;
} }
if (nation_town[conf.nationName].includes(conf.townName)){
rep+=`This conf.townName already exist you have to find a unique town name per nation`;
}
const getnation = Odmdb.get('./nationchains/socialworld/objects','towns',[conf.NationName];[nationId])
if getnation.data.notfound
conf.language.forEach( l => { conf.language.forEach( l => {
if( ![ "fr", "en", "it", "de", "sp" ].includes( l ) ) { if( ![ "fr", "en", "it", "de", "sp" ].includes( l ) ) {
rep += l + " Only fr,en,it,de,sp are available \n"; rep += l + " Only fr,en,it,de,sp are available \n";
} }
} ); } );
if( !fs.existsSync( `/home/${conf.linuxuser}` ) ) { if( !fs.existsSync( `/home/${conf.sudoerUser}` ) ) {
rep += `/home/${conf.linuxuser} does not exist, user has to be create with a /home on this server\n`; rep += `/home/${conf.sudoerUser} does not exist, user has to be create with a /home on this server\n`;
} }
// avant eslint if( !( /^[a-z\s\-]+$/.test( conf.druidid ) ) ) { try {
if( !( /^[a-z\s-]+$/.test( conf.druidid ) ) ) { if ("true"== execSync("timeout 2 sudo id && sudo=\"true\" || sudo=\"false\";echo \"$sudo\"").toString().trim().split(/\r?\n/).slice(-1)) {
rep += `${conf.druidid} have to contain only a-z characters `; rep+=`${sudoerUser} is not sudoer please change this `;
} } ;
// add a check later have to be unique if not in dev }catch(err){
if( !( /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&.])[A-Za-z\d$@$!%*?&.{}:|\s]{8,}/.test( conf.genericpsw ) ) ) { console.log(err);
rep += "Give a generic pasword for all your tribeid's user,they will change it min 8 char special char upper lower case and number" rep+=" Check your user it seems to not be a sudoer"
} }
if( conf.jwtsecret.length < 32 ) { if( conf.jwtsecret.length < 32 ) {
rep += "Your jwtsecretkey must have at least 32 characters" rep += "Your jwtsecretkey must have at least 32 characters"
} }
if( conf.mode != 'dev' && !dnsSync.resolve( `${conf.subdomain}.${conf.domain}` ) ) { if( conf.dns != 'unchain' && !dnsSync.resolve( `${conf.townName}.${conf.nationName}.${conf.dns}` ) ) {
rep += `\nresolving ${conf.subdomain}.${conf.domain} will not responding valid IP, please setup domain redirection IP before runing this script` rep += `\nresolving $${conf.townName}.${conf.nationName}.${conf.dns} will not responding valid IP, please setup domain redirection IP before runing this script`
} }
return rep return rep
}; };
Setup.config = ( confdata ) => {
Setup.config = ( townSetup ) => {
// Init this instance with a .config.js // Init this instance with a .config.js
Setup.configjs( confdata ); Setup.configjs( townSetup );
// Create tribeid space + a user admin + webspace withe apixtribe webapp install // Create tribeid space + a user admin + webspace withe apxtrib webapp install
Setup.druidid( confdata ); Setup.druidid( townSetup );
}; };
Setup.configjs = ( confdata ) => { Setup.configjs = ( townSetup ) => {
// Set /config.js // Set /config.js
let confapixtribe = fs.readFileSync( './setup/config.mustache', 'utf-8' ); let confapxtrib = fs.readFileSync( './setup/config.mustache', 'utf-8' );
fs.writeFileSync( './config.js', Mustache.render( confapixtribe, confdata ), 'utf-8' ); fs.writeFileSync( './config.js', Mustache.render( confapxtrib, townSetup ), 'utf-8' );
if( fs.existsSync( './config.js' ) ) { if( fs.existsSync( './config.js' ) ) {
console.log( 'config.js successfully created.' ); console.log( 'config.js successfully created.' );
} else { } else {
console.log( "config.js not created, check what's wrong in tpl:", confapixtribe ); console.log( "config.js not created, check what's wrong in tpl:", confapxtrib );
console.log( "for data :", confdata ); console.log( "for data :", townSetup );
process.exit(); process.exit();
} }
}; };
Setup.druidid = ( confdata ) => { Setup.druidid = ( townSetup ) => {
// create a tribeid with a user that will admin this instance into /tribes/tribeid /users // create a tribeid with a user that will admin this instance into /tribes/tribeid /users
const config = require( '../config.js' ); const config = require( '../config.js' );
// Need to do it on setup this is also done again in models/Tribes.js // Need to do it on setup this is also done again in models/Tribes.js
console.log( `${config.tribes}/${confdata.druidid}` ) console.log( `${config.tribes}/${townSetup.druidid}` )
fs.ensureDirSync( `${config.tribes}/${confdata.druidid}` ); fs.ensureDirSync( `${config.tribes}/${townSetup.druidid}` );
[ 'users', 'www', 'referentials', 'nationchains' ].forEach( r => { [ 'users', 'www', 'referentials', 'nationchains' ].forEach( r => {
fs.copySync( `${config.mainDir}/setup/tribes/apixtribe/${r}`, `${config.tribes}/${confdata.druidid}/${r}` ); fs.copySync( `${__base}/setup/tribes/apxtrib/${r}`, `${config.tribes}/${townSetup.druidid}/${r}` );
} ) } )
/* const confcli = JSON.parse( Mustache.render( fs.readFileSync( `${config.mainDir}/setup/tribes/apixtribe/clientconf.mustache`, 'utf8' ), confdata ) ); /* const confcli = JSON.parse( Mustache.render( fs.readFileSync( `${__base}/setup/tribes/apxtrib/clientconf.mustache`, 'utf8' ), townSetup ) );
fs.outputJsonSync( `${config.tribes}/${confdata.druidid}/clientconf.json`, confcli ); fs.outputJsonSync( `${config.tribes}/${townSetup.druidid}/clientconf.json`, confcli );
// Create a new tribeid + admin user for this tribeid // Create a new tribeid + admin user for this tribeid
// with access to {druidid}:webapp as admin // with access to {druidid}:webapp as admin
*/ */
const Tribes = require( '../models/Tribes.js' ); const Tribes = require( '../models/Tribes.js' );
const access = { app: {}, data: {} } const access = { app: {}, data: {} }
access.app[ `${confdata.druidid}:webapp` ] = "admin"; access.app[ `${townSetup.druidid}:webapp` ] = "admin";
access.data[ confdata.druidid ] = { "users": "CRUDO", "referentials": "CRUDO", "www": "CRUDO" }; access.data[ townSetup.druidid ] = { "users": "CRUDO", "referentials": "CRUDO", "www": "CRUDO" };
const createclient = Tribes.create( { const createclient = Tribes.create( {
tribeid: confdata.druidid, tribeid: townSetup.druidid,
genericpsw: confdata.genericpsw, genericpsw: townSetup.genericpsw,
lanquageReferential: confdata.language, lanquageReferential: townSetup.language,
useradmin: { useradmin: {
LOGIN: confdata.login, LOGIN: townSetup.login,
xlang: confdata.language[ 0 ], xlang: townSetup.language[ 0 ],
ACCESSRIGHTS: access ACCESSRIGHTS: access
} }
} ); } );
if( createclient.status == 200 ) { if( createclient.status == 200 ) {
console.log( `Your tribeid domain was created with login : ${confdata.login} and password: ${confdata.genericpsw}, change it after the 1st login on https://${confdata.subdomain}.${confdata.domain}` ); console.log( `Your tribeid domain was created with login : ${townSetup.login} and password: ${townSetup.genericpsw}, change it after the 1st login on https://${townSetup.subdomain}.${townSetup.domain}` );
// Create nginx conf for a first install // Create nginx conf for a first install
const confnginx = fs.readFileSync( './setup/nginx/nginx.conf.mustache', 'utf8' ); const confnginx = fs.readFileSync( './setup/nginx/nginx.conf.mustache', 'utf8' );
fs.outputFileSync( '/etc/nginx/nginx.conf', Mustache.render( confnginx, confdata ), 'utf-8' ); fs.outputFileSync( '/etc/nginx/nginx.conf', Mustache.render( confnginx, townSetup ), 'utf-8' );
// Create a spacedev for webapp of apixtribe // Create a spacedev for webapp of apxtrib
// that will be accesible in prod from https://subdomain.domain/ and in dev http://webapp.local.fr // that will be accesible in prod from https://subdomain.domain/ and in dev http://webapp.local.fr
const addspaceweb = Tribes.addspaceweb( { const addspaceweb = Tribes.addspaceweb( {
setup: true, setup: true,
dnsname: [ `${confdata.subdomain}.${confdata.domain}` ], dnsname: [ `${townSetup.subdomain}.${townSetup.domain}` ],
mode: confdata.mode, mode: townSetup.mode,
tribeid: confdata.druidid, tribeid: townSetup.druidid,
website: 'webapp', website: 'webapp',
pageindex: "app_index_fr.html" pageindex: "app_index_fr.html"
} ); } );

View File

@ -1,13 +1,10 @@
const fs = require( 'fs' ); const fs = require( 'fs-extra' );
const formidable = require( 'formidable' );
const jsonfile = require( 'jsonfile' );
const path = require( 'path' ); const path = require( 'path' );
const glob = require( 'glob' ); const glob = require( 'glob' );
const mustache = require( 'mustache' );
const moment = require( 'moment' ); const moment = require( 'moment' );
// Check if package is installed or not to pickup the right config file // Check if package is installed or not to pickup the right config file
const config = require( '../tribes/townconf.js' ); //const config = require( '../tribes/townconf.js' );
const config={}
const Tags = {}; const Tags = {};
/* /*
@ -64,7 +61,7 @@ Tags.getfile = ( filename, req ) => {
} ); } );
return { return {
status: 200, status: 200,
payload: { moreinfo: "Declenche tag", filename: `${config.mainDir}/public/imgtg.png` } payload: { moreinfo: "Declenche tag", filename: `${__base}/public/imgtg.png` }
} }
} }
return { status: 404, payload: {} } return { status: 404, payload: {} }
@ -226,4 +223,89 @@ Tags.dataloadstat = ( tribeid ) => {
console.log(ar.some(el => el[0] == 1 && el[1] == 1)) console.log(ar.some(el => el[0] == 1 && el[1] == 1))
console.log(ar.some(el => el == [1, 3])) console.log(ar.some(el => el == [1, 3]))
*/ */
Tags.nginxlog=(pathFile)=>{
/*
Read an nginx log file and return
@TODO standardiser le log nginx pour recuperer des données (IP,...)
@return {visites:{year:month:{day:number of visites}},
visitors:{year:month:{day: number of unique visitors for the day}}
year: number of unique visitors for the year}
month:month : number of unique visitors for the month]
}
*/
const log= fs.readFileSync(pathFile,'utf-8');
const logs=log.split('\n');
console.log(`nombre ligne ${logs.length}`)
const stat={visits:{},visitors:{}};
const visitor={}
var previousdt=moment();
var previoususeragent="";
console.log(moment(previousdt).format('DD/MMM/YYYY:hh:mm:ss'))
logs.forEach(l=>{
const elt= l.split('##');
const useragent = (elt[2] && elt[2].split("\" \"")[1]) ? elt[2].split("\" \"")[1]:"unknown";
//elt[0] = [30/Jun/2022:15:15:53 +0200]
const dttime = moment(elt[0].split(' ')[0].substring(1),'DD/MMM/YYYY:hh:mm:ss');
['visits','visitors'].forEach(ch=>{
if (!stat[ch][dttime.format('YYYY')]) stat[ch][dttime.format('YYYY')]={};
if (!stat[ch][dttime.format('YYYY')][dttime.format('MMM')]) stat[ch][dttime.format('YYYY')][dttime.format('MMM')]={}
if (!stat[ch][dttime.format('YYYY')][dttime.format('MMM')][dttime.format('DD')]) stat[ch][dttime.format('YYYY')][dttime.format('MMM')][[dttime.format('DD')]]=0
if (!visitor[dttime.format('YYYY')]) visitor[dttime.format('YYYY')]={};
if (!visitor[dttime.format('YYYY')][dttime.format('MMM')]) visitor[dttime.format('YYYY')][dttime.format('MMM')]={}
if (!visitor[dttime.format('YYYY')][dttime.format('MMM')][dttime.format('DD')]) visitor[dttime.format('YYYY')][dttime.format('MMM')][[dttime.format('DD')]]=[]
})
//console.log(elt[0].split(' ')[0]+ "####" + moment(elt[0],'DD/MMM/YYYY:hh:mm:ss').format('DD-MM-YYYY h:mm:ss'));
//console.log("EEEE"+moment(previousdt).format('DD/MMM/YYYY:hh:mm:ss') + "hhhhhhh" +moment(dttime).format('DD/MMM/YYYY:hh:mm:ss'))
//console.log(previousdt!=dttime)
if (!visitor[dttime.format('YYYY')][dttime.format('MMM')][dttime.format('DD')].includes(useragent)){
visitor[dttime.format('YYYY')][dttime.format('MMM')][dttime.format('DD')].push(useragent)
}
if (previoususeragent != useragent || parseInt(Math.round(previousdt.toDate().getTime()/100000)) != parseInt(Math.round(dttime.toDate().getTime()/100000))) {
/*console.log("###########################################################");
console.log(`${previousdt.toDate().getTime()} != ${dttime.toDate().getTime()}`);
console.log(moment(previousdt).format('DD/MMM/YYYY:hh:mm:ss') + "hhhhhhh" + moment(dttime).format('DD/MMM/YYYY:hh:mm:ss'))
console.log(`useragent: ${useragent} previoususeragent: ${previoususeragent}`);
*/
stat['visits'][dttime.format('YYYY')][dttime.format('MMM')][[dttime.format('DD')]]+=1
previousdt=dttime;
previoususeragent=useragent;
}else{
//console.log("identique compte pas" )
}
})
Object.keys(visitor).forEach(y=>{
var uniqvisitoryear=[];
Object.keys(visitor[y]).forEach(m=>{
var uniqvisitormonth=[];
Object.keys(visitor[y][m]).forEach(d=>{
uniqvisitormonth = [...uniqvisitormonth, ...visitor[y][m][d]]
stat.visitors[y][m][d] = visitor[y][m][d].length
})
uniqvisitoryear=[...uniqvisitoryear, ...uniqvisitormonth]
stat.visitors[y][m][m]=uniqvisitormonth.length;
})
stat.visitors[y][y]=uniqvisitoryear.length
})
return {status:200, data:stat}
}
Tags.statin2D=(stat,pathfile)=>{
if (stat.status==200){
stat=stat.data
}else {
return stat
}
let csv="type;year;month;day;Number\n\r";
["visits", "visitors"].forEach(ch=>{
Object.keys(stat[ch]).forEach(y=>{
Object.keys(stat[ch][y]).forEach(m=>{
Object.keys(stat[ch][y][m]).forEach(d=>{
csv+=`${ch};${y};${m};${d};${stat[ch][y][m][d]}\n\r`
})
})
})
})
fs.outputFileSync(pathfile,csv);
return {status:200, info:"fileready", moreinfo:pathfile}
}
console.log(Tags.statin2D(Tags.nginxlog('/home/phil/Documents/nginx/presentation.capsthd.access.log'),'/home/phil/Documents/nginx/stat.csv'));
module.exports = Tags; module.exports = Tags;

View File

@ -11,7 +11,7 @@ const moment = require( 'moment' );
const UUID = require( 'uuid' ); const UUID = require( 'uuid' );
const Outputs = require( './Outputs.js' ); const Outputs = require( './Outputs.js' );
const Pagans = require( './Pagans.js' ); const Pagans = require( './Pagans.js' );
const config = require( '../tribes/townconf.js' ); const config = require( '../tribes/townconf' );
const checkdata = require( `../nationchains/socialworld/contracts/checkdata.js`); const checkdata = require( `../nationchains/socialworld/contracts/checkdata.js`);
/* /*
@ -61,19 +61,19 @@ Tribes.init = () => {
Tribes.create = ( data ) => { Tribes.create = ( data ) => {
/* data = clientconf.json /* data = clientconf.json
{ {
"tribeid": "apixtribe", "tribeid": "apxtrib",
"genericpsw": "Trze3aze!", "genericpsw": "Trze3aze!",
"website": { "website": {
"presentation":"https://www.apixtribe.org", "presentation":"https://www.apxtrib.org",
"webapp": "https://webapp.apixtribe.org" "webapp": "https://webapp.apxtrib.org"
}, },
"allowedDOMs": ["local.fr", "localhost:9002", "ndda.fr", "apixtribe.org"], "allowedDOMs": ["local.fr", "localhost:9002", "ndda.fr", "apxtrib.org"],
"clientname": "apixtribe", "clientname": "apxtrib",
"clientlogo": "", "clientlogo": "",
"geoloc": [], "geoloc": [],
"useradmin": {PUBKEY:"",EMAIL:"",LOGIN:"adminapixtribe",UUID:"adminapixtribe"}, "useradmin": {PUBKEY:"",EMAIL:"",LOGIN:"adminapxtrib",UUID:"adminapxtrib"},
"smtp": { "smtp": {
"emailFrom": "support@apixtribe.org", "emailFrom": "support@apxtrib.org",
"emailcc": [], "emailcc": [],
"service": "gmail", "service": "gmail",
"auth": { "auth": {
@ -90,7 +90,7 @@ Tribes.create = ( data ) => {
"dnsname": a domain name belonging to the client "dnsname": a domain name belonging to the client
"subdns": "www", a sub domain subdns.dnsname give a public web access to "subdns": "www", a sub domain subdns.dnsname give a public web access to
"website": { keywebsite:url}, give access to config.tribes/tribeid/www/keywebsite/index.html, "website": { keywebsite:url}, give access to config.tribes/tribeid/www/keywebsite/index.html,
"allowedDOMs": ["local.fr", "localhost:9002", "nnda.fr"], //for CORS, @TODO generate from prévious URL this allow this apixtribe instance to be accessible "allowedDOMs": ["local.fr", "localhost:9002", "nnda.fr"], //for CORS, @TODO generate from prévious URL this allow this apxtrib instance to be accessible
"clientname": Name of the organisation if any, "clientname": Name of the organisation if any,
"clientlogo": logo of the organisation if any, "clientlogo": logo of the organisation if any,
"geoloc": [], if any "geoloc": [], if any
@ -98,7 +98,7 @@ Tribes.create = ( data ) => {
"PUBKEY":public key to be authentify without an email, "PUBKEY":public key to be authentify without an email,
"EMAIL":user email, we need at least one of authentification set up after the user can use both or only one "EMAIL":user email, we need at least one of authentification set up after the user can use both or only one
"LOGIN": login to use for access admintribeid, "LOGIN": login to use for access admintribeid,
"UUID": unique id normaly UUID but a uuid admintribeid is the same person in any apixtribe instance so we use it by convention. "UUID": unique id normaly UUID but a uuid admintribeid is the same person in any apxtrib instance so we use it by convention.
"xlang": lang used by this user "xlang": lang used by this user
}, },
"smtp": { smtp used to send email by nodemailer lib basic example with a google account "smtp": { smtp used to send email by nodemailer lib basic example with a google account
@ -134,10 +134,10 @@ Tribes.create = ( data ) => {
} }
fs.ensureDirSync( `${config.tribes}/${data.tribeid}` ); fs.ensureDirSync( `${config.tribes}/${data.tribeid}` );
[ 'users', 'www', 'referentials', 'nationchains' ].forEach( r => { [ 'users', 'www', 'referentials', 'nationchains' ].forEach( r => {
fs.copySync( `${config.mainDir}/setup/tribes/apixtribe/${r}`, `${config.tribes}/${data.tribeid}/${r}` ); fs.copySync( `${__base}/setup/tribes/apxtrib/${r}`, `${config.tribes}/${data.tribeid}/${r}` );
} ) } )
fs.outputJsonSync( `${config.tribes}/${data.tribeid}/clientconf.json`, data ); fs.outputJsonSync( `${config.tribes}/${data.tribeid}/clientconf.json`, data );
const confcli = JSON.parse( Mustache.render( fs.readFileSync( `${config.mainDir}/setup/tribes/apixtribe/clientconf.mustache`, 'utf8' ), data ) ); const confcli = JSON.parse( Mustache.render( fs.readFileSync( `${__base}/setup/tribes/apxtrib/clientconf.mustache`, 'utf8' ), data ) );
fs.outputJsonSync( `${config.tribes}/${data.tribeid}/clientconf.json`, confcli ); fs.outputJsonSync( `${config.tribes}/${data.tribeid}/clientconf.json`, confcli );
return Pagans.createUser( { return Pagans.createUser( {
@ -151,7 +151,7 @@ Tribes.archive = ( tribeid ) => {
// remove tribeid de data ou devdata // remove tribeid de data ou devdata
try { try {
fs.moveSync( `${config.tribes}/${tribeid}`, `${config.archivefolder}/${tribeid}` ); fs.moveSync( `${config.tribes}/${tribeid}`, `${config.archivefolder}/${tribeid}` );
//update apixtribeenv //update apxtribenv
Tribes.init(); Tribes.init();
return { status: 200, payload: { info: [ 'deletetribeidsuccessfull' ], models: 'Tribes', moreinfo: "TODO see in Tribes.archive" } } return { status: 200, payload: { info: [ 'deletetribeidsuccessfull' ], models: 'Tribes', moreinfo: "TODO see in Tribes.archive" } }
} catch ( err ) { } catch ( err ) {
@ -279,7 +279,7 @@ Tribes.addspaceweb = ( data ) => {
nginx conf and ssl to serve each https://dnsname to /{tribeid}/www/app/{website} nginx conf and ssl to serve each https://dnsname to /{tribeid}/www/app/{website}
Carefull this action is executed with root and restart nginx + apixtribe to work Carefull this action is executed with root and restart nginx + apxtrib to work
*/ */
data.configdomain = config.tribes; data.configdomain = config.tribes;
data.porthttp = config.porthttp; data.porthttp = config.porthttp;
@ -293,7 +293,7 @@ Tribes.addspaceweb = ( data ) => {
// add nginx http config // add nginx http config
const confnginx = fs.readFileSync( 'setup/nginx/modelwebsite.conf.mustache', 'utf-8' ); const confnginx = fs.readFileSync( 'setup/nginx/modelwebsite.conf.mustache', 'utf-8' );
fs.outputFileSync( `/etc/nginx/conf.d/${data.dnsname[0]}.conf`, Mustache.render( confnginx, data ), 'utf-8' ); fs.outputFileSync( `/etc/nginx/conf.d/${data.dnsname[0]}.conf`, Mustache.render( confnginx, data ), 'utf-8' );
if( data.mode == "dev" ) { if( data.dns == "unchain" ) {
//add in /etc/hosts //add in /etc/hosts
let hosts = fs.readFileSync( '/etc/hosts', 'utf8' ); let hosts = fs.readFileSync( '/etc/hosts', 'utf8' );
let chg = false; let chg = false;
@ -320,14 +320,14 @@ Tribes.addspaceweb = ( data ) => {
clientconf.allowedDOMs = [ ...new Set( ...clientconf.allowedDOMs, ...data.dnsname ) ]; clientconf.allowedDOMs = [ ...new Set( ...clientconf.allowedDOMs, ...data.dnsname ) ];
fs.outputJsonSync( `${config.tribes}/${data.tribeid}/clientconf.json`, clientconf, 'utf-8' ); fs.outputJsonSync( `${config.tribes}/${data.tribeid}/clientconf.json`, clientconf, 'utf-8' );
if( !data.setup ) { if( !data.setup ) {
// in setup apixtribe is not running and it will be start manually at the 1st run // in setup apxtrib is not running and it will be start manually at the 1st run
// in other case need to plan a restart for CORS // in other case need to plan a restart for CORS
setTimeout( Tribes.restartapixtribe, 300000, data.clienId ); setTimeout( Tribes.restartapxtrib, 300000, data.clienId );
} }
const nginxrestart = execSync( `sudo systemctl restart nginx` ) const nginxrestart = execSync( `sudo systemctl restart nginx` )
.toString(); .toString();
console.log( 'Restart nginx', nginxrestart ) console.log( 'Restart nginx', nginxrestart )
if( data.mode == "prod" ) { if( data.mode != "unchain" ) {
// get ssl certificate ATTENTION il faut ajouter -d devant chaque domain qui redirige vers l'espace web. // get ssl certificate ATTENTION il faut ajouter -d devant chaque domain qui redirige vers l'espace web.
const certbot = execSync( `sudo certbot --nginx -d ${data.dnsname.join(' -d ')}` ) const certbot = execSync( `sudo certbot --nginx -d ${data.dnsname.join(' -d ')}` )
.toString(); .toString();
@ -343,7 +343,7 @@ Tribes.addspaceweb = ( data ) => {
} }
}; };
} }
Tribes.restartapixtribe = ( tribeid ) => { Tribes.restartapxtrib = ( tribeid ) => {
console.log( 'A restarting was requested 5mn ago from a new spacedev for ' + tribeid ) console.log( 'A restarting was requested 5mn ago from a new spacedev for ' + tribeid )
execSync( 'yarn restartpm2' ); execSync( 'yarn restartpm2' );
} }

View File

@ -38,7 +38,7 @@ UploadFiles.addjson = function ( data, header ) {
try { try {
fs.outputJsonSync( header.destinationfile + '/' + header.filename, data.jsonp ); fs.outputJsonSync( header.destinationfile + '/' + header.filename, data.jsonp );
if( data.callback ) { if( data.callback ) {
const execCB = require( `${config.mainDir}/models/tribeid/${ const execCB = require( `${__base}/models/tribeid/${
header.xworkon header.xworkon
}` ); }` );
execCB[ data.callback ](); execCB[ data.callback ]();

4
models/lg/odmdb_en.json Normal file
View File

@ -0,0 +1,4 @@
{
"schemanotfound":"Schema not found",
"bjectpathnamedoesnotexist":"ObjectPath or objectName does not exist "
}

View File

@ -2,7 +2,7 @@
<html lang="fr"> <html lang="fr">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>apiXtribe pourquoi comment</title> <title>apxtrib pourquoi comment</title>
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<script src="script.js"></script> <script src="script.js"></script>
</head> </head>
@ -17,18 +17,18 @@ Our occidental society (globalization) wants us more and more money to control u
To make us under control, our masters print money and force us to breath it. We have no choice; they control institutions, they can stole our properties or our freedom, they drive the single thought. Forget strke and demonstration, to rebalance and create counter-powers, an alternative is to earn the minimum of their money to stay under their radar and keep our ressources (time, energy) to learn, create and share value for our tribes of friends, family, or people that share common view... To make us under control, our masters print money and force us to breath it. We have no choice; they control institutions, they can stole our properties or our freedom, they drive the single thought. Forget strke and demonstration, to rebalance and create counter-powers, an alternative is to earn the minimum of their money to stay under their radar and keep our ressources (time, energy) to learn, create and share value for our tribes of friends, family, or people that share common view...
A DAO, by design (the blockchain) cannot be control by a central power, because it is a common good, each actor has a benefit and is free to apply fair rules.<br> A DAO, by design (the blockchain) cannot be control by a central power, because it is a common good, each actor has a benefit and is free to apply fair rules.<br>
apiXtribes aims to allow any group of people to define rules to apply for their exchange of values. apxtribs aims to allow any group of people to define rules to apply for their exchange of values.
With our master's money to create value you have to respect their rules (a register company, list of standards, list of taxes, ...) in exchange you benefit of institutions like protections (police with the legitimate violence), justice (law), school, medical, ... If you are a good boy then master give you back cash grant. With our master's money to create value you have to respect their rules (a register company, list of standards, list of taxes, ...) in exchange you benefit of institutions like protections (police with the legitimate violence), justice (law), school, medical, ... If you are a good boy then master give you back cash grant.
If you agree with the master's world, and happy to let institution decide for you, this is fine (apiXtribe is not for you). But if you consider that diversity is more resilient than standard and **you want to have choices then this project is for you.** Who knows the futur ;-) apiXtribe could be use to run the democratie (demos kratos: by the people for the people). If you agree with the master's world, and happy to let institution decide for you, this is fine (apxtrib is not for you). But if you consider that diversity is more resilient than standard and **you want to have choices then this project is for you.** Who knows the futur ;-) apxtrib could be use to run the democratie (demos kratos: by the people for the people).
## Why money is the sinews of war ## Why money is the sinews of war
Our masters killed social ties by implementing the KPI (Key Performance Indicator) to quantify the value of each of us base on their rules. Their money is magic, they use as KPI of an individual value as well as the tools to drive our life. In occident, who can survive today without money in his pocket or in master's bank? Our masters killed social ties by implementing the KPI (Key Performance Indicator) to quantify the value of each of us base on their rules. Their money is magic, they use as KPI of an individual value as well as the tools to drive our life. In occident, who can survive today without money in his pocket or in master's bank?
By **disconnecting value of money with gold or other "physical limit"** the money just value what they decide.<br> By **disconnecting value of money with gold or other "physical limit"** the money just value what they decide.<br>
apiXtribe use a crypto (that looks like a money but is not a money) to value each rule application to create a proof of work and at least a proof of stake that any human involve has an interest to protect it. apxtrib use a crypto (that looks like a money but is not a money) to value each rule application to create a proof of work and at least a proof of stake that any human involve has an interest to protect it.
Then rules (**contracts**) can be set by anyone based on **an algo like if/then** between 2 humans. When the condition is trig then something is register in the blockchain. Then rules (**contracts**) can be set by anyone based on **an algo like if/then** between 2 humans. When the condition is trig then something is register in the blockchain.
@ -45,20 +45,20 @@ Then rules (**contracts**) can be set by anyone based on **an algo like if/then*
"B is baned of the community" "B is baned of the community"
``` ```
**apiXtribe blockchain will register this standard "contracts" and "reputation" of those who respects or not contracts. This cannot be change by any one and any one can read it.**<br> **apxtrib blockchain will register this standard "contracts" and "reputation" of those who respects or not contracts. This cannot be change by any one and any one can read it.**<br>
A and B are just unique identificator (anonymous or not), to prove a human own A or B, apiXtribe use cryptograpĥic PGP based on public/private key. apiXtribe needs a network topology to be strong enough to avoid central control. This is why apiXtribe recommand rewarding rules to actor that provide electricity, machine, network access. Virtual world exist because physical one exist. A and B are just unique identificator (anonymous or not), to prove a human own A or B, apxtrib use cryptograpĥic PGP based on public/private key. apxtrib needs a network topology to be strong enough to avoid central control. This is why apxtrib recommand rewarding rules to actor that provide electricity, machine, network access. Virtual world exist because physical one exist.
Until you stay **in crypto world, you just exchange data so no tax** (no master's rules). You can sale a service against money until you respect master/country's rule of this money (company that collect value tax, register turnover, ...). Then you can deliver crypto to your customer to consume your's or other's services when they want. If you exchange token against gov money then you have to respect your gov's laws (some country's law ask you to pay tax onto added value). So be aware of what you are doing some gov can kill you or put you in jail to exchange their money or data. This Xtrib coin is not for speculation is for social link without man in the middle that stole you. Until you stay **in crypto world, you just exchange data so no tax** (no master's rules). You can sale a service against money until you respect master/country's rule of this money (company that collect value tax, register turnover, ...). Then you can deliver crypto to your customer to consume your's or other's services when they want. If you exchange token against gov money then you have to respect your gov's laws (some country's law ask you to pay tax onto added value). So be aware of what you are doing some gov can kill you or put you in jail to exchange their money or data. This Xtrib coin is not for speculation is for social link without man in the middle that stole you.
</p> </p>
<p> <p>
**As a non tech,** you can invest and request to get your own nation or town (become a mayor) or tribe (become a druid). As non tech you'll need the help of a dev that will help you to modelise and setup Contracts. Any way you can also simply join any tribe as pagan and sales data/product and exchange it again Xtrib coin of a nation. **As a non tech,** you can invest and request to get your own nation or town (become a mayor) or tribe (become a druid). As non tech you'll need the help of a dev that will help you to modelise and setup Contracts. Any way you can also simply join any tribe as pagan and sales data/product and exchange it again Xtrib coin of a nation.
For non tech, if you have a project please request it to [support@apixtribe.org](mailto:support@apixtribe.org) For non tech, if you have a project please request it to [support@apxtrib.org](mailto:support@apxtrib.org)
**As tech**: **As tech**:
**- As sysadmin** you can install a town, for yourself or for a "non tech" and earn Xtrib in exchange<br> **- As sysadmin** you can install a town, for yourself or for a "non tech" and earn Xtrib in exchange<br>
**- As back-end and front-end dev** you can dev web service (node.js express static web based on pwa) that you can sale to a druid or a mayor, or become yourself a druid and host a town to sale usage against Xtribe.<br> **- As back-end and front-end dev** you can dev web service (node.js express static web based on pwa) that you can sale to a druid or a mayor, or become yourself a druid and host a town to sale usage against Xtribe.<br>
**- As a former** you can create tuto or training to explain how to install an apiXtribe node, how to dev quickly an app with a setup. This is agnostic about the front-end pwa framework, react, vue, angular, .. . For the back-end is suitable for node.js dev but you can use any linux command to produce something to deliver accross apiXtribe.<br> **- As a former** you can create tuto or training to explain how to install an apxtrib node, how to dev quickly an app with a setup. This is agnostic about the front-end pwa framework, react, vue, angular, .. . For the back-end is suitable for node.js dev but you can use any linux command to produce something to deliver accross apxtrib.<br>
**- As a newbie** you can join this open source project to learn how to dev as a part of the team and to increase your portfolio of node.js/linux project. **- As a newbie** you can join this open source project to learn how to dev as a part of the team and to increase your portfolio of node.js/linux project.
We strongly believe in the cypher punk philosophy french :[cypher punk manifesto](https://dev.ndda.fr/cypherpunkmanifestofrench.html) english: [cypher punk manifesto](https://dev.ndda.fr/cypherpunkmanifestoenglish.html). We strongly believe in the cypher punk philosophy french :[cypher punk manifesto](https://dev.ndda.fr/cypherpunkmanifestofrench.html) english: [cypher punk manifesto](https://dev.ndda.fr/cypherpunkmanifestoenglish.html).

View File

@ -2,12 +2,12 @@
<html lang="fr"> <html lang="fr">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>ANTS Nation</title> <title>Nation Base contract</title>
<link rel="stylesheet" href="static/css/style.css"> <link rel="stylesheet" href="static/css/style.css">
<script src="static/js/script.js"></script> <script src="static/js/script.js"></script>
</head> </head>
<body> <body>
<p> Info sur la nation des ANTS leur ville pour les rejoindre</p> <p> Info sur lla nation de <base href=""></p>
<p> </p> <p> </p>
</body> </body>
</html> </html>

View File

@ -3,183 +3,299 @@ This module have to be independant of any external package
it is shared between back and front and is usefull it is shared between back and front and is usefull
to apply common check in front before sending it in back to apply common check in front before sending it in back
can be include in project with can be include in project with
<script src="https://apiback.maildigit.fr/js/checkdata.js"></script> - into a browser : <script src="https://townName.nationName.dns/socialworld/contracts/check.js"></script>
or with const checkdata = require('../public/js/checkdata.js') - into a node.js : const check = require( `../nationchains/socialworld/contracts/check.js`);
*/ */
// --## // --##
const checkdata = {}; const check = {};
// each checkdata.test. return true or false check.schema = {};
checkdata.test = {}; check.schema.properties = {};
check.schema.properties.type = {};
checkdata.test.emailadress = ( ctx, email ) => { check.schema.properties.type.string = (str) => typeof str === "string";
const regExp = /^(([^<>()[\]\\.,;:\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,}))$/; check.schema.properties.type.number = (n) => typeof n === "number";
return regExp.test( email ); check.schema.properties.type.integer = (n) =>
n != "" && !isNaN(n) && Math.round(n) == n;
check.schema.properties.type.float = (n) =>
n != "" && !isNaN(n) && Math.round(n) != n; //not yet in json schema
check.schema.properties.minLength = (str, min) =>
typeof str === "string" && str.length > parseInt(min);
check.schema.properties.maxLength = (str, max) =>
typeof str === "string" && str.length < parseInt(max);
check.schema.properties.multipleOf = (n, val) =>
typeof n === "number" &&
typeof val === "number" &&
parseFloat(n) / parseFloat(val) -
Math.round(parseFloat(n) / parseFloat(val)) <
0.0000001;
check.schema.properties.range = (
n,
minimum,
exclusiveMinimum,
maximum,
exclusiveMaximum
) => {
//console.log(minimum,exclusiveMinimum,maximum, exclusiveMaximum,n)
if (typeof n !== "number") return false;
if (minimum && parseFloat(n) < parseFloat(minimum)) return false;
if (exclusiveMinimum && parseFloat(n) <= parseFloat(exclusiveMinimum))
return false;
if (maximum && parseFloat(n) > parseFloat(maximum)) return false;
if (exclusiveMaximum && parseFloat(n) >= parseFloat(exclusiveMaximum))
return false;
return true;
}; };
check.schema.properties.pattern = (str, pattern) => {
try {
new RegExp(pattern);
} catch (e) {
return false;
}
return pattern.test(str);
};
check.schema.properties.enum = (str, enumvalues) =>
typeof str === "string" && enumvalues.includes(str);
// see format https://json-schema.org/understanding-json-schema/reference/string.html#format
check.schema.properties.format = {
"date-time": / /,
time: / /,
date: / /,
duration: / /,
email:
/^(([^<>()[\]\\.,;:\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,}))$/,
"idn-email": / /,
uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
uri: / /,
"uri-reference": / /,
iri: / /,
hostname: / /,
"idn-hostname": / /,
ipv4: /^([09]{1,3}.){3}.([09]{1,3})$/,
ipv6: /^((([09A-Fa-f]{1,4}:){7}[09A-Fa-f]{1,4})|(([09A-Fa-f]{1,4}:){6}:[09A-Fa-f]{1,4})|(([09A-Fa-f]{1,4}:){5}:([09A-Fa-f]{1,4}:)?[09A-Fa-f]{1,4})|(([09A-Fa-f]{1,4}:){4}:([09A-Fa-f]{1,4}:){0,2}[09A-Fa-f]{1,4})|(([09A-Fa-f]{1,4}:){3}:([09A-Fa-f]{1,4}:){0,3}[09A-Fa-f]{1,4})|(([09A-Fa-f]{1,4}:){2}:([09A-Fa-f]{1,4}:){0,4}[09A-Fa-f]{1,4})|(([09A-Fa-f]{1,4}:){6}((b((25[05])|(1d{2})|(2[04]d)|(d{1,2}))b).){3}(b((25[05])|(1d{2})|(2[04]d)|(d{1,2}))b))|(([09A-Fa-f]{1,4}:){0,5}:((b((25[05])|(1d{2})|(2[04]d)|(d{1,2}))b).){3}(b((25[05])|(1d{2})|(2[04]d)|(d{1,2}))b))|(::([09A-Fa-f]{1,4}:){0,5}((b((25[05])|(1d{2})|(2[04]d)|(d{1,2}))b).){3}(b((25[05])|(1d{2})|(2[04]d)|(d{1,2}))b))|([09A-Fa-f]{1,4}::([09A-Fa-f]{1,4}:){0,5}[09A-Fa-f]{1,4})|(::([09A-Fa-f]{1,4}:){0,6}[09A-Fa-f]{1,4})|(([09A-Fa-f]{1,4}:){1,7}:))$/,
telephonefr: /^0[1-9][0-9]{9}$/,
telephoneinter: /^\+*(\d{3})*[0-9,\-]{8,}/,
password:
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&.])[A-Za-z\d$@$!%*?&.{}:|\s]{8,}/,
postalcodefr: /(^\d{5}$)|(^\d{5}-\d{4}$)/,
};
check.schema.validation = (schema) => {
/*validate a schema structure*/
const res = { status: 200, err: [] };
if (schema.properties) {
Object.keys(schema.properties).forEach((p) => {
const properties = schema.properties;
if (
properties[p].type &&
typeof properties[p].type === "string" &&
!check.schema.properties.type[properties[p].type]
) {
res.err.push({
info: "|checkdata|typedoesnotexistinschema",
moreinfo: ` ${properties[p].type}`,
});
}
if (
properties[p].type &&
typeof properties[p].type === "object" &&
Array.isArray(properties[p].type)
) {
properties[p].type.forEach((tp) => {
if (!check.schema.properties.type[tp])
res.err.push({
info: "|checkdata|typedoesnotexistinschema",
moreinfo: `${tp} of ${properties[p].type}`,
});
});
}
if (
properties[p].format &&
!check.schema.properties.format[properties[p].format]
) {
res.err.push({
info: "|checkdata|formatdoesnotexistinschema",
moreinfo: ` ${properties[p].format}`,
});
}
if (properties[p].enum && !Array.isArray(properties[p].enum)) {
res.err.push({
info: "|checkdata|enumisnotarrayinschema",
moreinfo: ` ${properties[p].enum}`,
});
}
});
}
// 406 means not acceptable
if (res.err.length > 0) res.status = 406;
return res;
};
check.schema.data = (schema, ctx, data) => {
/* validate a data set with a schema in a context ctx */
/*
console.log('#################')
console.log(schema);
console.log('---------')
console.log(data)
*/
const validschema = check.schema.validation(schema);
if (validschema.status != 200) return validschema;
const res = { status: 200, err: [] };
if (schema.properties) {
const properties = schema.properties;
Object.keys(properties).forEach((p) => {
//type is mandatory in a propertie
if (data[p]) {
const typlist =
properties[p].type && typeof properties[p].type === "string"
? [properties[p].type]
: properties[p].type;
let valid = false;
typlist.forEach((typ) => {
// at least one test have to be ok
if (check.schema.properties.type[typ](data[p])) valid = true;
});
if (!valid)
res.err.push({
info: "|checkdata|dataerrpropertie",
moreinfo: `${p} : ${data[p]}`,
});
if (
properties[p].minLength &&
!check.schema.properties.minLength(data[p], properties[p].minLength)
) {
res.err.push({
info: "|checkdata|dataerrpropertie",
moreinfo: `${p} : ${data[p]} minLength:${properties[p].minLength}`,
});
}
if (
properties[p].maxLength &&
!check.schema.properties.maxLength(data[p], properties[p].maxLength)
) {
res.err.push({
info: "|checkdata|dataerrpropertie",
moreinfo: `${p} : ${data[p]} maxLength:${properties[p].maxLength}`,
});
}
if (
properties[p].multipleOf &&
!check.schema.properties.multipleOf(data[p], properties[p].multipleOf)
) {
res.err.push({
info: "|checkdata|dataerrpropertie",
moreinfo: `${p} : ${data[p]} not a multipleOf:${properties[p].multipleOf}`,
});
}
if (
properties[p].minimum ||
properties[p].maximum ||
properties[p].exclusiveMinimum ||
properties[p].exclusiveMaximum
) {
// test range
if (
!check.schema.properties.range(
data[p],
properties[p].minimum,
properties[p].exclusiveMinimum,
properties[p].maximum,
properties[p].exclusiveMaximum
)
) {
res.err.push({
info: "|checkdata|dataerrpropertie",
moreinfo: `${p} : ${data[p]} not in range ${properties[p].minimum} exclu: ${properties[p].exclusiveMinimum} and ${properties[p].maximum} exclu: ${properties[p].exclusiveMaximum}`,
});
}
}
if (
properties[p].enum &&
!check.schema.properties.enum(data[p], properties[p].enum)
) {
res.err.push({
info: "|checkdata|dataerrpropertie",
moreinfo: `${p} : ${data[p]} not in enum list :${properties[p].enum}`,
});
}
if (properties[p].format) {
properties[p].pattern =
check.schema.properties.format[properties[p].format];
}
if (
properties[p].pattern &&
!check.schema.properties.pattern(data[p], properties[p].pattern)
) {
res.err.push({
info: "|checkdata|dataerrpropertie",
moreinfo: `${p} : ${data[p]} problem pattern or format ${properties[p].pattern}`,
});
}
} else if (schema.required.includes(p)) {
res.err.push({
info: "|checkdata|dataerrpropertiesrequired",
moreinfo: `${p}`,
});
}
});
}
if (res.err.length > 0) res.status = 417;
return res;
};
/* /*
* @emaillist = "email1,email2, email3" Normalize data link to check.schema.properties.format
* it check if each eamil separate by , are correct or any normalization to get consistent data
*/
checkdata.test.emailadresslist = ( ctx, emaillist ) => {
//console.log(emaillist.split(','))
if( emaillist.length > 0 ) {
const emails = emaillist.split( ',' );
for( var i in emails ) {
//console.log(emails[i])
if( !checkdata.test.emailadress( "", emails[ i ].trim() ) ) {
return false
}
}
};
return true;
};
checkdata.test.password = ( ctx, pwd ) => {
const regExp = new RegExp(
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&.])[A-Za-z\d$@$!%*?&.{}:|\s]{8,}/
);
return regExp.test( pwd );
};
checkdata.test.required = ( ctx, val ) =>
( val != null && val != 'undefined' && val.length > 0 ) || ( !!val && val.constructor === Array && val.length > 0 ) || ( !!val && val.constructor === Object && Object.keys( val )
.length > 0 );
checkdata.test.isNumber = ( ctx, n ) => typeof n === 'number';
checkdata.test.isInt = ( ctx, n ) => n != '' && !isNaN( n ) && Math.round( n ) == n;
checkdata.test.isFloat = ( ctx, n ) => n != '' && !isNaN( n ) && Math.round( n ) != n;
checkdata.test.unique = ( ctx, val ) => {
if( ctx.list[ ctx.currentfield ] ) {
return !ctx.list[ ctx.currentfield ].includes( val );
} else {
console.log( 'ERR no list for field:' + ctx.currentfield );
return false;
}
};
checkdata.test.isDateDay = ( ctx, dateDay ) => true;
/* checkdata.test.filterInvalidInArray = (array, validate) =>
array ? array.filter(el => !validate(el)) : true;
// return true when every elements is valid
*/ */
const normalize={};
checkdata.test.postalCode = ( ctx, postalCode ) => { normalize.telephonefr =(phone)=>{
if( postalCode.length == 0 ) return true; phone = phone.trim().replace(/[- .]/g, "");
const regExp = new RegExp( /(^\d{5}$)|(^\d{5}-\d{4}$)/ ); if (
return regExp.test( postalCode ); check.schema.properties.format.telephoenfr(phone) &&
phone.length == 10 &&
phone[0] == "0"
) {
phone = "+33 " + phone.substring(1);
}
return phone;
}; };
/** normalize.zfill10 = (num) => {
* PHONE let s = num + "";
*/ while (s.length < 10) s = "0" + s;
checkdata.test.phoneNumber = ( ctx, phoneNumber ) => { return s;
if( phoneNumber.length == 0 ) return true;
phoneNumber = phoneNumber.trim()
.replace( /[- .]/g, '' )
//french number
const regExpfr = new RegExp( /^0[1-9][0-9]{9}$/ );
const regExpInternational = new RegExp( /^\+*(\d{3})*[0-9,\-]{8,}/ );
return regExpfr.test( phoneNumber ) || regExpInternational.test( phoneNumber );
};
/*
* @phonelist = "phone1,phone2,phone3"
* it check if each phone separate by , are correct
*/
checkdata.test.phoneNumberlist = ( ctx, phonelist ) => {
//console.log(emaillist.split(','))
if( phonelist.length > 0 ) {
const phones = phonelist.split( ',' );
for( var i in phones ) {
//console.log(emails[i])
if( !checkdata.test.phoneNumber( "", phones[ i ].trim() ) ) {
return false
}
}
};
return true;
}; };
// checkdata.normalize take a correct data then reformat it to harmonise it
checkdata.normalize = {}; check.test.unique = (ctx, val) => {
checkdata.normalize.phoneNumber = ( ctx, phone ) => { if (ctx.list[ctx.currentfield]) {
phone = phone.trim() return !ctx.list[ctx.currentfield].includes(val);
.replace( /[- .]/g, '' ); } else {
if( checkdata.test.phoneNumber( '', phone ) && phone.length == 10 && phone[ 0 ] == "0" ) { console.log("ERR no list for field:" + ctx.currentfield);
phone = '+33 ' + phone.substring( 1 ); return false;
} }
return phone; };
}
checkdata.normalize.upperCase = ( ctx, txt ) => txt.toUpperCase(); // check.normalize take a correct data then reformat it to harmonise it
checkdata.normalize.lowerCase = ( ctx, txt ) => txt.toLowerCase(); check.normalize = {};
check.normalize.phoneNumber = (ctx, phone) => {
phone = phone.trim().replace(/[- .]/g, "");
if (
check.test.phoneNumber("", phone) &&
phone.length == 10 &&
phone[0] == "0"
) {
phone = "+33 " + phone.substring(1);
}
return phone;
};
check.normalize.upperCase = (ctx, txt) => txt.toUpperCase();
check.normalize.lowerCase = (ctx, txt) => txt.toLowerCase();
// fixe 10 position et complete par des 0 devant // fixe 10 position et complete par des 0 devant
checkdata.normalize.zfill10 = ( ctx, num ) => { check.normalize.zfill10 = (ctx, num) => {
let s = num + ''; let s = num + "";
while( s.length < 10 ) s = '0' + s; while (s.length < 10) s = "0" + s;
return s; return s;
};
/*let tt = "+33 1 02.03 04 05";
console.log(checkdata.test.phoneNumber('', tt))
console.log(checkdata.normalize.phoneNumber('', tt))
*/
checkdata.evaluate = ( contexte, referential, data ) => {
/*
* contexte object {} with full info for evaluation
* file referential path to get object to apply
* data related to object
- return {validefor =[keyword of error] if empty no error,
clean data eventually reformated
updateDatabase}
*/
console.log( 'contexte', contexte );
console.log( 'referentiel', referential );
console.log( 'data', data );
const invalidefor = [];
const objectdef = {};
const listfield = referential.map( ch => {
objectdef[ ch.idfield ] = ch;
return ch.idfield;
} );
Object.keys( data )
.forEach( field => {
if( !listfield.includes( field ) ) {
// some data can be inside an object with no control at all
// they are used for process only
// i leave it in case it will become a non sens
// invalidefor.push('ERRFIELD unknown of referentials ' + field);
} else {
if( objectdef[ field ].check ) {
// check data with rule list in check
objectdef[ field ].check.forEach( ctrl => {
console.log( 'ctrl', ctrl );
contexte.currentfield = field;
if( !checkdata.test[ ctrl ] ) {
invalidefor.push( 'ERR check function does not exist :' + ctrl + '___' + field )
} else {
if( !checkdata.test[ ctrl ]( contexte, data[ field ] ) )
invalidefor.push( 'ERR' + ctrl + '___' + field );
}
} );
}
if( objectdef[ field ].nouserupdate ) {
// check if user can modify this information
console.log(
'evaluation :' + field + ' -- ' + objectdef[ field ].nouserupdate,
eval( objectdef[ field ].nouserupdate )
);
const evalright = eval( objectdef[ field ].nouserupdate );
objectdef[ field ].nouserupdate = evalright;
}
}
} );
console.log( {
invalidefor,
data
} );
return {
invalidefor,
data
};
}; };
if( typeof module !== 'undefined' ) module.exports = checkdata; if (typeof module !== "undefined") module.exports = check;

View File

@ -0,0 +1,5 @@
{
"typedoesnnotexistinschema":"This type in your propertie is not manage by checkdata.js",
"dataerrpropertie":"Check your data that not fit your schema rules propertie",
"dataerrpropertiesrequired":"This propertie is required and not present in your data"
}

View File

@ -0,0 +1,36 @@
/*
Ants nation contract
*/
const Contract={
object:"nation",
id:"ants",
version:"0.0.0",
dt_create:"20230307",
dt_update:"",
info:"https://apxtrib.crabdance.com/nation_base.html",
};
Contract.trigger = ()=>{
// Identification of rule to trig
// Create token for a tribe =>
}
Contract.druidAllowedtoCreateToken = (tokenconf, hashtokenconf)=>{
/*
@tokenconf ={
tokenvalue: float value in apxtr,
quantity: int number of token,
druidId: uuid,
costrequest: float cost of this in apxtr to the mayorId
}
Check balance druid wallet
@return {status:200, data:{transacId:blocktimestamp,tokens:[token1, token2, ...]}
{status:<>200, info:'error message'}
Store transaction in open block with transacId
A token = druidUuid_hash(with blockchain elected privatekey)
Druid can sale his token with his rules at a tribe level but any user that request an exchange ffrom a token
*/
}
module.exports = Contract;

View File

@ -6,7 +6,7 @@ const moment = require( 'moment' );
const config = require( '../config' ); const config = require( '../config' );
const utils = {}; const utils = {};
console.log( "Check in /utils/index.js to find usefull function for your dev.\n Feel free to send suggestion, code to maintainer of apixtribe project (see /package.json to get email).\n We'll add to the roadmap to add it." ); console.log( "Check in /utils/index.js to find usefull function for your dev.\n Feel free to send suggestion, code to maintainer of apxtrib project (see /package.json to get email).\n We'll add to the roadmap to add it." );
/** /**
* EMAIL * EMAIL

View File

@ -0,0 +1,36 @@
/*
Town contract:town_base
*/
const Contract={
object:"town",
id:"town_base",
version:"0.0.0",
dt_create:"20230307",
dt_update:"",
info:"https://apxtrib.crabdance.com/town_base.html",
};
Contract.trigger = ()=>{
// Identification of rule to trig
// Create token for a tribe =>
}
Contract.druidAllowedtoCreateToken = (tokenconf, hashtokenconf)=>{
/*
@tokenconf ={
tokenvalue: float value in apxtr,
quantity: int number of token,
druidId: uuid,
costrequest: float cost of this in apxtr to the mayorId
}
Check balance druid wallet
@return {status:200, data:{transacId:blocktimestamp,tokens:[token1, token2, ...]}
{status:<>200, info:'error message'}
Store transaction in open block with transacId
A token = druidUuid_hash(with blockchain elected privatekey)
Druid can sale his token with his rules at a tribe level but any user that request an exchange ffrom a token
*/
}
module.exports = Contract;

View File

@ -0,0 +1,146 @@
/*
Unit testing
*/
const assert = require("assert");
const checkdata = require("../checkdata.js");
const ut = { name: "checkdata" };
const schema = {
$schema: "http://json-schema.org/schema#",
title: "Dummy schema to test checkdata.js",
description: "Checkdata is use on server as well as into a browser",
$comment: "We change schema type on the fly to simplify the test",
type: "Object",
properties: {
totest: {},
},
};
const testproperties = [
{
name: "test1",
data: { totest: "blabla" },
properties: { totest: { type: "string" } },
status: 200
},
{
name: "test2",
data: { totest: 123 },
properties: { totest: { type: "string" } },
status: 417
},
{
name: "test3",
data: { totest: 123.13 },
properties: { totest: { type: "integer" } },
status: 417
},
{
name: "test4",
data: { totest: 123 },
properties: { totest: { type: "number" } },
status: 200
},
{
name: "test5",
data: { totest: 12312 },
properties: { totest: { type: "number" } },
status: 200
},
{
name: "test6",
data: { totest: 12.313 },
properties: { totest: { type: "float" } },
status: 200
},
{
name: "test7",
data: { totest: "blablab sfde" },
properties: { totest: { type: "string", minLength: 1111 } },
status: 417
},
{
name: "test8",
data: { totest: "blablab sfde" },
properties: { totest: { type: "string", minLength: 4, maxLength: 128} },
status: 200
},
{
name: "test9",
data: { totest: 12 },
properties: { totest: { type: "integer", multipleOf:3} },
status: 200
},
{
name: "test10",
data: { totest: 9 },
properties: { totest: { type: "number", minimum:-10, exclusiveMaximum:10} },
status: 200
},
{
name: "test11",
data: { totest: 10 },
properties: { totest: { type: "number", minimum:-10, exclusiveMaximum:10} },
status: 417
},
{
name: "test12",
data: { totest: "gfhrtabcdgfr" },
properties: { totest: { type: "string", pattern:/.*abc.*/} },
status: 200
},
{
name: "test13",
data: { totest: "toto@google.com" },
properties: { totest: { type: "string", format:"email"} },
status: 200
},
{
name: "test14",
data: { totest: "Aze123@0" },
properties: { totest: { type: "string", format:"password"} },
status: 200
},
{
name: "test15",
data: { totest: "value1" },
properties: { totest: { type: "string", enum:["value1","value2","value3"]} },
status: 200
},
{
name: "test16",
data: { totest: ["t1","t2"] },
properties: { totest: { type: ["string", "number"] }},
status: 417
}
,
{
name: "test17",
data: { totest: 12 },
properties: { totest: { type: ["string", "number"] }},
status: 200
}
];
ut.testproperties = (options) => {
let msg = "";
testproperties.forEach((t) => {
schema.properties = t.properties;
const res = checkdata.schema.data(schema, {}, t.data);
if (res.status != t.status) {
msg = (msg == "") ? "Unconsistent testproperties() name list: " : `${msg},`;
if (options.verbose) {
console.log(t)
console.log(res);
}
msg += res.err.map((e) => ` ${t.name} ${e.info}`);
}
});
return assert.deepEqual(msg, "", msg);
};
ut.run = (options) => {
console.log("Test checkdata properties");
ut.testproperties(options);
};
module.exports = ut;

View File

@ -1,36 +0,0 @@
[
{
"idfield": "name",
"nouserupdate": true,
"nouservisible": true,
"desc": {
"fr": "Nom unique d'une nation dans un monde social",
"en": "A unique nation name in a social world"
},
"desclong": {
"fr": "Nom unique identifiant une nation dans le monde social créer par un maire d'une nouvelle ville avec un contrat sociale specifique",
"en": "Unique nation name in the social world created by a mayor of a town."
},
"info": {
"fr": "<p> Une nation posséde un nom unique, un contrat sociale (contracts/name.js) signé et validé par tous les maires des villes associées à cette nation </p>",
"en": "<p> A nation is defined by this unique name and a contratcs/nationname.js signed by each town's major define the common nation rules</p>"
},
"check": ["required", "unique"],
"type": "text",
"questioncollecte":"questioninput",
"searchindex":["all"]
},
{
"idfield": "nationtype",
"searchindex": ["name"],
"check": ["required"],
"desc": {
"fr": "Type de nation"
},
"default": "ACTIVE",
"type": "data",
"questioncollect": "questionselect",
"data": "state.json"
},
]

View File

@ -1,265 +0,0 @@
[{
"idfield": "UUID",
"nouserupdate": true,
"nouservisible": true,
"desc": {
"fr": "identifiant utilisateur",
"en": "user id"
},
"desclong": {
"fr": "Identifiant unique généré via UUID v4",
"en": "unique Id from a UUID v4"
},
"info": {
"fr": "<p> L'usage d'UUID v4 permet de générer un code unique sans centralisation, car il est basé sur un timestamp et une clé crypto ce qui donne un code du type 7d8291c0-e137-11e8-9f7b-1dc8e57bed33 </p>",
"en": "<p> UUID v4 allow a client to generate a unique code without centralisation, base on a timestamp and a salt it looks like 7d8291c0-e137-11e8-9f7b-1dc8e57bed33</p>"
},
"check": ["required", "unique"],
"type": "text",
"tpl": "input"
},
{
"idfield": "LOGIN",
"nouserupdate": true,
"check": ["required", "unique"],
"desc": {
"fr": "login",
"en": "login"
},
"type": "text",
"tpl": "input",
"info": {
"fr": "<p>Le login doit être unique sur une instance d'apixtribe.</p><p> Pour échanger en dehors d'une instance apixtribe on utilise la clé public du user ou pour un humain login@apixtribe.domain.xx avec le nom du domaine qui heberge l'instance</p><p> Ou encore login@domain.xx tout domain.xx utilisé pour heberger un espace web client /tribeid/www/</p>",
"en": "<p>Login have to be unique into an apixtribe instance</p><p> To exchange outside of an apixtribe instance, we use PublicKey or login@apixtribe.domain.xx or login@domainclient.xx where domain.xx is a apixtribe name server on internet and domain.xx is a tribeid name where a /tribeid/www is available on the net.</p>"
}
},
{
"idfield": "BIOGRAPHY",
"desc": {
"fr": "Vous en quelques mots",
"en": "Few words"
},
"placeholder": {
"fr": "",
"en": ""
},
"rows": 2,
"tpl": "textarea"
},
{
"nouserupdate": true,
"idfield": "PUBLICKEY",
"desc": {
"fr": "Votre clé public pour ce compte",
"en": "Your public key for this uuid"
},
"info": {
"fr": "<p>Cette clé est générée par votre navigateur, garder précisuesement votre clé privée que seule vous connaissez. En cas de perte de cette clé tous vos actifs seront perdus.</p><p>Cette méthode nous permet de vous garantir un contrôle total décentralisé.</p>",
"en": "<p>This key was generated by your browser, keep the private key related to this public key.</p><p>We garanty your total control by this way</p>."
},
"tpl": "textarea"
},
{
"idfield": "IMGAVATAR",
"tpl": "inputimg",
"altimg": "image avatar",
"classimg": "rounded-circle img-responsive mt-2",
"width": 128,
"height:"
128,
"classdivupload": "mt-2",
"classbtn": "btn-primary",
"desc": {
"fr": "changer votre avatar",
"en": "upload an avatar"
},
"info": {
"fr": "Pour un meilleur rendu, une mage carré de 128pc en foat jpg",
"en": "For best results, use an image at least 128px by 128px in .jpg format"
},
},
{
"idfield": "EMAIL",
"desc": {
"fr": "email",
"en": "email"
},
"tpl": "input",
"type": "email",
"check": ["emailadress", "unique"],
"placeholder": {
"fr": "#@",
"en": "@"
}
},
{
"idfield": "PHONE",
"desc": {
"fr": "Tel",
"en": "Phone"
},
"check": ["phone"]
"tpl": "input",
"type": "text"
},
{
"idfield": "NAME",
"desc": {
"fr": "Nom",
"en": "Name"
},
"tpl": "input",
"type": "text"
},
{
"idfield": "FIRSTNAME",
"desc": {
"fr": "Prénom",
"en": "First Name"
},
"tpl": "input",
"type": "text"
},
{
"idfield": "NICKNAME",
"desc": {
"fr": "Pseudo",
"en": "Nickname"
},
"tpl": "input",
"type": "text"
},
"info": {
"fr": "<p>Nom avec lequel vous souhaitez qu'on vous reconnaisse sur l'instance de l'apixtribe </p><p>Attention ce nom n'est unique que sur une instance d'apixtribe. Un même speudo peut-être utilisé sur un autre serveur pour garantir l'identité vérifié pseudo@ domaine de rattachement.</p>",
"en": "<p>Carrefull a pseudo is unique into an instance of apixtribe to be sure to contact the right person check pseudo@ domain</p>.<p> Pseudo can be changed that is not the case of login.</p>"
},
"tpl": "input",
"type": "text"
}, {
"idfield": "COMPANYNAME",
"desc": {
"fr": "Nom de Société",
"en": "Compagnie name"
},
"tpl": "input",
"type": "text"
}, {
"idfield": "BILLINGADD",
"desc": {
"fr": "Adresse complete de facturation par defaut",
"en": "Full billing adress default"
},
"tpl": "input",
"type": "text",
"placeholder": {
"fr": "1 chemin du paradis - 91430 IGNY France",
"en": "123 Main St- 123MZ -Oxford UK"
}
}, {
"idfield": "DELIVERYADD",
"desc": {
"fr": "Adresse complete de livraison par defaut",
"en": "Full delivery adress default"
},
"tpl": "input",
"type": "text",
"placeholder": {
"fr": "1 chemin du paradis - 91430 IGNY France",
"en": "123 Main St- 123MZ -Oxford UK"
}
}, {
"idfield": "ADDRESS1",
"desc": {
"fr": "Adresse",
"en": "Address"
},
"tpl": "input",
"type": "text",
"placeholder": {
"fr": "1 chemin du paradis",
"en": "123 Main St"
}
}, {
"idfield": "ADDRESS2",
"desc": {
"fr": "Adresse 2",
"en": "Address 2"
},
"tpl": "input",
"type": "text",
"placeholder": {
"fr": "Appartement B",
"en": "Apt B"
}
}, {
"idfield": "CITY",
"desc": {
"fr": "Ville ",
"en": "CITY"
},
"tpl": "input",
"type": "text"
}, {
"idfield": "ZIP",
"desc": {
"fr": "Code Postal",
"en": "ZIP"
},
"tpl": "input",
"type": "text"
}, {
"idfield": "COUNTRY",
"desc": {
"fr": "Pays",
"en": "Country"
},
"tpl": "input",
"type": "text"
}, {
"nouserupdate": true,
"idfield": "DATE_CREATE",
"desc": {
"fr": "Date de création",
"en": "Create Date"
},
"tpl": "date",
"format": "YYYY-MM-DD",
"default": "moment(new Date()).format('YYYY-MM-DD')"
}, {
"nouserupdate": true,o
"idfield": "DATE_UPDATE",
"desc": {
"fr": "Date mise à jour",
"en": "Update date"
},
"tpl": "date",
"format": "YYYY-MM-DD",
"default": "moment(new Date()).format('YYYY-MM-DD')"
}, {
"nouserupdate": true,
"idfield": "DATE_LASTLOGIN",
"desc": {
"fr": "Date de derniére connexion",
"en": "Last date login"
},
"tpl": "date",
"format": "YYYY-MM-DD",
"default": "moment(new Date()).format('YYYY-MM-DD')"
}, {
"idfield": "ACCESSRIGHTS",
"nouserupdate": true,
"desc": {
"fr": "Vos droits d'accès",
"en": "Your access rights"
},
"default": {
"app": {},
"data": {
"tribeidname": {
"users": "O"
}
}
},
"tpl": "jsoneditor"
}]

View File

@ -1 +0,0 @@
[]

View File

@ -1,7 +1,5 @@
{"UUID":"ants", {
"publickey":"123", "nationId":"ants",
"status":"open", "dtcreate":"2023-03-19T14:05:00+02:00",
"domain":["antsnation.mooo.com"], "contracts":"socialworld/contracts/nation_base.js"
"svg":"",
"towns":["hill"]
} }

View File

@ -1,5 +0,0 @@
{"UUID":"escape",
"publickey":"123",
"status":"open",
"towns":["game"]
}

View File

@ -0,0 +1,6 @@
{"ants":{
"nationId":"ants",
"publickey":"123",
"status":"unchain",
"svg":""
}}

View File

@ -1 +0,0 @@
{"archilinea":["escapenation","game"]}

View File

@ -0,0 +1,19 @@
{
"title":"Nation definition",
"description":"A nation from apXtrib social world",
"$comment":"",
"properties":{
"nationId":{
"title":"Unique nation name",
"description":"A unique string that define a nation a-z and 0-9 onlyin a social world"
},
"dtcreate":{
"title":"Creation date",
"description":"Nation date of creation"
},
"contracts":{
"title":"Social contract of the nation",
"description":"A uri of the signed js contract that rules this nation"
}
}
}

View File

@ -0,0 +1,7 @@
{
"nationnamedesc":"Nom unique d'une nation dans un monde social",
"nationnamedesclong":"Nom unique identifiant une nation dans le monde social créer par un maire d'une nouvelle ville avec un contrat sociale specifique",
"nationnameinfo":"<p> Une nation posséde un nom unique, un contrat sociale (contracts/name.js) signé et validé par tous les maires des villes associées à cette nation </p>",
"statusdesc":"Statut de la nation",
"statusactive":"Nation active"
}

View File

@ -0,0 +1,42 @@
{
"ERRcritical": "Critical Error",
"loginAlreadyExist": "Login already exists",
"emailAlreadyExist":"Email already exists",
"failtoWritefs":"Fail to write on system",
"successfullCreate": "Successfully created",
"successfullDelete": "Successfully deleted",
"serverNeedAuthentification":"This server needs authentification",
"forbiddenAccess":"Forbidden Access",
"userNotAllowtoCreate":"User is not allow to create",
"userNotAllowtoUpdate":"User is not allow to update",
"userNotAllowtoDelet":"User is not allow to delete",
"uuidNotFound":"Paggans {{uuid}} not found for {{tribeName}}",
"useremailNotfound":"Email not found",
"loginDoesNotExist":" Login does not exist",
"checkCredentials":" Check yopur credentials"
"wrongPassword":"Check your password",
"invalidData":"Check your data",
"pswToosimple":"Password too simple, need to contain at least 8 caracters lower and uppercase, number and @! ...",
"ERRemail":"Check your email",
"ERRnewnewbisdiff":"Both password are not the same",
"paganiddesc":"unique id",
"paganiddesclong":"Unique Identification based on UUID.v4()",
"paganidinfo":"<p> UUID v4 allow a client to generate a unique code without centralisation, base on a timestamp and a salt it looks like 7d8291c0-e137-11e8-9f7b-1dc8e57bed33</p>",
"logindesc":"login",
"logininfo":"<p>Login have to be unique into a town (composed of letter: a to z and 0 to 9)</p><p> To exchange outside of a town, we use PublicKey / uuid or login@tribeId.townId.nationId.dns</p>",
"pswdesc":"A strong password minimum 8char uper lower number specialm char",
"biographydesc":"Few words about you",
"publickeyinfo":"<p>This key was generated by your browser, keep the private key related to this public key.</p><p>We garanty your total control by this way</p>.",
"imgavatardesc":"Upload an avatar",
"imgavatarinfo":"For best results, use an image at least 128px by 128px in .jpg format",
"emaildesc":"Email de recuperation de mot de passe",
"telephonedesc":"Phone",
"familyNamedesc":"Last name",
"givenNamedesc":"First name",
"additionalNamedesc":"Nickname",
"additionalNamesinfo":"<p>Carrefull a pseudo is unique into an instance of apxtrib to be sure to contact the right person check pseudo@ domain</p>.<p> Pseudo can be changed that is not the case of login.</p>",
"dtcreatedesc":"Creation date",
"dtupdatedesc":"last update",
"dtlastlogindesc":"Last login access",
"accessrightsdesc":"Your accessrigts"
}

View File

@ -0,0 +1,41 @@
{
"ERRcritical": "Erreur critique",
"loginAlreadyExist": "Ce login exist déjà",
"emailAlreadyExist":"Cet email exist déjà",
"failtoWritefs":"Impossible d'ecrire sur le serveur",
"successfullCreate": "Création réussit",
"successfullDelete": "Mise à jour effectuée",
"serverNeedAuthentification":"Ce serveur a besoin d'une authentification",
"forbiddenAccess":"Accès interdit",
"userNotAllowtoCreate":"Pas d'autorisation de creation",
"userNotAllowtoUpdate":"Pas d'autorisatiuon de mise à jour",
"userNotAllowtoDelet":"Pas d'autorisation de suppression",
"uuidNotFound":"Le paîen {{uuid}} n'existe pas dans la tribu {{tribeName}}",
"useremailNotfound":"Email introuvable",
"loginDoesNotExist":" Login introuvable",
"checkCredentials":" Vérifier vos parametres d'accès"
"wrongPassword":"Vérifier votre mot de passe",
"invalidData":"Vérifier vos données",
"pswToosimple":"Votre mot de passe est trop simple, doit contenir au moins 8 caractères avec des lettres majusculmes, minuscules des nombres et au moins un caractere special @! ...",
"ERRemail":"Vérifier votre email",
"ERRnewnewbisdiff":"Les 2 mots de passe ne sont pas identique",
"uuiddesc":"Identifiant",
"uuiddesclong":"Identifiant unique au format UUID.v4()",
"uuidinfo":"<p> L'usage d'UUID v4 permet de générer un code unique sans centralisation, car il est basé sur un timestamp et une clé crypto ce qui donne un code du type 7d8291c0-e137-11e8-9f7b-1dc8e57bed33 </p>",
"logindesc":"login",
"logininfo":"<p>Le login doit être unique sur une instance d'apxtrib.</p><p> Pour échanger en dehors d'une instance apxtrib on utilise la clé public du user ou pour un humain login@trib.town§.nation.xx avec le nom du domaine qui heberge l'instance</p><p> Ou encore login@domain.xx tout domain.xx utilisé pour heberger un espace web client /tribeid/www/</p>",
"biographydesc":"Vous en quelques mots",
"publickeyinfo":"<p>Cette clé est générée par votre navigateur, garder précisuesement votre clé privée que seule vous connaissez. En cas de perte de cette clé tous vos actifs seront perdus.</p><p>Cette méthode nous permet de vous garantir un contrôle total décentralisé.</p>",
"imgavatardesc":"Changer votren avatar",
"imgavatarinfo":"Pour un meilleur rendu, une mage carré de 128pc en foat jpg",
"emaildesc":"Email",
"telephonedesc":"Tel",
"familyNamedesc":"Nom",
"givenNamedesc":"Prénom",
"additionalNamedesc":"Pseudo",
"additionalNamesinfo":"<p>Nom avec lequel vous souhaitez qu'on vous reconnaisse sur l'instance de l'apxtrib </p><p>Attention ce nom n'est unique que sur une instance d'apxtrib. Un même speudo peut-être utilisé sur un autre serveur pour garantir l'identité vérifié pseudo@ domaine de rattachement.</p>",
"dtcreatedesc":"Date de creation",
"dtupdatedesc":"Dernière mise à jour",
"dtlastlogindesc":"Dernier accès au login",
"accessrightsdesc":"Vos droits d'accès"
}

View File

@ -0,0 +1,8 @@
{
"townnamedesc":"A unique town name in a nation for a social world",
"townnamedesclong":"Unique town name in the social world created by a mayor.",
"townnameinfo":"<p> A town is defined by this unique name and a contratcs/townname.js signed by each druid that create a tribe inside this town</p>",
"antsnationdesc":"ants nation",
"statusdesc":"Town's status",
"statusactive":"Active Town"
}

View File

@ -0,0 +1,8 @@
{
"townnamedesc":"Nom unique d'une ville dans une nation",
"townnamedesclong":"Nom unique identifiant une ville dans une nation d'un monde social, créer par un maire d'une nouvelle ville avec un contrat sociale specifique",
"townnameinfo":"<p> Une ville posséde un nom unique, un contrat sociale (contracts/name.js) signé et validé par tous les maires des villes associées à cette nation </p>",
"antsnationdesc":"nation des ants",
"statusdesc":"Statut de la ville",
"statusactive":"Ville active"
}

View File

@ -0,0 +1,28 @@
{
"$schema":"http://json-schema.org/schema#",
"$id":"nationchains/socialworld/objects/schema/nations",
"title": "Nation definition",
"description": "A nation from apXtrib world",
"$comment":"see ./lg/nations_lg.json for description in your languange lg",
"type": "object",
"properties": {
"nationId": {
"type": "string",
"pattern":"^[a-z0-9]*$"
},
"dtcreate": {
"type": "string",
"format":"datetime"
},
"contracts":{
"type": "string",
"format":"uri"
}
},
"required": ["nationId", "dtcreate","contracts"],
"additionalProperties":false,
"apxprimarykey":"nationId",
"apxsearchindex": [
{ "key": "nationId", "value": [] }
]
}

View File

@ -0,0 +1,86 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "socialworld/schema/pagans",
"title":"Pagan definition",
"description": "A pagan is an uuid to manage identity by deliver a way to its owner to proof he owns from a privatekey in the socialworld of apXtrib and manage access keys deliver by druid or mayor to interact physical ressource (CRUD on it).",
"type": "objects",
"properties":{
"paganId":{
"description": "|Pagans|paganiddesc",
"apxdesclong": "|Pagans|paganiddesclong"
"apxinfo":"|Pagans|paganidinfo",
"type": "string",
"apxtype":"uuidv4"
},
"login":{
"description": "|Pagans|logindesc",
"type": "string",
"pattern":"^[a-z0-9]*$",
"apxinfo": "|Pagans|logininfo"
},
"password":{
"description": "|Pagans|pswdesc",
"type": "string"
},
"townId":{
"description":"",
"type":"string",
"$apxenumkey": "socialworld/objects/nations/searchindex/towns_townId_all.json"
},
"tribeId":{
"description":"",
"type":"string",
"$apxenumkey": "tribes/objects/tribes/searchindex/tribes_tribeId_all.json"
},
"publicKey":{
"description": "|Pagans|publickeydesc",
"type":"string",
"apxinfo": "|Pagans|publickeyinfo"
},
"biography":{
"description": "|Pagans|biographydesc",
"type":"string",
"pattern":"^.{O,150}$"
},
"imgavatar":{
"description": "|Pagans|imgavatardesc",
"apxinfo": "|Pagans|imgavatarinfo",
"type":"string",
"apxtype":"file"
},
"emailrecup":{
"description":"|Pagans|emaildesc",
"tpl": "input",
"type": "email",
"check": ["emailadress", "unique"],
},
"dtcreate":{
"description": "|Pagans|dtcreatedesc",
"type":"string",
"pattern":"^[0-9]{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$",
"default": "moment(new Date()).format('YYYY-MM-DD')"
},"dtupdate": {
"description": "|Pagans|dtupdatedesc",
"type":"string",
"pattern":"^[0-9]{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$",
"default": "moment(new Date()).format('YYYY-MM-DD')"
},"dtlastlogin" {
"description": "|Pagans|dtlastlogindesc",
"type":"string",
"pattern":"^[0-9]{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$",
"default": "moment(new Date()).format('YYYY-MM-DD')"
},"accessrights": {
"description": "|Pagans|accessrightsdesc",
"type":"object",
"$ref":"socialworld/schema/accessright.json"
}
},
"required": ["paganId","login","townId", "tribeId"],
"apxprimarykey": "paganId",
"apxunique":["login"],
"apxsearchindex": [
{ "key": "login", "value": "paganId" },
{ "key": "email", "value": "paganId" },
{ "key": "token", "value": "paganId" }
]
}

View File

@ -0,0 +1,45 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "socialworld/objects/schema/towns",
"title": "Town",
"description": "A town belonging to a nation from apXtrib world",
"type": "object",
"properties": {
"townId": {
"description": "|Towns|townnamedesc",
"desclong": "|Townss|townnamedesclong",
"info": "|Towns|townnameinfo",
"type": "string",
"pattern":"^[a-z0-9]*$"
},
"nationId": {
"description": "|Towns|nationdesc",
"desclong": "|Townss|nationdesclong",
"type": "string",
"$apxenumkey": "socialworld/objects/nations/searchindex/nations_uuid_uuid.json"
},
"status": {
"desc": "|Towns|statusdesc",
"default": "active",
"type": "string",
"$apxenumkey": "data",
"data": {
"chain": { "desc": "|Towns|statuschain" },
"tochain": { "desc": "|Towns|statustosync" },
"unchain": { "desc": "|Towns|statusunchain" }
}
},
"url": {
"desc": "|Towns|urldesc",
"type": "string",
"apxtype":"url"
}
},
"required": ["townId", "status", "nationId", "url"],
"apxprimarykey": "townId",
"apxsearchindex": [
{ "key": "status", "value": "townId" },
{ "key": "nationId", "value": "townId" },
{ "key": "townId", "value": [] }
]
}

View File

@ -1,7 +0,0 @@
{
"url":"https://escape.game.apixtribe.org",
"IP":"213.32.65.213",
"mayorid":"123",
"status":""
"tribes":[]
}

View File

@ -0,0 +1,9 @@
{
"id":"hill",
"nationid":"ants",
"contract":"town_base",
"url":"https://hill.ants.mooo.com",
"IP":"213.32.65.213",
"mayorid":"123",
"status":""
}

View File

@ -0,0 +1 @@
{"ants":["hill","wall"]}

View File

@ -0,0 +1,16 @@
{"hill":{
"townId":"hill",
"nationId":"ants",
"url":"https://hill.ants.mooo.com",
"IP":"213.32.65.213",
"mayorid":"123",
"status":""
},"wall":{
"townId":"wall"
"nationid":"ants",
"url":"https://wall.ants.mooo.com",
"IP":"213.32.65.213",
"mayorid":"123",
"status":""
}
}

View File

@ -0,0 +1,9 @@
{
"id":"wall",
"nationid":"ants",
"contract":"town_base",
"url":"https://wall.ants.mooo.com",
"IP":"213.32.65.213",
"mayorid":"123",
"status":""
}

View File

@ -0,0 +1,11 @@
{
"sudoerUser": "phil",
"nationName":"ants",
"townName":"devndda",
"tribeName":"devndda",
"dns":"unchain",
"paganslogin":"pat",
"apiport": 3018,
"language": ["fr", "en"],
"jwtsecret": "longsentenceusedtoencryptionChangethisforproduction"
}

View File

@ -0,0 +1,13 @@
{
"saltRounds":10,
"exposedHeaders":[ "xauth", "xpaganid", "xlang", "xtribe", "xworkon", "xapp" ],
"unittesting":["middlewares","models","routes","nationchains"],
"appset":{"trust proxy":true},
"bodyparse": {
"urlencoded": {
"limit": "50mb",
"extended": true
},
"json": { "limit": "500mb" }
}
}

View File

@ -0,0 +1,25 @@
{
"tribeid": "${tribeName}",
"genericpsw": "",
"saltRounds": "12",
"allowedDOMs": ["${townName}.${nationName}.${dns}"],
"customization": {
"claim": "Be a Producer, not a product.",
"name": "apxtrib",
"logo": "https://${townName}.${nationName}.${dns}/static/img/chartegraphique/logo_bgtransparent.png",
"favicon": "https://${townName}.${nationName}.${dns}/static/img//chartegraphique/favicon.png",
"colors": {
"primary": "#01717B",
"secondary": "#CA5F00",
"success": "",
"info": "",
"warning": "",
"danger": "",
"light": "#fff",
"dark": "#222"
}
},
"smtp": {},
"accepted-language": "fr,en",
"langueReferential": ["fr"]
}

View File

@ -0,0 +1,13 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<title>Town base contract</title>
<link rel="stylesheet" href="static/css/style.css">
<script src="static/js/script.js"></script>
</head>
<body>
<p> Info sur le contrat de base d'une ville</p>
<p> </p>
</body>
</html>

View File

@ -4,21 +4,21 @@
"logo": { "logo": {
"file": "./nationchains/static/img/chartegraphique/logocarre_bgplein.png" "file": "./nationchains/static/img/chartegraphique/logocarre_bgplein.png"
}, },
"description": "A standard conf api based on express.js with basic and usefull component to manage api project", "description": "A Decentralized Autonomous Organization based on express.js restFULL api, allowing Pagans to join social rules (contracts.js) engrave in a nationsChains without any man in the middle.",
"main": "apxtrib.js", "main": "apxtrib.js",
"repository": { "repository": {
"url": "https://gitea.ndda.fr/apxtrib/apxtrib", "url": "https://gitea.ndda.fr/apxtrib/apxtrib",
"type": "git" "type": "git"
}, },
"scripts": { "scripts": {
"apidoc": "apidoc -i routes/ -o apidoc/",
"stoppm2": "pm2 stop apxtrib.js", "stoppm2": "pm2 stop apxtrib.js",
"startpm2": "pm2 start apxtrib.js --log-date-format 'DD-MM HH:mm:ss.SSS'", "startpm2": "pm2 start apxtrib.js --log-date-format 'DD-MM HH:mm:ss.SSS'",
"restartpm2": "pm2 restart apxtrib.js --log-date-format 'DD-MM HH:mm:ss.SSS'", "restartpm2": "pm2 restart apxtrib.js --log-date-format 'DD-MM HH:mm:ss.SSS'",
"startblockchain": "pm2 start ./models/Blockchains.js --log-date-format 'DD-MM HH:mm:ss:SSS'", "startblockchain": "pm2 start ./models/Blockchains.js --log-date-format 'DD-MM HH:mm:ss:SSS'",
"logpm2": "pm2 logs apxtrib.js --lines 200", "logpm2": "pm2 logs apxtrib.js --lines 200",
"setup": "node models/Setup.js", "setup": "node models/Setup.js",
"dev": "node apxtrib.js" "dev": "node apxtrib.js",
"unittest": "node unittest.js"
}, },
"apidoc": { "apidoc": {
"url": "https://apxtrib.crabdance.com/apidoc" "url": "https://apxtrib.crabdance.com/apidoc"

View File

@ -26,7 +26,7 @@ Manage a new towns in a nation => update nation:[nationname:towns:[]} contracts/
*/ */
router.post( '/push', checkHeaders, ( req, res ) => { router.post( '/push', checkHeaders, ( req, res ) => {
// Get information from other apixtribe instance in req.body // Get information from other apxtrib instance in req.body
// check req.body.hashnext => means this is a candidate to validate next block // check req.body.hashnext => means this is a candidate to validate next block
// //
// return it's own information back with the last call to Nationchains.synchronize() // return it's own information back with the last call to Nationchains.synchronize()

View File

@ -30,7 +30,7 @@ appname is a website space object /sitewebsrc/appname
website live is strored into /dist source in /src website live is strored into /dist source in /src
This can be managed by maildigitcreator or not. This can be managed by maildigitcreator or not.
apixtribe/sitewebs/webapp is the webinterface of apixtribe 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. 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/ It is also possible to authorize update a field's object depending of rule into dataManagement/object/

View File

@ -15,11 +15,11 @@ const router = express.Router();
router.get( '/clientconf/:tribeid', checkHeaders, isAuthenticated, ( req, res ) => { router.get( '/clientconf/:tribeid', checkHeaders, isAuthenticated, ( req, res ) => {
/* /*
get a clientconf.json for a tribeid depending of user accessright get a clientconf.json for a tribeid depending of user accessright
if tribeid == all and user is admin of apixtribe => get /tmp/clientconfglob.json if tribeid == all and user is admin of apxtrib => get /tmp/clientconfglob.json
req.session.header.accessrights, req.session.header.apixpaganid req.session.header.accessrights, req.session.header.apixpaganid
*/ */
console.log( `Tribes/clientconf for tribeid:${req.params.tribeid}` ) console.log( `Tribes/clientconf for tribeid:${req.params.tribeid}` )
if( req.params.tribeid == "all" && req.session.header.accessrights.data.apixtribe && req.session.header.accessrights.data.apixtribe.tribeid && req.session.header.accessrights.data.apixtribe.tribeid.includes( 'R' ) ) { if( req.params.tribeid == "all" && req.session.header.accessrights.data.apxtrib && req.session.header.accessrights.data.apxtrib.tribeid && req.session.header.accessrights.data.apxtrib.tribeid.includes( 'R' ) ) {
res.status( 200 ) res.status( 200 )
.send( { moreinfo: fs.readJsonSync( `${config.tmp}/clientconfglob.json`, 'utf-8' ) } ); .send( { moreinfo: fs.readJsonSync( `${config.tmp}/clientconfglob.json`, 'utf-8' ) } );
return; return;
@ -207,10 +207,10 @@ router.delete( '/file', checkHeaders, isAuthenticated, ( req, res ) => {
router.post( '/uploadfile', checkHeaders, isAuthenticated, ( req, res ) => { router.post( '/uploadfile', checkHeaders, isAuthenticated, ( req, res ) => {
console.log( 'upload a file ' ) console.log( 'upload a file ' )
/* Authentification is needed to get a TOKEN /* Authentification is needed to get a TOKEN
curl -X POST -H "xtribe: apixtribe" -H "xworkon: pvmsaveurs" -H "xlang: fr" -H "xpaganid: 1" -H "xauth: 1" -H "xapp: pvmsaveurs:pvmsaveurs" -H "Content-Type: application/json" -d '{"LOGIN":"adminapixtribe","PASSWORD":"Trze3aze!"}' http://pvmsaveurs.pvmsaveurs.fr/app/users/login curl -X POST -H "xtribe: apxtrib" -H "xworkon: pvmsaveurs" -H "xlang: fr" -H "xpaganid: 1" -H "xauth: 1" -H "xapp: pvmsaveurs:pvmsaveurs" -H "Content-Type: application/json" -d '{"LOGIN":"adminapxtrib","PASSWORD":"Trze3aze!"}' http://pvmsaveurs.pvmsaveurs.fr/app/users/login
if exist replace xpaganidTOKEN with payload.TOKEN value if exist replace xpaganidTOKEN with payload.TOKEN value
curl -H "xtribe: pvmsaveurs" -H "xworkon: pvmsaveurs" -H "xlang: fr" -H "xpaganid: adminapixtribe" -H "xauth: xpressuuisToken" -H "xapp: pvmsaveurs:pvmsaveurs" -F 'data=@filename.xx' http://pvmsaveurs.pvmsaveurs.fr/app/Tribes/uploadfile curl -H "xtribe: pvmsaveurs" -H "xworkon: pvmsaveurs" -H "xlang: fr" -H "xpaganid: adminapxtrib" -H "xauth: xpressuuisToken" -H "xapp: pvmsaveurs:pvmsaveurs" -F 'data=@filename.xx' http://pvmsaveurs.pvmsaveurs.fr/app/Tribes/uploadfile
*/ */
const formidable = require( 'formidable' ); const formidable = require( 'formidable' );
const form = formidable( { multiples: false } ); const form = formidable( { multiples: false } );
@ -255,13 +255,13 @@ router.post( '/uploadzip', checkHeaders, ( req, res ) => {
}, },
Example: Example:
cd where zip file is stored cd where zip file is stored
curl -H "xtribe: pvmsaveurs" -H "xworkon: pvmsaveurs" -H "xlang: fr" -H "xpaganid: adminapixtribe" -H "xauth: 1" -H "xapp: pvmsaveurs:pvmsaveurs" -F 'data=@articlesTribespvm.zip' http://pvmsaveurs.pvmsaveurs.fr/app/Tribes/uploadzip curl -H "xtribe: pvmsaveurs" -H "xworkon: pvmsaveurs" -H "xlang: fr" -H "xpaganid: adminapxtrib" -H "xauth: 1" -H "xapp: pvmsaveurs:pvmsaveurs" -F 'data=@articlesTribespvm.zip' http://pvmsaveurs.pvmsaveurs.fr/app/Tribes/uploadzip
*/ */
const clientconf = fs.readJSONSync( `${config.tribes}/${req.session.header.xworkon}/clientconf.json` ) const clientconf = fs.readJSONSync( `${config.tribes}/${req.session.header.xworkon}/clientconf.json` )
if( !clientconf.uploadzip ) { if( !clientconf.uploadzip ) {
return res.status( '404' ) return res.status( '404' )
.send( { info: [ "missconf" ], models: "Tribes", moreinfo: `no uploadzip in clientconf for ${req.session.header.xworkon} please contact apixtribe admin ` } ); .send( { info: [ "missconf" ], models: "Tribes", moreinfo: `no uploadzip in clientconf for ${req.session.header.xworkon} please contact apxtrib admin ` } );
}; };
const uploadzip = clientconf.uploadzip; const uploadzip = clientconf.uploadzip;
const formidable = require( 'formidable' ); const formidable = require( 'formidable' );

View File

@ -3,7 +3,7 @@ const path = require( 'path' );
const fs = require( 'fs' ); const fs = require( 'fs' );
const config = {}; const config = {};
if( !process.env.NODE_ENV ) process.env.NODE_ENV = "dev" if( !process.env.NODE_ENV ) process.env.NODE_ENV = "dev"
console.log( 'apixtribe process.env.NODE_ENV: ', process.env.NODE_ENV ); console.log( 'apxtrib process.env.NODE_ENV: ', process.env.NODE_ENV );
// VOIR l'ancien fichier de cnfig au cas ou il manque des chemins dans config // VOIR l'ancien fichier de cnfig au cas ou il manque des chemins dans config
// voir la doc http://gitlab.ndda.fr/philc/apiamaildigitfr/wikis/InstallConf // voir la doc http://gitlab.ndda.fr/philc/apiamaildigitfr/wikis/InstallConf
config.prod = { config.prod = {
@ -44,7 +44,7 @@ config.prod = {
} }
}; };
// Development and test config // Development and test config
// apixtribe.local.fr // apxtrib.local.fr
config.dev = { config.dev = {
mainDir: __dirname, mainDir: __dirname,
@ -52,13 +52,13 @@ config.dev = {
public: path.join( __dirname, '/public' ), public: path.join( __dirname, '/public' ),
//public allow to serve on /public file into folder /public with or without login //public allow to serve on /public file into folder /public with or without login
archivefolder: path.join( __dirname, '/archive' ), archivefolder: path.join( __dirname, '/archive' ),
rootURL: 'apixtribe.local.fr', rootURL: 'apxtrib.local.fr',
domain: path.join( __dirname, '/data/tribee' ), domain: path.join( __dirname, '/data/tribee' ),
withssl: "YES", withssl: "YES",
SSLCredentials: { SSLCredentials: {
key: path.join( __dirname, '/setup/data/certs/apixtribe.local.fr.key' ), key: path.join( __dirname, '/setup/data/certs/apxtrib.local.fr.key' ),
cert: path.join( __dirname, '/setup/data/certs/apixtribe.local.fr.crt' ), cert: path.join( __dirname, '/setup/data/certs/apxtrib.local.fr.crt' ),
ca: path.join( __dirname, '/setup/data/certs/apixtribe.local.fr.csr' ) ca: path.join( __dirname, '/setup/data/certs/apxtrib.local.fr.csr' )
}, },
port: { port: {
http: "{{httpport}}", http: "{{httpport}}",

View File

@ -1,12 +1,12 @@
server { server {
server_name {{config.apixtribeDNS}}; server_name {{config.apxtribDNS}};
add_header X-Request-ID $request_id; # Return to client add_header X-Request-ID $request_id; # Return to client
add_header Access-Control-Allow-Origin *; add_header Access-Control-Allow-Origin *;
add_header Access-Control-Max-Age 3600; add_header Access-Control-Max-Age 3600;
add_header Access-Control-Expose-Headers Content-Length; add_header Access-Control-Expose-Headers Content-Length;
add_header Access-Control-Allow-Headers Range; add_header Access-Control-Allow-Headers Range;
access_log /media/phil/usbfarm/apixtribe/tmp/nginx/apixtribe.crabdance.access.log main; access_log /media/phil/usbfarm/apxtrib/tmp/nginx/apxtrib.crabdance.access.log main;
#location = /app { #location = /app {
# return 302 /app/; # return 302 /app/;
@ -28,10 +28,10 @@ server {
} }
location / { location / {
root /media/phil/usbfarm/apixtribe/nationchains/; root /media/phil/usbfarm/apxtrib/nationchains/;
index apixtribe.html; index apxtrib.html;
} }
error_page 404 /media/phil/usbfarm/apixtribe/nationchains/error/404.html; error_page 404 /media/phil/usbfarm/apxtrib/nationchains/error/404.html;
error_page 500 502 503 504 /media/phil/usbfarm/apixtribe/nationchains/error/50x.html; error_page 500 502 503 504 /media/phil/usbfarm/apxtrib/nationchains/error/50x.html;
} }

View File

@ -3,11 +3,11 @@ const config = {
loglevel:"{{consoleloglevel}}", loglevel:"{{consoleloglevel}}",
linuxuser:"{{linuxuser}}", linuxuser:"{{linuxuser}}",
druidid:"{{druidid}}", druidid:"{{druidid}}",
dnsapixtribe:"{{subdomain}}.{{domain}}", dnsapxtrib:"{{subdomain}}.{{domain}}",
mainDir: __dirname, mainDir: __dirname,
tmp: path.join( __dirname, '/tmp' ), tmp: path.join( __dirname, '/tmp' ),
public: path.join( __dirname, 'data/tribe/{{druidid}}/www/cdn' ), public: path.join( __dirname, 'data/tribe/{{druidid}}/www/cdn' ),
//(@TODO ASUP mettre /cdn de apixtribe) public allow to serve on /public file into folder /public with or without login //(@TODO ASUP mettre /cdn de apxtrib) public allow to serve on /public file into folder /public with or without login
archivefolder: path.join( __dirname, '/archive' ), archivefolder: path.join( __dirname, '/archive' ),
domain: path.join( __dirname, '/data/tribe' ), domain: path.join( __dirname, '/data/tribe' ),
porthttp:{{porthttp}} , porthttp:{{porthttp}} ,

View File

@ -8,8 +8,8 @@
"allowedDOMs": ["{{domain}}"], "allowedDOMs": ["{{domain}}"],
"customization": { "customization": {
"claim": "Be a Producer, not a product.", "claim": "Be a Producer, not a product.",
"name": "apixtribe", "name": "apxtrib",
"logo": "https://{{subdomain}}.{{domain}}/cdn/{{druidid}}/img/logo/apixtribe.png", "logo": "https://{{subdomain}}.{{domain}}/cdn/{{druidid}}/img/logo/apxtrib.png",
"favicon": "https://{{subdomain}}.{{domain}}/cdn/{{druidid}}/img/iconX74x74.png", "favicon": "https://{{subdomain}}.{{domain}}/cdn/{{druidid}}/img/iconX74x74.png",
"colors": { "colors": {
"primary": "#01717B", "primary": "#01717B",

View File

@ -29,8 +29,8 @@
"type": "text", "type": "text",
"tpl": "input", "tpl": "input",
"info": { "info": {
"fr": "<p>Le login doit être unique sur une instance d'apixtribe.</p><p> Pour échanger en dehors d'une instance apixtribe on utilise la clé public du user ou pour un humain login@apixtribe.domain.xx avec le nom du domaine qui heberge l'instance</p><p> Ou encore login@domain.xx tout domain.xx utilisé pour heberger un espace web client /tribeid/www/</p>", "fr": "<p>Le login doit être unique sur une instance d'apxtrib.</p><p> Pour échanger en dehors d'une instance apxtrib on utilise la clé public du user ou pour un humain login@apxtrib.domain.xx avec le nom du domaine qui heberge l'instance</p><p> Ou encore login@domain.xx tout domain.xx utilisé pour heberger un espace web client /tribeid/www/</p>",
"en": "<p>Login have to be unique into an apixtribe instance</p><p> To exchange outside of an apixtribe instance, we use PublicKey or login@apixtribe.domain.xx or login@domainclient.xx where domain.xx is a apixtribe name server on internet and domain.xx is a tribeid name where a /tribeid/www is available on the net.</p>" "en": "<p>Login have to be unique into an apxtrib instance</p><p> To exchange outside of an apxtrib instance, we use PublicKey or login@apxtrib.domain.xx or login@domainclient.xx where domain.xx is a apxtrib name server on internet and domain.xx is a tribeid name where a /tribeid/www is available on the net.</p>"
} }
}, },
{ {
@ -118,8 +118,8 @@
"en": "pseudo" "en": "pseudo"
}, },
"info": { "info": {
"fr": "<p>Nom avec lequel vous souhaitez qu'on vous reconnaisse sur l'instance de l'apixtribe </p><p>Attention ce nom n'est unique que sur une instance d'apixtribe. Un même speudo peut-être utilisé sur un autre serveur pour garantir l'identité vérifié pseudo@ domaine de rattachement.</p>", "fr": "<p>Nom avec lequel vous souhaitez qu'on vous reconnaisse sur l'instance de l'apxtrib </p><p>Attention ce nom n'est unique que sur une instance d'apxtrib. Un même speudo peut-être utilisé sur un autre serveur pour garantir l'identité vérifié pseudo@ domaine de rattachement.</p>",
"en": "<p>Carrefull a pseudo is unique into an instance of apixtribe to be sure to contact the right person check pseudo@ domain</p>.<p> Pseudo can be changed that is not the case of login.</p>" "en": "<p>Carrefull a pseudo is unique into an instance of apxtrib to be sure to contact the right person check pseudo@ domain</p>.<p> Pseudo can be changed that is not the case of login.</p>"
}, },
"tpl": "input", "tpl": "input",
"type": "text" "type": "text"

View File

@ -29,8 +29,8 @@
"type": "text", "type": "text",
"tpl": "input", "tpl": "input",
"info": { "info": {
"fr": "<p>Le login doit être unique sur une instance d'apixtribe.</p><p> Pour échanger en dehors d'une instance apixtribe on utilise la clé public du user ou pour un humain login@apixtribe.domain.xx avec le nom du domaine qui heberge l'instance</p><p> Ou encore login@domain.xx tout domain.xx utilisé pour heberger un espace web client /tribeid/www/</p>", "fr": "<p>Le login doit être unique sur une instance d'apxtrib.</p><p> Pour échanger en dehors d'une instance apxtrib on utilise la clé public du user ou pour un humain login@apxtrib.domain.xx avec le nom du domaine qui heberge l'instance</p><p> Ou encore login@domain.xx tout domain.xx utilisé pour heberger un espace web client /tribeid/www/</p>",
"en": "<p>Login have to be unique into an apixtribe instance</p><p> To exchange outside of an apixtribe instance, we use PublicKey or login@apixtribe.domain.xx or login@domainclient.xx where domain.xx is a apixtribe name server on internet and domain.xx is a tribeid name where a /tribeid/www is available on the net.</p>" "en": "<p>Login have to be unique into an apxtrib instance</p><p> To exchange outside of an apxtrib instance, we use PublicKey or login@apxtrib.domain.xx or login@domainclient.xx where domain.xx is a apxtrib name server on internet and domain.xx is a tribeid name where a /tribeid/www is available on the net.</p>"
} }
}, },
{ {
@ -118,8 +118,8 @@
"en": "pseudo" "en": "pseudo"
}, },
"info": { "info": {
"fr": "<p>Nom avec lequel vous souhaitez qu'on vous reconnaisse sur l'instance de l'apixtribe </p><p>Attention ce nom n'est unique que sur une instance d'apixtribe. Un même speudo peut-être utilisé sur un autre serveur pour garantir l'identité vérifié pseudo@ domaine de rattachement.</p>", "fr": "<p>Nom avec lequel vous souhaitez qu'on vous reconnaisse sur l'instance de l'apxtrib </p><p>Attention ce nom n'est unique que sur une instance d'apxtrib. Un même speudo peut-être utilisé sur un autre serveur pour garantir l'identité vérifié pseudo@ domaine de rattachement.</p>",
"en": "<p>Carrefull a pseudo is unique into an instance of apixtribe to be sure to contact the right person check pseudo@ domain</p>.<p> Pseudo can be changed that is not the case of login.</p>" "en": "<p>Carrefull a pseudo is unique into an instance of apxtrib to be sure to contact the right person check pseudo@ domain</p>.<p> Pseudo can be changed that is not the case of login.</p>"
}, },
"tpl": "input", "tpl": "input",
"type": "text" "type": "text"

View File

@ -5,10 +5,10 @@
"$2b$10$hFV/33UixB3Cn.XzLIhmTeRYU2XThnxYuwCVIifwQ7v/yCtRLIsuq", "$2b$10$hFV/33UixB3Cn.XzLIhmTeRYU2XThnxYuwCVIifwQ7v/yCtRLIsuq",
{ {
"app": { "app": {
"apixtribe:webapp": "admin" "apxtrib:webapp": "admin"
}, },
"data": { "data": {
"apixtribe": { "apxtrib": {
"users": "CRUDO", "users": "CRUDO",
"referentials": "CRUDO" "referentials": "CRUDO"
} }

View File

@ -1,5 +1,5 @@
<html data-tribeid="apixtribe" data-website="webapp" data-nametpl="app" data-pagename="index_fr" data-pageneedauthentification="false" data-pageredirectforauthentification="fullscreen_auth" data-urlbackoffice="apixtribe.ndda.fr" lang="fr" data-env="prod" data-version="1640518264045"> <html data-tribeid="apxtrib" data-website="webapp" data-nametpl="app" data-pagename="index_fr" data-pageneedauthentification="false" data-pageredirectforauthentification="fullscreen_auth" data-urlbackoffice="apxtrib.ndda.fr" lang="fr" data-env="prod" data-version="1640518264045">
<head><!--head --> <head><!--head -->
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

View File

@ -1,12 +1,12 @@
<html data-tribeid="apixtribe" data-website="webapp" data-nametpl="fullscreen" data-pagename="auth_fr" data-pageneedauthentification="false" data-pageredirectforauthentification="fullscreen_auth" data-urlbackoffice="apixtribe.ndda.fr" lang="fr" data-env="prod" data-version="1640518263426"> <html data-tribeid="apxtrib" data-website="webapp" data-nametpl="fullscreen" data-pagename="auth_fr" data-pageneedauthentification="false" data-pageredirectforauthentification="fullscreen_auth" data-urlbackoffice="apxtrib.ndda.fr" lang="fr" data-env="prod" data-version="1640518263426">
<head><!--head --> <head><!--head -->
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="author" content=""> <meta name="author" content="">
<meta name="email" content=""> <meta name="email" content="">
<meta name="keywords" content=""> <meta name="keywords" content="">
<title>apixtribe></title> <title>apxtrib></title>
<link rel="stylesheet" type="text/css" href="static&#x2F;fonts&#x2F;icofont&#x2F;icofont.min.css"> <link rel="stylesheet" type="text/css" href="static&#x2F;fonts&#x2F;icofont&#x2F;icofont.min.css">
<link rel="stylesheet" type="text/css" href="css&#x2F;fullscreen&#x2F;styles.css"> <link rel="stylesheet" type="text/css" href="css&#x2F;fullscreen&#x2F;styles.css">
<!-- /head--> <!-- /head-->
@ -22,19 +22,19 @@
<div class="text-center mt-4"> <div class="text-center mt-4">
<h1 class="h2">Need-Data</h1> <h1 class="h2">Need-Data</h1>
<p class="lead"> <p class="lead">
Votre hébergement apixtribe en toute confidentialité. Votre hébergement apxtrib en toute confidentialité.
</p> </p>
</div> </div>
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<div class="m-sm-4"> <div class="m-sm-4">
<div class="text-center"> <div class="text-center">
<img src="static/img/logo/ndda.png" alt="logo apixtribe" class="img-fluid" width="132" height="132" /> <img src="static/img/logo/ndda.png" alt="logo apxtrib" class="img-fluid" width="132" height="132" />
</div> </div>
<form> <form>
<div class="mb-3"> <div class="mb-3">
<label class="form-label">Identifiant</label> <label class="form-label">Identifiant</label>
<input class="form-control form-control-lg" type="text" name="login" value="adminapixtribe" placeholder="Votre identifiant (login ou clé public)" /> <input class="form-control form-control-lg" type="text" name="login" value="adminapxtrib" placeholder="Votre identifiant (login ou clé public)" />
</div> </div>
<div class="mb-3"> <div class="mb-3">
<label class="form-label">Mot de passe</label> <label class="form-label">Mot de passe</label>
@ -108,7 +108,7 @@ value="Trze3aze!" placeholder="Mot de passe ou hash sur clé public" />
<div class="text-center mt-4"> <div class="text-center mt-4">
<h1 class="h2">S'inscrire à votre communauté</h1> <h1 class="h2">S'inscrire à votre communauté</h1>
<p class="lead"> <p class="lead">
Vous devez disposez du nom de la communauté qui vous invite à ouvrir un compte chez elle.<br> Pour créer une communauté, sur cet hébergement: <a href='mailto:contact@need-data.com'>contact@need-data.com</a>.<br> En savoir plus sur <a href='https://apixtribe.org/anonymat_avec_apixppress.html'>Anomymat & apixtribe</a>. Vous devez disposez du nom de la communauté qui vous invite à ouvrir un compte chez elle.<br> Pour créer une communauté, sur cet hébergement: <a href='mailto:contact@need-data.com'>contact@need-data.com</a>.<br> En savoir plus sur <a href='https://apxtrib.org/anonymat_avec_apixppress.html'>Anomymat & apxtrib</a>.
</p> </p>
</div> </div>
<div class="card"> <div class="card">

View File

@ -1 +1 @@
{"name":"apixtribe Need-Data","short_name":"apixtribe","start_url":"app_index_fr.html","background_color":"purple","description":"Webapp to manage an apixtribe server.","display":"fullscreen","icons":[{"src":"static/img/icons/iconX74x74.png","sizes":"74x74","type":"image/png"}]} {"name":"apxtrib Need-Data","short_name":"apxtrib","start_url":"app_index_fr.html","background_color":"purple","description":"Webapp to manage an apxtrib server.","display":"fullscreen","icons":[{"src":"static/img/icons/iconX74x74.png","sizes":"74x74","type":"image/png"}]}

View File

@ -3,32 +3,32 @@ pwa.main = pwa.main || {};
pwa.main.tpldata = pwa.main.tpldata || {}; pwa.main.tpldata = pwa.main.tpldata || {};
pwa.main.tpl = pwa.main.tpl || {}; pwa.main.tpl = pwa.main.tpl || {};
//menu //menu
pwa.main.tpldata.sidebarAdminapixtribe = `static/components/adminapixtribe/sidebaradminapixtribe`; pwa.main.tpldata.sidebarAdminapxtrib = `static/components/adminapxtrib/sidebaradminapxtrib`;
// Custom data in user lang // Custom data in user lang
//tremplate to store //tremplate to store
pwa.main.tpl.adminapixtribe = 'static/components/adminapixtribe/adminapixtribe.mustache'; pwa.main.tpl.adminapxtrib = 'static/components/adminapxtrib/adminapxtrib.mustache';
pwa.main.tpl.adminapixtribesysinfo = 'static/components/adminapixtribe/adminapixtribesysinfo.mustache'; pwa.main.tpl.adminapxtribsysinfo = 'static/components/adminapxtrib/adminapxtribsysinfo.mustache';
pwa.main.tpl.adminapixtribeactivity = 'static/components/adminapixtribe/adminapixtribeactivity.mustache'; pwa.main.tpl.adminapxtribactivity = 'static/components/adminapxtrib/adminapxtribactivity.mustache';
pwa.adminapixtribe = {}; pwa.adminapxtrib = {};
pwa.adminapixtribe.init = () => { pwa.adminapxtrib.init = () => {
// Run back stuff to update data // Run back stuff to update data
} }
pwa.adminapixtribe.sysinfoview = () => { pwa.adminapxtrib.sysinfoview = () => {
const datasysinfo = {}; //request to get info and push them in template const datasysinfo = {}; //request to get info and push them in template
document.getElementById( 'maincontent' ) document.getElementById( 'maincontent' )
.innerHTML = Mustache.render( pwa.state.data.tpl.adminapixtribesysinfo, datasysinfo ); .innerHTML = Mustache.render( pwa.state.data.tpl.adminapxtribsysinfo, datasysinfo );
} }
pwa.adminapixtribe.activityview = () => { pwa.adminapxtrib.activityview = () => {
const dataactivity = {}; //request to get info and push them in template const dataactivity = {}; //request to get info and push them in template
document.getElementById( 'maincontent' ) document.getElementById( 'maincontent' )
.innerHTML = Mustache.render( pwa.state.data.tpl.adminapixtribeactivity, dataactivity ); .innerHTML = Mustache.render( pwa.state.data.tpl.adminapxtribactivity, dataactivity );
} }
pwa.adminapixtribe.tribeidview = () => { pwa.adminapxtrib.tribeidview = () => {
const datatribeid = {}; //request to get info and push them in template const datatribeid = {}; //request to get info and push them in template
document.getElementById( 'maincontent' ) document.getElementById( 'maincontent' )
.innerHTML = Mustache.render( pwa.state.data.tpl.adminapixtribe, datatribeid ); .innerHTML = Mustache.render( pwa.state.data.tpl.adminapxtrib, datatribeid );
} }

View File

@ -1,22 +1,22 @@
{ {
"groupheader": "Admin apixtribe", "groupheader": "Admin apxtrib",
"sbssgroupmenu": [{ "sbssgroupmenu": [{
"name": "Activité", "name": "Activité",
"icon": "sliders", "icon": "sliders",
"actionclick": "pwa.adminapixtribe.init()", "actionclick": "pwa.adminapxtrib.init()",
"iditemmenus": "adminxpress", "iditemmenus": "adminxpress",
"itemmenus": [{ "itemmenus": [{
"name": "Info activités", "name": "Info activités",
"actionclick": "pwa.adminapixtribe.activityview()" "actionclick": "pwa.adminapxtrib.activityview()"
}, },
{ {
"name": "Admin des tribeid", "name": "Admin des tribeid",
"actionclick": "pwa.adminapixtribe.tribeidview()" "actionclick": "pwa.adminapxtrib.tribeidview()"
} }
] ]
}, { }, {
"name": "System Info", "name": "System Info",
"icon": "sliders", "icon": "sliders",
"actionclick": "pwa.adminapixtribe.sysinfoview()" "actionclick": "pwa.adminapxtrib.sysinfoview()"
}] }]
} }

View File

@ -1,5 +1,5 @@
{ {
"groupheader": "Admin apixtribe", "groupheader": "Admin apxtrib",
"sbssgroupmenu": [{ "sbssgroupmenu": [{
"name": "Tribes", "name": "Tribes",
"icon": "sliders", "icon": "sliders",

View File

@ -10,7 +10,7 @@
<div class="row text-muted"> <div class="row text-muted">
<div class="col-6 text-start"> <div class="col-6 text-start">
<p class="mb-0"> <p class="mb-0">
<a href="{{{urlapixtribe}}}" class="text-muted"><strong>{{claim}}</strong></a> &copy; <a href="{{{urlapxtrib}}}" class="text-muted"><strong>{{claim}}</strong></a> &copy;
</p> </p>
</div> </div>
<div class="col-6 text-end"> <div class="col-6 text-end">

View File

@ -1,8 +1,8 @@
{ {
"navbarclass": "navbar-expand navbar-light navbar-bg", "navbarclass": "navbar-expand navbar-light navbar-bg",
"footer": { "footer": {
"urlapixtribe": "https://apixtribe.org", "urlapxtrib": "https://apxtrib.org",
"claim": "apixtribe made with love for freedom", "claim": "apxtrib made with love for freedom",
"links": [{ "links": [{
"url": "#", "url": "#",
"desc": "Support" "desc": "Support"

View File

@ -2,7 +2,7 @@
"sbbrandlink": "app_index_fr.html", "sbbrandlink": "app_index_fr.html",
"sbtitle": "Need-Data", "sbtitle": "Need-Data",
"sbgroupmenu": [{ "sbgroupmenu": [{
"groupheader": "apixtribe", "groupheader": "apxtrib",
"sbssgroupmenu": [{ "sbssgroupmenu": [{
"name": "Les news", "name": "Les news",
"icon": "sliders", "icon": "sliders",
@ -12,7 +12,7 @@
"name": "Reporting", "name": "Reporting",
"icon": "sliders", "icon": "sliders",
"actionclick": "pwa.reporting.init()", "actionclick": "pwa.reporting.init()",
"iditemmenus": "reportingapixtribe", "iditemmenus": "reportingapxtrib",
"itemmenus": [{ "itemmenus": [{
"name": "", "name": "",
"actionclick": "pwa.reporting.init()" "actionclick": "pwa.reporting.init()"

View File

@ -1,6 +1,6 @@
// app management for search request // app management for search request
/* /*
@todo create a search/index content for an apixtribe instance @todo create a search/index content for an apxtrib instance
//store request to analyse kind of looking for //store request to analyse kind of looking for
*/ */
@ -34,7 +34,7 @@ pwa.search.tpl = `
pwa.search.dataexample = { pwa.search.dataexample = {
searchtxt: "search string to looking for", searchtxt: "search string to looking for",
results: [ { results: [ {
url: "https://apixtribe.org", url: "https://apxtrib.org",
format: "pdf", format: "pdf",
title: "Search finding title of the page", title: "Search finding title of the page",
desc: "sentence contexte of the searchtxt", desc: "sentence contexte of the searchtxt",

View File

@ -1,8 +1,8 @@
{ {
"navbarclass": "navbar-expand navbar-light navbar-bg", "navbarclass": "navbar-expand navbar-light navbar-bg",
"footer": { "footer": {
"urlapixtribe": "https://apixtribe.org", "urlapxtrib": "https://apxtrib.org",
"claim": "apixtribe made with love for freedom", "claim": "apxtrib made with love for freedom",
"links": [{ "links": [{
"url": "#", "url": "#",
"desc": "Support" "desc": "Support"

View File

@ -1,7 +1,7 @@
{ {
"signin": { "signin": {
"claimh1": "Need-Data", "claimh1": "Need-Data",
"claimp": "Votre hébergement apixtribe en toute confidentialité.", "claimp": "Votre hébergement apxtrib en toute confidentialité.",
"logo": "static/img/logo/ndda.png", "logo": "static/img/logo/ndda.png",
"classlogo": "img-fluid", "classlogo": "img-fluid",
"login": "Identifiant", "login": "Identifiant",
@ -30,8 +30,8 @@
}, },
"register": { "register": {
"claimh1": "S'inscrire à votre communauté", "claimh1": "S'inscrire à votre communauté",
"claimp": "Vous devez disposez du nom de la communauté qui vous invite à ouvrir un compte chez elle.<br> Pour créer une communauté, sur cet hébergement: <a href='mailto:contact@need-data.com'>contact@need-data.com</a>.<br> En savoir plus sur <a href='https://apixtribe.org/anonymat_avec_apixppress.html'>Anomymat & apixtribe</a>.", "claimp": "Vous devez disposez du nom de la communauté qui vous invite à ouvrir un compte chez elle.<br> Pour créer une communauté, sur cet hébergement: <a href='mailto:contact@need-data.com'>contact@need-data.com</a>.<br> En savoir plus sur <a href='https://apxtrib.org/anonymat_avec_apixppress.html'>Anomymat & apxtrib</a>.",
"logoapixtribe": "static/img/logo/apixtribe.png", "logoapxtrib": "static/img/logo/apxtrib.png",
"logoowner": "static/img/logo/ndda.png", "logoowner": "static/img/logo/ndda.png",
"login": "Votre identifiant", "login": "Votre identifiant",
"loginph": "login ou clé public", "loginph": "login ou clé public",

View File

@ -1,5 +1,5 @@
{ {
"title": "apixtribe", "title": "apxtrib",
"js": [], "js": [],
"css": ["static/fonts/icofont/icofont.min.css", "css/fullscreen/styles.css"] "css": ["static/fonts/icofont/icofont.min.css", "css/fullscreen/styles.css"]
} }

View File

@ -1,5 +1,5 @@
[{ [{
"groupheader": "Admin apixtribe", "groupheader": "Admin apxtrib",
"sbssgroupmenu": [{ "sbssgroupmenu": [{
"name": "Tribes", "name": "Tribes",
"icon": "sliders", "icon": "sliders",

View File

@ -2,7 +2,7 @@
"sbbrandlink": "app_index_fr.html", "sbbrandlink": "app_index_fr.html",
"sbtitle": "Need-Data", "sbtitle": "Need-Data",
"sbgroupmenu": [{ "sbgroupmenu": [{
"groupheader": "apixtribe", "groupheader": "apxtrib",
"sbssgroupmenu": [{ "sbssgroupmenu": [{
"name": "Les news", "name": "Les news",
"icon": "sliders", "icon": "sliders",
@ -12,7 +12,7 @@
"name": "Reporting", "name": "Reporting",
"icon": "sliders", "icon": "sliders",
"actionclick": "pwa.reporting.init()", "actionclick": "pwa.reporting.init()",
"iditemmenus": "reportingapixtribe", "iditemmenus": "reportingapxtrib",
"itemmenus": [{ "itemmenus": [{
"name": "", "name": "",
"actionclick": "pwa.reporting.init()" "actionclick": "pwa.reporting.init()"

View File

@ -1,6 +1,6 @@
<map version="1.1.0"> <map version="1.1.0">
<!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net --> <!-- To view this file, download free mind mapping software FreeMind from http://freemind.sourceforge.net -->
<node COLOR="#808080" CREATED="1648107811020" ID="ID_788040965" MODIFIED="1648109044162" TEXT="apixtribe"> <node COLOR="#808080" CREATED="1648107811020" ID="ID_788040965" MODIFIED="1648109044162" TEXT="apxtrib">
<font NAME="Ubuntu Light" SIZE="12"/> <font NAME="Ubuntu Light" SIZE="12"/>
<node CREATED="1648108926891" HGAP="53" ID="ID_178913901" MODIFIED="1648109039795" POSITION="right" TEXT="Architecture" VSHIFT="-65"> <node CREATED="1648108926891" HGAP="53" ID="ID_178913901" MODIFIED="1648109039795" POSITION="right" TEXT="Architecture" VSHIFT="-65">
<font NAME="Ubuntu Light" SIZE="12"/> <font NAME="Ubuntu Light" SIZE="12"/>

View File

@ -1,4 +1,4 @@
<h1>ST**** ME I'M FAMOUS!</h1> <h1>ST**** ME I'M FAMOUS!</h1>
<p> apixtribe <p> apxtrib
</p> </p>

View File

@ -132,7 +132,7 @@ tg.action = (post) => {
xhttp.onreadystatechange = function() {}; xhttp.onreadystatechange = function() {};
xhttp.open( xhttp.open(
'POST', 'POST',
`${pwa.urlapixtribe}/tags/${pwa.tribeid}`, `${pwa.urlapxtrib}/tags/${pwa.tribeid}`,
true true
); );
xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
@ -151,7 +151,7 @@ tg.action = (post) => {
$(document) $(document)
.ready(function() { .ready(function() {
if(!pwa.tribeid) { if(!pwa.tribeid) {
pwa.urlapixtribe = 'https://api' + $('#mxp') pwa.urlapxtrib = 'https://api' + $('#mxp')
.attr('data-destin') + '.maildigit.fr'; .attr('data-destin') + '.maildigit.fr';
pwa.tribeid = $('#mxp') pwa.tribeid = $('#mxp')
.attr('data-tribeid'); .attr('data-tribeid');

View File

@ -16,7 +16,7 @@
version="1.1" version="1.1"
id="svg8" id="svg8"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)" inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
sodipodi:docname="suiviprojetapixtribe.svg"> sodipodi:docname="suiviprojetapxtrib.svg">
<defs <defs
id="defs2" /> id="defs2" />
<sodipodi:namedview <sodipodi:namedview
@ -285,7 +285,7 @@
x="155.44144" x="155.44144"
y="121.62955" y="121.62955"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan4614-7">Referentials /apixtribe/referentials/object/users.json</tspan><tspan id="tspan4614-7">Referentials /apxtrib/referentials/object/users.json</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="155.44144" x="155.44144"
y="123.39344" y="123.39344"
@ -382,7 +382,7 @@
x="214.0296" x="214.0296"
y="158.29131" y="158.29131"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan4959">http://gitlab.ndda.fr/philc/apixtribe/-/wikis/HOWTOMessage</tspan><tspan id="tspan4959">http://gitlab.ndda.fr/philc/apxtrib/-/wikis/HOWTOMessage</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="214.0296" x="214.0296"
y="160.05519" y="160.05519"
@ -702,7 +702,7 @@
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan855-7-8">get /clientconfglob =&gt; 200 full config for all server + token /403 (<tspan id="tspan855-7-8">get /clientconfglob =&gt; 200 full config for all server + token /403 (<tspan
style="fill:#9b7700;fill-opacity:1" style="fill:#9b7700;fill-opacity:1"
id="tspan4874">only for admin apixtribe)</tspan> </tspan><tspan id="tspan4874">only for admin apxtrib)</tspan> </tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="42.193268" x="42.193268"
y="181.51306" y="181.51306"
@ -720,8 +720,8 @@
id="tspan4586-9-0">get /contentfull/:source/:idref </tspan></text> id="tspan4586-9-0">get /contentfull/:source/:idref </tspan></text>
<a <a
id="a4922" id="a4922"
xlink:href="http://gitlab.ndda.fr/philc/apixtribe/-/wikis/SETUP4dev" xlink:href="http://gitlab.ndda.fr/philc/apxtrib/-/wikis/SETUP4dev"
xlink:title="gitlab apixtribe" xlink:title="gitlab apxtrib"
xlink:actuate="onclick" xlink:actuate="onclick"
transform="translate(-4.9872084,-5.3371879)"> transform="translate(-4.9872084,-5.3371879)">
<a <a
@ -749,7 +749,7 @@
x="4.0466719" x="4.0466719"
y="96.854599" y="96.854599"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan4916">http://gitlab.ndda.fr/philc/apixtribe/-/wikis/SETUP</tspan><tspan id="tspan4916">http://gitlab.ndda.fr/philc/apxtrib/-/wikis/SETUP</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="4.0466719" x="4.0466719"
y="98.618484" y="98.618484"
@ -802,8 +802,8 @@
id="flowPara5002" /></flowRoot> <a id="flowPara5002" /></flowRoot> <a
transform="translate(-5.4083819,8.1029941)" transform="translate(-5.4083819,8.1029941)"
id="a4922-6" id="a4922-6"
xlink:href="http://gitlab.ndda.fr/philc/apixtribe/-/wikis/SETUP4dev" xlink:href="http://gitlab.ndda.fr/philc/apxtrib/-/wikis/SETUP4dev"
xlink:title="gitlab apixtribe" xlink:title="gitlab apxtrib"
xlink:actuate="onclick"> xlink:actuate="onclick">
<a <a
id="a4926-1"> id="a4926-1">
@ -857,7 +857,7 @@
x="3.6254988" x="3.6254988"
y="119.11422" y="119.11422"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan1152"> Instance apixtribe http://local.apixtribe.fr (no ssl for nginx and express) </tspan><tspan id="tspan1152"> Instance apxtrib http://local.apxtrib.fr (no ssl for nginx and express) </tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="3.6254988" x="3.6254988"
y="120.87811" y="120.87811"
@ -879,12 +879,12 @@
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan4843"> &lt;<tspan id="tspan4843"> &lt;<tspan
style="font-weight:bold" style="font-weight:bold"
id="tspan1160">prod&gt; </tspan>registar dnsname to apixtribe IP serveur + let'sencrypt certbot </tspan><tspan id="tspan1160">prod&gt; </tspan>registar dnsname to apxtrib IP serveur + let'sencrypt certbot </tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="3.6254988" x="3.6254988"
y="127.93366" y="127.93366"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan1146"> Instance https://apixtribe.ndda.fr (ssll for nginx, reverse proxy to express.js)</tspan><tspan id="tspan1146"> Instance https://apxtrib.ndda.fr (ssll for nginx, reverse proxy to express.js)</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="3.6254988" x="3.6254988"
y="129.69756" y="129.69756"
@ -989,7 +989,7 @@
x="3.6254988" x="3.6254988"
y="164.97533" y="164.97533"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan5067">http://gitlab.ndda.fr/philc/apixtribe/-/wikis/HOWTOplugin</tspan><tspan id="tspan5067">http://gitlab.ndda.fr/philc/apxtrib/-/wikis/HOWTOplugin</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="3.6254988" x="3.6254988"
y="166.73923" y="166.73923"
@ -1634,12 +1634,12 @@
x="45.148746" x="45.148746"
y="365.5423" y="365.5423"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:2.11666656px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan1319">Process for Dev mod local apixtribe installation</tspan><tspan id="tspan1319">Process for Dev mod local apxtrib installation</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="45.148746" x="45.148746"
y="367.55453" y="367.55453"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan4891">incron detect in REGEXFOLDER='(.*\/apixtribe)\/(.*)\/domaine\/(.*)\/spacedev\/(.*)\/src\/(.*)'</tspan><tspan id="tspan4891">incron detect in REGEXFOLDER='(.*\/apxtrib)\/(.*)\/domaine\/(.*)\/spacedev\/(.*)\/src\/(.*)'</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="45.148746" x="45.148746"
y="369.31842" y="369.31842"
@ -1745,7 +1745,7 @@
x="45.148746" x="45.148746"
y="403.71426" y="403.71426"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan1245">1- POST http://mesa.apixtribe.fr/app/maildigitcreator/publish/presentation</tspan><tspan id="tspan1245">1- POST http://mesa.apxtrib.fr/app/maildigitcreator/publish/presentation</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="45.148746" x="45.148746"
y="405.47815" y="405.47815"
@ -2094,7 +2094,7 @@
x="84.487297" x="84.487297"
y="122.30761" y="122.30761"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:1.41111112px;font-family:Cantarell;-inkscape-font-specification:'Cantarell, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#063665;fill-opacity:1;stroke-width:0.26458332"
id="tspan4614-7-62">Referentials /apixtribe/referentials/object/Tribes.json</tspan><tspan id="tspan4614-7-62">Referentials /apxtrib/referentials/object/Tribes.json</tspan><tspan
sodipodi:role="line" sodipodi:role="line"
x="84.487297" x="84.487297"
y="124.0715" y="124.0715"

Before

Width:  |  Height:  |  Size: 515 KiB

After

Width:  |  Height:  |  Size: 515 KiB

105
unittest.js Normal file
View File

@ -0,0 +1,105 @@
const fs = require("fs-extra");
const glob = require("glob");
//const config = require( './tribes/townconf.js' );
const config = {
unittesting: ["middlewares", "models", "routes", "nationchains"],
};
global.__base = __dirname + "/";
const ut = {};
ut.help = `
\x1b[32m###################################\x1b[0m
\x1b[32m### Make it simple Unit Testing ###\x1b[0m
\x1b[32m###################################\x1b[0m
Any file into a folder **/unittest/*.js can be run as a unit test.
Each file have to be independant to test a full process in production as well than in dev.
After each test the data has to be clean up (don't forget that your running test is apply into production).
Please add explicit research track message to help understand your code and how to debug it.
yarn unittest [-Options] [filtername ]
Options available:
\x1b[1m-verbose :\x1b[0m add system error to debug.
\x1b[1m-publish :\x1b[0m if test valid then push to production server list for propagation.
\x1b[1m-help :\x1b[0m this help.
filername: any test file name usefull when you just want to test your code under dev
Each unit testing file is structured like
\x1b[100m\x1b[32m
const assert=require('assert');
const any components you require
...
any testing process from create to delete based on assert lib that allow to test if your test expected what it has to be
see https://nodejs.org/api/assert.html
...
const ut={name:"testing name", run: ()=>{the function to run}};
module.exports=ut;
\x1b[0m
To request any update or change in the code add to your git branch a new file into where you test your modifications /inittest/
We first run your test and check with git diff your code before merge your branch with your inittest
You'll be inform when a new release including your change into azpXtrib will be available.
\x1b[7mThanks for improving our democracy tool.\x1b[0m
`;
ut.run = (options) => {
if (options.filetotest.length == 0)
console.log(
"Check your files because no test to run (for more: yarn unittest -help)"
);
options.filetotest.forEach((f) => {
const unittest = require(f);
console.log("\x1b[34m", `Unittest ${f}`, "\x1b[0m");
try {
unittest.run(options);
console.log("✅", "\x1b[32m", unittest.name, "\x1b[0m");
} catch (e) {
console.log(
"❌",
"\x1b[41m",
unittest.name,
e.stack.split("\n")[0],
"\x1b[0m"
);
if (options.verbose) console.log(e.stack);
}
});
};
const options = { filetotest: [] };
process.argv.slice(2).forEach((arg) => {
switch (arg.substring(0, 2)) {
case "-v":
options.verbose = true;
break;
case "-p":
options.publish = true;
break;
case "-h":
options.active = true;
options.help = true;
break;
default:
options.active = true;
config.unittesting.forEach((codefolder) => {
glob
.sync(`${__base}${codefolder}/**/unittest/${arg}.js`)
.forEach((f) => {
if (!options.filetotest.includes(f)) options.filetotest.push(f);
});
});
break;
}
});
if (!options.active) {
config.unittesting.forEach((codefolder) => {
glob.sync(`${__base}${codefolder}/**/unittest/*.js`).forEach((f) => {
if (!options.filetotest.includes(f)) options.filetotest.push(f);
});
});
console.log(
"You can test only some unittest by passing yarn unittest name where name is a /unittest/name.js file that exist, type 'yarn unittest -help' for more"
);
console.log("Looking for unittest folder into ", config.unittesting);
}
options.help ? console.log(ut.help) : ut.run(options);