Note: We appreciate your feedback and bug reports to continue improving our platform. Thank you for your continued support!
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,3 +6,5 @@
|
||||
/file_info.json
|
||||
/node_modules/
|
||||
/data/
|
||||
/.idea/
|
||||
.vscode/
|
||||
@@ -1,34 +1,48 @@
|
||||
const fs = require('fs');
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
const { logger, logRequestInfo, ErrorLogger, authLogger } = require('../config/logs');
|
||||
const debug = require('debug')('app:authMiddleware');
|
||||
|
||||
const authMiddleware = async (req, res, next) => {
|
||||
if (req.isAuthenticated() || (req.session && req.session.user && req.session.user.name)) {
|
||||
const data = await fs.promises.readFile(path.join(__dirname, '../data', 'user.json'), 'utf8');
|
||||
|
||||
try {
|
||||
if (req.isAuthenticated()) {
|
||||
|
||||
const data = await fs.readFile(path.join(__dirname, '../data', 'user.json'), 'utf8');
|
||||
const users = JSON.parse(data);
|
||||
const user = users.find(user => user.name === (req.session.user && req.session.user.name));
|
||||
|
||||
const sessionUser = req.user;
|
||||
|
||||
|
||||
if (!user) {
|
||||
authLogger.info('User is not authenticated and user name is not set');
|
||||
if (!sessionUser) {
|
||||
authLogger.info('Session user is undefined');
|
||||
return res.redirect('/auth/login');
|
||||
}
|
||||
|
||||
if (!req.session.user) {
|
||||
authLogger.info('User connection attempt in progress, verification in progress...');
|
||||
authLogger.info(`Login successfully completed, logged in user is: id=${user.id}, name=${user.name}, role=${user.role}, IP: ${req.ip}, User Agent: ${req.headers['user-agent']}`);
|
||||
if (!sessionUser.id && !sessionUser.name) {
|
||||
authLogger.info('Session user lacks both id and name');
|
||||
return res.redirect('/auth/login');
|
||||
}
|
||||
|
||||
const user = users.find(user => user.id === sessionUser.id || user.name === sessionUser.name);
|
||||
|
||||
if (!user) {
|
||||
authLogger.info('User not found in user.json');
|
||||
return res.redirect('/auth/login');
|
||||
}
|
||||
|
||||
res.locals.user = user;
|
||||
req.session.user = user;
|
||||
res.locals.user = user;
|
||||
req.userData = user;
|
||||
|
||||
return next();
|
||||
} else {
|
||||
authLogger.info(`Authentication failed for IP: ${req.ip}, User Agent: ${req.headers['user-agent']}. Redirecting to login.`);
|
||||
debug('User is not authenticated, redirecting to login...');
|
||||
res.redirect('/auth/login');
|
||||
}
|
||||
} catch (error) {
|
||||
authLogger.error('Error in authentication middleware:', error);
|
||||
return next(error);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = authMiddleware;
|
||||
@@ -1,46 +1,50 @@
|
||||
const passport = require('passport');
|
||||
const DiscordStrategy = require('passport-discord').Strategy;
|
||||
const fs = require('fs');
|
||||
const fs = require('fs').promises;
|
||||
const path = require('path');
|
||||
|
||||
const setupFilePath = path.join(__dirname, '../data', 'setup.json');
|
||||
|
||||
let setupData;
|
||||
async function loadSetupData() {
|
||||
try {
|
||||
setupData = JSON.parse(fs.readFileSync(setupFilePath, 'utf-8'));
|
||||
console.log('Setup data loaded:', setupData);
|
||||
const setupFileContent = await fs.readFile(setupFilePath, 'utf-8');
|
||||
return JSON.parse(setupFileContent);
|
||||
} catch (err) {
|
||||
console.error('Error reading setup.json:', err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function initializePassport() {
|
||||
const setupData = await loadSetupData();
|
||||
|
||||
if (!setupData || !setupData[0]) {
|
||||
console.error('Setup data is not loaded or has an incorrect structure.');
|
||||
return;
|
||||
}
|
||||
|
||||
const discordConfig = setupData[0].discord;
|
||||
if (!discordConfig || !discordConfig.clientID || !discordConfig.clientSecret) {
|
||||
console.error('Discord configuration is missing clientID or clientSecret.');
|
||||
return;
|
||||
}
|
||||
|
||||
const callbackURL = `http://${setupData[0].domain}/auth/discord/callback`;
|
||||
console.log(`Callback URL: ${callbackURL}`);
|
||||
|
||||
passport.use(new DiscordStrategy({
|
||||
clientID: setupData[0].discord.clientID,
|
||||
clientSecret: setupData[0].discord.clientSecret,
|
||||
callbackURL: callbackURL
|
||||
}, (accessToken, refreshToken, profile, done) => {
|
||||
console.log('Discord profile received:', profile);
|
||||
|
||||
fs.readFile(path.join(__dirname, '../data', 'user.json'), 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error('Error reading user.json:', err);
|
||||
return done(err);
|
||||
}
|
||||
|
||||
let users;
|
||||
clientID: discordConfig.clientID,
|
||||
clientSecret: discordConfig.clientSecret,
|
||||
callbackURL: callbackURL,
|
||||
scope: ['identify', 'email']
|
||||
}, async (accessToken, refreshToken, profile, done) => {
|
||||
try {
|
||||
users = JSON.parse(data);
|
||||
} catch (parseErr) {
|
||||
console.error('Failed to parse user.json:', parseErr);
|
||||
return done(parseErr);
|
||||
}
|
||||
const userFilePath = path.join(__dirname, '../data', 'user.json');
|
||||
const data = await fs.readFile(userFilePath, 'utf8');
|
||||
let users = JSON.parse(data);
|
||||
|
||||
let existingUser = users.find(user => user.id === profile.id);
|
||||
|
||||
if (existingUser) {
|
||||
console.log('Existing user found:', existingUser);
|
||||
return done(null, existingUser);
|
||||
}
|
||||
|
||||
@@ -52,15 +56,13 @@ passport.use(new DiscordStrategy({
|
||||
|
||||
users.push(newUser);
|
||||
|
||||
fs.writeFile(path.join(__dirname, '../data', 'user.json'), JSON.stringify(users, null, 2), 'utf8', (err) => {
|
||||
if (err) {
|
||||
console.error('Error writing to user.json:', err);
|
||||
return done(err);
|
||||
}
|
||||
console.log('New user created:', newUser);
|
||||
await fs.writeFile(userFilePath, JSON.stringify(users, null, 2), 'utf8');
|
||||
done(null, newUser);
|
||||
});
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Error handling user data:', err);
|
||||
done(err);
|
||||
}
|
||||
}));
|
||||
|
||||
passport.serializeUser((user, done) => {
|
||||
@@ -68,19 +70,11 @@ passport.serializeUser((user, done) => {
|
||||
done(null, user.id);
|
||||
});
|
||||
|
||||
passport.deserializeUser((id, done) => {
|
||||
fs.readFile(path.join(__dirname, '../data', 'user.json'), 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
let users;
|
||||
passport.deserializeUser(async (id, done) => {
|
||||
try {
|
||||
users = JSON.parse(data);
|
||||
} catch (parseErr) {
|
||||
console.error('Failed to parse user data:', parseErr);
|
||||
return done(parseErr);
|
||||
}
|
||||
const userFilePath = path.join(__dirname, '../data', 'user.json');
|
||||
const data = await fs.readFile(userFilePath, 'utf8');
|
||||
const users = JSON.parse(data);
|
||||
|
||||
const user = users.find(user => user.id === id);
|
||||
|
||||
@@ -88,9 +82,14 @@ passport.deserializeUser((id, done) => {
|
||||
return done(null, false, { message: 'User not found.' });
|
||||
}
|
||||
|
||||
console.log('Deserializing user:', user);
|
||||
done(null, user);
|
||||
} catch (err) {
|
||||
console.error('Error deserializing user:', err);
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
initializePassport();
|
||||
|
||||
module.exports = passport;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@cdn-app/insider-myaxrin-labs-dinawo",
|
||||
"version": "1.0.0-beta.14",
|
||||
"version": "1.0.0-beta.15",
|
||||
"description": "",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -7,6 +7,10 @@ const { getUserData, getSetupData } = require('../../Middlewares/watcherMiddlewa
|
||||
let setupData;
|
||||
let user;
|
||||
|
||||
// Ensure Passport is initialized before using it
|
||||
router.use(passport.initialize());
|
||||
router.use(passport.session());
|
||||
|
||||
Promise.all([
|
||||
getSetupData(),
|
||||
getUserData()
|
||||
@@ -15,7 +19,7 @@ Promise.all([
|
||||
user = userData;
|
||||
|
||||
if (setupData[0].discord !== undefined) {
|
||||
const DiscordStrategy = require('../../models/Passport-Discord');
|
||||
require('../../models/Passport-Discord'); // Ensure the strategy is registered
|
||||
}
|
||||
|
||||
router.get("/auth/discord", (req, res) => {
|
||||
@@ -33,30 +37,33 @@ Promise.all([
|
||||
res.redirect('/auth/login');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
router.use(passport.initialize());
|
||||
router.use(passport.session());
|
||||
|
||||
passport.deserializeUser((user, done) => {
|
||||
done(null, user);
|
||||
});
|
||||
|
||||
router.get('/callback', passport.authenticate('discord', {
|
||||
failureRedirect: '/auth/login'
|
||||
}), (req, res, next) => {
|
||||
checkUserExistsDiscord(req, res, () => {
|
||||
if (req.userExists) {
|
||||
return res.redirect('/dpanel/dashboard');
|
||||
} else {
|
||||
createUser(req.user, (createErr) => {
|
||||
if (createErr) {
|
||||
return next(createErr);
|
||||
router.get('/callback', async (req, res, next) => {
|
||||
try {
|
||||
passport.authenticate('discord', { session: true }, (err, user, info) => {
|
||||
if (err) {
|
||||
console.error('Authentication error:', err);
|
||||
return next(err);
|
||||
}
|
||||
return res.redirect('/dpanel/dashboard');
|
||||
if (!user) {
|
||||
console.error('No user found:', info);
|
||||
return res.redirect('/auth/login');
|
||||
}
|
||||
req.logIn(user, (err) => {
|
||||
if (err) {
|
||||
console.error('Login error:', err);
|
||||
return next(err);
|
||||
}
|
||||
console.log('Authenticated user:', user);
|
||||
res.redirect('/dpanel/dashboard');
|
||||
});
|
||||
})(req, res, next);
|
||||
} catch (error) {
|
||||
console.error('Error handling callback:', error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -2,165 +2,45 @@ const express = require('express');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const router = express.Router();
|
||||
const fileUpload = require('express-fileupload');
|
||||
const authMiddleware = require('../../../Middlewares/authMiddleware');
|
||||
const { loggers } = require('winston');
|
||||
const ncp = require('ncp').ncp;
|
||||
let configFile = fs.readFileSync(path.join(__dirname, '../../../data', 'setup.json'), 'utf-8')
|
||||
let config = JSON.parse(configFile)[0];
|
||||
const bodyParser = require('body-parser');
|
||||
const crypto = require('crypto');
|
||||
const os = require('os');
|
||||
const { getUserData, getSetupData } = require('../../../Middlewares/watcherMiddleware');
|
||||
|
||||
let setupData = getSetupData();
|
||||
let userData = getUserData();
|
||||
router.use(bodyParser.json());
|
||||
router.use(express.json());
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /dashboard/getfilefolder/{folderName}?token={token}:
|
||||
* post:
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* tags:
|
||||
* - Folder
|
||||
* summary: Get files and folders in a specific folder
|
||||
* description: This route allows you to get the files and folders in a specific folder. It requires a valid JWT token in the Authorization header.
|
||||
* parameters:
|
||||
* - in: path
|
||||
* name: folderName
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: The name of the folder
|
||||
* - in: header
|
||||
* name: Authorization
|
||||
* required: true
|
||||
* schema:
|
||||
* type: string
|
||||
* description: The JWT token of your account to have access
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Success
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* files:
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* properties:
|
||||
* name:
|
||||
* type: string
|
||||
* type:
|
||||
* type: string
|
||||
* 401:
|
||||
* description: Unauthorized
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* 404:
|
||||
* description: The specified folder does not exist
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* error:
|
||||
* type: string
|
||||
* 500:
|
||||
* description: Internal server error
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* error:
|
||||
* type: string
|
||||
*/
|
||||
router.post('/wallpaper', (req, res) => {
|
||||
const userId = req.body.userId;
|
||||
const wallpaperUrl = req.body.wallpaperUrl;
|
||||
|
||||
|
||||
function authenticateToken(req, res, next) {
|
||||
let token = null;
|
||||
const authHeader = req.headers['authorization'];
|
||||
|
||||
if (authHeader) {
|
||||
token = authHeader.split(' ')[1];
|
||||
} else if (req.query.token) {
|
||||
token = req.query.token;
|
||||
if (!wallpaperUrl) {
|
||||
return res.status(400).send('No wallpaper URL provided.');
|
||||
}
|
||||
|
||||
if (token == null) {
|
||||
if (req.user) {
|
||||
return next();
|
||||
} else {
|
||||
return res.status(401).json({ message: 'Unauthorized' });
|
||||
}
|
||||
}
|
||||
|
||||
fs.readFile(path.join(__dirname, '../../../data', 'user.json'), 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
console.error('Error reading user.json:', err);
|
||||
return res.status(401).json({ message: 'Unauthorized' });
|
||||
}
|
||||
|
||||
const users = JSON.parse(data);
|
||||
|
||||
const user = users.find(u => u.token === token);
|
||||
|
||||
if (user) {
|
||||
req.user = user;
|
||||
req.userData = user;
|
||||
next();
|
||||
} else {
|
||||
return res.status(401).json({ message: 'Unauthorized' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
router.get('/wallpaper', authenticateToken, (req, res) => {
|
||||
fs.readFile(path.join(__dirname, '../../../data', 'user.json'), 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
return res.status(500).send('Error reading the file');
|
||||
}
|
||||
const users = JSON.parse(data);
|
||||
const user = users.find(u => u.token === req.userData.token);
|
||||
|
||||
res.json({ wallpaper: user.wallpaper || null });
|
||||
});
|
||||
updateUserWallpaper(userId, wallpaperUrl, res);
|
||||
});
|
||||
|
||||
router.post('/wallpaper', authenticateToken, (req, res) => {
|
||||
const newWallpaper = req.body.wallpaper;
|
||||
const updateUserWallpaper = (userId, wallpaperUrl, res) => {
|
||||
const userFilePath = path.join(__dirname, '../../../data', 'user.json');
|
||||
|
||||
fs.readFile(path.join(__dirname, '../../../data', 'user.json'), 'utf8', (err, data) => {
|
||||
fs.readFile(userFilePath, 'utf8', (err, data) => {
|
||||
if (err) {
|
||||
return res.status(500).send('Error reading the file');
|
||||
}
|
||||
|
||||
let users = JSON.parse(data);
|
||||
const userIndex = users.findIndex(u => u.token === req.userData.token);
|
||||
|
||||
const userIndex = users.findIndex(u => u.id === userId);
|
||||
|
||||
if (userIndex !== -1) {
|
||||
users[userIndex].wallpaper = newWallpaper;
|
||||
users[userIndex].wallpaper = wallpaperUrl;
|
||||
|
||||
fs.writeFile(path.join(__dirname, '../../../data', 'user.json'), JSON.stringify(users, null, 2), (err) => {
|
||||
fs.writeFile(userFilePath, JSON.stringify(users, null, 2), err => {
|
||||
if (err) {
|
||||
return res.status(500).send('Error writing to the file');
|
||||
}
|
||||
res.send('Wallpaper updated');
|
||||
res.json({ wallpaper: wallpaperUrl });
|
||||
});
|
||||
} else {
|
||||
res.status(401).send('Unauthorized');
|
||||
res.status(404).send('User not found');
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = router;
|
||||
@@ -24,6 +24,9 @@ const UpdateSetupAdminRoute = require('./Dpanel/API/Update-Setup-Admin.js');
|
||||
const DeleteFolderRoute = require('./Dpanel/API/DeleteFolfder.js');
|
||||
const DeleteFileFolderRoute = require('./Dpanel/API/DeleteFileFolder.js');
|
||||
const GetMetaDataFileRoute = require('./Dpanel/API/GetMetaDataFile.js');
|
||||
const BackgroundCustom = require('./Dpanel/API/BackgroundCustom.js');
|
||||
const ProfilUser = require('./Dpanel/Dashboard/ProfilUser.js');
|
||||
const PofilPictureRoute = require('./Dpanel/API/ProfilPicture.js');
|
||||
|
||||
const loginRoute = require('./Auth/Login.js');
|
||||
const logoutRoute = require('./Auth/Logout.js');
|
||||
@@ -50,12 +53,13 @@ router.use('/dpanel/dashboard/admin/users', AdminUsersDpanelRoute);
|
||||
router.use('/dpanel/dashboard/admin/settingsetup', AdminSettingSetupDpanelRoute)
|
||||
router.use('/dpanel/dashboard/admin/stats-logs', AdminStatsLogsDpanelRoute);;
|
||||
router.use('/dpanel/dashboard/admin/Privacy-Security', AdminPrivacySecurityDpanelRoute);
|
||||
router.use('/dpanel/dashboard/profil', ProfilUser);
|
||||
|
||||
router.use('/api/dpanel/dashboard/newfolder',discordWebhookSuspisiousAlertMiddleware, logApiRequest, NewFolderRoute);
|
||||
router.use('/api/dpanel/dashboard/rename',discordWebhookSuspisiousAlertMiddleware, logApiRequest, RenameFileRoute);
|
||||
router.use('/api/dpanel/dashboard/delete',discordWebhookSuspisiousAlertMiddleware, logApiRequest, DeleteFileRoute);
|
||||
router.use('/api/dpanel/dashboard/movefile',discordWebhookSuspisiousAlertMiddleware, logApiRequest, MoveFileRoute);
|
||||
router.use('/api/dpanel/upload', UploadRoute);
|
||||
router.use('/api/dpanel/upload',discordWebhookSuspisiousAlertMiddleware, logApiRequest, UploadRoute);
|
||||
router.use('/api/dpanel/dashboard/admin/update-role',discordWebhookSuspisiousAlertMiddleware, logApiRequest, UpdateRoleAdminRoute);
|
||||
router.use('/api/dpanel/dashboard/admin/update-setup',discordWebhookSuspisiousAlertMiddleware, logApiRequest, UpdateSetupAdminRoute);
|
||||
router.use('/api/dpanel/dashboard/deletefolder',discordWebhookSuspisiousAlertMiddleware, logApiRequest, DeleteFolderRoute);
|
||||
@@ -65,6 +69,8 @@ router.use('/api/dpanel/dashboard/backgroundcustom',discordWebhookSuspisiousAler
|
||||
router.use('/api/dpanel/generate-token',discordWebhookSuspisiousAlertMiddleware, logApiRequest, GenerateTokenRoute);
|
||||
router.use('/api/dpanel/dashboard/getfile', getFileDashboardRoute, logApiRequest);
|
||||
router.use('/api/dpanel/dashboard/getfilefolder', getFileFolderRoute, logApiRequest);
|
||||
router.use('/api/dpanel/dashboard/backgroundcustom', BackgroundCustom, logApiRequest);
|
||||
router.use('/api/dpanel/dashboard/profilpicture', PofilPictureRoute, logApiRequest);
|
||||
|
||||
router.use('/auth/login', loginRoute);
|
||||
router.use('/auth/logout', logoutRoute);
|
||||
|
||||
@@ -126,6 +126,9 @@
|
||||
</style>
|
||||
|
||||
<body class="light-mode animate">
|
||||
<div class="alert alert-primary text-center" role="alert">
|
||||
Un nouveau look sera bientôt disponible pour la page de connexion. Myaxrin Labs va améliorer son application pour la rendre plus rapide et plus facile à utiliser.
|
||||
</div>
|
||||
<div class="container mt-4 animate">
|
||||
<h1 class="title text-center animate">Connexion</h1>
|
||||
<% if (currentUrl === '/auth/activedirectory' || (setupData[0] && setupData[0].hasOwnProperty('ldap'))) { %>
|
||||
|
||||
@@ -21,6 +21,20 @@
|
||||
|
||||
</head>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-image: url('<%= user.wallpaper %>');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<body class="light-mode">
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-light header">
|
||||
<a class="navbar-brand">
|
||||
@@ -54,21 +68,27 @@
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="btn dropdown-toggle" id="accountDropdownBtn" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<img src="https://api.dicebear.com/7.x/initials/svg?seed=<%= user.name %>" alt="User Icon" class="rounded-circle" style="width: 30px; height: 30px;" />
|
||||
<img
|
||||
src="<%= user.profilePicture || 'https://api.dicebear.com/7.x/initials/svg?seed=' + user.name %>"
|
||||
alt="User Icon"
|
||||
class="rounded-circle"
|
||||
style="width: 30px; height: 30px;"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<div class="dropdown-menu dropdown-menu-right p-4 bg-dark text-white" id="accountDropdownMenu">
|
||||
<div class="mb-3 text-center">
|
||||
<h6 class="text-lg font-semibold"><%= user.name %></h6>
|
||||
<p class="mb-0">ID: <%= user.id %></p>
|
||||
<p class="mb-0">Role: <%= user.role %></p>
|
||||
<a class="dropdown-item text-center text-white no-hover custom-btn" href="/dpanel/dashboard/profil" id="logoutLink">
|
||||
<i class="fas fa-sign-out-alt text-white"></i> Mon profile
|
||||
</a>
|
||||
</div>
|
||||
<div class="dropdown-divider mb-2"></div>
|
||||
<% if (user.role === 'admin') { %>
|
||||
<a class="dropdown-item text-center text-white no-hover custom-btn" href="/dpanel/dashboard/admin" id="adminLink">
|
||||
<i class="fas fa-user-shield"></i> Administration du site
|
||||
</a>
|
||||
</a><br>
|
||||
<% } %>
|
||||
<br><br><a class="dropdown-item text-center text-white no-hover custom-btn" href="/auth/logout" id="logoutLink">
|
||||
<br><a class="dropdown-item text-center text-white no-hover custom-btn" href="/auth/logout" id="logoutLink">
|
||||
<i class="fas fa-sign-out-alt text-white"></i> Déconnexion
|
||||
</a>
|
||||
</div>
|
||||
@@ -76,6 +96,9 @@
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="alert alert-primary text-center" role="alert">
|
||||
Un nouveau look sera bientôt disponible pour le tableau de bord. Myaxrin Labs va améliorer son application pour la rendre plus rapide et plus facile à utiliser.
|
||||
</div>
|
||||
|
||||
<div class="container mt-4 table-container">
|
||||
<div class="table-responsive">
|
||||
@@ -164,35 +187,44 @@
|
||||
|
||||
<div class="modal fade" id="patchNoteModal" tabindex="-1" role="dialog" aria-labelledby="patchNoteModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg rounded-lg" role="document">
|
||||
<div class="modal-content dark-mode">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="patchNoteModalLabel">Patch Note<span class="badge badge-info ml-1">v1.0.0-beta.14</span></h5>
|
||||
<h5 class="modal-title" id="patchNoteModalLabel">Patch Note<span class="badge badge-info ml-1">v1.0.0-beta.15</span></h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="patch-note-item pl-3">
|
||||
<p><i class="fas fa-tools"></i> Améliorations :</p>
|
||||
<div class="modal-body">
|
||||
<div class="patch-note-item">
|
||||
<p><i class="fas fa-tools"></i> Nouvelles Fonctionnalités :</p>
|
||||
<ul>
|
||||
<li>Améliorations mineures et corrections mineures sur tous les niveaux de l'application.<span class="badge badge-success ml-1">AMÉLIORATION MINEURE</span></li>
|
||||
<li>Déplacement de fichier d'un dossier à la racine.<span class="badge badge-success ml-1">AMÉLIORATION MAJEURE</span></li>
|
||||
<li>Suppression chargement login avec la connexion active directory.<span class="badge badge-success ml-1">AMÉLIORATION MAJEURE</span></li>
|
||||
<li>Modification de la suppression des fichiers à la racine.<span class="badge badge-success ml-1">AMÉLIORATION MINEURE</span></li>
|
||||
<li>Modification déplacement fichier sans destination.<span class="badge badge-success ml-1">AMÉLIORATION MINEURE</span></li>
|
||||
<li>Intégration de l'authentification Discord<span class="badge badge-success ml-1">AMÉLIORATION MINEURE</span></li>
|
||||
<li>Personnalisation de l'arrière-plan de l'application<span class="badge badge-success ml-1">AMÉLIORATION MAJEURE</span></li>
|
||||
<li>Nouveau design pour l'affichage du token dans le panneau administrateur<span class="badge badge-success ml-1">AMÉLIORATION MAJEURE</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="patch-note-item pl-3">
|
||||
<p><i class="fas fa-wrench"></i> Modifications :</p>
|
||||
<div class="patch-note-item">
|
||||
<p><i class="fas fa-wrench"></i> Améliorations :</p>
|
||||
<ul>
|
||||
<li>Correction majeure d'un bug de sécurité.<span class="badge badge-success ml-1">MODIFICATION MAJEURE</span></li>
|
||||
<li>Modification du message "move file" réponse JSON.<span class="badge badge-success ml-1">MODIFICATION MINEURE</span></li>
|
||||
<li>Optimisation des performances de l'application<span class="badge badge-success ml-1">AMÉLIORATION MINEURE</span></li>
|
||||
<li>Amélioration de l'interface utilisateur pour une meilleure expérience<span class="badge badge-success ml-1">AMÉLIORATION MAJEURE</span></li>
|
||||
<li>Mise à jour des dépendances pour une meilleure stabilité<span class="badge badge-success ml-1">AMÉLIORATION MINEURE</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="patch-note-item pl-3">
|
||||
<p>Remarque : Nous apprécions vos retours d'expérience et vos rapports de bogues pour continuer à améliorer notre plateforme. Merci pour votre soutien continu !</p>
|
||||
<div class="patch-note-item">
|
||||
<p><i class="fas fa-bug"></i> Corrections de Bugs :</p>
|
||||
<ul>
|
||||
<li>Correction des erreurs d'affichage dans certains navigateurs<span class="badge badge-success ml-1">CORRECTION MINEURE</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="patch-note-item">
|
||||
<p><i class="fas fa-lock"></i> Sécurité :</p>
|
||||
<ul>
|
||||
<li>Renforcement de la sécurité de l'authentification<span class="badge badge-success ml-1">AMÉLIORATION MAJEURE</span></li>
|
||||
<li>Mise à jour des protocoles de chiffrement<span class="badge badge-success ml-1">AMÉLIORATION MINEURE</span></li>
|
||||
</ul>
|
||||
</div>
|
||||
<p class="note">Remarque : Nous sommes toujours à l'écoute de vos retours pour améliorer notre plateforme. N'hésitez pas à nous faire part de vos commentaires et suggestions !</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Fermer</button>
|
||||
@@ -234,7 +266,7 @@
|
||||
<ul class="nav justify-content-center border-bottom pb-3 mb-3">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link px-2 text-muted" href="#" data-toggle="modal" data-target="#patchNoteModal">
|
||||
Version: 1.0.0-beta.14
|
||||
Version: 1.0.0-beta.15
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -18,6 +18,20 @@
|
||||
<link rel="icon" href="/public/assets/homelab_logo.png" />
|
||||
</head>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-image: url('<%= user.wallpaper %>');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<body class="light-mode">
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light header">
|
||||
<a class="navbar-brand">
|
||||
@@ -49,6 +63,9 @@
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="alert alert-primary text-center" role="alert">
|
||||
Un nouveau look sera bientôt disponible pour le tableau de bord. Myaxrin Labs va améliorer son application pour la rendre plus rapide et plus facile à utiliser.
|
||||
</div>
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb custom-breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="/dpanel/dashboard">Accueil</a></li>
|
||||
@@ -174,7 +191,7 @@
|
||||
<div class="container">
|
||||
<footer class="py-3 my-4">
|
||||
<ul class="nav justify-content-center border-bottom pb-3 mb-3">
|
||||
<li class="nav-item"><a class="nav-link px-2 text-muted">Version: 1.0.0-beta.14</a></li>
|
||||
<li class="nav-item"><a class="nav-link px-2 text-muted">Version: 1.0.0-beta.15</a></li>
|
||||
</ul>
|
||||
<p class="text-center text-muted">© 2024 Myaxrin Labs</p>
|
||||
</footer>
|
||||
|
||||
@@ -126,10 +126,17 @@
|
||||
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
|
||||
|
||||
<script>
|
||||
const body = document.body;
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const darkModeSwitch = document.getElementById('darkModeSwitch');
|
||||
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
document.body.classList.toggle('dark-mode', darkModeMediaQuery.matches);
|
||||
darkModeMediaQuery.addListener(function (e) {
|
||||
document.body.classList.toggle('dark-mode', e.matches);
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('themeSwitcher').addEventListener('click', function () {
|
||||
body.classList.toggle('dark-mode');
|
||||
document.body.classList.toggle('dark-mode');
|
||||
});
|
||||
|
||||
document.getElementById('usersPerPage').addEventListener('change', function () {
|
||||
@@ -137,44 +144,11 @@
|
||||
});
|
||||
|
||||
window.onload = function () {
|
||||
var urlParams = new URLSearchParams(window.location.search);
|
||||
var limit = urlParams.get('limit');
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const limit = urlParams.get('limit');
|
||||
document.getElementById('usersPerPage').value = limit;
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const darkModeSwitch = document.getElementById('darkModeSwitch');
|
||||
|
||||
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
body.classList.toggle('dark-mode', darkModeMediaQuery.matches);
|
||||
|
||||
darkModeMediaQuery.addListener(function (e) {
|
||||
body.classList.toggle('dark-mode', e.matches);
|
||||
});
|
||||
});
|
||||
|
||||
function searchUsers() {
|
||||
var input = document.getElementById('searchInput');
|
||||
var filter = input.value.toUpperCase();
|
||||
var table = document.querySelector('.table');
|
||||
var tr = table.getElementsByTagName('tr');
|
||||
|
||||
for (var i = 0; i < tr.length; i++) {
|
||||
var tdName = tr[i].getElementsByTagName('td')[1];
|
||||
var tdId = tr[i].getElementsByTagName('td')[0];
|
||||
if (tdName || tdId) {
|
||||
var txtValueName = tdName.textContent || tdName.innerText;
|
||||
var txtValueId = tdId.textContent || tdId.innerText;
|
||||
if (txtValueName.toUpperCase().indexOf(filter) > -1 || txtValueId.toUpperCase().indexOf(filter) > -1) {
|
||||
tr[i].style.display = "";
|
||||
} else {
|
||||
tr[i].style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('searchButton').addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
searchUsers();
|
||||
@@ -187,19 +161,32 @@
|
||||
}
|
||||
});
|
||||
|
||||
var isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
|
||||
var searchInput = document.getElementById('searchInput');
|
||||
searchInput.placeholder = isMac ? 'Rechercher par nom ou ID (Cmd + K)' : 'Rechercher par nom ou ID (Ctrl + K)';
|
||||
function searchUsers() {
|
||||
const input = document.getElementById('searchInput');
|
||||
const filter = input.value.toUpperCase();
|
||||
const table = document.querySelector('.table');
|
||||
const tr = table.getElementsByTagName('tr');
|
||||
|
||||
for (let i = 0; i < tr.length; i++) {
|
||||
const tdName = tr[i].getElementsByTagName('td')[1];
|
||||
const tdId = tr[i].getElementsByTagName('td')[0];
|
||||
if (tdName || tdId) {
|
||||
const txtValueName = tdName.textContent || tdName.innerText;
|
||||
const txtValueId = tdId.textContent || tdId.innerText;
|
||||
tr[i].style.display = txtValueName.toUpperCase().indexOf(filter) > -1 || txtValueId.toUpperCase().indexOf(filter) > -1 ? "" : "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('generate-token-form').addEventListener('submit', function(e) {
|
||||
// Ajout d'un événement pour les formulaires de génération de token
|
||||
document.querySelectorAll('form[id="generate-token-form"]').forEach(form => {
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var url = this.getAttribute('action');
|
||||
var method = this.getAttribute('method');
|
||||
|
||||
var name = this.querySelector('input[name="name"]').value;
|
||||
var id = this.querySelector('input[name="id"]').value;
|
||||
var data = { name: name, id: id };
|
||||
const url = this.getAttribute('action');
|
||||
const method = this.getAttribute('method');
|
||||
const name = this.querySelector('input[name="name"]').value;
|
||||
const id = this.querySelector('input[name="id"]').value;
|
||||
const data = { name: name, id: id };
|
||||
|
||||
fetch(url, {
|
||||
method: method,
|
||||
@@ -212,7 +199,7 @@
|
||||
.then(response => {
|
||||
Swal.fire({
|
||||
title: 'Votre Token',
|
||||
html: `<input type="text" id="swal-input1" class="swal2-input" value="${response.token}">`,
|
||||
html: `<input type="text" id="swal-input1" class="swal2-input" value="${response.token}" readonly>`,
|
||||
confirmButtonText: 'Copier le Token',
|
||||
footer: '<div style="text-align: center;">Gardez ce token en sécurité. Il ne sera pas possible de le récupérer sans le régénérer.</div>',
|
||||
focusConfirm: false,
|
||||
@@ -226,7 +213,8 @@
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
Swal.fire('Error', error.message, 'error');
|
||||
Swal.fire('Erreur', error.message, 'error');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -12,7 +12,24 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@10"></script>
|
||||
</head>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-image: url('<%= user.wallpaper %>');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
margin: 0;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<body class="light-mode">
|
||||
<div class="alert alert-primary text-center" role="alert">
|
||||
Un nouveau look sera bientôt disponible pour la page de téléversement. Myaxrin Labs va améliorer son application pour la rendre plus rapide et plus facile à utiliser.
|
||||
</div>
|
||||
<div class="container mt-4 flex-column">
|
||||
<h1 class="mb-4">Upload de Fichiers</h1>
|
||||
<form id="uploadForm" enctype="multipart/form-data">
|
||||
|
||||
Reference in New Issue
Block a user