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 */ console.log( `Tribes/clientconf for tribeid:${req.params.tribeid}` ) 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 ) => { console.log( 'Create a new tribeid, with a useradmin' ) console.log( ' send data = clientconf.json with all parameter.' ) // !!!!! 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 ) => { console.log( "request archive tribeid" ) 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 console.log( 'Create a new webapp for xworkon ' ) 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}` console.log( `Request components file from ${file}` ) 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}` console.log( 'Tribes/plugins/ ', file ) 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 console.log( 'request dirls', `${config.tribes}/${req.session.header.xworkon}/${req.query.rep}` ); 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 ); console.log( info ) 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:{...}} //console.log( req.body ) const dest = `${config.tribes}/${req.session.header.xworkon}/${req.body.object}/${req.body.path}`; console.log( `Send json to saved to ${dest}` ); 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 ) => { console.log( 'post /Tribes/uploadfilepond' ); // 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; } //console.log( 'fields',fields); // 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, "_" ); //console.log( 'files.filepond:', files.filepond ); console.log( idfile, `${config.tribes}/${req.session.header.xworkon}/www/${subfolder}/${name}` ) // 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" ); console.log( 'Remove file', `${config.tribes}/${req.session.header.xworkon}/${req.query.src}` ) console.log( req.body ) 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 ) => { console.log( 'upload a file ' ) /* 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 ) { //console.log( files.data ) var oldPath = files.data.path; var newPath = `${config.tribes}/${req.session.header.xworkon}/${clientconf.uploadzip[files.data.name].dest}`; console.log( 'oldPath', oldPath ) console.log( 'newPath', newPath ) var rawData = fs.readFileSync( oldPath ) fs.outputFile( newPath, rawData, function ( err ) { if( err ) { console.log( err ); 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 ) => { console.log( 'uploadzip a file ' ) /* 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 ) { //console.log( files.data ) 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 { console.log( "context:", clientconf.uploadzip[ files.data.name ] ) var newPath = `${config.tribes}/${req.session.header.xworkon}/${clientconf.uploadzip[files.data.name].dest}`; //console.log( 'oldPath', oldPath ) //console.log( 'newPath', `${newPath}/${files.data.name}` ) fs.moveSync( oldPath, `${newPath}/${files.data.name}`, { overwrite: true } ); const cp = require( 'child_process' ); //console.log( `7z e -p${clientconf.uploadzip[ files.data.name ].psw} ${newPath}/${files.data.name}` ); console.log( '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 ] ); 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 ] ); console.log( newFiles.output.toString() ) 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(); console.log( 'integration', integ ) 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
*/ console.log( 'Envoie image' ) console.log( 'body', req.body ); console.log( 'params', req.params ); //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() console.log( 'thefile:' + thefile ); 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;