Version 1.1.0 - Refactor + Intergration Backend

This commit is contained in:
2025-07-25 17:56:30 +02:00
parent a59d7a66db
commit 98cdae97c0
58 changed files with 244 additions and 70 deletions

View File

@@ -0,0 +1,146 @@
const { LogType } = require('loguix');
const dlog = new LogType("DiscordAuth");
const { getWebsiteLink, getClientSecret } = require('../../utils/Database/Configuration');
async function getDiscordUser(sessionId, auth_code) {
return new Promise((resolve, reject) => {
const discordBot = require("../../discord/Bot")
const discordBotClient = discordBot.getClient()
dlog.step.init("discord_auth_" + sessionId, "Authentification Discord de la session :" + sessionId);
dlog.log("Récupération de l'autorisation de récupération des informations de l'utilisateur Discord associé à la session : " + sessionId);
const params = new URLSearchParams();
params.append("client_id", discordBotClient.user.id);
params.append("client_secret", getClientSecret());
params.append("grant_type", "authorization_code");
params.append("code", auth_code);
params.append("redirect_uri", getWebsiteLink() + "/redirect");
params.append("scope", "identify guilds");
fetch("https://discord.com/api/oauth2/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: params,
}).then(accessTokenResp => accessTokenResp.json()).then(accessToken => {
if (accessToken.error) {
dlog.step.error("discord_auth_" + sessionId, "Erreur lors de la récupération du token d'accès Discord associé à la session : " + sessionId + " : " + accessToken.error + " : " + accessToken.error_description);
resolve("ACCESS_TOKEN_ERROR");
return;
}
dlog.log("Récupération réussi du token d'accès Discord associé à la session : " + sessionId);
fetch("https://discord.com/api/users/@me", {
headers: {
authorization: `${accessToken.token_type} ${accessToken.access_token}`,
},
}).then(userResp => userResp.json()).then(user => {
dlog.log("Récupération réussi des informations de l'utilisateur Discord associé à la session : " + sessionId + " avec le nom d'utilisateur : " + user.username + " (" + user.id + ")");
// Get the guilds of the user
fetch("https://discord.com/api/users/@me/guilds", {
headers: {
authorization: `${accessToken.token_type} ${accessToken.access_token}`,
},
}).then(guildsResp => guildsResp.json()).then(guilds => {
dlog.log("Récupération réussi des guildes de l'utilisateur Discord associé à la session : " + sessionId + " avec le nom d'utilisateur : " + user.username + " (" + user.id + ")");
dlog.step.end("discord_auth_" + sessionId)
const userData = {
auth: accessToken,
identity: user,
guilds: guilds,
}
resolve(userData);
}).catch(err => {
dlog.step.error("discord_auth_" + sessionId, "Erreur lors de la récupération des guildes de l'utilisateur Discord" + " avec le nom d'utilisateur : " + user.username + " (" + user.id + ")" + " associé à la session : " + sessionId + " : " + err);
resolve("GUILDS_ERROR");
});
}).catch(err => {
dlog.step.error("discord_auth_" + sessionId, "Erreur lors de la récupération des informations de l'utilisateur Discord associé à la session : " + sessionId + " : " + err);
resolve( "USER_INFO_ERROR");
})
}).catch(err => {
dlog.step.error("discord_auth_" + sessionId, "Erreur lors de la récupération du token d'accès Discord associé à la session : " + sessionId + " : " + err);
resolve("ACCESS_TOKEN_ERROR");
})
})
}
function refreshToken(refresh_token) {
return new Promise((resolve, reject) => {
const discordBot = require("../../discord/Bot")
const params = new URLSearchParams();
params.append("client_id", discordBot.getClient().user.id);
params.append("client_secret", getClientSecret());
params.append("grant_type", "refresh_token");
params.append("refresh_token", refresh_token);
params.append("scope", "identify guilds");
fetch("https://discord.com/api/oauth2/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: params,
}).then(accessTokenResp => accessTokenResp.json()).then(accessToken => {
if (accessToken.error) {
dlog.error("Erreur lors de la récupération du token d'accès Discord : " + accessToken.error + " : " + accessToken.error_description);
resolve(null);
return;
}
resolve(accessToken);
}).catch(err => {
dlog.error("Erreur lors de la récupération du token d'accès Discord : " + err);
resolve(null);
})
})
}
function getUserGuilds(accessToken) {
return new Promise((resolve, reject) => {
fetch("https://discord.com/api/users/@me/guilds", {
headers: {
authorization: `${accessToken.token_type} ${accessToken.access_token}`,
},
}).then(guildsResp => guildsResp.json()).then(guilds => {
if (guilds.error) {
dlog.error("Erreur lors de la récupération des guildes de l'utilisateur Discord : " + guilds.error + " : " + guilds.error_description);
dlog.log(accessToken.token_type + " " + accessToken.access_token )
resolve(null);
return;
}
resolve(guilds);
}).catch(err => {
dlog.error( "Erreur lors de la récupération des guildes de l'utilisateur Discord : " + err);
resolve(null);
})
})
}
function getUserIdentity(accessToken) {
return new Promise((resolve, reject) => {
fetch("https://discord.com/api/users/@me", {
headers: {
authorization: `${accessToken.token_type} ${accessToken.access_token}`,
},
}).then(userResp => userResp.json()).then(user => {
if (user.error) {
dlog.error("Erreur lors de la récupération des informations de l'utilisateur Discord : " + user.error + " : " + user.error_description);
resolve(null);
return;
}
resolve(user);
}).catch(err => {
dlog.error("Erreur lors de la récupération des informations de l'utilisateur Discord : " + err);
resolve(null);
})
})
}
module.exports = {getDiscordUser, refreshToken, getUserGuilds, getUserIdentity}

View File

@@ -0,0 +1,33 @@
const { LogType } = require('loguix');
const { generateSessionId } = require('../../utils/TokenManager');
const clog = new LogType("Session");
const sessions = new Array();
function checkSession(sessionId) {
return sessions.includes(sessionId);
}
function addSession() {
const sessionId = generateSessionId();
if (checkSession(sessionId)) {
clog.warn(`Session ${sessionId} non trouvée dans la liste des sessions.`);
return addSession(); // Recursively generate a new session ID if it already exists
}
sessions.push(sessionId);
clog.log(`Nouvelle session ${sessionId} ajoutée.`);
return sessionId;
}
function removeSession(sessionId) {
const index = sessions.indexOf(sessionId);
if (index > -1) {
sessions.splice(index, 1);
clog.log(`Suppression de la session ${sessionId}.`);
} else {
clog.warn(`Session ${sessionId} non trouvée dans la liste des sessions.`);
}
}
module.exports = {checkSession, addSession, removeSession};

570
src/server/auth/User.js Normal file
View File

@@ -0,0 +1,570 @@
const { Database } = require('../../utils/Database/Database');
const { __glob } = require('../../utils/GlobalVars');
const { generateToken } = require('../../utils/TokenManager');
const { LogType } = require('loguix');
const clog = new LogType("User");
const discordAuth = require('./DiscordAuth');
const e = require('cors');
const UserDB = new Database("Users", __glob.USERFILE, []);
var userList = new Array();
class User {
auth;
identity;
tokens;
labels;
guilds;
constructor(auth, identity, tokens, labels, guilds) {
this.auth = auth;
this.identity = identity;
this.tokens = tokens;
this.labels = labels;
this.guilds = guilds;
}
setAdmin() {
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return null;
}
if (userInUserList.labels.includes("ADMIN")) {
userInUserList.labels.splice(userInUserList.labels.indexOf("ADMIN"), 1);
clog.log(`L'utilisateur ${this.identity.username} n'est plus admin.`);
} else {
userInUserList.labels.push("ADMIN");
clog.log(`L'utilisateur ${this.identity.username} est maintenant admin.`);
}
saveUsers()
}
setBan(guildId) {
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return null;
}
const banLabel = `BAN_${guildId}`;
if (userInUserList.labels.includes(banLabel)) {
userInUserList.labels.splice(userInUserList.labels.indexOf(banLabel), 1);
clog.log(`L'utilisateur ${this.identity.username} n'est plus banni du serveur ${guildId}.`);
} else {
userInUserList.labels.push(banLabel);
clog.log(`L'utilisateur ${this.identity.username} est maintenant banni du serveur ${guildId}.`);
}
saveUsers()
}
createToken() {
const token = generateToken(this.identity.id);
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return null;
}
userInUserList.tokens.push(token);
saveUsers();
clog.log(`Token créé pour l'utilisateur ${this.identity.username}.`);
return token;
}
removeToken(token) {
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return null;
}
const index = userInUserList.tokens.indexOf(token);
if (index > -1) {
userInUserList.tokens.splice(index, 1);
saveUsers();
clog.log(`Token supprimé pour l'utilisateur ${this.identity.username}.`);
} else {
clog.warn(`Token non trouvé pour l'utilisateur ${this.identity.username}.`);
}
}
clearToken() {
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return null;
}
userInUserList.tokens = [];
saveUsers();
clog.log(`Tous les tokens supprimés pour l'utilisateur ${this.identity.username}.`);
return userInUserList.tokens;
}
clearAuth() {
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return null;
}
userInUserList.auth = null;
saveUsers();
clog.log(`Authentification supprimée pour l'utilisateur ${this.identity.username}.`);
}
destroyAuth() {
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return null;
}
userInUserList.auth = null;
userInUserList.tokens = [];
saveUsers();
clog.log(`Authentification et tokens supprimés pour l'utilisateur ${this.identity.username}.`);
}
setFullBan() {
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return null;
}
if (userInUserList.labels.find(label => label == "BAN")) {
userInUserList.labels.splice(userInUserList.labels.indexOf("BAN"), 1);
clog.log(`L'utilisateur ${this.identity.username} n'est plus banni.`);
} else {
userInUserList.labels.push("BAN");
clog.log(`L'utilisateur ${this.identity.username} est maintenant banni.`);
}
saveUsers()
}
isBanned(guildId) {
const banLabel = `BAN_${guildId}`;
return this.labels.includes(banLabel);
}
isFullBanned() {
return this.labels.includes("BAN");
}
isAdmin() {
return this.labels.includes("ADMIN");
}
isMod(guildId) {
if(this.isOwner(guildId)) return true;
const modLabel = `MOD_${guildId}`;
return this.labels.includes(modLabel);
}
isOwner(guildId) {
const ownerLabel = `OWNER_${guildId}`;
if(this.isAdmin()) return true;
return this.labels.includes(ownerLabel);
}
justUpdated() {
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return false;
}
userInUserList.labels = userInUserList.labels.filter(label => !label.startsWith("UPDATED["));
userInUserList.labels.push("UPDATED[" + new Date().toISOString() + "]");
saveUsers();
}
needUpdate() {
const userInUserList = userList.find(user => user.identity.id === this.identity.id);
if (!userInUserList) {
clog.warn(`Utilisateur ${this.identity.username} non trouvé dans la liste des utilisateurs.`);
return false;
}
const lastUpdate = userInUserList.labels.find(label => label.startsWith("UPDATED["));
if (lastUpdate) {
const date = new Date(lastUpdate.replace("UPDATED[", "").replace("]", ""));
const now = new Date();
const diff = now - date;
// Check for 30 seconds
clog.log(`Dernière mise à jour de l'utilisateur ${this.identity.username} : ${date.toISOString()} (${diff} ms) - Besoin de mise à jour : ${diff > 30000}`);
// If the difference is greater than 30 seconds, we need to update
return diff > 30000; // 30 seconds
}
clog.log(`Aucune mise à jour n'a été effectuée pour l'utilisateur ${this.identity.username}.`);
return true;
}
}
//REFRESH USER
async function refreshAllUserInformation() {
await loadUsers();
clog.log("Récupération des informations de tous les utilisateurs...");
for (const user of userList) {
await updateCredientials(user.identity.id);
}
saveUsers();
}
async function updateCredientials(id) {
const user = getUserById(id);
if (!user) {
clog.warn(`Utilisateur ${id} non trouvé.`);
return null;
}
clog.log(`Mise à jour des informations d'authentification Discord de l'utilisateur ${user.identity.username} (${user.identity.id})...`);
if (user.auth) {
// Check if the token is expired
const auth = await discordAuth.refreshToken(user.auth.refresh_token);
if (auth) {
// Check Rate limit by checking if auth.message exists
if(typeof auth.message !== "undefined") {
clog.warn(`Erreur lors de la mise à jour des informations d'authentification de l'utilisateur ${user.identity.username} (${user.identity.id}) : ${auth.message}`);
return null;
}
user.auth = auth;
clog.log(`Mise à jour réussie des informations d'authentification de l'utilisateur ${user.identity.username} (${user.identity.id})`);
} else {
clog.warn(`Erreur lors de la mise à jour des informations d'authentification de l'utilisateur ${user.identity.username} (${user.identity.id})`);
}
// Update the user in the list
const userInUserList = userList.find(u => u.identity.id === user.identity.id);
if (userInUserList) {
userInUserList.auth = user.auth;
}
}
else {
clog.warn(`Aucune authentification trouvée pour l'utilisateur ${user.identity.username} (${user.identity.id})`);
}
saveUsers();
return user.auth;
}
async function updateGuilds(id) {
const user = getUserById(id);
if (!user) {
clog.warn(`Utilisateur ${id} non trouvé.`);
return null;
}
clog.log(`Mise à jour des guildes de l'utilisateur ${user.identity.username} (${user.identity.id})...`);
if (user.auth) {
const guilds = await discordAuth.getUserGuilds(user.auth);
if(guilds) {
if(typeof guilds.message !== "undefined") {
clog.warn(`Erreur lors de la mise à jour des guildes de l'utilisateur ${user.identity.username} (${user.identity.id}) : ${guilds.message}`);
return null;
}
user.guilds = guilds;
clog.log(`Mise à jour réussie des guildes de l'utilisateur ${user.identity.username} (${user.identity.id})`);
}
else {
clog.warn(`Erreur lors de la mise à jour des guildes de l'utilisateur ${user.identity.username} (${user.identity.id})`);
return null;
}
// Update the user in the list
const userInUserList = userList.find(u => u.identity.id === user.identity.id);
if (userInUserList) {
userInUserList.auth = user.auth;
userInUserList.guilds = user.guilds;
}
} else {
clog.warn(`Aucune authentification trouvée pour l'utilisateur ${user.identity.username} (${user.identity.id})`);
return null;
}
saveUsers();
return user.guilds;
}
async function updateIdentity(id) {
const user = getUserById(id);
if (!user) {
clog.warn(`Utilisateur ${id} non trouvé.`);
return null;
}
clog.log(`Mise à jour de l'identité de l'utilisateur ${user.identity.username} (${user.identity.id})...`);
if (user.auth) {
const identity = await discordAuth.getUserIdentity(user.auth);
if(identity) {
// Check Rate limit by checking if identity.message exists
if(typeof identity.message !== "undefined") {
clog.warn(`Erreur lors de la mise à jour de l'identité de l'utilisateur ${user.identity.username} (${user.identity.id}) : ${identity.message}`);
return null;
}
user.identity = identity;
clog.log(`Mise à jour réussie de l'identité de l'utilisateur ${user.identity.username} (${user.identity.id})`);
}
else {
clog.warn(`Erreur lors de la mise à jour de l'identité de l'utilisateur ${user.identity.username} (${user.identity.id})`);
return null
}
// Update the user in the list
const userInUserList = userList.find(u => u.identity.id === user.identity.id);
if (userInUserList) {
userInUserList.auth = user.auth;
userInUserList.identity = user.identity;
}
} else {
clog.warn(`Aucune authentification trouvée pour l'utilisateur ${user.identity.username} (${user.identity.id})`);
return null;
}
saveUsers();
return user.identity;
}
// EDIT USER
/**
*
* @param {*} auth
* @param {*} identity
* @param {*} guilds
* @returns {User} user
*/
async function addUser(auth, identity, guilds) {
// Check if the user already exists
const existingUser = userList.find(user => user.identity.id === identity.id);
if (existingUser) {
clog.warn(`L'utilisateur ${identity.username} existe déjà.`);
// Update the existing user with new information
existingUser.auth = auth;
existingUser.identity = identity;
existingUser.guilds = guilds;
existingUser.tokens = existingUser.tokens || []; // Ensure tokens array exists
existingUser.labels = existingUser.labels || []; // Ensure labels array exists
saveUsers();
clog.log(`Utilisateur ${identity.username} mis à jour.`);
return existingUser;
}
const newUser = new User(auth, identity, [], [], guilds);
userList.push(newUser);
await saveUsers();
return newUser;
}
function removeUser(id) {
const index = userList.findIndex(user => user.identity.id === id);
if (index > -1) {
userList.splice(index, 1);
saveUsers();
clog.log(`Utilisateur ${id} supprimé.`);
} else {
clog.warn(`Utilisateur ${id} non trouvé.`);
}
}
function removeToken(token) {
const user = getUserByToken(token);
if (user) {
const index = user.tokens.indexOf(token);
if (index > -1) {
user.tokens.splice(index, 1);
saveUsers();
clog.log(`Token ${token} supprimé pour l'utilisateur ${user.identity.username}.`);
} else {
clog.warn(`Token ${token} non trouvé pour l'utilisateur ${user.identity.username}.`);
}
} else {
clog.warn(`Utilisateur avec le token "${token}" non trouvé.`);
}
return user;
}
function addToken(id) {
const user = getUserById(id);
if (user) {
const token = generateToken();
user.tokens.push(token);
saveUsers();
clog.log(`Token "${token}" ajouté pour l'utilisateur ${user.identity.username}.`);
return token;
} else {
clog.warn(`Utilisateur ${id} non trouvé.`);
return null;
}
}
// GET
/**
* @param {string} id
* @returns {User} user
*/
function getUserById(id) {
return userList.find(user => user.identity.id === id) || null;
}
/**
*
* @param {string} token
* @returns {User} user
*/
function getUserByToken(token) {
return userList.find(user => user.tokens.includes(token)) || null;
}
function getUsers() {
return userList;
}
function getSimpleUsers() {
return userList.map(user => {
return {
identity: user.identity,
labels: user.labels,
guilds: user.guilds
};
});
}
function getSimpleUser(id) {
const user = getUserById(id);
if(user) {
return {
identity: user.identity,
labels: user.labels,
guilds: user.guilds
};
} else {
return null;
}
}
// SET LABELS
function setAdmin(id) {
const user = getUserById(id);
if (user) {
user.setAdmin();
saveUsers();
} else {
clog.warn(`Utilisateur ${id} non trouvé.`);
}
}
function setGuildMod(id, guildId) {
const user = getUserById(id);
if (user) {
const modLabel = `MOD_${guildId}`;
if (user.labels.includes(modLabel)) {
user.labels.splice(user.labels.indexOf(modLabel), 1);
clog.log(`L'utilisateur ${user.identity.username} n'est plus modérateur du serveur ${guildId}.`);
} else {
user.labels.push(modLabel);
clog.log(`L'utilisateur ${user.identity.username} est maintenant modérateur du serveur ${guildId}.`);
}
saveUsers();
} else {
clog.warn(`Utilisateur ${id} non trouvé.`);
}
}
function setGuildBan(id, guildId) {
const user = getUserById(id);
if (user) {
if(user.isAdmin()) {
clog.warn(`L'utilisateur ${user.identity.username} est admin, il ne peut pas être banni.`);
return;
}
user.setBan(guildId);
saveUsers();
} else {
clog.warn(`Utilisateur ${id} non trouvé.`);
}
}
function setFullBan(id) {
const user = getUserById(id);
if (user) {
if(user.isAdmin()) {
clog.warn(`L'utilisateur ${user.identity.username} est admin, il ne peut pas être banni.`);
return;
}
user.setFullBan();
saveUsers();
} else {
clog.warn(`Utilisateur ${id} non trouvé.`);
}
}
function setGuildOwner(id, guildId, force) {
const user = getUserById(id);
if (user) {
const ownerLabel = `OWNER_${guildId}`;
if (user.labels.includes(ownerLabel) && !force) {
user.labels.splice(user.labels.indexOf(ownerLabel), 1);
clog.log(`L'utilisateur ${user.identity.username} n'est plus propriétaire du serveur ${guildId}.`);
} else {
if(force && user.labels.includes(ownerLabel)) {
return;
}
user.labels.push(ownerLabel);
clog.log(`L'utilisateur ${user.identity.username} est maintenant propriétaire du serveur ${guildId}.`);
}
saveUsers();
} else {
clog.warn(`Utilisateur ${id} non trouvé.`);
}
}
// USERS DB
function loadUsers() {
UserDB.load()
userList = new Array();
for (const user of UserDB.getData()) {
userList.push(new User(user.auth, user.identity, user.tokens, user.labels, user.guilds));
}
clog.log(`Chargement de ${userList.length} utilisateurs.`);
return userList;
}
function saveUsers() {
UserDB.data = userList.map(user => {
return {
auth: user.auth,
identity: user.identity,
tokens: user.tokens,
labels: user.labels,
guilds: user.guilds
};
});
UserDB.save()
clog.log(`Sauvegarde de ${userList.length} utilisateurs.`);
return loadUsers();
}
function clearNeedUpdateForUsers() {
userList.forEach(user => {
user.labels = user.labels.filter(label => !label.startsWith("UPDATED["));
});
saveUsers();
clog.log("Nettoyage des mises à jour nécessaires pour tous les utilisateurs.");
}
module.exports = {User}
module.exports = {
addUser,
setGuildOwner,
setFullBan,
removeUser,
getUserByToken,
getUserById,
getUsers,
setAdmin,
setGuildMod,
setGuildBan,
addToken,
removeToken,
getSimpleUsers,
getSimpleUser,
updateCredientials,
refreshAllUserInformation,
updateGuilds,
updateIdentity,
clearNeedUpdateForUsers
};