This commit is contained in:
CICD - Pipeline 2023-02-21 12:02:37 +01:00
parent 4f022a0d97
commit 9764132760
32 changed files with 3347 additions and 63 deletions

14
app.js
View File

@ -2,16 +2,21 @@ var createError = require('http-errors');
var express = require('express'); var express = require('express');
var path = require('path'); var path = require('path');
var cookieParser = require('cookie-parser'); var cookieParser = require('cookie-parser');
var favicon = require('express-favicon'); var favicon = require('serve-favicon');
var logger = require('morgan'); var logger = require('morgan');
var fs = require("fs") var fs = require("fs")
var uuid = require('uuid'); var uuid = require('uuid');
var CryptoJS = require("crypto-js") var CryptoJS = require("crypto-js")
var fileUpload = require('express-fileupload')
var indexRouter = require('./routes/index'); var indexRouter = require('./routes/index');
var loginRouter = require('./routes/login'); var loginRouter = require('./routes/login');
var signoutRouter = require('./routes/signout'); var signoutRouter = require('./routes/signout');
var getRouter = require('./routes/get');
var setRouter = require('./routes/set');
var uploadRouter = require('./routes/upload');
@ -27,11 +32,16 @@ app.use(express.urlencoded({ extended: false }));
app.use(cookieParser()); app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public'))); app.use(express.static(path.join(__dirname, 'public')));
app.use(favicon(path.join(__dirname + '/public/' + 'favicon.ico'))) app.use(favicon(path.join(__dirname + '/public/' + 'favicon.ico')))
app.use(fileUpload({
debug: true,
}));
app.use('/', indexRouter); app.use('/', indexRouter);
app.use('/login', loginRouter); app.use('/login', loginRouter);
app.use('/signout', signoutRouter); app.use('/signout', signoutRouter);
app.use('/get', getRouter);
app.use('/set', setRouter)
app.use('/upload', uploadRouter)
// catch 404 and forward to error handler // catch 404 and forward to error handler

View File

@ -31,7 +31,7 @@ module.exports.checkToken = (req, res) => {
} else if(tokens.has(req.cookies.tokenID)) { } else if(tokens.has(req.cookies.tokenID)) {
const user = tokens.get(req.cookies.tokenID) const user = tokens.get(req.cookies.tokenID)
const userData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + users.get(user) + ".json")) const userData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + users.get(user) + ".json", 'utf-8'))
if(userData.token.livableToken == true) { if(userData.token.livableToken == true) {
@ -46,7 +46,7 @@ module.exports.checkToken = (req, res) => {
return user; return user;
} else { } else {
res.delete('tokenID'); res.clearCookie('tokenID');
return false; return false;
@ -63,6 +63,12 @@ module.exports.checkToken = (req, res) => {
} }
module.exports.getFullName = (username) => {
const userData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + this.getUUID(username) + ".json", 'utf-8'))
return userData.fullname
}
module.exports.generateTokenID = (username, userData, req, users) => { module.exports.generateTokenID = (username, userData, req, users) => {
const tokenID = uuid.v4() const tokenID = uuid.v4()
const date = Date.now() const date = Date.now()
@ -99,7 +105,7 @@ module.exports.getUsers = () => {
const users = new Map(); const users = new Map();
fs.readdirSync(__dirname + path.sep + "users").forEach(file => { fs.readdirSync(__dirname + path.sep + "users").forEach(file => {
const fileData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + file)) const fileData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + file, 'utf-8'))
users.set(fileData.username, fileData.uuid) users.set(fileData.username, fileData.uuid)
}) })
@ -112,10 +118,102 @@ module.exports.getAllToken = () => {
const token = new Map(); const token = new Map();
fs.readdirSync(__dirname + path.sep + "users").forEach(file => { fs.readdirSync(__dirname + path.sep + "users").forEach(file => {
const fileData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + file)) const fileData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + file, 'utf-8'))
token.set(fileData.token.tokenID, fileData.username) token.set(fileData.token.tokenID, fileData.username)
}) })
return token return token
} }
module.exports.getUUID = (username) => {
const users = new Map();
fs.readdirSync(__dirname + path.sep + "users").forEach(fileD => {
const fileData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + fileD, 'utf-8'))
users.set(fileData.username, fileData.uuid)
})
return users.get(username);
}
module.exports.changeFullName = (username, req, res) => {
const userData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + this.getUUID(this.checkToken(req, res)) + ".json", 'utf-8'))
Object.defineProperties(userData, {
fullname: {
value: username,
writable: true
}
})
const user = this.getUUIDRequest(req);
fs.writeFileSync(__dirname + path.sep + "users" + path.sep + user + ".json", JSON.stringify(userData, null, 2))
}
module.exports.getUUIDRequest = (req) => {
const users = this.getUsers()
const tokens = this.getAllToken()
users.get(tokens.get(req.cookies.tokenID))
if(req.cookies.tokenID == null) {
return false;
} else if(tokens.has(req.cookies.tokenID)) {
return users.get(tokens.get(req.cookies.tokenID))
} else {
return false;
}
}
module.exports.changePassword = (req, res) => {
const userData = JSON.parse(fs.readFileSync(__dirname + path.sep + "users" + path.sep + this.getUUID(this.checkToken(req, res)) + ".json", 'utf-8'))
const oldp = CryptoJS.AES.encrypt(req.body.additional, "D*G-KaPdSgVkYp3s")
const newp = CryptoJS.AES.encrypt(req.body.value, "D*G-KaPdSgVkYp3s")
if(CryptoJS.AES.decrypt(oldp, "D*G-KaPdSgVkYp3s").toString(CryptoJS.enc.Utf8) == CryptoJS.AES.decrypt(userData.password, "D*G-KaPdSgVkYp3s").toString(CryptoJS.enc.Utf8)) {
Object.defineProperties(userData, {
password: {
value: newp.toString(),
writable: true
}
})
const user = this.getUUIDRequest(req);
fs.writeFileSync(__dirname + path.sep + "users" + path.sep + user + ".json", JSON.stringify(userData, null, 2))
res.send({"result":"success", "content": "<span style='color:rgb(130, 255, 163);'>Le mot de passe a été changé avec succès.</span>"})
} else {
res.send({"result":"success", "content": "Le mot de passe actuel est éronné."})
}
}

1652
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "neutral", "name": "neutral",
"version": "DEV_1.0", "version": "DEV_2.0",
"private": true, "private": true,
"nodemonConfig": { "nodemonConfig": {
"ext": "js", "ext": "js",
@ -22,10 +22,13 @@
"express": "~4.16.1", "express": "~4.16.1",
"express-basic-auth": "^1.2.1", "express-basic-auth": "^1.2.1",
"express-favicon": "^2.0.4", "express-favicon": "^2.0.4",
"express-fileupload": "^1.4.0",
"http-errors": "~1.6.3", "http-errors": "~1.6.3",
"jimp": "^0.22.4",
"jquery": "^3.6.3", "jquery": "^3.6.3",
"morgan": "~1.9.1", "morgan": "~1.9.1",
"nodemon": "^2.0.20", "nodemon": "^2.0.20",
"serve-favicon": "^2.5.0",
"uuid": "^9.0.0" "uuid": "^9.0.0"
}, },
"devDependencies": { "devDependencies": {

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -1,32 +1,225 @@
const logoutBtn = document.getElementById("logout")
logoutBtn.addEventListener("click", () => {
fetch('/signout', { const account = document.getElementById("account")
method: 'GET', const menu = document.getElementById("accmenu")
const sidebar = document.getElementById("sidebar")
const content = document.getElementById("content")
getPage("home.html")
function getPage(name) {
fetch('/get', {
method: 'POST',
redirect: 'follow', redirect: 'follow',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify({"request":"page", "name": name})
}) })
.then(response => response.json()) .then(response => response.json())
.then(response => redirect(response)) .then(response => load(response))
function load(response) {
if(response.result == "failed") {
content.innerHTML = ' <h1 style="color:red;"><i style="color:yellow; font-size: 2vw;" class="fa fa-warning"></i> Erreur de chargement des données - Erreur : ' + response.content + '</h1>'
function redirect(response) { } else if(response.result == "success") {
if(response.success == true) { function setInnerHTML(elm, html) {
window.location.href = "/login" elm.innerHTML = html;
} else if(response.token == "auth_success") { Array.from(elm.querySelectorAll("script"))
.forEach( oldScriptEl => {
const newScriptEl = document.createElement("script");
window.location.href = "/" Array.from(oldScriptEl.attributes).forEach( attr => {
newScriptEl.setAttribute(attr.name, attr.value)
});
const scriptText = document.createTextNode(oldScriptEl.innerHTML);
newScriptEl.appendChild(scriptText);
oldScriptEl.parentNode.replaceChild(newScriptEl, oldScriptEl);
});
}
setInnerHTML(content, response.content)
const accountpicture = document.getElementById("*accountpicture")
const accountname = document.getElementById("*accountname")
if(accountpicture != null) {
fetch('/get', {
method: 'POST',
redirect: 'follow',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"request":"username", "name": ""})
})
.then(response => response.json())
.then(response => load(response))
function load(response) {
if(response.result == "failed") {
content.innerHTML = ' <h1 style="color:red;"><i style="color:yellow; font-size: 2vw;" class="fa fa-warning"></i> Erreur de chargement des données - Erreur : ' + response.content + '</h1>'
console.log("FAILED")
} else if(response.result == "success") {
accountpicture.innerHTML = "<img width='200' height='200' style='border-radius: 100%;' src='/images/userspics/" + response.content + ".png'>"
}
}
}
if(accountname != null) {
fetch('/get', {
method: 'POST',
redirect: 'follow',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"request":"fullname", "name": ""})
})
.then(response => response.json())
.then(response => load(response))
function load(response) {
if(response.result == "failed") {
content.innerHTML = ' <h1 style="color:red;"><i style="color:yellow; font-size: 2vw;" class="fa fa-warning"></i> Erreur de chargement des données - Erreur : ' + response.content + '</h1>'
console.log("FAILED")
} else if(response.result == "success") {
accountname.innerHTML = response.content
}
}
} }
}
}
}
const b1 = document.getElementById("s-home")
const b2 = document.getElementById("s-files")
const b3 = document.getElementById("s-users")
const b4 = document.getElementById("s-moni")
const b5 = document.getElementById("s-device")
const b6 = document.getElementById("s-cv")
const b7 = document.getElementById("s-link")
const settings = document.getElementById("settingsBtn")
b1.addEventListener("click", () => {
getPage("home.html")
})
b2.addEventListener("click", () => {
getPage("files.html")
})
b3.addEventListener("click", () => {
getPage("users.html")
})
b4.addEventListener("click", () => {
getPage("monitor.html")
})
b5.addEventListener("click", () => {
getPage("devices.html")
})
b6.addEventListener("click", () => {
getPage("cv.html")
})
b7.addEventListener("click", () => {
getPage("link.html")
})
settings.addEventListener("click", () => {
getPage("settings.html")
})
sidebar.addEventListener("mouseleave", () => {
menu.classList.remove("viewbar")
content.classList.remove("sidecontent")
})
sidebar.addEventListener("click", (event) => {
if(menu.classList.contains("viewbar") && !(event.target.classList.contains("noside"))) {
menu.classList.remove("viewbar")
} }
}) })
account.addEventListener("click", () => {
menu.classList.add("viewbar")
})
sidebar.addEventListener("mouseenter", () => {
content.classList.add("sidecontent")
})

View File

@ -4,8 +4,23 @@ const remindus = document.getElementById("remindus");
const loginButton = document.getElementById("loginButton"); const loginButton = document.getElementById("loginButton");
const info = document.getElementById("info"); const info = document.getElementById("info");
loginButton.addEventListener("click", () => {
userField.addEventListener("keyup", (event) => {
if (event.key === "Enter") {
passwordField.value = null;
passwordField.focus()
}
});
passwordField.addEventListener("keyup", (event) => {
if (event.key === "Enter") {
login()
}
});
function login() {
info.innerHTML = "" info.innerHTML = ""
const userValue = userField.value; const userValue = userField.value;
const passwordValue = passwordField.value; const passwordValue = passwordField.value;
@ -42,8 +57,9 @@ loginButton.addEventListener("click", () => {
function redirect(response) { function redirect(response) {
if(response.token == "auth_failed") { if(response.token == "auth_failed") {
passwordField.value = null;
info.innerHTML = "Le nom d'utilisateur ou le mot de passe est éronné" info.innerHTML = "Le nom d'utilisateur ou le mot de passe est éronné"
} else if(response.token == "auth_success") { } else if(response.token == "auth_success") {
window.location.href = "/" window.location.href = "/"
@ -54,4 +70,12 @@ loginButton.addEventListener("click", () => {
} }
} }
}
loginButton.addEventListener("click", () => {
login()
}); });

View File

@ -1,5 +1,6 @@
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap');
body { body {
background: rgb(58, 56, 56); background: rgb(58, 56, 56);
@ -7,19 +8,19 @@ body {
padding: 0; padding: 0;
font-family: 'Roboto', sans-serif; font-family: 'Roboto', sans-serif;
color: white; color: white;
} }
.content { .content {
padding: 3%; padding: 3%;
width: 100%;
height: 100%;
display: flex; display: flex;
align-items: center;
justify-content: center;
} }
/*CSS for Login*/
@media (max-width: 768px) { @media (max-width: 768px) {
.box { .box {
@ -31,6 +32,7 @@ body {
box-shadow: 5px 5px 5px rgba(80, 80, 80, 0.477) ; box-shadow: 5px 5px 5px rgba(80, 80, 80, 0.477) ;
} }
} }
@media (min-width: 768px) { @media (min-width: 768px) {
@ -60,15 +62,24 @@ body {
border-style: hidden; border-style: hidden;
border-radius: 1vw; border-radius: 1vw;
transition: all 0.2s ease 0s; transition: all 0.2s ease 0s;
padding-left: 1vw;
} }
.box form input:hover { .box form input:hover {
box-shadow: 2px 2px 5px rgba(255, 255, 255, 0.477) ;
}
.box form input:focus {
box-shadow: 5px 5px 5px rgba(0, 174, 255, 0.477) ; box-shadow: 5px 5px 5px rgba(0, 174, 255, 0.477) ;
} }
.box form .inp { .box form .inp {
margin: 2%; margin: 2%;
@ -78,6 +89,7 @@ body {
border-style:solid; border-style:solid;
border-radius: 1vw; border-radius: 1vw;
border-color: white;
padding: 1%; padding: 1%;
margin: 3%; margin: 3%;
transition: all 0.2s ease 0s; transition: all 0.2s ease 0s;
@ -103,7 +115,7 @@ body {
transition: all 0.2s ease 0s; transition: all 0.2s ease 0s;
color: white; color: white;
background-color: transparent; background-color: transparent;
border-color: black; border-color: white;
box-shadow: none; box-shadow: none;
} }
@ -121,3 +133,363 @@ body {
font-size: larger; font-size: larger;
} }
/*CSS for Dashboard*/
.header {
justify-content: space-between;
text-align: center;
margin: 0%;
font-family: 'Barlow', sans-serif;
--bs-gutter-x: 0rem;
}
.header p {
cursor: pointer;
}
.edropdown {
display: inline-block;
position: relative;
--bs-gutter-x: 0rem;
}
.edropdown-content {
text-align: center;
display: none;
background-color: rgb(80, 80, 80);
position: absolute;
width: 90%;
right: 5%;
padding: 0%;
bottom: 15%;
overflow: auto;
border-radius: 1vw;
box-shadow: 5px 5px 5px rgba(0,0,0,0.4);
transition: all 0.1s ease 0s;
margin-left: 1%;
}
.viewbar {
display: block !important;
}
.edropdown-content a {
display: block;
color: white;
padding: 4%;
text-decoration: none;
transition: all 0.1s ease 0s;
}
.edropdown-content .logout {
color: red;
}
.edropdown-content .logout:hover {
color: white;
background-color: red;
}
.edropdown-content a:hover {
color: black;
background-color: white;
}
.edropdown-content p {
display: block;
color: white;
padding: 4%;
text-decoration: none;
transition: all 0.1s ease 0s;
}
.edropdown-content p:hover {
color: black;
background-color: white;
}
@media (min-width: 992px) {
.logo {
content: url("/images/minlogo.png");
transition: all 0.3s ease 0s;
}
.sidebar:hover .logo {
content: url("/images/logo.png");
transform: scale(0.85);
}
.sidebar {
width: 5%;
position: fixed;
height: 100%;
background-color: rgb(32, 32, 32);
transition: all 0.4s ease 0s;
}
.sidebar:hover {
width: 15%;
}
.d-content {
margin-left: 5%;
position: fixed;
height: 100%;
width: 100%;
padding: 3%;
padding-right: 8%;
transition: all 0.4s ease 0s;
overflow:scroll;
overflow-x:hidden;
}
.sidecontent{
margin-left: 15% !important;
padding-right: 15%;
}
.sidebar-content {
text-align: center;
height: 85%;
padding-top: 50%;
padding-bottom: 50%;
}
.sidebar:hover .sidebar-content {
height: 80%;
}
.sidebar:hover .sidebar-footer{
text-align: unset;
padding-top: 5%;
padding-left: 30%;
}
.sidebar-footer {
height: 5%;
text-align: center;
}
.sidebar-footer:hover {
background-color: white;
color: black;
cursor: pointer;
height: 10%;
}
.sidebar-image {
border-radius: 100%;
vertical-align: center;
align-items: center;
align-self: center;
}
.sidebar:hover .sidebar-image {
display: unset;
}
.sidebar-text {
display: none;
-moz-user-select: none; /* Firefox */
-webkit-user-select: none; /* Chrome, Safari, Opéra depuis la version 15 */
-ms-user-select: none; /* Internet explorer depuis la version 10 et Edge */
user-select: none; /* Propriété standard */
}
.username {
display: none;
-moz-user-select: none; /* Firefox */
-webkit-user-select: none; /* Chrome, Safari, Opéra depuis la version 15 */
-ms-user-select: none; /* Internet explorer depuis la version 10 et Edge */
user-select: none; /* Propriété standard */
}
.account {
display: flex;
justify-content: center;
vertical-align: center;
}
.sidebar:hover .username {
display: unset;
}
.sidebar:hover .sidebar-text {
display: unset;
}
.sidebar-item {
transition: all 0.2s ease 0s;
padding: 5%;
margin-top: 5%;
margin-bottom: 5%;
}
.sidebar-item:hover {
background-color: white;
color: black;
cursor: pointer;
}
}
@media (max-width: 992px) {
.sidebar {
font-size: 7vw;
width: 100%;
background-color: rgb(32, 32, 32);
transition: all 0.4s ease 0s;
}
.sidebar-content {
text-align: center;
height: 80%;
}
.sidebar-footer {
height: 5%;
text-align: unset;
padding-top: 5%;
padding-left: 30%;
}
.sidebar-footer:hover {
background-color: white;
color: black;
cursor: pointer;
height: 10%;
}
.sidebar-image {
border-radius: 100%;
}
.sidebar:hover .sidebar-image {
display: unset;
}
.sidebar-text {
display: none;
-moz-user-select: none; /* Firefox */
-webkit-user-select: none; /* Chrome, Safari, Opéra depuis la version 15 */
-ms-user-select: none; /* Internet explorer depuis la version 10 et Edge */
user-select: none; /* Propriété standard */
}
.sidebar:hover .sidebar-text {
display: unset;
}
.sidebar-item {
transition: all 0.2s ease 0s;
padding: 5%;
margin-top: 5%;
margin-bottom: 5%;
}
.sidebar-item:hover {
background-color: white;
color: black;
cursor: pointer;
}
}

111
public/templates/home.html Normal file
View File

@ -0,0 +1,111 @@
<div class="home">
<h1>Accueil</h1>
</br>
<div class="homepanel">
<div class="row w-100">
<div class="hbox col-lg">
<h1><i class="fa fa-bell"></i> Notifications</h1>
<table class="table">
<thead>
<tr>
<th scope="col">Appareil</th>
<th scope="col">Device</th>
<th scope="col">Notifications</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
<tr>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
<tr>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
<div class="hbox col-lg">
<h1>EcoleDirecte</h1>
</div>
</div>
<div class="row w-100">
<div class="hbox col-lg">
<h1>Contenu épinglé</h1>
</div>
<div class="hbox col-lg">
<h1>Contenu épinglé</h1>
</div>
</div>
</div>
</div>
<!-- Style-->
<style>
.home {
}
.hbox h1 {
font-size: large;
}
table {
color: white;
}
.hbox {
margin: 1%;
padding: 1%;
background-color: rgb(80, 80, 80);
border-radius: 1vw;
box-shadow: 5px 5px 5px rgba(80, 80, 80, 0.477) ;
}
</style>

View File

@ -0,0 +1,338 @@
<div class="home">
<h1>Paramètres du compte</h1>
</br>
<div class="homepanel">
<div class="row w-100">
<div class="hbox col">
<p class="title"><i class="fa fa-id-card"></i> Mes informations</p>
<div class="settings-content">
<p>Photo de profil :</p>
<div id="*accountpicture"></div>
<input id='user_files' accept="image/png, image/jpeg" name="apic" type="file" id="logo"/>
<p style="color: rgb(255, 76, 76);" id="user_ainfo"></p>
<p class="fullnameinfo">Nom complet <i>(max 18 caractères)</i> :</p>
<p>Actuel : <span id="*accountname"></span></p>
<input id="user_fullname" class="inp" type="text">
<div style="color: rgb(255, 76, 76);" id="user_finfo"></div>
</div>
<p class="title"><i class="fa fa-key"></i> Mot de passe :</p>
<div class="settings-content">
<p>Mot de passe actuel : </p>
<input class="inp" type="password" id="user_lastpassword">
<p>Nouveau mot de passe : </p>
<input class="inp" type="password" id="user_newpassword">
<div style="color: rgb(255, 76, 76);" id="user_pinfo"></div>
</div>
<button id="user_actBtn" class="ubutton">Sauvegarder</button>
</div>
</div>
</div>
<script>
if(typeof user_sub == 'undefined') {
const user_sub = document.getElementById("user_actBtn");
const user_oldp = document.getElementById("user_lastpassword");
const user_newp = document.getElementById("user_newpassword");
const user_fullname = document.getElementById("user_fullname");
const user_pinfo = document.getElementById("user_pinfo");
const user_finfo = document.getElementById("user_finfo");
const user_ainfo = document.getElementById("user_ainfo");
const user_files = document.getElementById("user_files")
const fID = document.getElementById("*accountname");
const aID = document.getElementById("*accountpicture");
const dID = document.getElementById("*dashaccountname")
user_sub.addEventListener("click", () => {
user_finfo.innerHTML = "";
user_pinfo.innerHTML = "";
user_ainfo.innerHTML = "";
if(user_files.files[0] != null) {
const image_acc = new FormData();
image_acc.append("apic", user_files.files[0])
fetch('/upload', {
method: 'POST',
mode:"cors",
cache:"no-cache",
credentials:"same-origin",
referrerPolicy:"no-referrer",
redirect: 'follow',
body: image_acc
})
.then(response => response.json())
.then(response => resp(response))
function resp(response) {
if(response.result == "failed") {
content.innerHTML = ' <h1 style="color:red;"><i style="color:yellow; font-size: 2vw;" class="fa fa-warning"></i> Erreur de chargement des données - Erreur : ' + response.content + '</h1>'
console.log("FAILED")
} else if(response.result == "success") {
user_files.value = ""
user_ainfo.innerHTML = response.content
fetch('/get', {
method: 'POST',
redirect: 'follow',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"request":"username", "name": ""})
})
.then(response => response.json())
.then(response => load(response))
function load(response) {
if(response.result == "failed") {
content.innerHTML = ' <h1 style="color:red;"><i style="color:yellow; font-size: 2vw;" class="fa fa-warning"></i> Erreur de chargement des données - Erreur : ' + response.content + '</h1>'
console.log("FAILED")
} else if(response.result == "success") {
const daID = document.getElementById("*dashaccountpicture")
var randomNum = new Date().getTime();
daID.innerHTML = '<img class="w-25 sidebar-image noside" src="/images/userspics/' + response.content + '.png?' + randomNum + '">'
aID.innerHTML = "<img style='border-radius: 100%;' src='/images/userspics/" + response.content + ".png?" + randomNum + "'>"
}
}
}
}
if(user_oldp.value != "" | user_newp.value != "") {
console.log("test")
if(user_oldp.value != "" && user_newp.value != "") {
if(user_oldp.value != user_newp.value) {
fetch('/set', {
method: 'POST',
redirect: 'follow',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"request":"password", "value": user_newp.value, "additional":user_oldp.value})
})
.then(response => response.json())
.then(response => load(response))
function load(response) {
if(response.result == "failed") {
content.innerHTML = ' <h1 style="color:red;"><i style="color:yellow; font-size: 2vw;" class="fa fa-warning"></i> Erreur de chargement des données - Erreur : ' + response.content + '</h1>'
console.log("FAILED")
} else if(response.result == "success") {
user_oldp.value = ""
user_newp.value = ""
user_pinfo.innerHTML = response.content
}
}
} else {
user_pinfo.innerHTML = "<p>Le nouveau et l'ancien mot de passe ne peuvent pas être le même</p>"
}
} else {
user_pinfo.innerHTML = "<p>Le nouveau et l'ancien mot de passe doivent être rempli</p>"
}
}
if(user_fullname.value.length >= 18) {
user_finfo.innerHTML = "<p>Le nom complet ne doit pas dépasser 18 caractères</p>"
} else if(user_fullname.value != "") {
fetch('/set', {
method: 'POST',
redirect: 'follow',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({"request":"fullname", "value": user_fullname.value, "additional":"empty"})
})
.then(response => response.json())
.then(response => load(response))
function load(response) {
if(response.result == "failed") {
content.innerHTML = ' <h1 style="color:red;"><i style="color:yellow; font-size: 2vw;" class="fa fa-warning"></i> Erreur de chargement des données - Erreur : ' + response.content + '</h1>'
console.log("FAILED")
} else if(response.result == "success") {
user_fullname.value = ""
dID.innerHTML = response.additional
fID.innerHTML = response.additional
document.title = "Neutral - " + response.additional
user_finfo.innerHTML = response.content
}
}
}
}
})
}
</script>
<!-- Style-->
<style>
.ubutton {
border-style:solid;
border-radius: 1vw;
border-color: white;
padding: 1%;
transition: all 0.2s ease 0s;
color: white;
background-color: transparent;
}
.ubutton:hover {
background: white;
color: black;
border-color: transparent;
box-shadow: 2px 2px 5px rgba(0, 174, 255, 0.477);
}
.ubutton:active {
border-style:solid;
border-radius: 1vw;
padding: 1%;
transition: all 0.2s ease 0s;
color: white;
background-color: transparent;
border-color: white;
box-shadow: none;
}
.hbox .title{
font-size: larger;
}
.fullnameinfo {
margin-top: 2%;
}
.settings-content {
padding: 1%;
}
.settings-content input {
margin-bottom: 1%;
}
.settings-content .inp {
border-style: hidden;
border-radius: 1vw;
padding-left: 1vw;
transition: all 0.2s ease 0s;
}
.settings-content .inp:hover {
box-shadow: 2px 2px 5px rgba(255, 255, 255, 0.477) ;
}
.settings-content .inp:focus {
box-shadow: 5px 5px 5px rgba(0, 174, 255, 0.477) ;
}
.hbox {
margin: 1%;
padding: 1%;
background-color: rgb(80, 80, 80);
border-radius: 1vw;
box-shadow: 5px 5px 5px rgba(80, 80, 80, 0.477) ;
}
</style>

View File

@ -0,0 +1,56 @@
<div class="home">
<h1>Gestion des utilisateurs</h1>
</br>
<div class="homepanel">
<div class="row w-100">
<div class="hbox col">
<h1><i class="fa fa-users"></i> Utilisateurs</h1>
</div>
</div>
</div>
</div>
<!-- Style-->
<style>
.home {
}
.hbox h1 {
font-size: large;
}
table {
color: white;
}
.hbox {
margin: 1%;
padding: 1%;
background-color: rgb(80, 80, 80);
border-radius: 1vw;
box-shadow: 5px 5px 5px rgba(80, 80, 80, 0.477) ;
}
</style>

95
routes/get.js Normal file
View File

@ -0,0 +1,95 @@
var express = require('express');
var router = express.Router();
var ntr = require("../neutral-functions.js");
var fs = require("fs")
var path = require("path")
/* GET home page. */
router.get('/', function(req, res, next) {
var check = ntr.checkToken(req, res)
if(check == false) {
res.redirect(302, "/login")
} else {
res.redirect(302, "/")
}
});
router.post("/", function(req, res, next) {
var check = ntr.checkToken(req, res)
if(check == false) {
res.send({"result":"failed", "content":"ERROR_TOKEN_NOT_VALID"})
} else {
if(req.body.request == null | req.body.name == null) {
if(req.body.request == null) {
res.send({"result":"failed", "content":"ERROR_REQUEST_MISSING_FIELDS", "additional": "REQUEST_MISSING"})
} else {
res.send({"result":"failed", "content":"ERROR_REQUEST_MISSING_FIELDS", "additional": "NAME_MISSING"})
}
} else {
console.log("[Get] - GET[" + req.body.request + '-' + req.body.name + "]")
if(req.body.request == "page") {
try {
const file = fs.readFileSync(__dirname.replace("routes", "public" + path.sep + "templates" + path.sep) + path.sep + req.body.name, 'utf-8') ;
res.send({"result":"success", "content":file})
} catch(error) {
res.send({"result":"failed", "content":"ERROR_FILE_NOT_EXIST"})
}
} else if(req.body.request == "accountpic") {
try {
const file = fs.readFileSync(__dirname.replace("routes", "images" + path.sep + "userspics" + path.sep) + path.sep + req.body.name + ".png", 'utf-8') ;
res.send({"result":"success", "content":file})
} catch(error) {
res.send({"result":"failed", "content":"ERROR_FILE_NOT_EXIST"})
}
} else if(req.body.request == "username") {
res.send({"result":"success", "content": ntr.checkToken(req, res)})
} else if(req.body.request == "fullname") {
res.send({"result":"success", "content": ntr.getFullName(ntr.checkToken(req, res))})
} else {
res.send({"result":"failed", "content":"ERROR_REQUEST_NOT_VALID"})
}
}
}
})
module.exports = router;

View File

@ -15,7 +15,7 @@ router.get('/', function(req, res, next) {
} else { } else {
res.render('index', { title: check }); res.render('index', { title: ntr.getFullName(check), username: ntr.getFullName(check), accountpic: '<img width="200" class="w-25 sidebar-image noside" src="images/userspics/' + check + '.png">' });
} }

View File

@ -21,9 +21,6 @@ router.get('/', function(req, res, next) {
res.render('login', {error: ""}); res.render('login', {error: ""});
} }
}); });
@ -51,12 +48,13 @@ router.post("/", function(req, res, next) {
const tokenID = ntr.generateTokenID(bod.username, userData, req, users) const tokenID = ntr.generateTokenID(bod.username, userData, req, users)
res.cookie('tokenID' , tokenID) res.cookie('tokenID' , tokenID, { maxAge: 900000000, httpOnly: true })
res.status(202).send({"token":"auth_success"}) res.status(202).send({"token":"auth_success"})
} else { } else {
userpassword = null; userpassword = null;
res.status(202).send({"token":"auth_failed"}) res.status(202).send({"token":"auth_failed"})
} }

88
routes/set.js Normal file
View File

@ -0,0 +1,88 @@
var express = require('express');
var router = express.Router();
var path = require("path")
var fs = require("fs")
var CryptoJS = require("crypto-js");
var uuid = require("uuid")
var ntr = require("../neutral-functions.js")
/* GET home page. */
router.get('/', function(req, res, next) {
var check = ntr.checkToken(req, res)
if(check != false) {
res.redirect(302, "/")
} else {
res.render('login', {error: ""});
}
});
router.post("/", function(req, res, next) {
var check = ntr.checkToken(req, res)
if(check == false) {
res.send({"result":"failed", "content":"ERROR_TOKEN_NOT_VALID"})
} else {
if(req.body.request == null | req.body.value == null | req.body.additional == null) {
if(req.body.request == null) {
res.send({"result":"failed", "content":"ERROR_REQUEST_MISSING_FIELDS", "additional": "REQUEST_MISSING"})
} else if(req.body.value == null){
res.send({"result":"failed", "content":"ERROR_REQUEST_MISSING_FIELDS", "additional": "VALUE_MISSING"})
} else {
res.send({"result":"failed", "content":"ERROR_REQUEST_MISSING_FIELDS", "additional": "ADDITIONAL_MISSING"})
}
} else {
console.log("[Set] - SET[" + req.body.request + '-' + req.body.value + "-" + req.body.additional+ "]")
if(req.body.request == "password") {
ntr.changePassword(req, res);
} else if(req.body.request == "fullname") {
ntr.changeFullName(req.body.value, req, res);
res.send({"result":"success", "content": "<span style='color:rgb(130, 255, 163);'>Le nom complet a été changé avec succès.</span>", "additional": req.body.value})
} else {
res.send({"result":"failed", "content":"ERROR_REQUEST_NOT_VALID"})
}
}
}
})
module.exports = router;

View File

@ -1,7 +1,12 @@
var express = require('express'); var express = require('express');
var router = express.Router(); var router = express.Router();
var path = require("path")
var fs = require("fs")
var CryptoJS = require("crypto-js");
var uuid = require("uuid")
var ntr = require("../neutral-functions.js") var ntr = require("../neutral-functions.js")
/* GET home page. */ /* GET home page. */
router.get('/', function(req, res, next) { router.get('/', function(req, res, next) {
@ -15,7 +20,8 @@ router.get('/', function(req, res, next) {
} else { } else {
res.clearCookie('tokenID') res.clearCookie('tokenID')
res.send({"success":true}) res.redirect(302, "/login")
} }

139
routes/upload.js Normal file
View File

@ -0,0 +1,139 @@
var express = require('express');
var router = express.Router();
var path = require("path")
var fs = require("fs")
var CryptoJS = require("crypto-js");
var uuid = require("uuid")
var ntr = require("../neutral-functions.js");
const Jimp = require("jimp");
/* GET home page. */
router.get('/', function(req, res, next) {
var check = ntr.checkToken(req, res)
if(check != false) {
res.redirect(302, "/")
} else {
res.render('login', {error: ""});
}
});
router.post("/", function(req, res, next) {
var check = ntr.checkToken(req, res)
if(check == false) {
res.send({"result":"failed", "content":"ERROR_TOKEN_NOT_VALID"})
} else {
const image = req.files.apic
if(req.files.apic.mimetype == "image/png" | req.files.apic.mimetype == "image/jpeg" ) {
var uploadPath = "";
var uploadDir = __dirname.replace("routes","public" + path.sep + "images" + path.sep + "userspics" + path.sep)
if(req.files.apic.mimetype == "image/png") {
uploadPath = ntr.checkToken(req, res) + ".png"
}
if(req.files.apic.mimetype == "image/jpeg") {
uploadPath = ntr.checkToken(req, res) + ".jpg"
}
image.mv(uploadPath, function(err) {
if(err) {
res.send({"result":"success", "content": "La photo de profil n'a pas pu être chargé."})
console.log(err)
} else {
if(fs.existsSync(uploadDir + ntr.checkToken(req, res) + ".png") | fs.existsSync(uploadDir + ntr.checkToken(req, res) + ".jpg")) {
if(fs.existsSync(uploadDir + ntr.checkToken(req, res) + ".png")) {
fs.rmSync(uploadDir + ntr.checkToken(req, res) + ".png")
}
fs.renameSync(__dirname.replace("routes", "") + uploadPath , uploadDir + uploadPath)
if(req.files.apic.mimetype == "image/jpeg") {
Jimp.read(uploadDir + uploadPath, function (err, image) {
image.resize(200,200, function(err){
if (err) throw err;
}).write(uploadDir + uploadPath.replace("jpg", "png"))
fs.rmSync(uploadDir + ntr.checkToken(req, res) + ".jpg")
res.send({"result":"success", "content": "<span style='color:rgb(130, 255, 163);'>La photo de profil a été changé avec succès.</span>",})
})
} else if(req.files.apic.mimetype == "image/png") {
Jimp.read(uploadDir + uploadPath, function (err, image) {
image.resize(200,200, function(err){
if (err) throw err;
}).write(uploadDir + uploadPath)
res.send({"result":"success", "content": "<span style='color:rgb(130, 255, 163);'>La photo de profil a été changé avec succès.</span>",})
})
} else {
res.send({"result":"success", "content": "<span style='color:rgb(130, 255, 163);'>La photo de profil a été changé avec succès.</span>",})
}
} else {
console.log(uploadDir + uploadPath)
res.send({"result":"success", "content": "La photo de profil n'a pas pu être chargé."})
console.log("ERROR - UPLOAD NOT WORK CORRECYLT")
}
}
})
} else {
res.send({"result":"success", "content": "Seul les images (JPEG et PNG) sont acceptés."})
}
}
})
module.exports = router;

View File

@ -0,0 +1,11 @@
{
"username": "root",
"password": "U2FsdGVkX183RDwFR0hVxkFizv9rTwppNiaWkUVowis=",
"uuid": "24a17fe1-32c3-4269-b83b-88b6bcd66cef",
"fullname": "Admin",
"token": {
"tokenID": "5aefa3fc-1e35-4195-89ab-b1603e867a51",
"livableToken": true,
"createdAt": 1676914169253
}
}

View File

@ -1,10 +1,11 @@
{ {
"username": "raphix", "username": "raphix",
"password": "U2FsdGVkX18qYuDgnMfjve6jokb1mqH1f7wuktw9YO8=", "password": "U2FsdGVkX195kOSeYbWRWFD3ys/5ubkaNSm9XacK0OE=",
"uuid": "9ace80e0-1ee3-4eed-924f-8a55fc55822b", "uuid": "9ace80e0-1ee3-4eed-924f-8a55fc55822b",
"fullname": "Raphael PICOT",
"token": { "token": {
"tokenID": "23e2178e-3ad0-400b-ae42-c8efa35de27c", "tokenID": "1679485c-2139-4939-a429-56480bba0336",
"livableToken": false, "livableToken": true,
"createdAt": 1676754468956 "createdAt": 1676925451610
} }
} }

View File

@ -1,3 +1,49 @@
<h1><%= message %></h1> <!DOCTYPE html>
<h2><%= error.status %></h2> <html>
<head>
<title>Neutral</title>
<script src="neutron.bundle.js"></script>
<link rel='stylesheet' href='/stylesheets/style.css'/>
<style>
body {
padding: 2%;
}
div {
background-color: rgb(32, 32, 32);
border-radius: 1vw;
padding: 2%;
}
button {
color: red;
background-color: transparent;
border-radius: 1vw;
border-color: red;
border-style: solid;
padding: 10px;
transition: all 0.2s ease 0s;
}
button:hover {
color: white;
background-color: red;
}
</style>
</head>
<body>
<div>
<h1>Erreur</h1>
<h2><%= message %> - <%= error.status %></h1>
<pre><%= error.stack %></pre> <pre><%= error.stack %></pre>
</div>
<br>
<a href="/"><button>Retourner sur le panel</button></a>
</body>
</html>

View File

@ -1,13 +1,67 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title><%= title %></title> <title>Neutral - <%= title %></title>
<script src="neutron.bundle.js"></script>
<link rel='stylesheet' href='/stylesheets/style.css' /> <link rel='stylesheet' href='/stylesheets/style.css' />
</head> </head>
<body> <body>
<h1><%= title %></h1> <div id="sidebar" class="sidebar">
<p>Welcome to <%= title %></p> <img class=" logo img-fluid" src="images/logo.png"></img>
<button id="logout">Deconnexion</button> <div class="sidebar-content align-items-center">
<div class="middle">
<div class="sidebar-item" id="s-home">
<i class="fa-solid fa-home"></i>
<p class="sidebar-text">Accueil</p>
</div>
<div class="sidebar-item" id="s-files">
<i class="fa fa-folder"></i>
<p class="sidebar-text">Gestionnaire de fichiers</p>
</div>
<div class="sidebar-item " id="s-users">
<i class="fa fa-users"></i>
<p class="sidebar-text">Gestionnaire des utilisateurs</p>
</div>
<div class="sidebar-item " id="s-moni">
<i class="fa fa-computer"></i>
<p class="sidebar-text">Monitoring</p>
</div>
<div class="sidebar-item" id="s-device">
<i class="fa-solid fa-server"></i>
<p class="sidebar-text">Appareils et serveurs</p>
</div>
<div class="sidebar-item" id="s-cv">
<i class="fa-solid fa-file-lines"></i>
<p class="sidebar-text">Mon CV</p>
</div>
<div class="sidebar-item" id="s-link">
<i class="fa-solid fa-link"></i>
<p class="sidebar-text">Générateur de lien</p>
</div>
</div>
</div>
<div id="account" class="noside sidebar-footer">
<span class="noside" id="*dashaccountpicture"><%- accountpic %></span>
<p class="noside username"><span class="noside" id="*dashaccountname"><%- username %></span></p>
<div id="accmenu" class="noside edropdown-content">
<a href="https://gitlab.com"><i class="fa-brands fa-gitlab"></i> Gitlab</a>
<p id="settingsBtn"><i class="fa fa-gear"></i> Paramètres</p>
<a class="logout" href="/signout"><i class="fa-solid fa-arrow-right-from-bracket"></i> Déconnexion</a>
</div>
</div>
</div>
<div id="content" class="d-content">
</div>
</div>
<script src="/javascripts/dashboard.js"></script> <script src="/javascripts/dashboard.js"></script>
</body> </body>
</html> </html>

View File

@ -33,5 +33,6 @@
</div> </div>
<script src="/javascripts/loginscript.js"></script> <script src="/javascripts/loginscript.js"></script>
</body> </body>
</html> </html>