Premier commit
This commit is contained in:
commit
aa5176a04c
137
.gitignore
vendored
Normal file
137
.gitignore
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
# ---> Node
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
#data
|
||||
data
|
||||
data/*
|
||||
|
||||
private
|
9
LICENSE
Normal file
9
LICENSE
Normal file
@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 infrastructure
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
113
bin/auth.js
Normal file
113
bin/auth.js
Normal file
@ -0,0 +1,113 @@
|
||||
const { LogType } = require("loguix")
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
const { __glob } = require("./global-variables")
|
||||
const alog = new LogType("Authentification")
|
||||
const keygen = require("./keygen")
|
||||
const users = require("./users")
|
||||
|
||||
/**
|
||||
* Vérifie si le token est présent et appartient à un utilisateur
|
||||
* @param {string} token
|
||||
*/
|
||||
|
||||
module.exports.check = function(token) {
|
||||
var isApproved = false;
|
||||
var username = null
|
||||
users.fetchUsers().forEach((fetchUser) => {
|
||||
if(fetchUser.tokens.includes(token)) {
|
||||
isApproved = true
|
||||
username = fetchUser.username
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
if(isApproved) {
|
||||
return true
|
||||
} else {
|
||||
if(token) {
|
||||
|
||||
alog.warn("Erreur d'authentification - Token n'existe pas : " + token)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Permet de se connecter à Inventory
|
||||
* @param {object} data
|
||||
* @returns Token or AUTH_FAILED
|
||||
*/
|
||||
module.exports.login = function(data) {
|
||||
var username = data.username
|
||||
var password = data.password
|
||||
|
||||
if(users.fetchUsers().has(username)) {
|
||||
const user = users.fetchUsers().get(username)
|
||||
if(password == user.getPassword()) {
|
||||
const token = user.generateToken()
|
||||
alog.log("Connexion approuvé de l'utilisateur : " + username)
|
||||
return token
|
||||
} else {
|
||||
alog.warn("Echec de connexion de l'utilisateur : " + username + " - Mot de passe incorrect")
|
||||
return "AUTH_FAILED"
|
||||
}
|
||||
|
||||
} else {
|
||||
alog.warn("Echec de connexion de l'utilisateur : " + username + " - Utilisateur non-inscrit dans la base de donnée")
|
||||
return "AUTH_FAILED"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the token
|
||||
* @param {string} token
|
||||
* @returns
|
||||
*/
|
||||
module.exports.signout = function(token) {
|
||||
var isDone = false;
|
||||
var username = null
|
||||
users.fetchUsers().forEach((fetchUser) => {
|
||||
if(fetchUser.tokens.includes(token)) {
|
||||
isDone = true
|
||||
username = fetchUser.username
|
||||
fetchUser.removeToken(token)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
if(isDone) {
|
||||
alog.log("Suppression du Token '" + token + "' de l'utilisateur : " + username)
|
||||
return true
|
||||
} else {
|
||||
if(token) {
|
||||
|
||||
alog.warn("Erreur d'opération lors de la déconnexion - Token n'existe pas : " + token)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports.getUserByToken = function(token) {
|
||||
var isApproved = false;
|
||||
var userGetted = null
|
||||
users.fetchUsers().forEach((fetchUser) => {
|
||||
if(fetchUser.tokens.includes(token)) {
|
||||
userGetted = fetchUser
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
if(userGetted) {
|
||||
return userGetted
|
||||
|
||||
} else {
|
||||
if(token) {
|
||||
|
||||
alog.warn("Erreur d'authentification - Token n'existe pas : " + token)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
}
|
43
bin/config.js
Normal file
43
bin/config.js
Normal file
@ -0,0 +1,43 @@
|
||||
const { LogType } = require("loguix")
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
const { __glob } = require("./global-variables")
|
||||
const clog = new LogType("Configuration")
|
||||
|
||||
setup()
|
||||
|
||||
function setup() {
|
||||
if(!fs.existsSync(__glob.CONFIG)) {
|
||||
clog.log("Création du fichier de configuration dans : " + __glob.CONFIG)
|
||||
fs.writeFileSync(__glob.CONFIG, JSON.stringify({
|
||||
ENCRYPTION_KEY: "1",
|
||||
}, null, 2))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns Config File
|
||||
*/
|
||||
module.exports.getFile = function () {
|
||||
const file = JSON.parse(fs.readFileSync(__glob.CONFIG))
|
||||
return file
|
||||
}
|
||||
|
||||
/**
|
||||
* Update le fichier configuration avec un object
|
||||
* @param {Array} file
|
||||
*/
|
||||
module.exports.updateFile = function (file) {
|
||||
if(fs.existsSync(__glob.CONFIG)) {
|
||||
clog.log("Mise à jour du fichier configuration dans : " + __glob.CONFIG)
|
||||
fs.writeFileSync(__glob.CONFIG, JSON.stringify(file, null, 2))
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.saveSettings = function (settings) {
|
||||
const file = this.getFile()
|
||||
file.JENKINS_TOKEN = settings.jenkins_token
|
||||
file.OMEGA_KEY = settings.omega_token
|
||||
this.updateFile(file)
|
||||
}
|
17
bin/global-variables.js
Normal file
17
bin/global-variables.js
Normal file
@ -0,0 +1,17 @@
|
||||
const path = require("path");
|
||||
const root = path.resolve(__dirname, '../')
|
||||
|
||||
const __glob = {
|
||||
ROUTES: root + path.sep + "routes" + path.sep,
|
||||
ROOT: root,
|
||||
LOGS: root + path.sep + "logs",
|
||||
DATA: root + path.sep + "data",
|
||||
USERS: root + path.sep + "data" + path.sep + "users.json",
|
||||
CONFIG: root + path.sep + "data" + path.sep + "config.json",
|
||||
PACKAGE_JSON: root + path.sep + "package.json",
|
||||
};
|
||||
|
||||
|
||||
|
||||
module.exports = { __glob };
|
||||
|
29
bin/keygen.js
Normal file
29
bin/keygen.js
Normal file
@ -0,0 +1,29 @@
|
||||
const { LogType } = require("loguix")
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
var CryptoJS = require("crypto-js")
|
||||
const { __glob } = require("./global-variables")
|
||||
const clog = new LogType("KeyGen")
|
||||
const config = require("./config")
|
||||
|
||||
const keypass = config.getFile().ENCRYPTION_KEY
|
||||
|
||||
setup()
|
||||
|
||||
function setup() {
|
||||
if(keypass) {
|
||||
clog.log("Clé de chiffrement trouvé et importé")
|
||||
} else {
|
||||
clog.error("Clé de chiffrement inconnu : Passage en mode par défaut")
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.encrypt = function (text) {
|
||||
let encryptedText = CryptoJS.AES.encrypt(text, keypass).toString();
|
||||
return encryptedText;
|
||||
}
|
||||
|
||||
module.exports.decrypt = function(text) {
|
||||
let decryptedText = CryptoJS.AES.decrypt(text, keypass).toString(CryptoJS.enc.Utf8);
|
||||
return decryptedText;
|
||||
}
|
430
bin/users.js
Normal file
430
bin/users.js
Normal file
@ -0,0 +1,430 @@
|
||||
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,
|
||||
tokens: userFetched.tokens,
|
||||
lastLogin: userFetched.lastLogin,
|
||||
|
||||
})
|
||||
|
||||
usersList.set(user.username, user)
|
||||
}
|
||||
|
||||
if(usersList.size == 0) {
|
||||
const adminUser = new this.User({
|
||||
"username": "admin",
|
||||
"password": "inventory",
|
||||
"display_name": "Administrateur",
|
||||
"tokens": [],
|
||||
"lastLogin": "DEFAULT ACCOUNT",
|
||||
})
|
||||
|
||||
|
||||
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
|
||||
*/
|
||||
module.exports.User = class {
|
||||
username = null
|
||||
password = null;
|
||||
display_name = null
|
||||
tokens = []
|
||||
lastLogin = new Date()
|
||||
|
||||
constructor(properties) {
|
||||
|
||||
if(properties) {
|
||||
|
||||
this.username = properties.username
|
||||
this.password = keygen.encrypt(properties.password)
|
||||
this.display_name = properties.display_name
|
||||
this.tokens = properties.tokens
|
||||
this.lastLogin = properties.lastLogin
|
||||
|
||||
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.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.tokens == null) {
|
||||
this.tokens = []
|
||||
}
|
||||
if(this.lastLogin == null) {
|
||||
this.lastLogin = new Date()
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
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.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)
|
||||
|
||||
const user = new this.User({
|
||||
username: settings.username,
|
||||
display_name: settings.display_name
|
||||
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
105
bin/www
Normal file
105
bin/www
Normal file
@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
var log = require("loguix")
|
||||
var {LogType} = require("loguix")
|
||||
var { __glob } = require("./global-variables")
|
||||
log.setup(__glob.LOGS, __glob.PACKAGE_JSON)
|
||||
|
||||
const wlog = new LogType("Serveur")
|
||||
|
||||
if(process.env.DEV ) {
|
||||
|
||||
wlog.log("MODE DEVELOPEMENT ACTIF")
|
||||
}
|
||||
|
||||
wlog.step.init("start_server", "Démarrage du serveur Express JS")
|
||||
|
||||
var app = require('../main');
|
||||
var http = require('http');
|
||||
var config = require("./config")
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var port = normalizePort(process.env.PORT || '5005');
|
||||
app.set('port', port);
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
*/
|
||||
|
||||
var server = http.createServer(app);
|
||||
|
||||
/**
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
|
||||
|
||||
server.listen(port);
|
||||
server.on('error', onError);
|
||||
server.on('listening', onListening);
|
||||
|
||||
/**
|
||||
* Normalize a port into a number, string, or false.
|
||||
*/
|
||||
|
||||
function normalizePort(val) {
|
||||
var port = parseInt(val, 10);
|
||||
|
||||
if (isNaN(port)) {
|
||||
// named pipe
|
||||
return val;
|
||||
}
|
||||
|
||||
if (port >= 0) {
|
||||
// port number
|
||||
return port;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "error" event.
|
||||
*/
|
||||
|
||||
function onError(error) {
|
||||
if (error.syscall !== 'listen') {
|
||||
throw error;
|
||||
}
|
||||
|
||||
var bind = typeof port === 'string'
|
||||
? 'Pipe ' + port
|
||||
: 'Port ' + port;
|
||||
|
||||
// handle specific listen errors with friendly messages
|
||||
switch (error.code) {
|
||||
case 'EACCES':
|
||||
wlog.step.error("start_server", bind + ' requires elevated privileges');
|
||||
process.exit(1);
|
||||
break;
|
||||
case 'EADDRINUSE':
|
||||
wlog.step.error("start_server" , bind + ' is already in use');
|
||||
process.exit(1);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener for HTTP server "listening" event.
|
||||
*/
|
||||
|
||||
function onListening() {
|
||||
wlog.log("Serveur entrain d'écouter sur le port : " + server.address().port)
|
||||
var addr = server.address();
|
||||
var bind = typeof addr === 'string'
|
||||
? 'pipe ' + addr
|
||||
: 'port ' + addr.port;
|
||||
wlog.step.end("start_server")
|
||||
}
|
85
main.js
Normal file
85
main.js
Normal file
@ -0,0 +1,85 @@
|
||||
const createError = require('http-errors');
|
||||
const express = require('express');
|
||||
const path = require('path');
|
||||
const cookieParser = require('cookie-parser');
|
||||
var favicon = require('express-favicon');
|
||||
const app = express();
|
||||
const fs = require("fs");
|
||||
const log = require("loguix")
|
||||
|
||||
const { __glob } = require('./bin/global-variables');
|
||||
const users = require("./bin/users")
|
||||
const {User} = require("./bin/users")
|
||||
|
||||
|
||||
|
||||
var wlog = log.getInstance("Serveur")
|
||||
|
||||
|
||||
|
||||
setup()
|
||||
|
||||
|
||||
function getRouters() {
|
||||
|
||||
wlog.log("Récupération de " + fs.readdirSync(__glob.ROUTES).length + " routeurs depuis : " + __glob.ROUTES)
|
||||
for(var route of fs.readdirSync(__glob.ROUTES)) {
|
||||
|
||||
if(route == "index.js") {
|
||||
|
||||
app.use("/", require(__glob.ROUTES + "index"))
|
||||
} else {
|
||||
|
||||
app.use("/" + route.replace(".js", ""), require(__glob.ROUTES + route))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function setup() {
|
||||
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
app.set('view engine', 'ejs');
|
||||
|
||||
app.use(express.json());
|
||||
app.use(express.urlencoded({ extended: false }));
|
||||
app.use(cookieParser());
|
||||
app.use(express.static(path.join(__dirname, 'public')));
|
||||
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')))
|
||||
|
||||
|
||||
getRouters()
|
||||
users.fetchUsers()
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use(function(req, res, next) {
|
||||
res.locals.message = "Page non trouvé";
|
||||
res.locals.error = {
|
||||
"status": "404",
|
||||
"stack": ""
|
||||
}
|
||||
|
||||
// render the error page
|
||||
res.status(404 || 404);
|
||||
res.render('utils/error');
|
||||
});
|
||||
|
||||
// error handler
|
||||
app.use(function(err, req, res, next) {
|
||||
// set locals, only providing error in development
|
||||
res.locals.message = err.message;
|
||||
res.locals.error = req.app.get('env') === 'development' ? err : {};
|
||||
|
||||
// render the error page
|
||||
res.status(err.status || 500);
|
||||
res.render('utils/error');
|
||||
});
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = app;
|
2314
package-lock.json
generated
Normal file
2314
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
38
package.json
Normal file
38
package.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "inventory",
|
||||
"version": "1.0.0",
|
||||
"description": "Gestion de veteements",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "nodemon ./bin/www",
|
||||
"dev": "set DEV=true & nodemon ./bin/www"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.raphix.fr/raphix/inventory.git"
|
||||
},
|
||||
"nodemonConfig": {
|
||||
"ext": "js, html",
|
||||
"ignore": [
|
||||
"*.json"
|
||||
],
|
||||
"delay": "10000000"
|
||||
},
|
||||
"keywords": [],
|
||||
"dependencies": {
|
||||
"cookie-parser": "~1.4.4",
|
||||
"crypto-js": "^4.2.0",
|
||||
"debug": "~2.6.9",
|
||||
"ejs": "~2.6.1",
|
||||
"express": "~4.16.1",
|
||||
"http-errors": "~1.6.3",
|
||||
"loguix": "^1.4.2",
|
||||
"nodemon": "^3.0.1",
|
||||
"os-utils": "^0.0.14",
|
||||
"pm2": "^5.3.0",
|
||||
"express-favicon": "^2.0.4",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"author": "Raphix",
|
||||
"license": "ISC"
|
||||
}
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
0
public/stylesheets/style.css
Normal file
0
public/stylesheets/style.css
Normal file
25
routes/index.js
Normal file
25
routes/index.js
Normal file
@ -0,0 +1,25 @@
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
var auth = require("../bin/auth")
|
||||
|
||||
/* GET home page. */
|
||||
router.get('/', function(req, res, next) {
|
||||
|
||||
if(!auth.check(req.cookies.token)) {
|
||||
res.clearCookie('token')
|
||||
res.redirect(302, "/login")
|
||||
} else {
|
||||
|
||||
if(process.env.DEV ) {
|
||||
|
||||
res.render('index', {dev: "<p class='view-item yellow'>DÉVELOPEMENT</p>"});
|
||||
} else {
|
||||
|
||||
res.render('index', {dev: ""});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
61
routes/login.js
Normal file
61
routes/login.js
Normal file
@ -0,0 +1,61 @@
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
var auth = require("../bin/auth")
|
||||
|
||||
/* GET home page. */
|
||||
router.get('/', function(req, res, next) {
|
||||
|
||||
if(auth.check(req.cookies.token)) {
|
||||
|
||||
res.redirect(302, "/")
|
||||
} else {
|
||||
res.clearCookie('token')
|
||||
res.render('login', {version: require("../package.json").version});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
router.post("/", (req, res) => {
|
||||
const body = req.body
|
||||
|
||||
const token = auth.login({
|
||||
username: body.username,
|
||||
password: body.password
|
||||
})
|
||||
|
||||
if(token == "AUTH_FAILED") {
|
||||
|
||||
setTimeout(() => {
|
||||
res.status(403).send("AUTH_FAILED")
|
||||
}, 1000)
|
||||
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
res.cookie('token' , token, { maxAge: 900000000, httpOnly: true })
|
||||
res.status(200).send("AUTH_SUCCESS")
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
router.get('/signout', function(req, res, next) {
|
||||
|
||||
if(!auth.check(req.cookies.token)) {
|
||||
|
||||
res.clearCookie('token')
|
||||
res.redirect(302, "/")
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
auth.signout(req.cookies.token)
|
||||
res.clearCookie('token')
|
||||
res.redirect(302, "/")
|
||||
|
||||
}
|
||||
|
||||
});
|
9
routes/stylepage.js
Normal file
9
routes/stylepage.js
Normal file
@ -0,0 +1,9 @@
|
||||
var express = require('express');
|
||||
var router = express.Router();
|
||||
|
||||
/* GET home page. */
|
||||
router.get('/', function(req, res, next) {
|
||||
res.render('utils/stylepage');
|
||||
});
|
||||
|
||||
module.exports = router;
|
12
views/index.ejs
Normal file
12
views/index.ejs
Normal file
@ -0,0 +1,12 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Inventory</title>
|
||||
<link rel='stylesheet' href='/stylesheets/style.css' />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<script defer="" src="https://use.fontawesome.com/releases/v6.4.2/js/all.js" crossorigin="anonymous"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
14
views/login.ejs
Normal file
14
views/login.ejs
Normal file
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Inventory</title>
|
||||
<link rel='stylesheet' href='/stylesheets/style.css' />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<script defer="" src="https://use.fontawesome.com/releases/v6.4.2/js/all.js" crossorigin="anonymous"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
32
views/utils/error.ejs
Normal file
32
views/utils/error.ejs
Normal file
@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Inventory - Erreur</title>
|
||||
<link rel='stylesheet' href='/stylesheets/style.css'/>
|
||||
<style>
|
||||
body {
|
||||
|
||||
padding: 2%;
|
||||
|
||||
}
|
||||
|
||||
div {
|
||||
|
||||
background-color: rgb(32, 32, 32);
|
||||
border-radius: 1vw;
|
||||
padding: 2%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1>Erreur <%= error.status %></h1>
|
||||
<h2><%= message %> - <%= error.status %></h1>
|
||||
<pre><%= error.stack %></pre>
|
||||
|
||||
</div>
|
||||
<br>
|
||||
<a href="/"><button class="btn red"><span>Retourner sur le panel</span></button></a>
|
||||
</body>
|
||||
</html>
|
||||
|
75
views/utils/stylepage.ejs
Normal file
75
views/utils/stylepage.ejs
Normal file
@ -0,0 +1,75 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Inventory</title>
|
||||
<link rel='stylesheet' href='/stylesheets/style.css' />
|
||||
</head>
|
||||
<body>
|
||||
<h1>Inventory - Page de style</h1>
|
||||
<p>Cette page est dédiée au développement et n'est pas en relation avec Inventory.</p>
|
||||
<a href="/"><button class="btn red"><span>Revenir sur le panel</span></button></a>
|
||||
<hr>
|
||||
<p>Police : <code>'Roboto', sans-serif</code></p>
|
||||
<p>Liens : <a href="/stylepage">https://inventory.raphix.fr/stylepage</a></p>
|
||||
<hr>
|
||||
<br>
|
||||
<style>
|
||||
.box-color {
|
||||
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
transition: 0.2s;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
.box-color:hover {
|
||||
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.box-color:active {
|
||||
|
||||
transform: scale(1);
|
||||
color: rgb(58, 255, 3);
|
||||
}
|
||||
|
||||
|
||||
button {
|
||||
width: fit-content ;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<div class="col">
|
||||
<p>Classe : <code>btn</code></p>
|
||||
<div class="row">
|
||||
<button class="btn red"><span>Error Button</span></button>
|
||||
<button class="btn blue "><span>Info Button</span></button>
|
||||
<button class="btn yellow"><span>Warning Button</span></button>
|
||||
<button class="btn green"><span>Confirm Button</span></button>
|
||||
<button class="btn"><span>Default Button</span></button>
|
||||
</div>
|
||||
<p>Classe : <code>btn min</code></p>
|
||||
<div class="row">
|
||||
<button class="btn min red"><span><i class="fa fa-xmark"></i></span></button>
|
||||
<button class="btn min blue"><span><i class="fa fa-info"></i></span></button>
|
||||
<button class="btn min"><span><i class="fa fa-def"></i></span></button>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div onclick="copyToClipboard('#323031')" style='background-color: #323031;' class="box-color"><p style="text-align: center;">#323031</p></div>
|
||||
<div onclick="copyToClipboard('#f10000')" style='background-color: #f10000;' class="box-color"><p style="text-align: center;">#f10000</p></div>
|
||||
<div onclick="copyToClipboard('#605e5863')" style='background-color: #605e5863;' class="box-color"><p style="text-align: center;">#605e5863</p></div>
|
||||
</div>
|
||||
<p>Classe : <code>field</code></p>
|
||||
<input type="text" class="field">
|
||||
|
||||
<script>
|
||||
function copyToClipboard(text) {
|
||||
navigator.clipboard.writeText(text)
|
||||
}
|
||||
|
||||
</script>
|
||||
<script defer="" src="https://use.fontawesome.com/releases/v6.4.2/js/all.js" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user