apxtrib/routes/tribes.js

375 lines
17 KiB
JavaScript
Raw Normal View History

2023-01-22 09:53:09 +00:00
const express = require( 'express' );
const fs = require( 'fs-extra' );
const path = require( 'path' );
const config = require( '../tribes/townconf.js' );
// Classes
const Tribes = require( '../models/Tribes.js' );
// Middlewares
const checkHeaders = require( '../middlewares/checkHeaders' );
const isAuthenticated = require( '../middlewares/isAuthenticated' );
const hasAccessrighton = require( '../middlewares/hasAccessrighton' );
const router = express.Router();
router.get( '/clientconf/:tribeid', checkHeaders, isAuthenticated, ( req, res ) => {
/*
get a clientconf.json for a tribeid depending of user accessright
if tribeid == all and user is admin of apixtribe => get /tmp/clientconfglob.json
req.session.header.accessrights, req.session.header.apixpaganid
*/
2023-02-21 20:51:11 +00:00
logger.info( `Tribes/clientconf for tribeid:${req.params.tribeid}` )
2023-01-22 09:53:09 +00:00
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' ) ) {
res.status( 200 )
.send( { moreinfo: fs.readJsonSync( `${config.tmp}/clientconfglob.json`, 'utf-8' ) } );
return;
}
if( req.session.header.accessrights.data[ req.params.tribeid ] &&
req.session.header.accessrights.data[ req.params.tribeid ].tribeid &&
req.session.header.accessrights.data[ req.params.tribeid ].tribeid.includes( 'R' ) &&
fs.existsSync( `${config.tribes}/${req.params.tribeid}/clientconf.json` ) ) {
// const conftribeid = { moreinfo: {} }
// conftribeid.moreinfo[ req.params.tribeid ] = fs.readJsonSync( `${config.tribes}/${req.params.tribeid}/clientconf.json`, 'utf-8' );
res.status( 200 )
.send( { moreinfo: [ fs.readJsonSync( `${config.tribes}/${req.params.tribeid}/clientconf.json`, 'utf-8' ) ] } );
return;
}
// if not authorized or dos not exist return empty
// no specific message is send for security reason (check only log)
res.status( 403 )
.send( { info: [ 'forbidenAccess' ], models: 'Tribes' } )
.end();
} )
router.put( '/', checkHeaders, isAuthenticated, ( req, res ) => {
2023-02-21 20:51:11 +00:00
logger.info( 'Create a new tribeid, with a useradmin' )
logger.info( ' send data = clientconf.json with all parameter.' )
2023-01-22 09:53:09 +00:00
// !!!!! check for security any ; \n or so because data can be used into shell
const add = Tribes.create( req.body );
res.status( add.status )
.send( add.payload )
} )
router.delete( '/archivetribeid/:tribeid', checkHeaders, isAuthenticated, ( req, res ) => {
2023-02-21 20:51:11 +00:00
logger.info( "request archive tribeid" )
2023-01-22 09:53:09 +00:00
const archive = Tribes.archive( req.params.tribeid );
res.status( archive.status )
.send( archive.payload )
} );
router.post( '/spaceweb', checkHeaders, isAuthenticated, ( req, res ) => {
// !!!!! check for security any ; \n or so because data can be used into shell
2023-02-21 20:51:11 +00:00
logger.info( 'Create a new webapp for xworkon ' )
2023-01-22 09:53:09 +00:00
req.body.tribeid = req.session.header.xworkon;
const add = Tribes.addspaceweb( req.body )
res.status( add.status )
.send( add.payload )
} )
router.get( '/spaceweb/components/:tribeid/:website/:key', checkHeaders, ( req, res ) => {
// check if key is valid before continue
// exemple: get Tribes/spaceweb/components/ndda/mesa/123?rep=appmesatable/appsimpletable.mustache
const file = `${config.tribes}/${req.params.tribeid}/spacedev/${req.params.website}/src/ctatic/components/${req.query.path}`
2023-02-21 20:51:11 +00:00
logger.info( `Request components file from ${file}` )
2023-01-22 09:53:09 +00:00
if( fs.existsSync( file ) ) {
res.sendFile( file );
} else {
res.send( `console.error("Missing components file in ${req.params.tribeid}/spacedev/${req.params.website}/src/ctatic/components/${req.query.path}");` );
}
} )
router.get( '/plugins/:tribeid/:pluginname/:key/:filename', ( req, res ) => {
// No accessright possible cause it is load on the fly
// @todo Check key to authorize access to the plugin (key comme from user ACCESSRIGHTS[tribeid plugin owner:pluginname]).key
// return a file into /:tribeid owner of plugin/plugins/:pluginname/components/:filename
// if not exist or invalid key then return console.error
const file = `${config.tribes}/${req.params.tribeid}/plugins/${req.params.pluginname}/components/${req.params.filename}`
2023-02-21 20:51:11 +00:00
logger.info( 'Tribes/plugins/ ', file )
2023-01-22 09:53:09 +00:00
if( fs.existsSync( file ) ) {
res.sendFile( file );
} else {
res.send( `console.error("Missing plugin file in ${req.params.tribeid}/plugins/${req.params.pluginname}/components/${req.params.filename}");` );
}
} );
router.get( '/dirls', checkHeaders, isAuthenticated, ( req, res ) => {
// url /Tribes/dirls?rep=referentials/dataManagement
// request information about a req.query.rep from header xworkon/
// return
// {file:[{}],dir:[{}]}
// @todo check if isAuthorized and exist
2023-02-21 20:51:11 +00:00
logger.info( 'request dirls', `${config.tribes}/${req.session.header.xworkon}/${req.query.rep}` );
2023-01-22 09:53:09 +00:00
if( !fs.existsSync( `${config.tribes}/${req.session.header.xworkon}/${req.query.rep}` ) ) {
res.status( 404 )
.send( { 'info': [ 'dirnotexist' ], model: 'Tribes' } );
}
const info = Tribes.dirls( req.session.header.xworkon, req.query.rep );
2023-02-21 20:51:11 +00:00
logger.info( info )
2023-01-22 09:53:09 +00:00
res.status( info.status )
.send( info.payload );
} )
router.delete( '/ls', checkHeaders, isAuthenticated, ( req, res ) => {
// check Accessright with D or O on each
// url /Tribes/ls
// req.body.files=[listfiles file to delete ]
const authfiles = Tribes.checkaccessfiles( req.body, 'D', req.session.header.accessrights, req.session.header.apixpaganid );
authfiles.ok.forEach( f => { fs.remove( `${config.tribes}/${f}` ); } )
res.status( 200 )
.send( { 'info': [ 'fileauthdeleted' ], models: 'Tribes', moreinfo: authfiles } )
} );
router.put( '/sendjson', checkHeaders, isAuthenticated, ( req, res ) => {
//req.body = {object:spacedev, path:website/src/data/tpldataname_lg.json, data:{...}}
2023-02-21 20:51:11 +00:00
//logger.info( req.body )
2023-01-22 09:53:09 +00:00
const dest = `${config.tribes}/${req.session.header.xworkon}/${req.body.object}/${req.body.path}`;
2023-02-21 20:51:11 +00:00
logger.info( `Send json to saved to ${dest}` );
2023-01-22 09:53:09 +00:00
if( !( req.body.object && fs.existsSync( `${config.tribes}/${req.session.header.xworkon}/${req.body.object}` ) ) ) {
res.status( '404' )
.send( { info: [ 'objectmissiong' ], models: 'Tribes', moreinfo: `object: ${req.body.object} does not exist req.body must {object, data, path} into data ${req.session.header.xworkon}/${req.body.object}` } )
} else {
if( fs.existsSync( `${config.tribes}/${req.session.header.xworkon}/${req.body.object}/${req.body.path}` ) ) {
// exist so can be update check accessright update on this
hasAccessrighton( req.body.object, "U" );
} else {
hasAccessrighton( req.body.object, "C" );
}
fs.outputJsonSync( dest, req.body.data );
res.status( 200 )
.send( { info: [ 'filesaved' ], models: 'Tribes' } )
}
} );
router.post( '/downloadls', checkHeaders, isAuthenticated, ( req, res ) => {
// midlleware hasAccessrighton.js is not apply here only to access/update/create information inside an object
// to get file a user need accessrights to data: object: R or to Own it
// or if exist a .info.json into folder get shared as R in uuid
//req.body contain list of path file or folder if only 1 file then download it, otherwise zip list and send zip file
const authfiles = Tribes.checkaccessfiles( req.body.files, 'R', req.session.header.accessrights, req.session.header.xpaganid );
if( authfiles.ok.length == 1 ) {
// bidouille en attendnat de faire un .zip binaire propre
if( !authfiles.ok[ 0 ].includes( '.xml' ) ) {
res.status( 200 )
.download( `${config.tribes}/${authfiles.ok[0]}`, authfiles.ok[ 0 ] );
} else {
fs.copySync( `${config.tribes}/${authfiles.ok[0]}`, `${config.tribes}/${config.mayorId}/www/app/webapp/static/tmp/${authfiles.ok[ 0 ]}` )
}
} else if( authfiles.ok.length > 1 ) {
// on zip et on envoie
//res.status( 200 )
// .download( `${config.tribes}/${authfiles.ok[0]}`, authfiles.ok[ 0 ])
res.status( 200 )
.attachment( `${config.tribes}/${authfiles.ok[0]}` );
} else {
req.body.filepon
res.status( 403 )
.send( 'Forbidden access' )
}
} );
router.post( '/upfilepond', checkHeaders, isAuthenticated, ( req, res ) => {
2023-02-21 20:51:11 +00:00
logger.info( 'post /Tribes/uploadfilepond' );
2023-01-22 09:53:09 +00:00
// Store file and return a unique id to save button
// that provide folder where to store it
const formidable = require( 'formidable' );
const form = formidable( { multiples: false } );
form.parse( req, ( err, fields, files ) => {
if( err ) { next( err ); return; }
2023-02-21 20:51:11 +00:00
//logger.info( 'fields',fields);
2023-01-22 09:53:09 +00:00
// fileMetadaObject send
let context = JSON.parse( fields.filepond );
let idfile = files.filepond.path;
let name = files.filepond.name;
let subfolder = context.subfolder;
name = name.replace( /[ ,'"]/g, "_" );
2023-02-21 20:51:11 +00:00
//logger.info( 'files.filepond:', files.filepond );
logger.info( idfile, `${config.tribes}/${req.session.header.xworkon}/www/${subfolder}/${name}` )
2023-01-22 09:53:09 +00:00
// On le supprime s'il existe deja
fs.removeSync( `${config.tribes}/${req.session.header.xworkon}/www/${subfolder}/${name}` );
// mv tmp
fs.moveSync( idfile, `${config.tribes}/${req.session.header.xworkon}/www/${subfolder}/${name}` );
//res.status(200).send({models:"Tribes",info:["Savedsuccess"],moreinfo:{id:file.filepond.path}})
//return for filepond
res.writeHead( 200, { 'Content-Type': 'text/plain' } );
res.end( idfile );
} )
} );
router.delete( '/file', checkHeaders, isAuthenticated, ( req, res ) => {
//src = objectfolder with accessright/...
//hasAccessrighton( "www", "D" ),
if( !req.query.src ) {
res.status( 404 )
.send( { info: [ 'deleteerror' ], models: "Tribes", moreinfo: "your del req need a src" } )
return;
};
hasAccessrighton( req.query.src.split( '/' )[ 0 ], "D" );
2023-02-21 20:51:11 +00:00
logger.info( 'Remove file', `${config.tribes}/${req.session.header.xworkon}/${req.query.src}` )
logger.info( req.body )
2023-01-22 09:53:09 +00:00
fs.removeSync( `${config.tribes}/${req.session.header.xworkon}/${req.query.src}` );
res.status( 200 )
.send( { info: [ 'Successfullremove' ], models: "Tribes" } )
} );
router.post( '/uploadfile', checkHeaders, isAuthenticated, ( req, res ) => {
2023-02-21 20:51:11 +00:00
logger.info( 'upload a file ' )
2023-01-22 09:53:09 +00:00
/* 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
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
*/
const formidable = require( 'formidable' );
const form = formidable( { multiples: false } );
form.parse( req, function ( err, fields, files ) {
2023-02-21 20:51:11 +00:00
//logger.info( files.data )
2023-01-22 09:53:09 +00:00
var oldPath = files.data.path;
var newPath = `${config.tribes}/${req.session.header.xworkon}/${clientconf.uploadzip[files.data.name].dest}`;
2023-02-21 20:51:11 +00:00
logger.info( 'oldPath', oldPath )
logger.info( 'newPath', newPath )
2023-01-22 09:53:09 +00:00
var rawData = fs.readFileSync( oldPath )
fs.outputFile( newPath, rawData, function ( err ) {
if( err ) {
2023-02-21 20:51:11 +00:00
logger.info( err );
2023-01-22 09:53:09 +00:00
return res.status( 405 )
.send( { info: [ 'savederror' ], models: "Tribes", moreinfo: "your file was not able to be saved into the server" } )
} else {
return res.status( 200 )
.send( {
info: [ "successfullsent" ],
models: "Tribes"
} );
}
} )
} );
} );
router.post( '/uploadzip', checkHeaders, ( req, res ) => {
2023-02-21 20:51:11 +00:00
logger.info( 'uploadzip a file ' )
2023-01-22 09:53:09 +00:00
/* no authentification to upload a zip filename into /tribes/${xworkon}/${clientconf.uploadzip[filename].dest}
unzip it using the password ${clientconf.uploadzip[filename].psw
if no error then run the callback ${clientconf.uploadzip[filename].callback
but a password to unzip
in clientconf.json need to be set
"uploadzip": {
"articlesTribespvm.zip": {
"comment": "unzip with overwrite if same name",
"psw": "azPI1209qtrse",
"dest": "importexport/tmp",
"unzipoption": "-aoa",
"callback": "importexport/integrationitem.js"
}
},
Example:
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
*/
const clientconf = fs.readJSONSync( `${config.tribes}/${req.session.header.xworkon}/clientconf.json` )
if( !clientconf.uploadzip ) {
return res.status( '404' )
.send( { info: [ "missconf" ], models: "Tribes", moreinfo: `no uploadzip in clientconf for ${req.session.header.xworkon} please contact apixtribe admin ` } );
};
const uploadzip = clientconf.uploadzip;
const formidable = require( 'formidable' );
const form = formidable( { multiples: false } );
form.parse( req, function ( err, fields, files ) {
2023-02-21 20:51:11 +00:00
//logger.info( files.data )
2023-01-22 09:53:09 +00:00
var oldPath = files.data.path;
if( !Object.keys( clientconf.uploadzip )
.includes( files.data.name ) ) {
return res.status( 403 )
.send( { info: [ "notAllowed" ], models: "Tribes", moreinfo: `file ${files.data.name} not allowed to be upload` } )
} else {
2023-02-21 20:51:11 +00:00
logger.info( "context:", clientconf.uploadzip[ files.data.name ] )
2023-01-22 09:53:09 +00:00
var newPath = `${config.tribes}/${req.session.header.xworkon}/${clientconf.uploadzip[files.data.name].dest}`;
2023-02-21 20:51:11 +00:00
//logger.info( 'oldPath', oldPath )
//logger.info( 'newPath', `${newPath}/${files.data.name}` )
2023-01-22 09:53:09 +00:00
fs.moveSync( oldPath, `${newPath}/${files.data.name}`, { overwrite: true } );
const cp = require( 'child_process' );
2023-02-21 20:51:11 +00:00
//logger.info( `7z e -p${clientconf.uploadzip[ files.data.name ].psw} ${newPath}/${files.data.name}` );
logger.info( '7z', [ 'e', `-p${clientconf.uploadzip[ files.data.name ].psw}`, `${newPath}/${files.data.name}`, `-o${config.tribes}/${req.session.header.xworkon}/${clientconf.uploadzip[ files.data.name ].dest}`, clientconf.uploadzip[ files.data.name ].unzipoption ] );
2023-01-22 09:53:09 +00:00
var newFiles = cp.spawnSync( '7z', [ 'e', `-p${clientconf.uploadzip[ files.data.name ].psw}`, `${newPath}/${files.data.name}`, `-o${config.tribes}/${req.session.header.xworkon}/${clientconf.uploadzip[ files.data.name ].dest}`, clientconf.uploadzip[ files.data.name ].unzipoption ] );
2023-02-21 20:51:11 +00:00
logger.info( newFiles.output.toString() )
2023-01-22 09:53:09 +00:00
if( newFiles.output.toString()
.includes( 'Everything is Ok' ) ) {
if( clientconf.uploadzip[ files.data.name ].callback ) {
const integ = require( `${config.tribes}/${req.session.header.xworkon}/${clientconf.uploadzip[files.data.name].callback}` )
.run();
2023-02-21 20:51:11 +00:00
logger.info( 'integration', integ )
2023-01-22 09:53:09 +00:00
return res.status( integ.status )
.send( integ.payload );
} else {
return res.status( 200 )
.send( {
info: [ "successfullsent" ],
models: "Tribes"
} );
}
} else {
return res.status( 400 )
.send( {
info: [ "zipfileerror" ],
models: "Tribes",
moreinfo: newFiles.output.toString()
} )
}
}
} )
} );
router.post( '/upload', checkHeaders, isAuthenticated, ( req, res ) => {
1 // ACHANGER VIA usage sendjson
// url /Tribes/upload?save=tmp&rep=referentials/dataManagement
// if save=tmp then store in a tmp file
// if save=ok then mv the tmp file to the folder
// midlleware hasAccessrighton.js is not apply here only to access/update/create information inside an object
// to upload a file a user need accessrights to data: object: C or to Own it
// or if dir.file exist a .info.json into folder get shared as C in uuid accessright
/*
to add in front
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit" value="upload"/>
</form>
*/
2023-02-21 20:51:11 +00:00
logger.info( 'Envoie image' )
logger.info( 'body', req.body );
logger.info( 'params', req.params );
2023-01-22 09:53:09 +00:00
//const authfolder = Tribes.checkaccessfiles( req.params.rep, 'C', req.session.header.accessrights, req.session.header.xpaganid );
// cheack autorisation to create or replace a file for this accessrights user
const authfolder = { ok: "tt" }
if( authfolder.ok ) {
if( req.params.save == 'file' ) {
if( fs.existsSync( req.body.filepond ) ) {
fs.mv( req.body.filepond, req.params.rep );
}
};
// voir si c'est toujours pertinent car upload est géré par filepond pour les image
if( req.params.save == 'upload' ) {
const form = formidable( { multiples: false } );
form.parse( req, ( err, fields, files ) => {
if( err ) { next( err ); return; }
let thefile = files.filebond.path;
fs.outputFileSync()
2023-02-21 20:51:11 +00:00
logger.info( 'thefile:' + thefile );
2023-01-22 09:53:09 +00:00
res.writeHead( 200, { 'Content-Type': 'text/plain' } );
res.end( theFile );
} )
}
} else {
res.status( 403 )
.send( 'forbiden access' );
}
} );
/*
Manage tribeid into /data/tribee/tribeid
client space dedicated
@Todo
clientconfglob copy cut from Referentials.clientconfglob
clientconf.json copy cut from Referentials.clientconf
list of tribeid copy cut from Referentials.
Add a tribeid
update clientconf
*/
module.exports = router;