const glob = require( 'glob' ); const path = require( 'path' ); const fs = require( 'fs-extra' ); const config = require( '../tribes/townconf.js' ); const Referentials = {}; /* Manage Referential object data each object is compose of a list of fields each fields have it owns structur and check those common rules allow to be used to manage: - forms (creation to collect data) - data check - data access rights common referential data stored in /data/shared/referential/ */ Referentials.clientconf = ( xworkOn, listkey ) => { /* Retourne les info d'un clientconf.json sur une liste de [cle] */ let conf = {}; let dataconf = {}; //logger.info( `${config.tribes}/${xworkOn}/clientconf.json` ) try { conf = fs.readJsonSync( `${config.tribes}/${xworkOn}/clientconf.json` ); // remove information notrelevant for [ 'emailFrom', 'emailClient', 'emailCc', 'commentkey', 'clezoomprivate', 'stripekeyprivate', 'genericpsw' ].forEach( c => { delete conf[ c ]; } ); listkey.forEach( k => dataconf[ k ] = conf[ k ] ) //logger.info( 'dataconf', dataconf ) } catch ( err ) { logger.info( 'Attention demande sur clienId inconnu ' + xworkOn ); } return { status: 200, payload: { data: dataconf } }; }; Referentials.clientconfglob = () => ( { status: 200, payload: { data: fs.readJsonSync( `${config.tmp}/clientconfglob.json` ) } } ); Referentials.getref = ( origin, source, ref, xworkOn, xlang ) => { // If request origin then send back referential with all language in it // if not origin or json source return by language let referent = {}; let src; if( origin && [ 'object', 'data' ].includes( source ) ) { src = `${config.tribes}/${xworkOn}/referentials/${source}/${ref}.json` } else { src = `${config.tribes}/${xworkOn}/referentials/${source}/${ref}_${xlang}.json`; } //logger.info( src ) try { referent = fs.readJsonSync( src ); } catch ( err ) { logger.info( `Request ${src} does not exist ` ); } return { status: 200, payload: { data: referent } }; }; Referentials.putref = ( source, name, xworkOn, data ) => { /* We get a referential, we have 3 kinds of sources: * data = [{uuid,DESC:{fr:,en,},DESCLONG:{fr:,en:}, other field}] only DESC and DESCLONG have a translation * json = are full complex object in language name_lg.json * object = [{uuid,DESC:{fr,en},DESCLONG:{fr,en}},tpl,}] Difference between data and object is that object defines rule to manage an object, and how to create a forms to get data each data is saved in one folder object/uuid.json and have to respect the corresponding object referentials definition. For data and object it is possible only to put a file with all language available. When store this script erase with the new file per _lg name for source=json must end by _lg */ //logger.info( data ) const pat = /.*_..\.json$/; const file = `${config.tribes}/${xworkOn}/referentials/${source}/${name}.json` if( [ 'object', 'data' ].includes( source ) ) { if( pat.test( name ) ) { return { status: 404, payload: { model: 'Referentials', info: [ 'nameunconsistent' ], moreinfo: "can not be update with one lang need a full file with language for object or data" } } } else { fs.outputJsonSync( file, data ); return Refernetials.update( xworkOn, source, name ) } } else { if( !pat.test( name ) ) { return { status: 404, payload: { model: 'Referentials', info: [ 'nameunconsistent' ], moreinfo: "can not be update without a lang _lg.json a referential json" } } } else { fs.outputJsonSync( file, data ); return { status: 200, payload: { model: 'Referentials', info: [ 'successfull' ], moreinfo: "ref json updated " } } } }; }; Referentials.updatefull = ( tribeid ) => { let err = ""; let nbrefupdate = 0; const pat = /.*_..\.json$/; [ 'object', 'data' ].forEach( o => { glob.sync( `${config.tribes}/${tribeid}/referentials/${o}/*.json` ) .forEach( f => { if( !pat.test( f ) ) { const res = Referentials.update( tribeid, o, path.basename( f, '.json' ) ); if( res.status != 200 ) { err += `Error on ${o}/${path.basename(f)}` } else { nbrefupdate += 1; } } } ) } ); if( err != "" ) { return { status: 500, payload: { info: [ 'Errupdateref' ], model: "Referentials", moreinfo: err } } } return { status: 200, payload: { info: [ 'Success' ], model: "Referentials", moreinfo: `Number of object and data ref updated: ${nbrefupdate}` } } }; Referentials.inittribeid = () => { logger.info( "Clientconf list for this server", `${config.tribes}/**/clientconf.json` ); const TribesGlobalConfig = glob.sync( `${config.tribes}/**/clientconf.json` ) .map( f => fs.readJsonSync( f ) ); // store global conf for sharing to other api fs.outputJsonSync( `${config.tmp}/clientconfglob.json`, TribesGlobalConfig, { spaces: 2 } ); return { status: 200, payload: { moreinfo: TribesGlobalConfig } } } Referentials.generetribeids = () => { const tribeids = []; fs.readJsonSync( `${config.tmp}/clientconfglob.json` ) .forEach( c => { if( !tribeids.includes( c.tribeid ) ) tribeids.push( c.tribeid ); } ); fs.outputJsonSync( `${config.tmp}/tribeids.json`, tribeids ); logger.info( `update ${config.tribes}/tribeids` ); return tribeids; } Referentials.genereallowedDOM = () => { const confglob = fs.readJsonSync( `${config.tmp}/clientconfglob.json` ); let allDom = []; confglob.forEach( c => { c.allowedDOMs.forEach( d => { if( !allDom.includes( d ) ) allDom = allDom.concat( d ); } ) } ); return allDom; }; /* A voir si encore necessaire pour générer un environnement identique sur un autre server // Génére les domaines s'ils n'existe pas dans le repertoire function genereEnvClient() { const confglob = fs.readJsonSync( `${config.sharedData}/clientconfglob.json` ); confglob.forEach(function(c) { config.tribeidsConf[c.tribeid] = c; if (c.allowedURLs) { c.allowedURLs.forEach(u => { if (!config.allowedURLs.includes(u)) { config.allowedURLs.push(u); } }); } else { logger.info('erreur de fichier config d\'un site pour ', c); } // GLOBAL Tribes IDS INDEX maketribeidsIndex(); if (!fs.existsSync(`${config.tribes}/${c.tribeid}`)) { const execSync = require('child_process').execSync; execSync(`cp -r ${config.tribes}/modele ${config.tribes}/${c.tribeid}`); } }); } */ Referentials.update = ( tribeid, source, name ) => { /* Replace for each language the referential name for a tribeid After each update the version number is incremented by 1 in clientconf.json */ if( !fs.existsSync( `${config.tribes}/${tribeid}/referentials/${source}/${name}.json` ) ) { return { status: 500, payload: { info: [ "unknownRef" ], model: "Referentials", moreinfo: `file does not exist ${config.tribes}/${tribeid}/referentials/${source}/${name}.json` } } }; const clientconf = fs.readJsonSync( `${config.tribes}/${tribeid}/clientconf.json` ); if( !clientconf.langueReferential ) { return { status: 500, payload: { info: [ "missingConf" ], model: "Referentials", moreinfo: ` ${config.tribes}/${tribeid}/clientconf.json does not contain langueReferential array` } } } const ref = fs.readJsonSync( `${config.tribes}/${tribeid}/referentials/${source}/${name}.json` ); clientconf.langueReferential.forEach( lg => { //manage translation let refnew = []; refnew = []; ref.forEach( d => { if( d.DESC ) d.DESC = d.DESC[ lg ]; if( d.DESCLONG ) d.DESCLONG = d.DESCLONG[ lg ]; if( d.INFO ) d.INFO = d.INFO[ lg ]; if( d.desc ) d.desc = d.desc[ lg ]; if( d.desclong ) d.desclong = d.desclong[ lg ]; if( d.info ) d.info = d.info[ lg ]; if( d.placeholder ) d.placeholder = d.placeholder[ lg ]; refnew.push( d ) } ) //save new ref in language //logger.info( "New ref", refnew ) logger.info( `Update referentials per lg ${config.tribes}/${tribeid}/referentials/${source}/${name}_${lg}.json` ) fs.outputJsonSync( `${config.tribes}/${tribeid}/referentials/${source}/${name}_${lg}.json`, refnew, { spaces: 2 } ); } ); //upgrade version number if( !clientconf.referentials ) clientconf.referentials = {}; if( !clientconf.referentials[ source ] ) clientconf.referentials[ source ] = {}; if( !clientconf.referentials[ source ][ name ] ) clientconf.referentials[ source ][ name ] = { version: 0 }; clientconf.referentials[ source ][ name ].version += 1; fs.outputJsonSync( `${config.tribes}/${tribeid}/clientconf.json`, clientconf, 'utf8' ); return { status: 200, payload: { info: [ 'successUpdate' ], model: "Referentials", moreinfo: `${name} updated` } } }; //logger.info( Referentials.update( 'apixtribe', "object", "user" ) ) Referentials.genereobjet = ( tribeid, destination, tplmustache, objet, filtre ) => { /* @TODO Genere des objets d'agregat @tribeid = data/tribee/ identifiant client @destinations = [] of destination @tplmustache = fichier mustache de mise en page @objet = nom d'objet contact, companies, items, users @filtre = fonction a executer */ } //////// EN DESSOUS DE CETTE LIGNE A SUPPRIMER /* Le principe consistait à partager des referentiels dans shareddataLa gestion est trop compliqué => le principe chaque client duplique un referentiel pour que les app qui s'appuie sur des composants communs puissent fonctionner */ /*Referentials.genereClientObjectASUPP = () => { const confglob = fs.readJsonSync( `${config.tmp}/clientconfglob.json` ); // Check and update folder and data per lang // c as tribeid confglob.forEach( ( c, postribeid ) => { //check folder are well create const lstfolder = [ 'actions', 'actions/done', 'actions/todo', 'cards', 'logs', 'orders', 'orders/reservation', 'orders/purchase', 'orders/contact', 'public', 'public/reservation', 'tags', 'tags/stats', 'tags/archives', 'tags/hits', 'tags/imgtg', 'users' ]; lstfolder.forEach( fol => { if( !fs.existsSync( `${config.tribes}/${c.tribeid}/${fol}` ) ) { fs.mkdirSync( `${config.tribes}/${c.tribeid}/${fol}` ); } } ) if( c.referentials && !c.langue ) { logger.info( `ERREUR referentials mais pas de langue:[] pour ${c.tribeid}/clientconf.json` ) } if( c.referentials && c.langue ) { let majclientconf = false; // Create and check Object structure Object.keys( c.referentials.object ) .forEach( o => { // if object exist in shared then it merge sharedObject and domain referential object let objfull = []; const objshared = `${config.sharedData}/referentials/dataManagement/object/${o}.json`; if( fs.existsSync( objshared ) ) { objfull = objfull.concat( fs.readJsonSync( objshared ) ); } const objdomain = `${config.tribes}/${c.tribeid}/referentials/dataManagement/object/${o}.json`; if( fs.existsSync( objdomain ) ) { objfull = objfull.concat( fs.readJsonSync( objdomain ) ); } c.langue.forEach( lg => { const objfulllg = objfull.map( field => { if( field.DESC ) field.DESC = field.DESC[ lg ]; if( field.DESCLONG ) field.DESCLONG = field.DESCLONG[ lg ]; return field; } ); const objectdomlg = `${config.tribes}/${c.tribeid}/referentials/${lg}/object/${o}.json`; let savedObject = {}; if( fs.existsSync( objectdomlg ) ) { savedObject = fs.readJsonSync( objectdomlg ); } // TODO Always true change later to update only if needded if( !fs.existsSync( objectdomlg ) || objfulllg.length !== savedObject.length || 1 == 1 ) { fs.outputJsonSync( objectdomlg, objfulllg, { spaces: 2 } ); confglob[ postribeid ].referentials.object[ o ].version += 1; majclientconf = true; } } ); } ); // datafile Object.keys( c.referentials.data ) .forEach( d => { // if object exist in shared then it merge sharedObject and domain referential object // logger.info(c.tribeid + '--' + d); let datafull = []; const datashared = `${ config.sharedData }/referentials/dataManagement/data/${d}.json`; if( fs.existsSync( datashared ) ) { datafull = datafull.concat( fs.readJsonSync( datashared ) ); } const datadomain = `${config.tribes}/${ c.tribeid }/referentials/dataManagement/data/${d}.json`; if( fs.existsSync( datadomain ) ) { datafull = datafull.concat( fs.readJsonSync( datadomain ) ); } /* const defdata = `${config.tribes}/${ c.tribeid }/referentials/dataManagement/data/${d}.json`; */ // for each Langues => generate fr.obj and compare it with existing file // if diff then => upgrade version number in clientconf // logger.info(datafull); // this could be improved by usind d.meta wich is the object that DESCribe this data /* c.langue.forEach( lg => { let meta; if( c.referentials.data[ d ].meta ) { meta = fs.readJsonSync( `${config.tribes}/${c.tribeid}/referentials/${lg}/object/${ c.referentials.data[d].meta }.json` ); } let datalg; const datafulllg = datafull.map( tup => { datalg = {}; meta.forEach( ch => { if( tup[ ch.idfield ] ) { if( ch.multilangue ) { datalg[ ch.idfield ] = tup[ ch.idfield ][ lg ]; } else { datalg[ ch.idfield ] = tup[ ch.idfield ]; } } } ); return datalg; } ); // lit le fichier correspondant et le compare si différent le sauvegarde // stocke l'information d'upgrade d ela version const datadomlg = `${config.tribes}/${ c.tribeid }/referentials/${lg}/data/${d}.json`; let saveddata = {}; if( fs.existsSync( datadomlg ) ) { saveddata = fs.readJsonSync( datadomlg ); } // Condition to improve // TODO always change file to improvelater by detecting real change. if( !fs.existsSync( datadomlg ) || datafulllg.length != saveddata.length || 1 == 1 ) { fs.outputJsonSync( datadomlg, datafulllg, { spaces: 2 } ); confglob[ postribeid ].referentials.data[ d ].version += 1; majclientconf = true; } } ); } ); // json file that have to start with lg {lg:'':{json }} Object.keys( c.referentials.json ) .forEach( j => { // if object exist in shared then it merge sharedObject and domain referential object // logger.info(c.tribeid + '--' + d); let jsonfull = []; const jsondomain = `${config.tribes}/${c.tribeid}/referentials/dataManagement/json/${j}.json`; if( fs.existsSync( jsondomain ) ) { jsonfull = fs.readJsonSync( jsondomain ); } c.langue.forEach( lg => { const jsondomlg = `${config.tribes}/${ c.tribeid }/referentials/${lg}/json/${j}.json`; // logger.info('jsondomlg', jsondomlg); let datalg = jsonfull; if( jsonfull[ lg ] ) { datalg = jsonfull[ lg ]; } fs.outputJsonSync( jsondomlg, datalg, { spaces: 2 } ); } ); } ); // update clientconf domain with updated version if( majclientconf ) { fs.outputJsonSync( `${config.tribes}/${c.tribeid}/clientconf.json`, c, { spaces: 2 } ); } } } ); // update global conf fs.outputJsonSync( `${config.tmp}/clientconfglob.json`, confglob, { spaces: 2 } ); };*/ module.exports = Referentials;