const fs = require("fs-extra"); const path = require("path"); const dnsSync = require("dns-sync"); const mustache = require("mustache"); const readlineSync = require("readline-sync"); const Wwws = require("../models/Wwws.js"); /** * This Setup is run at the first installation * This is not an exportable module * * * */ const Setup = {}; //const nationsync = require('./Nations').updateChains(); Setup.check = () => { if ("testinternet" != "testinternet") { console.log( "\x1b[31m Check your internet access, to setup this town we need to update the Nations. It seems we cannot do it" ); process.exit(); } 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" ); process.exit(); } if (fs.existsSync("./nationchains/www/nginx_adminapx.conf")) { console.log( "\x1b[31m Be carefull you already have a town set, check http://adminapx or remove ./nationchains/www/nginx_adminapx.conf to reset a sync with the last nationchains" ); process.exit(); } return true; }; Setup.init = async () => { /** * create empty nationchains * rsync all subfolder nationchains except the tribes/ and /www/nginx_adminapx.conf * * Then to send new version we fix a master production * */ const initconf = fs.readJSONSync( "./nationchains/www/adminapx/static/tpldata/initconf.json" ); initconf.sudoerUser = process.env.USER; initconf.dirname = path.resolve(`${__dirname}/../../`); // To allow to serve the nation website until the end initconf.nginx.include.push( `${townconf.dirname}/nationchains/www/nginx_*.conf` ); // To allow to serve tribes web site initconf.nginx.include.push( `${townconf.dirname}/nationchains/tribes/*/www/nginx_*.conf` ); initconf.nginx.logs = `${townconf.dirname}/nationchains/logs/nginx`; initconf.nginx.website = "adminapx"; initconf.nginx.fswww = "nationchains/"; //for a local tribe nationchains/tribes/tribeid initconf.nginx.tribeid = "town"; initconf.nginx.pageindex = "index_en.html"; const nginxconf = Wwws.apxtribinstall(initconf); if (nginxconf.status == 200) { } }; if (Setup.check()) Setup.init(); // After testing remove all stuff after this line Setup.initold = async () => { // Get standard conf and current data const townconf = fs.readJsonSync("./nationchains/www/adminapx/townconf.json"); const apxnations = fs.readJsonSync( `./nationchains/nations/idx/nationId_all.json` ); const apxtowns = fs.readJsonSync(`./nationchains/towns/idx/townId_all.json`); let apxpagans = {}; if (fs.existsSync(`./nationchains/pagans/idx/alias_all.json`)) { apxpagans = fs.readJsonSync(`./nationchains/pagans/idx/alias_all.json`); } if (!Object.keys(apxnations).includes(townconf.nationId)) { console.log( `Sorry nationId ${townconf.nationId} does not exist, please change with an existing nation ` ); process.exit(); } if (Object.keys(apxtowns).includes(townconf.townId)) { console.log( `Sorry townId ${townconf.townId} already exist, please change it` ); process.exit(); } /* if (Object.keys(apxpagans).includes(townconf.mayorId)) { console.log( `Sorry paganId ${townconf.maorId} already exist ti create a town you need a new identity, please change it` ); process.exit(); } */ townconf.sudoerUser = process.env.USER; townconf.dirname = path.resolve(`${__dirname}/../../`); // To allow to serve the nation website until the end townconf.nginx.include.push( `${townconf.dirname}/nationchains/www/nginx_*.conf` ); // To allow to serve tribes web site townconf.nginx.include.push( `${townconf.dirname}/nationchains/tribes/*/www/nginx_*.conf` ); townconf.nginx.logs = `${townconf.dirname}/nationchains/logs/nginx`; townconf.nginx.website = "adminapx"; townconf.nginx.fswww = "nationchains/"; //for a local tribe nationchains/tribes/tribeid townconf.nginx.tribeid = "town"; townconf.nginx.pageindex = "index_en.html"; console.log(townconf); if ( !readlineSync.keyInYN( `\x1b[42mThis is the first install from ./nationchains/www/adminapx/townconf.json (check it if you want) \nthis will change your nginx config in /etc/nginx and run nginx from sudoer user ${townconf.sudoerUser} (Yes/no)? \nno if you want to change parameter and run yarn setup again \x1b[0m` ) ) process.exit(); // saved and change nginx conf if (!fs.existsSync("/etc/nginx/nginxconf.saved")) { fs.moveSync("/etc/nginx/nginx.conf", "/etc/nginx/nginxconf.saved"); console.log( "your previous /etc/nginx/nginx.conf was backup in /etc/nginx/nginxconf.saved" ); } const tplnginxconf = fs.readFileSync( "./nationchains/www/adminapx/nginx/nginx.conf.mustache", "utf8" ); fs.outputFileSync( "/etc/nginx/nginx.conf", mustache.render(tplnginxconf, townconf), "utf8" ); //proxyparam const proxy_params = fs.readFileSync( "./nationchains/www/adminapx/nginx/proxy_params.mustache", "utf8" ); fs.outputFileSync( "/etc/nginx/proxy_params", mustache.render(proxy_params, townconf), "utf8" ); const tplnginxwww = fs.readFileSync( "./nationchains/www/adminapx/nginx/modelwebsite.conf.mustache", "utf8" ); fs.outputFileSync( `./${townconf.nginx.fswww}www/nginx_${townconf.nginx.website}.conf`, mustache.render(tplnginxwww, townconf), "utf8" ); fs.outputJsonSync("./nationchains/tribes/conf.json", townconf, { spaces: 2, }); // Integrer cette partie du setup en inteactif. // l'objectif du setup est de rendere accessible adminapx en local (IP local) ou production IP public //CREATE A TOWN setup local voir utiliser towns.create /* townconf.town = { townId: townconf.townId, nationId: townconf.nationId, url: `http://${townconf.dns[0]}`, IP: townconf.IP, mayorid: townconf.mayorId, status: "unchain", }; apxtowns[townconf.townId] = townconf.town; fs.outputJsonSync(`./nationchains/towns/idx/townId_all.json`, apxtowns); fs.outputJsonSync( `./nationchains/towns/itm/${townconf.townId}.json`, townconf.town, { spaces: 2 } ); // Create tribe id voir a utiliser tribes.create() townconf.tribe = { tribeId: townconf.tribeId, dns: [], status: "unchain", nationId: townconf.nationId, townId: townconf.townId, }; //tribe does not exist in a new town apxtribes = {}; apxtribes[townconf.tribeId] = townconf.tribe; fs.outputJsonSync(`./nationchains/tribes/idx/tribeId_all.json`, apxtribes); fs.outputJsonSync( `./nationchains/tribes/itm/${townconf.tribeId}.json`, townconf.tribe, { spaces: 2 } ); fs.ensureDirSync(`./nationchains/tribes/${townconf.tribeId}/logs/nginx`); //CREATE a mayorId pagans if it does not exist if (!apxpagans[townconf.mayorId]) { const Pagans = require("./Pagans"); const createPagans = await Pagans.createId( townconf.mayorId, townconf.passphrase ); if (createPagans.status == 200) { fs.outputFileSync( `./${townconf.mayorId}_PrivateKey.txt`, createPagans.data.privateKey, "utf8" ); fs.outputFileSync( `./${townconf.mayorId}_PublicKey.txt`, createPagans.data.publicKey, "utf8" ); console.log( `\x1b[43mCut paste your keys /${townconf.mayorId}_PrivateKey.txt /${townconf.mayorId}_PublicKey.txt \x1b[0m` ); } else { console.log("Error at Pagan creation "); console.log(createPagans); process.exit(); } }*/ //fin de partie à integer dans l'interface graphique adminapx //restart nginx const { exec } = require("child_process"); exec(townconf.nginx.restart, (error, stdout, stderr) => { if (error) { console.log("\x1b[42m", error, stdout, stderr, "x1b[0m"); } else { console.log( `\x1b[42m###########################################################################################\x1b[0m\n\x1b[42mWellcome into apxtrib, you can now 'yarn dev' for dev or 'yarn startpm2' for prod or \n'yarn unittest' for testing purpose. Access to your town here \x1b[0m\x1b[32mhttp://${townconf.dns}\x1b[0m \x1b[42m \nto finish your town set up. Check README's project to learn more. \x1b[0m\n\x1b[42m###########################################################################################\x1b[0m` ); } }); }; Setup.Checkjson = (conf) => { var rep = ""; const nation_town = fs.readJsonSync( "./nationchains/socialworld/objects/towns/searchindex/towns_nation_uuid.json" ); if (!ObjectKeys(nation_town).includes(conf.nationId)) { rep += `your nationId ${conf.nationId} does not exist you have to choose an existing one`; } if (nation_town[conf.nationId].includes(conf.townId)) { rep += `This conf.townId already exist you have to find a unique town name per nation`; } const getnation = Odmdb.get( "./nationchains/socialworld/objects", "towns", [conf.NationId], [nationId] ); //if getnation.data.notfound conf.language.forEach((l) => { if (!["fr", "en", "it", "de", "sp"].includes(l)) { rep += l + " Only fr,en,it,de,sp are available \n"; } }); if (!fs.existsSync(`/home/${conf.sudoerUser}`)) { rep += `/home/${conf.sudoerUser} does not exist, user has to be create with a /home on this server\n`; } try { if ( "true" == execSync('timeout 2 sudo id && sudo="true" || sudo="false";echo "$sudo"') .toString() .trim() .split(/\r?\n/) .slice(-1) ) { rep += `${sudoerUser} is not sudoer please change this `; } } catch (err) { console.log(err); rep += " Check your user it seems to not be a sudoer"; } if (conf.jwtsecret.length < 32) { rep += "Your jwtsecretkey must have at least 32 characters"; } if ( conf.dns != "unchain" && !dnsSync.resolve(`${conf.townId}.${conf.nationId}.${conf.dns}`) ) { rep += `\nresolving $${conf.townId}.${conf.nationId}.${conf.dns} will not responding valid IP, please setup domain redirection IP before runing this script`; } return rep; }; Setup.config = (townSetup) => { // Init this instance with a .config.js Setup.configjs(townSetup); // Create tribeid space + a user admin + webspace withe apxtrib webapp install Setup.druidid(townSetup); }; Setup.configjs = (townSetup) => { // Set /config.js let confapxtrib = fs.readFileSync("./setup/config.mustache", "utf-8"); fs.writeFileSync( "./config.js", Mustache.render(confapxtrib, townSetup), "utf-8" ); if (fs.existsSync("./config.js")) { console.log("config.js successfully created."); } else { console.log( "config.js not created, check what's wrong in tpl:", confapxtrib ); console.log("for data :", townSetup); process.exit(); } }; Setup.druidid = (townSetup) => { // create a tribeid with a user that will admin this instance into /tribes/tribeid /users const config = require("../config.js"); // Need to do it on setup this is also done again in models/Tribes.js console.log(`${config.tribes}/${townSetup.druidid}`); fs.ensureDirSync(`${config.tribes}/${townSetup.druidid}`); ["users", "www", "referentials", "nationchains"].forEach((r) => { fs.copySync( `${__base}/setup/tribes/apxtrib/${r}`, `${config.tribes}/${townSetup.druidid}/${r}` ); }); /* const confcli = JSON.parse( Mustache.render( fs.readFileSync( `${__base}/setup/tribes/apxtrib/clientconf.mustache`, 'utf8' ), townSetup ) ); fs.outputJsonSync( `${config.tribes}/${townSetup.druidid}/clientconf.json`, confcli ); // Create a new tribeid + admin user for this tribeid // with access to {druidid}:webapp as admin */ const Tribes = require("./Tribes.js"); const access = { app: {}, data: {} }; access.app[`${townSetup.druidid}:webapp`] = "admin"; access.data[townSetup.druidid] = { users: "CRUDO", referentials: "CRUDO", www: "CRUDO", }; const createclient = Tribes.create({ tribeid: townSetup.druidid, genericpsw: townSetup.genericpsw, lanquageReferential: townSetup.language, useradmin: { LOGIN: townSetup.login, xlang: townSetup.language[0], ACCESSRIGHTS: access, }, }); if (createclient.status == 200) { 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 const confnginx = fs.readFileSync( "./setup/nginx/nginx.conf.mustache", "utf8" ); fs.outputFileSync( "/etc/nginx/nginx.conf", Mustache.render(confnginx, townSetup), "utf-8" ); // Create a spacedev for webapp of apxtrib // that will be accesible in prod from https://subdomain.domain/ and in dev http://webapp.local.fr const addspaceweb = Tribes.addspaceweb({ setup: true, dnsname: [`${townSetup.subdomain}.${townSetup.domain}`], mode: townSetup.mode, tribeid: townSetup.druidid, website: "webapp", pageindex: "app_index_fr.html", }); if (addspaceweb.status == 200) { console.log(`WELL DONE run yarn dev to test then yarn startpm2 `); } } else { console.log("Issue ", createclient); } }; if (Setup.check()) Setup.init();