Début du projet

This commit is contained in:
TopScritch committed 2026-10-25 20:05:12 +01:00
commit e7d4e607f6
23 files changed
+4855

No files matched your search

+170
View File
@@ -0,0 +1,170 @@
const express = require('express');
const router = express.Router();
const { db } = require('../db');
const { v4: uuidv4 } = require('uuid');
function requireAuth(req, res, next) {
if (req.session && req.session.authenticated) {
return next();
}
res.redirect('/admin/login');
}
router.get('/login', (req, res) => {
if (req.session && req.session.authenticated) {
return res.redirect('/admin');
}
res.render('admin/login', { error: null });
});
router.post('/login', (req, res) => {
const { username, password } = req.body;
const adminUser = process.env.ADMIN_USERNAME || 'admin';
const adminPass = process.env.ADMIN_PASSWORD || 'changeme123';
if (username === adminUser && password === adminPass) {
console.log("[DEBUG] Connexion OK")
req.session.authenticated = true;
req.session.username = username;
return req.session.save((err) => {
if (err) {
console.error('Session save error:', err);
}
return res.redirect('/admin');
});
}
res.render('admin/login', { error: 'Identifiants incorrects' });
});
router.get('/logout', (req, res) => {
req.session.destroy(() => {
res.redirect('/admin/login');
});
});
router.use(requireAuth);
router.get('/', (req, res) => {
const status = req.query.status || 'all';
const language = req.query.language || 'all';
// Filtre langue identique au site public (repli sur la langue de la source)
const languageExpr = `COALESCE(language, source_language, 'fr')`;
const conditions = [];
const params = [];
if (status !== 'all') {
conditions.push(`status = ?`);
params.push(status);
}
if (language !== 'all') {
conditions.push(`${languageExpr} = ?`);
params.push(language);
}
const where = conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : '';
const articles = db
.prepare(`SELECT * FROM articles${where} ORDER BY datetime(created_at) DESC`)
.all(...params);
// Stats (filtrées sur la langue sélectionnée)
const stats = {};
['pending', 'published', 'hidden', 'rejected'].forEach(s => {
const statParams = [s];
let statQuery = `SELECT COUNT(*) as c FROM articles WHERE status = ?`;
if (language !== 'all') {
statQuery += ` AND ${languageExpr} = ?`;
statParams.push(language);
}
stats[s] = db.prepare(statQuery).get(...statParams).c;
});
let totalQuery = `SELECT COUNT(*) as c FROM articles`;
const totalParams = [];
if (language !== 'all') {
totalQuery += ` WHERE ${languageExpr} = ?`;
totalParams.push(language);
}
stats.total = db.prepare(totalQuery).get(...totalParams).c;
// Langues disponibles dans l'ensemble des articles
const languages = db
.prepare(`SELECT ${languageExpr} as lang, COUNT(*) as c FROM articles GROUP BY lang ORDER BY c DESC, lang`)
.all();
res.render('admin/dashboard', { articles, status, stats, languages, language });
});
router.post('/article/:id/validate', (req, res) => {
const { id } = req.params;
const { categories, summary } = req.body;
try {
const categoriesJson = categories ? JSON.stringify(categories.split(',').map(c => c.trim()).filter(Boolean)) : null;
db.prepare(`UPDATE articles SET status='published', categories=COALESCE(?, categories), summary=COALESCE(?, summary), updated_at=datetime('now') WHERE id=?`)
.run(categoriesJson, summary || null, id);
db.prepare(`INSERT INTO activity_log (action, article_id, details) VALUES ('validate', ?, 'Article publié')`).run(id);
res.redirect(req.get('referer') || '/admin');
} catch(e) {
console.error(e);
res.redirect('/admin');
}
});
router.post('/article/:id/hide', (req, res) => {
const { id } = req.params;
db.prepare(`UPDATE articles SET status='hidden', updated_at=datetime('now') WHERE id=?`).run(id);
db.prepare(`INSERT INTO activity_log (action, article_id, details) VALUES ('hide', ?, 'Article masqué')`).run(id);
res.redirect(req.get('referer') || '/admin');
});
router.post('/article/:id/reject', (req, res) => {
const { id } = req.params;
db.prepare(`UPDATE articles SET status='rejected', updated_at=datetime('now') WHERE id=?`).run(id);
db.prepare(`INSERT INTO activity_log (action, article_id, details) VALUES ('reject', ?, 'Article rejeté')`).run(id);
res.redirect(req.get('referer') || '/admin');
});
router.post('/article/:id/publish', (req, res) => {
const { id } = req.params;
db.prepare(`UPDATE articles SET status='published', updated_at=datetime('now') WHERE id=?`).run(id);
db.prepare(`INSERT INTO activity_log (action, article_id, details) VALUES ('publish', ?, 'Article republié')`).run(id);
res.redirect(req.get('referer') || '/admin');
});
router.post('/article/:id/delete', (req, res) => {
const { id } = req.params;
db.prepare(`DELETE FROM articles WHERE id=?`).run(id);
db.prepare(`INSERT INTO activity_log (action, article_id, details) VALUES ('delete', ?, 'Article supprimé')`).run(id);
res.redirect(req.get('referer') || '/admin');
});
router.post('/collect', (req, res) => {
const { collect } = require('../../collector/index');
collect().then(() => {
db.prepare(`INSERT INTO activity_log (action, details) VALUES ('collect', 'Collecte manuelle déclenchée')`).run();
res.redirect('/admin?status=pending');
}).catch(err => {
console.error(err);
res.redirect('/admin');
});
});
router.get('/sources', (req, res) => {
const sourcesPath = require('path').join(__dirname, '..', '..', 'config', 'sources.json');
const sources = JSON.parse(require('fs').readFileSync(sourcesPath, 'utf8'));
res.render('admin/sources', { sources });
});
router.get('/log', (req, res) => {
const logs = db.prepare(`SELECT * FROM activity_log ORDER BY datetime(created_at) DESC LIMIT 100`).all();
res.render('admin/log', { logs });
});
module.exports = router;
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.