2023-05-31 15:19:21 +02:00
const { argv } = require ( "process" ) ;
2023-05-12 07:59:32 +02:00
const fs = require ( "fs-extra" ) ;
2023-05-31 15:19:21 +02:00
const mustache = require ( "mustache" ) ;
2023-05-12 07:59:32 +02: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-01-22 10:53:09 +01:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2023-03-27 07:52:21 +02: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 10:53:09 +01:00
2023-05-31 15:19:21 +02: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 06:17:20 +02:00
* /
2023-05-31 15:19:21 +02:00
/ * *
* 1 st 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 12:03:25 +01:00
* if no parameter from adminapi / www / adminapx / conf / setup _xx . json
2023-05-31 15:19:21 +02: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 07:59:32 +02:00
2023-05-31 15:19:21 +02:00
// check nginx exist
2023-05-12 07:59:32 +02: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 10:53:09 +01:00
}
2023-05-31 15:19:21 +02:00
const param = { } ;
argv . slice ( 2 ) . forEach ( ( arg ) => {
const kv = arg . split ( ":" ) ;
if ( kv . length == 2 ) {
param [ kv [ 0 ] ] = kv [ 1 ] ;
}
} ) ;
2023-06-28 15:23:17 +02:00
2023-06-07 07:32:23 +02:00
// setup_xx.json is gitignore so at first install we are in dev configuration
let infotown = {
nationId : "ants" ,
townId : "devfarm" ,
2023-06-28 15:23:17 +02:00
dns : "devfarm-ants" ,
2023-06-07 07:32:23 +02: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 12:03:25 +01:00
}
2023-06-28 15:23:17 +02: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 12:03:25 +01:00
}
2023-06-28 15:23:17 +02:00
fs . outputJsonSync (
2023-11-05 12:03:25 +01: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 15:19:21 +02:00
if (
2023-06-28 15:23:17 +02:00
! fs . existsSync ( ` ${ infotown . dirtown } /conf.json ` ) ||
2023-05-31 15:19:21 +02:00
! fs . existsSync ( ` ${ _ _dirname } /adminapi/www/nginx_adminapx.conf ` )
) {
2023-06-07 07:32:23 +02:00
// Case of new town or request a reset of dns to access adminapx
2023-06-28 15:23:17 +02:00
// genere a minimum conf with nationId, townId, dns, dirapi, dirtown
2023-11-05 12:03:25 +01:00
fs . outputJsonSync ( ` ${ infotown . dirtown } /conf.json ` , infotown , { space : 2 } ) ;
const Towns = require ( "./api/models/Towns" ) ;
2023-06-28 15:23:17 +02:00
const rescreate = Towns . create ( ) ;
2023-11-05 12:03:25 +01:00
if ( rescreate . status != 200 ) {
console . log ( "Sorry error " ) ;
2023-06-28 15:23:17 +02:00
process . exit ( ) ;
}
2023-01-22 10:53:09 +01:00
}
2023-06-28 15:23:17 +02:00
const conf = require ( ` ${ infotown . dirtown } /conf.json ` ) ;
2023-05-16 10:31:27 +02:00
2023-05-31 15:19:21 +02: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 07:59:32 +02:00
2023-05-31 15:19:21 +02:00
// Run main express process for a /towId-nationId/tribes
2023-05-12 07:59:32 +02:00
2023-05-31 15:19:21 +02: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 07:59:32 +02:00
let doms = conf . dns ; // only dns of town during the init process
let tribeIds = [ ] ;
2023-05-16 10:31:27 +02:00
let routes = glob . sync ( ` ${ conf . dirapi } /api/routes/*.js ` ) . map ( ( f ) => {
2023-05-12 07:59:32 +02:00
return { url : ` / ${ path . basename ( f , ".js" ) } ` , route : f } ;
} ) ;
2023-11-05 12:03:25 +01: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 07:59:32 +02: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 07:46:35 +02:00
2023-04-27 06:17:20 +02:00
const app = express ( ) ;
2023-05-12 07:59:32 +02:00
// load express parameter from conf
Object . keys ( conf . api . appset ) . forEach ( ( p ) => {
app . set ( p , conf . api . appset [ p ] ) ;
} ) ;
2023-01-22 10:53:09 +01:00
// To set depending of data form or get size to send
2023-05-12 07:59:32 +02:00
app . use ( bodyParser . urlencoded ( conf . api . bodyparse . urlencoded ) ) ;
2023-01-22 10:53:09 +01:00
// To set depending of post put json data size to send
2023-05-12 07:59:32 +02:00
app . use ( express . json ( ) ) ;
app . use ( bodyParser . json ( conf . api . bodyparse . json ) ) ;
2023-11-05 12:03:25 +01:00
app . disable ( 'x-powered-by' ) ; // for security
2023-04-27 06:17:20 +02:00
app . locals . tribeids = tribeIds ;
2023-05-12 07:59:32 +02:00
console . log ( "app.locals.tribeids" , app . locals . tribeids ) ;
2023-01-22 10:53:09 +01:00
// Cors management
const corsOptions = {
2023-05-12 07:59:32 +02:00
origin : ( origin , callback ) => {
2023-11-05 12:03:25 +01:00
//before modif only origin == undefined
if (
( infotown . townId == "devfarm" &&
( origin == undefined || origin == null ) ) ||
origin . indexOf ( "chrome-extension" ) > - 1
) {
2023-05-12 07:59:32 +02:00
callback ( null , true ) ;
} else {
const rematch = /^https?:\/\/(.*):.*/g . exec ( origin ) ;
//console.log( rematch )
let tmp = origin . replace ( /http.?:\/\//g , "" ) . split ( "." ) ;
2023-01-22 10:53:09 +01:00
2023-05-12 07:59:32 +02: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 12:03:25 +01:00
callback ( false ) ;
2023-05-12 07:59:32 +02:00
}
}
} ,
exposedHeaders : Object . keys ( conf . api . exposedHeaders ) ,
2023-01-22 10:53:09 +01:00
} ;
// CORS
2023-05-12 07:59:32 +02:00
app . use ( cors ( corsOptions ) ) ;
// Static Routes // try to use nginx route instead in comments
2023-04-28 13:21:02 +02:00
/ * a p p . u s e ( e x p r e s s . s t a t i c ( ` $ { _ _ d i r n a m e } / n a t i o n c h a i n s / t r i b e s / $ { c o n f . m a y o r I d } / w w w / c d n / p u b l i c ` , {
2023-05-31 15:19:21 +02:00
dotfiles : 'allow'
2023-01-22 10:53:09 +01:00
} ) ) ;
2023-04-27 06:17:20 +02:00
* /
2023-01-22 10:53:09 +01:00
// Routers add any routes from /routes and /plugins
2023-11-05 12:03:25 +01:00
let logroute = "Routes available on this apxtrib instance:\n " ;
2023-05-31 15:19:21 +02:00
2023-05-12 07:59:32 +02:00
routes . forEach ( ( r ) => {
try {
2023-11-05 12:03:25 +01:00
logroute += r . url . padEnd ( 30 , ' ' ) + r . route + "\n " ;
2023-05-12 07:59:32 +02:00
app . use ( r . url , require ( r . route ) ) ;
} catch ( err ) {
2023-05-31 15:19:21 +02:00
logroute += " (err check it)" ;
2023-05-12 07:59:32 +02:00
console . log ( "raise err-:" , err ) ;
}
} ) ;
2023-05-31 15:19:21 +02:00
console . log ( logroute ) ;
if ( infotown . townId == "devfarm" ) {
console . log (
2023-11-05 12:03:25 +01:00
` \x 1b[42m############################################################################################ \x 1b[0m \n \x 1b[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 \x 1b[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. \x 1b[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 \x 1b[42m############################################################################################ \x 1b[0m `
2023-05-31 15:19:21 +02:00
) ;
}
2023-05-12 07:59:32 +02:00
app . listen ( conf . api . port , ( ) => {
2023-11-05 12:03:25 +01:00
let webaccess = ` api waits request on ` ;
2023-05-31 15:19:21 +02:00
conf . dns . forEach ( ( u ) => {
webaccess += ` http:// ${ u } : ${ conf . api . port } ` ;
} ) ;
console . log ( webaccess ) ;
2023-05-12 07:59:32 +02:00
} ) ;
console . log (
"\x1b[42m\x1b[37m" ,
"Made with love for people's freedom, enjoy !!!" ,
"\x1b[0m"
) ;