123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- // server.js - Fichier principal du serveur
- const express = require('express');
- const sqlite3 = require('sqlite3').verbose();
- const bcrypt = require('bcrypt');
- const cors = require('cors');
- const path = require('path');
- const app = express();
- const port = process.env.PORT || 3000;
- // Middleware
- app.use(express.json());
- app.use(cors());
- app.use(express.static(path.join(__dirname, 'public')));
- // Connexion à la base de données SQLite
- const db = new sqlite3.Database('/app/data/framed.db', (err) => {
- if (err) {
- console.error('Erreur de connexion à la base de données:', err.message);
- } else {
- console.log('Connecté à la base de données SQLite');
- initDatabase();
- }
- });
- // Initialiser la base de données
- function initDatabase() {
- // Activer les clés étrangères
- db.run('PRAGMA foreign_keys = ON');
- // Créer la table des utilisateurs
- db.run(`
- CREATE TABLE IF NOT EXISTS users (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- username TEXT UNIQUE NOT NULL,
- password TEXT NOT NULL,
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
- )
- `);
- // Créer la table des scores
- db.run(`
- CREATE TABLE IF NOT EXISTS scores (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
- user_id INTEGER NOT NULL,
- date TEXT NOT NULL,
- game_type TEXT NOT NULL,
- game_number INTEGER,
- score INTEGER NOT NULL,
- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE
- )
- `);
- console.log('Tables vérifiées/créées');
- }
- // Routes d'API
- // Inscription
- app.post('/api/register', async (req, res) => {
- const { username, password } = req.body;
- if (!username || !password) {
- return res.status(400).json({ error: 'Nom d\'utilisateur et mot de passe requis' });
- }
- try {
- // Vérifier si l'utilisateur existe déjà
- db.get('SELECT * FROM users WHERE username = ?', [username], async (err, user) => {
- if (err) {
- return res.status(500).json({ error: err.message });
- }
-
- if (user) {
- return res.status(400).json({ error: 'Cet utilisateur existe déjà' });
- }
-
- // Hasher le mot de passe
- const hashedPassword = await bcrypt.hash(password, 10);
-
- // Insérer le nouvel utilisateur
- db.run('INSERT INTO users (username, password) VALUES (?, ?)',
- [username, hashedPassword],
- function(err) {
- if (err) {
- return res.status(500).json({ error: err.message });
- }
-
- res.status(201).json({
- message: 'Utilisateur créé avec succès',
- userId: this.lastID,
- username
- });
- }
- );
- });
- } catch (error) {
- res.status(500).json({ error: error.message });
- }
- });
- // Connexion
- app.post('/api/login', (req, res) => {
- const { username, password } = req.body;
- if (!username || !password) {
- return res.status(400).json({ error: 'Nom d\'utilisateur et mot de passe requis' });
- }
- db.get('SELECT * FROM users WHERE username = ?', [username], async (err, user) => {
- if (err) {
- return res.status(500).json({ error: err.message });
- }
-
- if (!user) {
- return res.status(401).json({ error: 'Identifiants invalides' });
- }
-
- // Vérifier le mot de passe
- const validPassword = await bcrypt.compare(password, user.password);
-
- if (!validPassword) {
- return res.status(401).json({ error: 'Identifiants invalides' });
- }
-
- res.json({
- userId: user.id,
- username: user.username
- });
- });
- });
- // Ajouter un score
- app.post('/api/scores', (req, res) => {
- const { userId, date, gameType, gameNumber, score } = req.body;
- if (!userId || !date || !gameType || !score) {
- return res.status(400).json({ error: 'Données incomplètes' });
- }
- db.run(
- 'INSERT INTO scores (user_id, date, game_type, game_number, score) VALUES (?, ?, ?, ?, ?)',
- [userId, date, gameType, gameNumber, score],
- function(err) {
- if (err) {
- return res.status(500).json({ error: err.message });
- }
-
- res.status(201).json({
- id: this.lastID,
- userId,
- date,
- gameType,
- gameNumber,
- score
- });
- }
- );
- });
- // Récupérer les scores d'un utilisateur
- app.get('/api/scores/user/:userId', (req, res) => {
- const userId = req.params.userId;
- db.all('SELECT * FROM scores WHERE user_id = ? ORDER BY date DESC', [userId], (err, scores) => {
- if (err) {
- return res.status(500).json({ error: err.message });
- }
-
- res.json(scores);
- });
- });
- // Récupérer tous les scores (pour le classement)
- app.get('/api/scores', (req, res) => {
- const gameType = req.query.gameType || 'all';
-
- let query = `
- SELECT s.*, u.username
- FROM scores s
- JOIN users u ON s.user_id = u.id
- `;
-
- if (gameType !== 'all') {
- query += ` WHERE s.game_type = '${gameType}'`;
- }
-
- db.all(query, (err, scores) => {
- if (err) {
- return res.status(500).json({ error: err.message });
- }
-
- res.json(scores);
- });
- });
- // Supprimer un score
- app.delete('/api/scores/:id', (req, res) => {
- const scoreId = req.params.id;
- const userId = req.query.userId;
- if (!userId) {
- return res.status(400).json({ error: 'Utilisateur non spécifié' });
- }
- db.run('DELETE FROM scores WHERE id = ? AND user_id = ?', [scoreId, userId], function(err) {
- if (err) {
- return res.status(500).json({ error: err.message });
- }
-
- if (this.changes === 0) {
- return res.status(404).json({ error: 'Score non trouvé ou non autorisé' });
- }
-
- res.json({ message: 'Score supprimé avec succès' });
- });
- });
- // Récupérer les statistiques d'un utilisateur
- app.get('/api/stats/:userId', (req, res) => {
- const userId = req.params.userId;
-
- const query = `
- SELECT
- game_type,
- COUNT(*) as total_games,
- AVG(score) as average_score,
- MIN(score) as best_score
- FROM scores
- WHERE user_id = ?
- GROUP BY game_type
- `;
-
- db.all(query, [userId], (err, stats) => {
- if (err) {
- return res.status(500).json({ error: err.message });
- }
-
- res.json(stats);
- });
- });
- // Récupérer le classement
- app.get('/api/leaderboard', (req, res) => {
- const gameType = req.query.gameType || 'all';
-
- let query = `
- SELECT
- u.id,
- u.username,
- COUNT(*) as total_games,
- AVG(s.score) as average_score,
- MIN(s.score) as best_score
- FROM scores s
- JOIN users u ON s.user_id = u.id
- `;
-
- if (gameType !== 'all') {
- query += ` WHERE s.game_type = '${gameType}'`;
- }
-
- query += `
- GROUP BY u.id
- ORDER BY average_score ASC, best_score ASC
- `;
-
- db.all(query, (err, leaderboard) => {
- if (err) {
- return res.status(500).json({ error: err.message });
- }
-
- res.json(leaderboard);
- });
- });
- // Route par défaut pour servir l'application React
- app.get('*', (req, res) => {
- res.sendFile(path.join(__dirname, 'public', 'index.html'));
- });
- // Démarrer le serveur
- //app.listen(port, () => {
- // console.log(`Serveur en écoute sur le port ${port}`);
- //});
- if (process.env.NODE_ENV === 'production') {
- // En production, servir les fichiers statiques
- app.use(express.static(path.join(__dirname, 'public')));
-
- // Route par défaut pour servir l'application React
- app.get('*', (req, res) => {
- res.sendFile(path.join(__dirname, 'public', 'index.html'));
- });
- } else {
- // En développement, juste répondre à l'API
- app.get('/', (req, res) => {
- res.json({ message: 'API Framed Tracker fonctionne correctement. Utilisez le port 3001 pour accéder au frontend.' });
- });
- }
- // Fermer proprement la connexion à la base de données lors de l'arrêt du serveur
- process.on('SIGINT', () => {
- db.close((err) => {
- if (err) {
- console.error(err.message);
- }
- console.log('Connexion à la base de données fermée');
- process.exit(0);
- });
- });
|