UNPKG

@fto-consult/common

Version:

Un ensemble de bibliothèques et d'utilistaires communs pour le développement d'applications javascript

531 lines (471 loc) 17.2 kB
// Copyright 2022 @fto-consult/Boris Fouomene. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. import notify from "$active-platform/notify"; import {encrypt,decrypt} from "$crypto"; import { SIGN_IN} from "../routes"; import {getURIPathName} from "$cutils/uri"; import {NOT_SIGNED_IN} from "$capi/status"; import {defaultObj,extendObj,isNonNullString,isObj,defaultStr} from "$cutils"; import appConfig from "$capp/config"; import crypToJS from "$clib/crypto-js"; import {parseJSON} from "$cutils/json"; import {isClientSide} from "$cplatform"; import $session from "$session"; import {updateTheme as uTheme} from "$theme"; import { getThemeData } from "$theme/utils"; import APP from "$capp/instance"; import DateLib from "$clib/date"; export const permProfilesTableName = "PERMS_PROFILES"; export const notAllowedMsg = "Vous n'êtes pas autorisé à accéder à la ressource demandée"; export const decryptPassword = (pass,userCode)=>{ if(isObj(pass)){ userCode = defaultStr(userCode,pass.code) pass = pass.pass; } userCode = defaultStr(userCode).toUpperCase().trim(); return decrypt(pass,userCode) }; export const encryptPassword = (pass,userCode)=>{ if(isObj(pass)){ userCode = defaultStr(userCode,pass.code) pass = pass.pass; } userCode = defaultStr(userCode).toUpperCase().trim(); return encrypt(pass,userCode) } /*** affiche un message d'erreur passé en paramètre */ export const showError = (errorMsg)=>{ errorMsg = defaultStr(errorMsg,notAllowedMsg); notify.error(errorMsg); } export const NOT_SIGNED_IN_MESSAGE = "Utilisateur non connecté!!\nMerci de tout d'abord faire connecter l'utilisateur"; export const NOT_SIGNED_IN_API_PATH = "/api/not-signed-in"; export const isSignInPage = (route)=>{ route = getURIPathName(route).ltrim("/").trim().toLowerCase(); return route.startsWith(SIGN_IN.ltrim("/").rtrim("/")) ? true : false; } /*** retourne le résultat de requête mentionnant l'utilisateur non connecté, lorsqu'il s'agit d'un appel à l'api * @param {object} res : l'objet response à utiliser pour retourner le resultat à l'utilisateur * @return {boolean|object} */ export const handleNotSignedInApiResponse = (res)=>{ if(res && typeof res=='object' && typeof res.status =='function' && typeof res.json =='function'){ return res.status(NOT_SIGNED_IN).json({message:NOT_SIGNED_IN_MESSAGE}); } return false; } export const tableDataPerms = {}; export const structDataPerms = {}; export const defaultPermsActions = ['read','create','write','update','edit','delete','remove']; const localUserRef = {current:null}; const signInRef = {}; const USER_SESSION_KEY = "user-session"; export const TOKEN_SESSION_KEY = "user-token-key"; export const getEncryptKey = x=>defaultStr(appConfig.get("authSessionEncryptKey"),process.env.AUTH_SESSION_ENCRYPT_KEY,"auth-decrypted-key"); export const isValidLoginId = (loginId)=> isNonNullString(loginId) || typeof loginId ==='number'; /*** check wheater the singleUserAllowed mode is enabled * */ export const isSingleUserAllowed = ()=>{ return (!!appConfig.get("isAuthSingleUserAllowed") && isObj(appConfig.get("authDefaultUser"))) && true || false; } /*** check wheater the multi user is allowed on application */ export const isMultiUsersAllowed = ()=>{ return !isSingleUserAllowed(); } export const canSignOut = ()=>{ if(!isClientSide() || isSingleUserAllowed()) return false; return true; } export const canLogout = canSignOut; /*** return the default single user * when multiuser not allowed */ export const getDefaultSingleUser = ()=>{ if(isSingleUserAllowed()){ const defUser = appConfig.get("authDefaultUser"); return isObj(defUser) && defUser || null; } return null; } const maxProcessSessionAge = parseFloat(process.env.AUTH_SESSION_MAX_AGE||'') || 0; //par défaut les sessions utilisateur expirent après 3 jours export const getAuthSessionMaxAge = ()=>{ const maxAgeConfig = appConfig.get("authMaxSessionAge"); if(typeof maxAgeConfig =='number' && maxAgeConfig > 10) return maxAgeConfig; return typeof maxProcessSessionAge =="number" && maxProcessSessionAge > 10 ? maxProcessSessionAge : 3* 60 * 60 * 24 // 3 days } export const checkSessionExpire = (u)=>{ if(!isValidUser(u) || isSingleUserAllowed()) return false; const {authSessionCreatedAt} = u; if(typeof authSessionCreatedAt ==="number" && authSessionCreatedAt){ const expiresAt = authSessionCreatedAt + (getAuthSessionMaxAge() * 1000); if (new Date().getTime() > expiresAt) { setLocalUser(null); //la session utilisateur a expirée, on la supprime throw new Error(`Session utilisateur expirée pour l'utilisateur`); } } return false; } export const getLocalUser = x=> { if(!isClientSide()) return null; const defaultUser = getDefaultSingleUser(); if(isValidUser(localUserRef.current)){ try { checkSessionExpire(localUserRef.current); return localUserRef.current; } catch(e){ return defaultUser; } } const encrypted = $session.get(USER_SESSION_KEY); if(isNonNullString(encrypted)){ try { const ded = crypToJS.decode(encrypted,getEncryptKey()); if(isObj(ded) && typeof ded?.toString =='function'){ const decoded = ded.toString(crypToJS.enc.Utf8); const u = parseJSON(decoded); if(isValidUser(u)){ checkSessionExpire(u); localUserRef.current = extendObj({},defaultUser,u); return localUserRef.current; } } } catch(e){ console.log("getting local user ",e); } } return defaultUser ; }; export const getLoggedUser = getLocalUser; export const updateTheme = (u)=>{ if(!isObj(u)){ u = getLoggedUser(); } if(isObj(u) && isObj(u.theme) && u.theme.name && u.theme.primary){ uTheme(getThemeData(u.theme).theme); } } export const setLocalUser = u => { if(!isClientSide()) return null; const uToSave = isValidUser(u)? u : null; localUserRef.current = uToSave; let encrypted = null; try { if(isObj(uToSave)){ uToSave.authSessionCreatedAt = new Date().getTime(); } encrypted = uToSave ? crypToJS.encode(JSON.stringify(uToSave),getEncryptKey()).toString() : null; } catch(e){ localUserRef.current = null; console.log(e," setting local user"); } return $session.set(USER_SESSION_KEY,encrypted) } export const isLoggedIn = x => { const u = getLocalUser(); return isValidUser(u) ? true : false; } export const isSignedIn = isLoggedIn; export const isValidUser = u=> { if(!isObj(u) || !Object.size(u,true)) { return false; } return !!(hasToken() || String(getLoginId(u,false))); }; export const getToken = ()=>{ if(!isClientSide()) return null; const token = $session.get(TOKEN_SESSION_KEY); return isValidToken(token) ? token : null; } export const setToken = (token)=>{ if(!isClientSide()) return null; return $session.set(TOKEN_SESSION_KEY,token); } export const isValidToken = (token)=>{ return isNonNullString(token)? true : false; } export const hasToken = ()=>{ const token = getToken(); return isValidToken(token); } const hasMethod = function(methodName){ if(!isNonNullString(methodName)) return false; return typeof signInRef[methodName] === "function"; }; /**** SignIn2Signout est étendue avec le composant AuthProvider*/ const SignIn2SignOut = { get hasMethod(){ return hasMethod; }, get getMethod (){ return (methodName)=>{ if(hasMethod(methodName)){ return signInRef[methodName]; } return undefined; } }, get callMethod (){ return (methodName,...args)=>{ const method = this.getMethod(methodName); if(method){ return method(...args); } return undefined; } }, /**** vérifie si l'utilisateur est le master admin @param {object}, l'utilisateur @parma {booleans}, si l'objet vide est passé alors il sera remplacé par l'utilisateur connecté s'il est vide à moins que cet options ne passe à false */ get isMasterAdmin(){ return (user,pickDefaultUser)=>{ if(isSingleUserAllowed()){ return !!getDefaultSingleUser(); } if(pickDefaultUser !== false){ user = defaultObj(user,getLoggedUser()); } else { user = isObj(user)? user : defaultObj(getLoggedUser()); } if(hasMethod("isMasterAdmin")){ return signInRef.isMasterAdmin(user,pickDefaultUser); } throw "isMasterAdminFunction is not defined on AuthProvider. set IsMasterAdmin callback on AuthProvider"; } }, get upsertUser1(){ return (...a)=>{ if(hasMethod("upsertUser")){ return signInRef.upsertUser(...a); } throw "upsertUser function is not defined on AuthProvider. set IsMasterAdmin callback on AuthProvider"; } }, get signIn1(){ return (...p)=>{ if(hasMethod("signIn")){ return signInRef.signIn(...p); } } }, /***** recupère le nom de la resource table data à partir de la tableName passée en paramètre @param {string} tableName, le nom de la table, @return {string}, le nom de la resource obtenue à partir de la table */ get tableDataPermResourcePrefix(){ return (tableName,...rest)=>{ if(hasMethod("getTableDataPermResourcePrefix")){ return defaultStr(this.getTableDataPermResource(tableName,...rest)); } return tableName.trim().toLowerCase(); } }, get structDataPermResourcePrefix(){ return (tableName,...rest)=>{ if(hasMethod("getStructDataPermResourcePrefix")){ return defaultStr(this.getTableDataPermResource(tableName,...rest)); } return tableName.trim().toLowerCase(); } }, get signOut1(){ return (...p)=>{ if(hasMethod("signOut")){ return Promise.resolve(signInRef.signOut(...p)).then((d)=>{ logout(); return d; }); } return Promise.resolve(logout()); } }, /**** permet de définir les références vers les fonctions de déconnexion et de connexion à l'application*/ get setRef (){ return (currentSigninRef)=>{ extendObj(signInRef,currentSigninRef); return signInRef; } }, get getRef(){ return ()=> signInRef; }, get getUserProp(){ return (user,propsName,methodName,force)=>{ if(!isObj(user) && force !== false){ user = getLocalUser(); } user = defaultObj(user); if(hasMethod(methodName)){ return signInRef[methodName](user,propsName,methodName); } if(hasMethod("getUserProp")){ return signInRef.getUserProp(user,propsName,methodName); } return user[propsName]; } } } /*** retourne le username de l'utilsateur passé en paramètre */ export const getUserName = (user)=>{ return SignIn2SignOut.getUserProp(user,"userName","getUserName"); } /*** retourne le pseudo de l'utilisateur passé en paramètre */ export const getUserPseudo = (user)=>{ return SignIn2SignOut.getUserProp(user,"pseudo","getUserPseudo"); } export const getUserFirstName = (user)=>{ return SignIn2SignOut.getUserProp(user,"firstName","getUserFirstName"); } export const getUserLastName = (user)=>{ return SignIn2SignOut.getUserProp(user,"lastName","getUserLastName"); } export const getUserFullName = (user)=>{ const fullName = SignIn2SignOut.getUserProp(user,"fullName","getUserFullName"); if(!isNonNullString(fullName)){ let firstName = getUserFirstName(user), lastName = getUserLastName(user); if(isNonNullString(firstName) && isNonNullString(lastName)){ if(firstName.toLowerCase() != lastName.toLowerCase()){ return firstName +" "+lastName; } } return firstName; } return fullName; } export const getUserEmail = (user)=>{ return SignIn2SignOut.getUserProp(user,"email","getUserEmail"); } export const getUserCode = (user,force)=>{ return SignIn2SignOut.getUserProp(user,"code","getUserCode",force); } export const getLoginId = (user,force)=>{ const v = SignIn2SignOut.getUserProp(user,"loginId","getLoginId",force); if(isValidLoginId(v)) return v; return getUserCode(user,force); } export const getTableDataPermResourcePrefix = (tableName,...rest)=>{ return SignIn2SignOut.tableDataPermResourcePrefix(defaultStr(tableName).trim().ltrim("/"),...rest); } export const getStructDataPermResourcePrefix = (tableName,...rest)=>{ return SignIn2SignOut.structDataPermResourcePrefix(defaultStr(tableName).trim().ltrim("/"),...rest); } export const getLoggedUserCode = (data)=>{ return getUserCode((isObj(data) && data || getLocalUser())) } export const DEFAULT_SESSION_NAME = "USER-DEFAULT-SESSION"; export const getSessionKey = (sessionName)=>{ sessionName = defaultStr(sessionName,DEFAULT_SESSION_NAME); const userCode = getLoginId(); if(!isValidLoginId(userCode)) return sessionName; return sessionName+"-"+userCode; } export const getSessionData = (sessionKey,sessionName)=>{ if(!isClientSide()){ return isNonNullString(sessionKey)? undefined : {}; } const key = getSessionKey(sessionName); const dat = isNonNullString(key)? defaultObj($session.get(key)) : {}; if(isNonNullString(sessionKey)){ return dat[sessionKey] } return dat; } export const setSessionData = (sessionKey,sessionValue,sessionName)=>{ if(!isClientSide()) return null; if(isObj(sessionKey)){ sessionName = defaultStr(sessionName,sessionValue); } const key = getSessionKey(sessionName); if(!isNonNullString(key)) return false; let dat = defaultObj(getSessionData()); if(isNonNullString(sessionKey)){ dat[sessionKey] = sessionValue; } else if(isObj(sessionKey)){ extendObj(dat,sessionKey,sessionValue); } else { return dat; } $session.set(key,dat); return dat; } /*** déconnecte l'utilisateur actuel */ export const logout = () =>{ if(!canSignOut()) return null; setLocalUser(null); resetPerms(); APP.trigger(APP.EVENTS.AUTH_LOGOUT_USER); return true; } /*** * - on peut définir la liste des noms de tables data dans le propriété tables|tableNames de appConfig.tablesData * - on peut définir la liste des noms struct data dans la propriété structData | structDataTableNames de appConfig.structsData * */ export const resetPerms = ()=>{ const allPerms = {}; Object.map(tableDataPerms,(v,i)=>{ delete tableDataPerms[i]; }) Object.map(structDataPerms,(v,i)=>{ delete structDataPerms[i]; }) const action = defaultPermsActions; Object.map(appConfig.tablesData,(table,tableName)=>{ tableName = defaultStr(isObj(table) && (table.tableName || table.table),tableName) if(!(tableName)) return null; tableName = tableName.toLowerCase().trim(); const resource = getTableDataPermResourcePrefix(tableName).trim().rtrim("/"); tableDataPerms[tableName] = Auth.isAllowed({resource,action}); }) Object.map(appConfig.structsData,(table,tableName)=>{ tableName = defaultStr(isObj(table) && (table.tableName || table.table),tableName) if(!(tableName)) return null; tableName = tableName.toLowerCase().trim(); const resource = getStructDataPermResourcePrefix(tableName).trim().rtrim("/"); structDataPerms[tableName] = Auth.isAllowed({resource,action}); }) allPerms.tableDataPerms = tableDataPerms; allPerms.structDataPerms = structDataPerms; return allPerms; } export const disableAuth = ()=>{ appConfig.set("isAuthSingleUserAllowed",true); appConfig.set("authDefaultUser",{code:"root",password:"admin123",label:"Master admin"}); resetPerms(); return true; } export const enableAuth = ()=>{ appConfig.set("isAuthSingleUserAllowed",false); appConfig.set("authDefaultUser",null); resetPerms(); return true; } export function login (user,trigger){ if(typeof user =='boolean'){ trigger = user; user = trigger; } if(!isObj(user)){ user = getLoggedUser(); } try { if(isValidUser(user)){ setLocalUser(user); updateTheme(user); if(trigger !== false){ resetPerms(); APP.trigger(APP.EVENTS.AUTH_LOGIN_USER,user); } return true; } } catch(e){ console.log(e," is errror rloggin user hein"); return false; } return false; } export const loginUser = login; export default SignIn2SignOut;