apxtrib/apxtrib.js

228 lines
8.4 KiB
JavaScript
Raw Normal View History

2023-05-31 13:19:21 +00:00
const { argv } = require("process");
2023-05-12 05:59:32 +00:00
const fs = require("fs-extra");
2023-05-31 13:19:21 +00:00
const mustache = require("mustache");
2023-05-12 05:59:32 +00:00
const bodyParser = require("body-parser");
const glob = require("glob");
const path = require("path");
const cors = require("cors");
const express = require("express");
const process = require("process");
2023-11-19 15:34:37 +00:00
2023-01-22 09:53:09 +00:00
/*******************************************
2023-03-27 05:52:21 +00:00
SEE https://gitea.ndda.fr/apxtrib/apxtrib/wiki/Devrules
To have a quick understanding and convention before doing deeply in source code
2023-01-22 09:53:09 +00:00
2023-05-31 13:19:21 +00:00
To share configuration :
process.env.dirtown is folder where town folder name /townId-nationId is accessible
const conf = require(`${process.env.dirtown}/conf.json`);
app.locals.tribeids is defined later in apixtrib.js and allow express app to always have in memory a dynamic of tribeId available in req.app.locals.tribeids
2023-04-27 04:17:20 +00:00
*/
2023-05-31 13:19:21 +00:00
/**
* 1st install for dev
* run $ node apxtrib.js nationId:ants townId:devfarm dns:devfarm-ants
* then just yarn dev
* it create a folder outside ../townId-nationId/
* To convert a dev into a chain town run again with relevant param:
* run $ node apxtrib.js nationId:ants townId:devfarm dns:devfarm-ants
* check the web interface http://dns
* then just yarn startpm2 your town is under PM2 control
*
*
* @param {args} args key:value example node apxtrib nationId:ants townId:devfarm dns:devfarm-ants
2023-11-05 11:03:25 +00:00
* if no parameter from adminapi/www/adminapx/conf/setup_xx.json
2023-05-31 13:19:21 +00:00
*
* Keyword townId = "devfarm" then this is unchain town to dev
* else this is a production town ready to chain to the nationId
*
* @returns listen onto http:/dns (80 and 443) for admin webapp and http://localhost:initconf.api.port
* by setting the nginx parameter
* A folder for town data is created at the same level than apxtrib as /townId-nationId/conf.json ...
*/
2023-05-12 05:59:32 +00:00
2023-05-31 13:19:21 +00:00
// check nginx exist
2023-05-12 05:59:32 +00:00
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."
);
process.exit();
2023-01-22 09:53:09 +00:00
}
2023-05-31 13:19:21 +00:00
const param = {};
argv.slice(2).forEach((arg) => {
const kv = arg.split(":");
if (kv.length == 2) {
param[kv[0]] = kv[1];
}
});
2023-06-28 13:23:17 +00:00
2023-06-07 05:32:23 +00:00
// setup_xx.json is gitignore so at first install we are in dev configuration
let infotown = {
nationId: "ants",
townId: "devfarm",
2023-06-28 13:23:17 +00:00
dns: "devfarm-ants",
2023-06-07 05:32:23 +00:00
comment:
"Auto generate setup from apxtrib after node apxtrib nationId:value townId:value dns:domaine_to_access",
};
if (fs.existsSync(`${__dirname}/adminapi/www/adminapx/conf/setup_xx.json`)) {
infotown = fs.readJsonSync(
`${__dirname}/adminapi/www/adminapx/conf/setup_xx.json`
);
2023-11-05 11:03:25 +00:00
}
2023-06-28 13:23:17 +00:00
if (
Object.keys(param).length > 0 &&
param.nationId &&
param.townId &&
param.dns
) {
infotown.nationId = param.nationId;
infotown.townId = param.townId;
infotown.dns = param.dns;
2023-11-05 11:03:25 +00:00
}
2023-06-28 13:23:17 +00:00
fs.outputJsonSync(
2023-11-05 11:03:25 +00:00
`${__dirname}/adminapi/www/adminapx/conf/setup_xx.json`,
infotown
);
infotown.dirapi = __dirname;
infotown.dirtown = path.resolve(
`${__dirname}/../${infotown.townId}-${infotown.nationId}`
);
process.env.dirtown = infotown.dirtown;
infotown.dirapxwebapp = path.resolve(`${infotown.dirapi}/..`); //same level as apxtrib
2023-05-31 13:19:21 +00:00
if (
2023-06-28 13:23:17 +00:00
!fs.existsSync(`${infotown.dirtown}/conf.json`) ||
2023-05-31 13:19:21 +00:00
!fs.existsSync(`${__dirname}/adminapi/www/nginx_adminapx.conf`)
) {
2023-06-07 05:32:23 +00:00
// Case of new town or request a reset of dns to access adminapx
2023-06-28 13:23:17 +00:00
// genere a minimum conf with nationId, townId, dns, dirapi, dirtown
2023-11-05 11:03:25 +00:00
fs.outputJsonSync(`${infotown.dirtown}/conf.json`, infotown, { space: 2 });
const Towns = require("./api/models/Towns");
2023-06-28 13:23:17 +00:00
const rescreate = Towns.create();
2023-11-05 11:03:25 +00:00
if (rescreate.status != 200) {
console.log("Sorry error ");
2023-06-28 13:23:17 +00:00
process.exit();
}
2023-01-22 09:53:09 +00:00
}
2023-06-28 13:23:17 +00:00
const conf = require(`${infotown.dirtown}/conf.json`);
2023-05-16 08:31:27 +00:00
2023-05-31 13:19:21 +00:00
// Create and update ./nationchains
const { updateobjectsfromfreshesttown } = require("./api/models/Nations.js");
updateobjectsfromfreshesttown(conf.towns, {
pagans: "alias_all.json",
towns: "townId_all.json",
nations: "nationId_all.json",
});
2023-05-12 05:59:32 +00:00
2023-05-31 13:19:21 +00:00
// Run main express process for a /towId-nationId/tribes
2023-05-12 05:59:32 +00:00
2023-05-31 13:19:21 +00:00
let tribelist = {};
if (fs.existsSync(`${conf.dirtown}/tribes/idx/tribeId_all.json`)) {
tribelist = fs.readJsonSync(`${conf.dirtown}/tribes/idx/tribeId_all.json`);
}
2023-05-12 05:59:32 +00:00
let doms = conf.dns; // only dns of town during the init process
let tribeIds = [];
2023-05-16 08:31:27 +00:00
let routes = glob.sync(`${conf.dirapi}/api/routes/*.js`).map((f) => {
2023-05-12 05:59:32 +00:00
return { url: `/${path.basename(f, ".js")}`, route: f };
});
2023-11-05 11:03:25 +00:00
glob.sync(`${conf.dirtown}/tribes/*/api/routes/*.js`).forEach((f) => {
const ids = f.indexOf(`${conf.dirtown}/tribes/`);
const trib = f.slice(
ids + `${conf.dirtown}/tribes/`.length,
f.lastIndexOf("/api/routes")
);
routes.push({ url: `/${trib}/${path.basename(f, ".js")}`, route: f });
});
2023-05-12 05:59:32 +00:00
//routes={url,route} check how to add plugin tribe route later
// keep only the 2 last part (.) of domain name to validate cors with it (generic domain)
Object.keys(tribelist).forEach((t) => {
tribelist[t].dns.forEach((d) => {
const dm = d.split(".").slice(-2).join(".");
if (!doms.includes(dm)) doms.push(dm);
});
tribeIds.push(t);
});
console.log("Allowed DOMs to access to this apxtrib server: ", doms);
2023-04-13 05:46:35 +00:00
2023-04-27 04:17:20 +00:00
const app = express();
2023-05-12 05:59:32 +00:00
// load express parameter from conf
Object.keys(conf.api.appset).forEach((p) => {
app.set(p, conf.api.appset[p]);
});
2023-01-22 09:53:09 +00:00
// To set depending of data form or get size to send
2023-05-12 05:59:32 +00:00
app.use(bodyParser.urlencoded(conf.api.bodyparse.urlencoded));
2023-01-22 09:53:09 +00:00
// To set depending of post put json data size to send
2023-05-12 05:59:32 +00:00
app.use(express.json());
app.use(bodyParser.json(conf.api.bodyparse.json));
2023-11-05 11:03:25 +00:00
app.disable('x-powered-by');// for security
2023-04-27 04:17:20 +00:00
app.locals.tribeids = tribeIds;
2023-05-12 05:59:32 +00:00
console.log("app.locals.tribeids", app.locals.tribeids);
2023-01-22 09:53:09 +00:00
// Cors management
const corsOptions = {
2023-05-12 05:59:32 +00:00
origin: (origin, callback) => {
2023-11-05 11:03:25 +00:00
//before modif only origin == undefined
if (
2023-11-20 11:43:55 +00:00
(origin == undefined || (infotown.townId == "devfarm" &&
2023-11-05 11:03:25 +00:00
(origin == undefined || origin == null)) ||
2023-11-20 11:43:55 +00:00
origin.indexOf("chrome-extension") > -1)
2023-11-05 11:03:25 +00:00
) {
2023-05-12 05:59:32 +00:00
callback(null, true);
} else {
const rematch = /^https?:\/\/(.*):.*/g.exec(origin);
//console.log( rematch )
let tmp = origin.replace(/http.?:\/\//g, "").split(".");
2023-01-22 09:53:09 +00:00
2023-05-12 05:59:32 +00:00
if (rematch && rematch.length > 1) tmp = rematch[1].split(".");
//console.log( 'tmp', tmp )
let dom = tmp[tmp.length - 1];
if (tmp.length > 1) {
dom = `${tmp[tmp.length - 2]}.${tmp[tmp.length - 1]}`;
}
console.log(
`origin: ${origin}, dom:${dom}, CORS allowed? : ${doms.includes(dom)}`
);
if (doms.includes(dom)) {
callback(null, true);
} else {
2023-11-05 11:03:25 +00:00
callback(false);
2023-05-12 05:59:32 +00:00
}
}
},
exposedHeaders: Object.keys(conf.api.exposedHeaders),
2023-01-22 09:53:09 +00:00
};
// CORS
2023-05-12 05:59:32 +00:00
app.use(cors(corsOptions));
// Static Routes // try to use nginx route instead in comments
2023-04-28 11:21:02 +00:00
/*app.use( express.static( `${__dirname}/nationchains/tribes/${conf.mayorId}/www/cdn/public`, {
2023-05-31 13:19:21 +00:00
dotfiles: 'allow'
2023-01-22 09:53:09 +00:00
} ) );
2023-04-27 04:17:20 +00:00
*/
2023-01-22 09:53:09 +00:00
// Routers add any routes from /routes and /plugins
2023-11-05 11:03:25 +00:00
let logroute = "Routes available on this apxtrib instance:\n ";
2023-05-12 05:59:32 +00:00
routes.forEach((r) => {
try {
2023-11-05 11:03:25 +00:00
logroute += r.url.padEnd(30,' ') + r.route +"\n ";
2023-05-12 05:59:32 +00:00
app.use(r.url, require(r.route));
} catch (err) {
2023-11-19 15:34:37 +00:00
logroute += " (err check it module.exports=router;? or ...)\n======\n ";
2023-05-12 05:59:32 +00:00
console.log("raise err-:", err);
}
});
2023-05-31 13:19:21 +00:00
console.log(logroute);
if (infotown.townId == "devfarm") {
console.log(
2023-11-05 11:03:25 +00:00
`\x1b[42m############################################################################################\x1b[0m\n\x1b[42mThis is dev conf accessible in http://devfarm-ants to switch this as production, you must run:\n 1 - 'yarn dev nationId:ants townId:usbfarm dns:usbfarm-ants ' to conf your town and check it.\n 2 - 'yarn startpm2'\n Where:\n\x1b[42m * nationId have to exist in the nationchains\n * townId new or if exist must have the smae current dns,\n * dns domaine that has to redirect 80/443 into this server (example wall-ants.ndda.fr redirect to 213.32.65.213 ).\n Check README's project to learn more.\x1b[0m\n To work with apxweb for the front use http://defarm-ants/apxweb/www/tplname/src/index.html to use the api during dev process\n\x1b[42m############################################################################################\x1b[0m`
2023-05-31 13:19:21 +00:00
);
}
2023-05-12 05:59:32 +00:00
app.listen(conf.api.port, () => {
2023-11-05 11:03:25 +00:00
let webaccess = `api waits request on `;
2023-05-31 13:19:21 +00:00
conf.dns.forEach((u) => {
webaccess += `http://${u}:${conf.api.port}`;
});
console.log(webaccess);
2023-05-12 05:59:32 +00:00
});
console.log(
"\x1b[42m\x1b[37m",
"Made with love for people's freedom, enjoy !!!",
"\x1b[0m"
);