const { LogType } = require("loguix") const fs = require("fs") const path = require("path") const { __glob } = require("./global-variables") const ulog = new LogType("Users") const keygen = require("./keygen") const uuid = require("uuid") var usersList = new Map() setup() function setup() { if(!fs.existsSync(__glob.USERS)) { ulog.log("Création du fichier utilisateur dans : " + __glob.USERS) fs.writeFileSync(__glob.USERS, JSON.stringify([], null, 2)) } } module.exports.getAllUsers = async function() { return new Promise(async (resolve, reject) => { const users = await this.fetchUsers() // Remove for every people the password & the tokens for(var user of users) { user = user[1] user.password = null user.tokens = null } resolve(JSON.stringify(Array.from(users))) }) } /** * Get all users from Users Data Base */ module.exports.fetchUsers = function () { ulog.step.init("fetch_user", "Récupération de tous les utilisateurs inscrit dans la base de donnée") const userFile = getFile() usersList = new Map() for(var userFetched of userFile) { const user = new this.User({ username: userFetched.username, password: userFetched.password, display_name: userFetched.display_name, permission: userFetched.permission, tokens: userFetched.tokens, lastLogin: userFetched.lastLogin, picture: userFetched.picture }) usersList.set(user.username, user) } if(usersList.size == 0) { const adminUser = new this.User({ "username": "admin", "password": "neutral", "display_name": "Administrateur", "permission": [ "FILES_EXPLORER", "SERVICES", "SERVERS", "PIPELINES", "METRICS", "USERS", "LINKS", "SETTINGS" ], "tokens": [], "lastLogin": "DEFAULT ACCOUNT", "picture": "/images/default.jpg" }) adminUser.register() } ulog.step.end("fetch_user") return usersList } /** * User Class is used to access to default user's properties and methods * @param {object} properties User properties with : username, password, display_name, permission... */ module.exports.User = class { username = null password = null; display_name = null permission = [] tokens = [] lastLogin = new Date() picture = "/images/default.jpg" constructor(properties) { if(properties) { this.username = properties.username this.password = keygen.encrypt(properties.password) this.display_name = properties.display_name this.permission = properties.permission this.tokens = properties.tokens this.lastLogin = properties.lastLogin this.picture = properties.picture const userFile = getFile() for(var userFetched of userFile) { if(properties.username == userFetched.username) { ulog.log("Récupération dans la base de donnée, de l'utilisateur : " + userFetched.username) this.username = userFetched.username this.password = userFetched.password this.display_name = userFetched.display_name this.permission = userFetched.permission this.tokens = userFetched.tokens this.lastLogin = userFetched.lastLogin } } } if(this.username == null) { ulog.error("One of user is without username ! [IMPORANT_FIELD_IS_MISSING]") this.username = Math.random() } if(this.password == null) { ulog.error("'" + this.username + "' is without password ! Password reset to 'default' [IMPORANT_FIELD_IS_MISSING]") this.password = keygen.encrypt("default") } if(this.display_name == null) { ulog.warn("'" + this.username + "' is without display name !") this.display_name = this.username } if(this.permission == null) { ulog.warn("'" + this.username + "' has no longer permission !") } if(this.tokens == null) { this.tokens = [] } if(this.permission == null) { this.permission = [] } if(this.lastLogin == null) { this.lastLogin = new Date() } if(this.picture == null) { this.picture = "/images/default.jpg" } } register() { var alreadyExist = false const userFile = getFile() for(var userFetched of userFile) { if(userFetched.username == this.username) { userFile.splice(userFile.indexOf(userFetched), 1) ulog.log("Mise à jour dans la base de donnée, de l'utilisateur : " + this.username) alreadyExist = true } } if(!alreadyExist) { ulog.log("Création dans la base de donnée de l'utilisateur : " + this.username) } userFile.push(this) updateFile(userFile) usersList.set(this.username, this) } unregister() { var alreadyExist = false const userFile = getFile() for(var userFetched of userFile) { if(userFetched.username == this.username) { userFile.splice(userFile.indexOf(userFetched), 1) ulog.log("Mise à jour dans la base de donnée, de l'utilisateur : " + this.username) alreadyExist = true } } if(!alreadyExist) { ulog.log("L'utilisateur n'est pas enregistré dans la base de donnée : " + this.username) } updateFile(userFile) usersList.delete(this.username) } checkPermission(name) { this.#sync() if(this.permission.includes(name)) { return true } else { return false } } addPermission(name) { this.#sync() for(var perms of this.permission) { if(name == perms) { ulog.warn("'" + this.username + "' a déjà la permission : " + name) return false } } this.permission.push(name) this.register() } removePermission(name) { this.#sync() var havePermission = false for(var perms of this.permission) { if(name == perms) { havePermission = true } } if(havePermission) { this.permission.splice(this.permission.indexOf(name), 1) this.register() } else { ulog.warn("'" + this.username + "' n'a pas la permission : " + name) return false } } setPassword(newPassword) { this.#sync() this.password = keygen.encrypt(newPassword) this.register() ulog.log("Le mot de passe de l'utilisateur a été modifié : " + this.username) } getPassword() { this.#sync() return keygen.decrypt(this.password) } generateToken() { this.#sync() const gToken = uuid.v4().toString() this.tokens.push(gToken) this.register() return gToken } removeToken(token) { this.#sync() var haveToken = false for(var aToken of this.tokens) { if(token == aToken) { haveToken = true } } if(haveToken) { this.tokens.splice(this.tokens.indexOf(token), 1) this.register() } else { ulog.warn("'" + this.username + "' n'a pas le token : " + token) return false } } setPicture(text) { this.#sync() this.picture = text this.register() ulog.log("La photo de l'utilisateur a été modifié : " + this.username) } setDisplayName(text) { this.#sync() this.display_name = text this.register() ulog.log("Le nom d'affichage de l'utilisateur a été modifié : " + this.username) } setNewUsername(text) { this.#sync() module.exports.deleteUser(this.username) this.username = text this.register() ulog.log("Le nom d'utilisateur de l'utilisateur a été modifié : " + this.username) } setLastLogin(text) { this.#sync() this.lastLogin = text this.register() } setPicture(file) { this.#sync() var pictureDir = __glob.USERS_IMAGES + path.sep + uuid.v4().toString() + ".png" if(!fs.existsSync(__glob.USERS_IMAGES)) { fs.mkdirSync(__glob.USERS_IMAGES) } fs.writeFileSync(pictureDir, file) this.picture = pictureDir.replace(__glob.USERS_IMAGES + path.sep, "/users/") this.register() } setPermissions(permissions) { this.#sync() this.permission = permissions this.register() } clearTokens() { this.#sync() this.tokens = [] this.register() } #sync() { for(var userGet of usersList.keys()) { const userFetched = usersList.get(userGet) if(this.username == userFetched.username) { this.username = userFetched.username this.password = userFetched.password this.display_name = userFetched.display_name this.permission = userFetched.permission this.tokens = userFetched.tokens this.lastLogin = userFetched.lastLogin } } } } module.exports.addUser = function(settings) { if(settings.username == '') { ulog.error("Le nom d'utilisateur est manquant") return "USERNAME_MISSING" } else if(settings.password == '') { ulog.error("Le mot de passe est manquant") return "PASSWORD_MISSING" } else if(settings.display_name == '') { ulog.error("Le nom d'affichage est manquant") return "DISPLAY_NAME_MISSING" } else if(this.getUser(settings.username)) { ulog.error("L'utilisateur existe déjà : " + settings.username) return "ALREADY_EXIST" } else { ulog.step.init("add_user", "Ajout d'un utilisateur dans la base de donnée : " + settings.username) var pictureDir = null if(settings.picture == null) { pictureDir = "/images/default.jpg" } else { pictureDir = __glob.USERS_IMAGES + path.sep + uuid.v4().toString() + ".png" fs.writeFileSync(pictureDir, settings.picture) } const user = new this.User({ username: settings.username, display_name: settings.display_name, permission: settings.permissions, picture: pictureDir.replace(__glob.USERS_IMAGES + path.sep, "/images/users/") }) user.setPassword(settings.password) user.register() ulog.step.end("add_user") } } module.exports.deleteUser = function(username) { ulog.step.init("delete_user", "Suppression d'un utilisateur dans la base de donnée : " + username) const user = this.getUser(username) user.unregister() ulog.step.end("delete_user") return "OK" } module.exports.getUser = function(username) { return usersList.get(username) } module.exports.editUser = function(settings) { if(settings.username == '') { ulog.error("Le nom d'utilisateur est manquant") return "USERNAME_MISSING" } else if(settings.display_name == '') { ulog.error("Le nom d'affichage est manquant") return "DISPLAY_NAME_MISSING" } else { ulog.step.init("edit_user", "Modification d'un utilisateur dans la base de donnée : " + settings.username) const user = this.fetchUsers().get(settings.username) if(user) { if(settings.newusername && settings.newusername != settings.username) { if(this.getUser(settings.newusername)) { ulog.error("L'utilisateur existe déjà : " + settings.username) return "ALREADY_EXIST" } else { user.setNewUsername(settings.newusername) } } if(settings.display_name) { user.setDisplayName(settings.display_name) } if(settings.password) { user.setPassword(settings.password) } if(settings.picture) { user.setPicture(settings.picture) } if(settings.permissions) { user.setPermissions(settings.permissions) } ulog.step.end("edit_user") return "OK" } else { ulog.step.end("edit_user") return "NOT_EXIST" } } } module.exports.editMySelf = function (settings, user) { if(user.username == settings.username) { if(settings.username == '') { ulog.error("Le nom d'utilisateur est manquant") return "USERNAME_MISSING" } else if(settings.display_name == '') { ulog.error("Le nom d'affichage est manquant") return "DISPLAY_NAME_MISSING" } else { ulog.step.init("edit_user", "Modification d'un utilisateur dans la base de donnée : " + settings.username) const user = this.fetchUsers().get(settings.username) if(user) { console.log(settings) if(settings.newusername && settings.newusername != settings.username) { if(this.getUser(settings.newusername)) { ulog.error("L'utilisateur existe déjà : " + settings.username) return "ALREADY_EXIST" } else { user.setNewUsername(settings.newusername) } } if(settings.display_name) { user.setDisplayName(settings.display_name) } if(settings.password) { user.setPassword(settings.password) } if(settings.picture) { user.setPicture(settings.picture) } ulog.step.end("edit_user") return "OK" } else { ulog.step.end("edit_user") return "NOT_EXIST" } } } else { ulog.error("Vous ne pouvez pas modifier les informations d'un autre utilisateur !") return "NOT_ALLOWED" } } module.exports.clearTokens = function(username) { const user = this.fetchUsers().get(username) user.clearTokens() } /** * * @returns User File */ function getFile() { const file = JSON.parse(fs.readFileSync(__glob.USERS)) return file } /** * Update le fichier utilisateur avec un object * @param {Array} file */ function updateFile(file) { if(fs.existsSync(__glob.USERS)) { ulog.log("Mise à jour du fichier utilisateur dans : " + __glob.USERS) fs.writeFileSync(__glob.USERS, JSON.stringify(file, null, 2)) } }