const bcrypt = require( 'bcrypt' ); const fs = require( 'fs-extra' ); const jsonfile = require( 'jsonfile' ); const glob = require( 'glob' ); const moment = require( 'moment' ); const jwt = require( 'jwt-simple' ); const UUID = require( 'uuid' ); const Outputs = require( './Outputs.js' ); const config = require( '../tribes/townconf.js' ); const checkdata = require( `../nationchains/socialworld/contracts/checkdata.js`); /* Gestion des utilisateurs connecte /tribes/tribeid/users/ UUID.json /searchindex/indexTOKEN = {TOKEN:UUID} to check authentification indexLOGIN = {LOGIN:UUID} to check if LOGIN exist Used for referntial: To update Global: datashared/referentials/dataManagement/object/users.json Local: data/tribe/*${header.workOn}/referentials/dataManagement/object/users.json To use after a server rerun data/tribe/*${header.workOn}/referentials/${header.langue}/object/users.json Faire comme contact charger les index au lancement et changer la logique de user/id/profil o On initialise les objets au lancement du serveur this.uids[u.UUID] = [u.LOGIN, u.EMAIL, u.password, u.profil, u.TOKEN]; this.logins[u.LOGIN] = u.UUID; this.tokens[u.UUID] = u.TOKEN; on stocke /domain/tribeid/users/logins.json et /uids.json on stocke /domain/tribeids.json et tokkens.json On retourne l'objet {tribeids:[list tribeid], tokens:{UUID:TOKEN}} */ const Pagans = {}; Pagans.init = tribeids => { console.group( 'init Pagans logins, tokens ...' ); // store globaly tokens const tokens = {}; const emailsglob = {}; const loginsglob = {}; // For each tribeid create series of indexes //logger.info(tribeids); tribeids.forEach( tribeid => { // Reset for each domain const uids = {}; const logins = {}; const emails = {}; //check folder exist /*if( !fs.existsSync( `${config.tribes}/${tribeid}/users` ) ) { fs.mkdirSync( `${config.tribes}/${tribeid}/users` ) } if( !fs.existsSync( `${config.tribes}/${tribeid}/users/searchindex` ) ) { fs.mkdirSync( `${config.tribes}/${tribeid}/users/searchindex` ) }*/ glob.sync( `${config.tribes}/${tribeid}/users/*.json` ) .forEach( file => { //logger.info( file ); const u = fs.readJsonSync( file, 'utf-8' ); if( !u.TOKEN ) { u.TOKEN = ''; } //logger.info( u ) uids[ u.UUID ] = [ u.LOGIN, u.EMAIL, u.PASSWORD, u.ACCESSRIGHTS, u.TOKEN ]; logins[ u.LOGIN ] = u.UUID; loginsglob[ u.LOGIN ] = tribeid; // On ne charge que les TOKEN valide let decodedTOKEN = {}; if( u.TOKEN != '' ) { try { decodedTOKEN = jwt.decode( u.TOKEN, config.jwtSecret ); //logger.info( 'decodeTOKEN', decodedTOKEN ) if( moment( decodedTOKEN.expiration ) > moment() ) { tokens[ u.UUID ] = { TOKEN: u.TOKEN, ACCESSRIGHTS: u.ACCESSRIGHTS }; //logger.info( `add token valid for ${u.UUID}:`, tokens[ u.UUID ] ) } } catch ( err ) { logger.info( 'pb de TOKEN impossible a decoder' + u.TOKEN, err ); } } if( u.EMAIL ) { emails[ u.EMAIL ] = u.UUID; emailsglob[ u.EMAIL ] = tribeid; } } ); // UIDS INDEX BY DOMAIN ={UUID:[LOGIN,EMAIL,psw,accessRight,TOKEN]} fs.outputJson( `${config.tribes}/${tribeid}/users/searchindex/uids.json`, uids, { spaces: 2 }, err => { if( err ) throw err; } ); // LOGINS INDEX BY DOMAIN ={LOGIN:UUID} fs.outputJson( `${config.tribes}/${tribeid}/users/searchindex/logins.json`, logins, { spaces: 2 }, err => { if( err ) throw err; } ); // EMAILS INDEX BY DOMAIN ={EMAIL:UUID} fs.outputJson( `${config.tribes}/${tribeid}/users/searchindex/emails.json`, emails, { spaces: 2 }, err => { if( err ) throw err; } ); } ); // EMAILS et appartenance domain fs.outputJson( `${config.tmp}/emailsglob.json`, emailsglob, { spaces: 2 }, err => { if( err ) throw err; } ); // logins et appartenance domain (permet de retrouver tribeid pour un LOGIN) fs.outputJson( `${config.tmp}/loginsglob.json`, loginsglob, { spaces: 2 }, err => { if( err ) throw err; } ); // TOKENS GLOBAL INDEX Centralise tous les TOKEN pour plus de rapidité // {UUID:TOKEN} fs.outputJson( `${config.tmp}/tokens.json`, tokens, { spaces: 2 }, err => { if( err ) throw err; } ); console.groupEnd(); return { tokens }; }; /** * Update indexes: logins, uids and tokens * @param {object} user User object * @param {string} tribeid - The client identifier * @rm {boolean} false => update, true => remove */ Pagans.updateDatabase = ( user, tribeid, rm = false ) => { console.group( `Pagans.updateDatabase for ${tribeid} with user ${user.LOGIN}` ) console.assert( config.loglevel == "quiet", 'user', user ); const loginsIndex = `${config.tribes}/${tribeid}/users/searchindex/logins.json`; jsonfile.readFile( loginsIndex, function ( err, logins ) { console.assert( config.loglevel == "quiet", 'logins', logins ); try { if( rm ) { delete logins[ user.LOGIN ]; } else { logins[ user.LOGIN ] = user.UUID; } jsonfile.writeFile( loginsIndex, logins, { spaces: 2 }, err => { if( err ) logger.info( err ); } ); } catch ( err ) { logger.info( 'Gros pb de mise à jour Pagans.updateDatabase conflit des logins' ); } } ); const uidsIndex = `${config.tribes}/${tribeid}/users/searchindex/uids.json`; jsonfile.readFile( uidsIndex, function ( err, uids ) { try { if( rm ) { delete uids[ user.UUID ]; } else { uids[ user.UUID ] = [ user.LOGIN, user.EMAIL, user.PASSWORD, user.ACCESSRIGHTS, user.TOKEN ]; } jsonfile.writeFile( uidsIndex, uids, { spaces: 2 }, err => { if( err ) logger.info( err ); } ); } catch ( err ) { logger.info( 'Gros pb de mise à jour Pagans.updateDatabase conflit des uids si ce reproduit passer en mode sync bloquant' ); } } ); const emailsIndex = `${config.tribes}/${tribeid}/users/searchindex/emails.json`; jsonfile.readFile( emailsIndex, function ( err, emails ) { console.assert( config.loglevel == "quiet", 'emailss', emails ); try { if( rm ) { delete emails[ user.EMAIL ]; } else { emails[ user.EMAIL ] = user.UUID; } jsonfile.writeFile( emailsIndex, emails, { spaces: 2 }, err => { if( err ) logger.info( err ); } ); } catch ( err ) { logger.info( 'Gros pb de mise à jour Pagans.updateDatabase conflit des emails' ); } } ); const tokensIndex = `${config.tmp}/tokens.json`; let tokens = {}; try { tokens = jsonfile.readFileSync( tokensIndex ); } catch ( err ) { logger.info( 'tokens.json not available' ) } // tokens[user.UUID] = user.TOKEN; tokens[ user.UUID ] = { TOKEN: user.TOKEN, ACCESSRIGHTS: user.ACCESSRIGHTS }; jsonfile.writeFileSync( tokensIndex, tokens, { spaces: 2 } ); /* jsonfile.readFile(tokensIndex, function(err, tokens) { tokens[user.UUID] = user.TOKEN; jsonfile.writeFile(tokensIndex, tokens, { spaces: 2 }, err => { if (err) logger.info(err); }); });*/ console.groupEnd(); }; /** * Read the profil.json of an user * @param {[type]} UUID ID of the user * @param {[type]} tribeid tribeid * @return {Promise} - Return a promise resolved with user data or rejected with an error */ // A S U P P R I M E R utiliser getinfousers pour recuperer des indexs de users // en créer d'autres si necessaire Pagans.getUserlist = ( header, filter, field ) => { console.group( `getUserlist filter with filter ${filter} to get ${field}` ); /* const getuser = Pagans.getUser(header.xuuid, header.xtribeid); if (getuser.status != 200) return { status: getuser.status, data: getuser.payload }; const user = getuser.payload.data; // logger.info(user); // check if update accessright allowed // choose the level depending of ownby xuuid let accessright = user.objectRights[header.xtribeid].users[0]; if (user.ownby.includes(header.xtribeid)) { accessright = user.objectRights[header.xtribeid].users[1]; } // Check update is possible at least user itself ownby itself logger.info(accessright); logger.info(accessright & 4); if ((accessright & 4) != 4) { return { status: 403, data: { info: ['forbiddenAccess'], model: 'Pagans' } }; } */ const Userlist = []; glob.sync( `${config.tribes}/${header.xworkon}/users/*/profil.json` ) .forEach( f => { const infouser = jsonfile.readFileSync( f ); // Ajouter filter et liste de field if( filter != 'all' ) { // decode filter et test } const info = {}; field.split( '______' ) .forEach( k => { if( ![ 'password' ].includes( k ) ) info[ k ] = infouser[ k ]; } ); Userlist.push( info ); } ); // logger.info('userlist', Userlist); console.groupEnd(); return { status: 200, data: { data: Userlist } }; }; Pagans.getinfoPagans = ( tribeid, accessrights, listindex ) => { const info = {} const object = 'users'; const indexs = listindex.split( '_' ) let access = true; indexs.forEach( index => { access = !( [ 'emails', 'logins', 'uids' ].includes( index ) && !( accessrights.data[ object ] && accessrights.data[ object ].includes( 'R' ) ) ); if( access && fs.existsSync( `${config.tribes}/${tribeid}/${object}/searchindex/${index}.json` ) ) { info[ index ] = jsonfile.readFileSync( `${config.tribes}/${tribeid}/${object}/searchindex/${index}.json` ) } } ) logger.info( info ) return { status: 200, data: { info: info } } } Pagans.getUser = ( UUID, tribeid, accessrights ) => { console.assert( config.loglevel == "quiet", `getUser on ${UUID} for ${tribeid} with ${JSON.stringify(accessrights)}` ); if( !fs.existsSync( `${config.tribes}/${tribeid}/users/${UUID}.json` ) ) { return { status: 404, data: { info: [ 'useridNotfound' ], model: 'Pagans', render: { UUID, tribeid } } } } const user = jsonfile.readFileSync( `${config.tribes}/${tribeid}/users/${UUID}.json` ); let access = true; //logger.info("test accessrights.data['users'].includes('R')", accessrights.data['users'].includes('R')) console.assert( config.loglevel == "quiet", 'accessrights', accessrights ) access = accessrights.users && ( accessrights.users.includes( 'R' ) || ( accessrights.users.includes( 'O' ) && user.OWNEDBY.includes( UUID ) ) ); if( access ) { return { status: 200, data: { user: user, model: "User", info: [ "Authorizedtogetuserinfo" ] } }; } return { status: 403, data: { info: [ 'Forbidden' ], model: 'Pagans', render: { UUID, tribeid } } }; }; Pagans.getUserIdFromEMAIL = ( tribeid, EMAIL ) => { if( !checkdata.test.EMAIL( EMAIL ) ) { return { status: 400, data: { info: [ 'ERREMAIL' ], model: 'Pagans' } }; } const emailsIndex = jsonfile.readFileSync( `${config.tribes}/${tribeid}/users/searchindex/emails.json` ); if( !emailsIndex.hasOwnProperty( EMAIL ) ) { return { status: 404, data: { info: [ 'userEMAILNotfound' ], model: 'Pagans' } }; } return emailsIndex[ EMAIL ]; }; Pagans.updateUserpassword = ( UUID, header, data ) => { const getUser = Pagans.getUser( UUID, header.xtribeid, { users: 'W' } ); if( getUser.status == 200 ) { const user = getUser.data.user; // logger.info('user exist', user); const match = bcrypt.compareSync( data.password, user.PASSWORD ); if( !match ) { return { status: 401, data: { info: [ 'checkCredentials' ], model: 'Pagans' } }; } // logger.info('Credentials are matching!'); if( checkdata.test.password( {}, data.pswnew ) ) { user.PASSWORD = bcrypt.hashSync( data.pswnew, config.saltRounds ); jsonfile.writeFileSync( `${config.tribes}/${header.xworkon}/users/${UUID}.json`, user, { spaces: 2 } ); Pagans.updateDatabase( user, header.xworkon, false ); return { status: 200, data: { info: [ 'successfulUpdate' ], model: 'Pagans' } }; } else { return { status: 401, data: { info: [ 'pswTooSimple' ], model: 'Pagans' } }; } } }; Pagans.createUser = ( header, data ) => { /* @input data={PUBKEY,EMAIL,LOGIN,UUID} check and create for header xworkon a user with generic password */ logger.info( 'createUser on header.xworkon:' + header.xworkon + ' by user:' + header.xpaganid ); console.assert( config.loglevel == "quiet", 'with data:', data ); const ref = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/referentials/${header.xlang}/object/users.json` ); const logins = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/searchindex/logins.json` ); const LOGIN = Object.keys( logins ); console.assert( config.loglevel == "quiet", 'LOGIN list', LOGIN ); const emails = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/searchindex/emails.json` ); console.assert( config.loglevel == "quiet", 'emails', emails ); const EMAIL = Object.keys( emails ); console.assert( config.loglevel == "quiet", 'EMAIL list', EMAIL ); // list.UUID est forcement unique car on est en update et pas en create if( !data.UUID ) data.UUID = UUID.v4(); // pour la logique de checkdata il faut passer le parametre const check = checkdata.evaluate( { list: { LOGIN, EMAIL, UUID: [] } }, ref, data ); console.assert( config.loglevel == "quiet", 'check & clean data before update ', check ); if( check.invalidefor.length > 0 ) { return { status: 403, data: { model: 'Pagans', info: check.invalidefor } }; } const clientConfig = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/clientconf.json` ); const user = check.data; user.DATE_CREATE = new Date() .toISOString(); user.PASSWORD = bcrypt.hashSync( clientConfig.genericpsw, config.saltRounds ); user.OWNBY = [ data.UUID ]; user.OBJECT = 'users'; // set le minimum de droit sur l'objet users dont il est le Owner if( data.ACCESSRIGHTS ) { user.ACCESSRIGHTS = data.ACCESSRIGHTS } else { user.ACCESSRIGHTS = { app: {}, data: {} }; } user.ACCESSRIGHTS.data[ header.xworkon ] = { users: "O" }; jsonfile.writeFileSync( `${config.tribes}/${header.xworkon}/users/${user.UUID}.json`, user, { spaces: 2 } ); Pagans.updateDatabase( user, header.xworkon, false ); return { status: 200, data: { uuid: user.UUID, info: [ 'successfulCreate' ], model: 'Pagans' } }; }; Pagans.updateUser = ( UUID, header, data ) => { logger.info( 'updateUser UUID:' + UUID + ' on header.xworkon:' + header.xworkon + ' by user' + header.xpaganid ); // logger.info('header', header); console.assert( config.loglevel == "quiet", 'with data', data ); const getuser = Pagans.getUser( UUID, header.xworkon, { users: 'R' } ); if( getuser.status != 200 ) return { status: getuser.status, data: getuser.data.user }; const user = getuser.data.user; /* let userconnected = user; if (UUID != header.xuuid) { // mean connected user want to change other user const getuserconnected = Pagans.getUser(header.xuuid, header.xtribeid); userconnected = getuserconnected.payload.data; } logger.info('user to update', user); logger.info('user connected that request update', userconnected); // check if update accessright allowed // choose the level depending of ownby xuuid let accessright = userconnected.objectRights[header.xworkon].users[0]; if (user.ownby.includes(header.xuuid)) { accessright = userconnected.objectRights[header.xworkon].users[1]; } // Check update is possible at least user itself ownby itself logger.info(accessright); logger.info(accessright & 2); if ((accessright & 2) != 2) { return { status: 403, data: { info: ['forbiddenAccess'], model: 'Pagans' } }; } */ const ref = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/referentials/object/users_${ header.xlang }.json` ); const logins = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/searchindex/logins.json` ); const LOGIN = Object.keys( logins ) .filter( l => logins[ l ] != user.UUID ); // logger.info( 'LOGIN list', LOGIN ); const emails = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/searchindex/emails.json` ); // logger.info( 'emails', emails ); const EMAIL = Object.keys( emails ) .filter( e => emails[ e ] != user.UUID ); // logger.info( 'EMAIL list', EMAIL ); // list.UUID est forcement unique car on est en update et pas en create // pour la logique de checkdata il faut passer le parametre const check = checkdata.evaluate( { profil: user[ 'apps' + header.xworkon + 'profil' ], list: { LOGIN, EMAIL, UUID: [] } }, ref, data ); if( check.invalidefor.length > 0 ) { return { status: 403, data: { model: 'Pagans', info: check.invalidefor, } }; } data = check.data; let saveuser = false; let updateDatabase = false; Object.keys( data ) .forEach( k => { //logger.info( user[ k ] ) //logger.info( data[ k ] ) //logger.info( '---' ) if( user[ k ] != data[ k ] ) { user[ k ] = data[ k ]; saveuser = true; if( [ 'TOKEN', 'LOGIN', 'EMAIL' ].includes( k ) ) updateDatabase = true; // attention si LOGIN ou EMAIL change il faut checker qu il n existe pas dejà risque de conflit } } ); if( saveuser ) { //logger.info( 'mise à jour user profile.json' ); if( data.TOKEN ) { user.date_lastLOGIN = new Date() .toISOString(); } else { user.date_update = new Date() .toISOString(); } try { jsonfile.writeFileSync( `${config.tribes}/${header.xworkon}/users/${UUID}.json`, user, { spaces: 2 } ); //logger.info( 'declenche updatabase', updateDatabase ) if( updateDatabase ) { // mean index have to be updated Pagans.updateDatabase( user, header.xworkon, false ); console.assert( config.loglevel == "quiet", 'MISE A JOUR DU TOKEN ou de l\'EMAIL ou du LOGIN' ); } } catch ( err ) { logger.info( 'ERRRRR need to understand update impossible of user: ' + UUID + ' in domain:' + header.xworkon + ' from user ' + header.xpaganid + ' of domain:' + header.xtribe ); logger.info( 'with data :', data ); return { status: 400, data: { info: [ 'failtoWritefs' ], model: 'Pagans' } }; } } return { status: 200, data: { info: [ 'successfulUpdate' ], model: 'Pagans' } }; }; Pagans.deleteUser = ( UUID, header ) => { // Delete remove from users object UUID and update index // Activity is not deleted => means some activity can concern an UUID that does not exist anymore. // update index const infouser = jsonfile.readFileSync( `${config.tribes}/${header.xworkon}/users/${UUID}.json` ); Pagans.updateDatabase( infouser, header.xworkon, true ); fs.removeSync( `${config.tribes}/${header.xworkon}/users/${UUID}.json` ); return { status: 200, data: { info: [ 'successfulDelete' ], modedl: 'Pagans' } }; }; /* @header { xtribeid: client domain name data A VERIFIER inutile ,xworkon: client domain name where user is store and where data are stored ,xuuid: 1 if unknown else if user id auhtneticated ,xlanguage: langue used fr en return referential in this lang ,xauth: TOKEN valid for 24h'} workon=xtribeid in an app client usage in case of xtribeid=mymaidigit, if workon==mymaildigit => admin role on any xworkon else adlin role only in xworkon specified @body {LOGIN: password:} return {status:200, data:{data:{TOKEN,UUID}}} return {status:401,data:{info:[code list], model: referential}} */ Pagans.loginUser = ( header, body, checkpsw ) => { // On recupere tribeid du LOGIN // ATTENTION xworkon peut être different du user xtribeid //(cas d'un user qui a des droits sur un autre domain et qui travail sur cet autre domain) // les function Pagans utilise le domain de travail xWorkon // il faut donc modifier le header au moment du LOGIN // pour que l'update du user au moment du LOGIN concerne bien le bon domain header.xworkon = header.xtribe const LOGINdom = jsonfile.readFileSync( `${config.tmp}/loginsglob.json` ); console.assert( config.loglevel == "quiet", LOGINdom ) console.assert( config.loglevel == "quiet", body ) if( !LOGINdom[ body.LOGIN ] ) { return { status: 401, data: { info: [ 'LoginDoesNotExist' ], model: 'Pagans' } }; } const logins = jsonfile.readFileSync( `${config.tribes}/${LOGINdom[body.LOGIN]}/users/searchindex/logins.json` ); if( !Object.keys( logins ) .includes( body.LOGIN ) ) { return { status: 401, data: { info: [ 'LOGINDoesNotExist' ], model: 'Pagans', moreinfo: `Le login ${body.LOGIN} does not exist for tribeid ${LOGINdom[body.LOGIN]}` } }; } // Load user const uid = logins[ body.LOGIN ]; const getUser = Pagans.getUser( uid, LOGINdom[ body.LOGIN ], { users: 'R' } ); logger.info( 'getPagans', getUser ) if( getUser.status != 200 ) { return { status: 200, data: { model: 'Pagans', user: getUser.data.user } }; } const user = getUser.data.user; logger.info( 'user', user ) if( checkpsw ) { const match = bcrypt.compareSync( body.PASSWORD, user.PASSWORD ); if( !match ) { return { status: 401, data: { info: [ 'checkCredentials' ], model: 'Pagans' } }; } } // Mise à jour user pour app LOGIN user.tribeid = LOGINdom[ body.LOGIN ] user.TOKEN = jwt.encode( { expiration: moment() .add( 1, 'day' ), UUID: user.UUID }, config.jwtSecret ); // on met à jour le header qui authentifie le user connecte header.xtribe = LOGINdom[ body.LOGIN ] header.xpaganid = user.UUID; header.xauth = user.TOKEN; // On modifie xworkon car au LOGIN on est forcemenet identifiable sur tribeid // xworkon est utiliser pour travailler sur un environnement client different de celui // de l'appartenace du user header.xworkon = LOGINdom[ body.LOGIN ]; const majuser = Pagans.updateUser( user.UUID, header, { UUID: user.UUID, TOKEN: user.TOKEN } ); // Enleve info confidentiel delete user.PASSWORD; if( user.ACCESSRIGHTS.data[ "Alltribeid" ] ) { //cas admin on transforme les droits sur tous les tribeid existant const newaccessrightsdata = {} jsonfile.readFileSync( `${config.tribes}/tribeids.json` ) .forEach( cid => { newaccessrightsdata[ cid ] = user.ACCESSRIGHTS.data[ "Alltribeid" ] } ) user.ACCESSRIGHTS.data = newaccessrightsdata; } // on recupere le menu de l app qui demande le LOGIN si existe dans user.ACCESSRIGHTS.app[] // header['X-app'] = tribeid:Projet pour récuperer le menu correspondant console.assert( config.loglevel == "quiet", "header.xapp", header.xapp ) console.assert( config.loglevel == "quiet", "user.ACCESSRIGHTS.app[header.xapp]", user.ACCESSRIGHTS.app[ header.xapp ] ); return { status: 200, data: { model: "Pagans", info: [ 'loginSuccess' ], user: user } }; }; Pagans.getlinkwithoutpsw = async ( EMAIL, header ) => { // check le domain d'appartenance de l'eamail dans /tribes/emailsglob.json={email:cleintId} // on remplace le header.xtribeid const domforemail = jsonfile.readFileSync( `${config.tribes}/emailsglob.json`, 'utf-8' ); if( domforemail[ EMAIL ] ) { header.xtribe = domforemail[ EMAIL ] } else { return { status: 404, info: { model: 'Pagans', info: [ 'emailnotfound' ], moreinfo: "email does not exist in /emailsglob.json" } }; } // recupere le uuid du user dans /tribes/tribeid/users/searchindex/emails.json // puis l'ensemble des info des user du domain /uuids.json // infoforuuid[uuidforemail[EMAIL]] permet de récupérer toutes info du user, droit, etc... const uuidforemail = jsonfile.readFileSync( `${config.tribes}/${header.xtribe}/users/searchindex/emails.json`, 'utf8' ); const infoforuuid = jsonfile.readFileSync( `${config.tribes}/${header.xtribe}/users/searchindex/uids.json`, 'utf8' ); // On recupere le modele d'email appemailinfo qui doit être présent dans clientconf.json let confdom = jsonfile.readFileSync( `${config.tribes}/${header.xtribe}/clientconf.json`, 'utf8' ); let checkinfomail = ""; if( !confdom.appemailinfo ) { checkinfomail += ' Erreur de clientconfig il manque un objet appemailinfo pour poursuivre'; } if( checkinfomail != "" ) { logger.info( `Pb de config pour ${header.xtribe} ${checkinfomail} ` ) return { status: 500, info: { model: 'Pagans', info: [ 'objectmissingclientconf' ], moreinfo: checkinfomail } }; } let simulelogin; try { simulelogin = await Pagans.loginUser( header, { LOGIN: infoforuuid[ uuidforemail[ EMAIL ] ][ 0 ], PASSWORD: "" }, false ); logger.info( 'info simulelogin', simulelogin ) } catch ( err ) { return { status: 501, info: { model: 'Pagans', info: [ 'loginImpossible' ], moreinfo: "Impossible de se loger avec " + infoforuuid[ uuidforemail[ EMAIL ] ][ 0 ] } }; } const url = `${config.rootURL}?xauth=${simulelogin.data.TOKEN}&xuuid=${simulelogin.data.UUID}&xtribeid=${simulelogin.data.tribeid}&xworkOn=${header.xworkon}&xlang=${header.xlang}` //logger.info('envoi email avec' + url) confdom.appemailinfo.msg.destperso = [ {} ]; confdom.appemailinfo.msg.destperso[ 0 ].email = EMAIL; confdom.appemailinfo.msg.destperso[ 0 ].subject = "Lien de réinitialisation valable 1h" confdom.appemailinfo.msg.destperso[ 0 ].titre = "Vous avez oublier votre mot de passe" confdom.appemailinfo.msg.destperso[ 0 ].texte = `

Bonjour,
Vous nous avez signalé que vous avez oublié votre mot de passe pour cette email. Avec le lien suivant vous allez pouvoir utiliser votre interface 1h maximum. Clicker ICI.
Nous vous conseillons de changer votre mot de passe.

` //logger.info('envoi header :', header); Outputs.sendMailcampain( confdom.appemailinfo.msg, header ); logger.info( confdom.appemailinfo ); return { status: 200, info: { model: 'Pagans', info: [ 'emailsentforReinit' ], moreinfo: 'EMAIL sent with unique link ' + url } }; } module.exports = Pagans;