apxtrib/api/routes/tribes.js
2023-12-05 07:42:35 +01:00

414 lines
18 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require( 'express' );
const fs = require( 'fs-extra' );
const path = require( 'path' );
const glob = require('glob');
const conf = require(`${process.env.dirtown}/conf.json`);
// Classes
const Tribes = require( '../models/Tribes.js' );
// Middlewares
const checkHeaders = require( '../middlewares/checkHeaders' );
const isAuthenticated = require( '../middlewares/isAuthenticated' );
const router = express.Router();
/**
* @api {get} /tribes/www/:tribeId - tribe list
* @apiName getlisttrib
* @apiDescription Get list of www object (space web)
* @apiGroup Tribes
*
* @apiParam {String} tribeId it identify an existing tribe*
* @apiSuccess (object) listwww contains folder name in www for tribeId
* @apiSuccessExample {json} listwww
* HTTP/1.1 200 OK
* {status:200,ref:"Tribes",msg:"listwww",data:{listwww}}
*/
router.get('www', checkHeaders,isAuthenticated,(req,res)=>{
let listwww=[]
glob.sync(`${conf.dirtown}/tribes/${req.params.tribeId}/www/*`).forEach(d=>{
listwww.push(d.split("/").pop())
})
res.status(200).json({status:200,ref:"Tribes",msg:"listwww",data:{listwww}})
})
//router.post('www/') to create a webspace
//router.put('www/:app') to update
//router.delete('www/:tribeId/:app)
router.post('/actionanonyme',checkHeaders,(req,res)=>{
if (!fs.existsSync(`${conf.dirtown}/tribes/${req.session.header.xtribe}/actions/${req.body.action}.js`)){
res.status(403).send({status:403,msg:"actionmissing",ref:"Tribes", data:{action:req.body.action,tribe:req.session.header.xtribe}})
}
const action = require(`${conf.dirtown}/tribes/${req.session.header.xtribe}/actions/${req.body.action}.js`)
const resaction= action.run(req.body,req.session.header);
res.status(resaction.status).send(resaction);
})
router.post('/action',checkHeaders,isAuthenticated,(req,res)=>{
})
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 apxtrib => 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.apxtrib && req.session.header.accessrights.data.apxtrib.tribeid && req.session.header.accessrights.data.apxtrib.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
//A REVOIR hasAccessrighton( req.body.object, "U" );
} else {
// AREVOIRhasAccessrighton( 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;
};
// A REVOIR 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: apxtrib" -H "xworkon: pvmsaveurs" -H "xlang: fr" -H "xpaganid: 1" -H "xauth: 1" -H "xapp: pvmsaveurs:pvmsaveurs" -H "Content-Type: application/json" -d '{"LOGIN":"adminapxtrib","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: adminapxtrib" -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: adminapxtrib" -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 apxtrib 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
<form action="/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit" value="upload"/>
</form>
*/
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;