mirror of
https://github.com/arthur-pbty/streaming-site.git
synced 2026-06-03 23:36:26 +02:00
Add files via upload
This commit is contained in:
+28
@@ -0,0 +1,28 @@
|
||||
const sqlite3 = require('sqlite3').verbose();
|
||||
const db = new sqlite3.Database('./users.db');
|
||||
|
||||
db.serialize(() => {
|
||||
db.run(`CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password TEXT NOT NULL,
|
||||
status TEXT DEFAULT 'pending',
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)`);
|
||||
db.run(`CREATE TABLE IF NOT EXISTS movies (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL,
|
||||
genre TEXT,
|
||||
description TEXT,
|
||||
cover TEXT,
|
||||
video TEXT
|
||||
)`);
|
||||
db.run(`CREATE TABLE IF NOT EXISTS logs (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
action TEXT,
|
||||
user_id INTEGER,
|
||||
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)`);
|
||||
});
|
||||
|
||||
module.exports = db;
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"title": "Titre du film",
|
||||
"description": "Description du film",
|
||||
"genre": "Genre du film",
|
||||
"releaseDate": "Date de sortie",
|
||||
"rating": "Note"
|
||||
}
|
||||
Generated
+2500
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "site-streaming",
|
||||
"version": "1.0.0",
|
||||
"description": "Site d'hébergement de films avec Vanilla JavaScript et Node.js",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"bcrypt": "^5.1.1",
|
||||
"body-parser": "^1.20.3",
|
||||
"express": "^4.21.1",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"sqlite3": "^5.1.7"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Administration</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Administration</h1>
|
||||
<nav>
|
||||
<a href="index.html">Accueil</a>
|
||||
<button id="logout-button">Déconnexion</button>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<div id="users-list">
|
||||
<!-- Liste des utilisateurs -->
|
||||
</div>
|
||||
</main>
|
||||
<script src="auth.js"></script>
|
||||
<script src="admin.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,87 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
fetch('/users', {
|
||||
headers: {
|
||||
'Authorization': token
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(users => {
|
||||
const usersList = document.getElementById('users-list');
|
||||
users.forEach(user => {
|
||||
const userElement = document.createElement('div');
|
||||
userElement.classList.add('user');
|
||||
userElement.innerHTML = `
|
||||
<p>${user.email} - ${user.status}</p>
|
||||
<button class="approve-button" data-id="${user.id}">Approuver</button>
|
||||
<button class="delete-button" data-id="${user.id}">Supprimer</button>
|
||||
<button class="admin-button" data-id="${user.id}">Rendre Admin</button>
|
||||
`;
|
||||
usersList.appendChild(userElement);
|
||||
});
|
||||
|
||||
document.querySelectorAll('.approve-button').forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const userId = button.getAttribute('data-id');
|
||||
fetch('/approve', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': token
|
||||
},
|
||||
body: JSON.stringify({ userId })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
alert(data.message);
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('.delete-button').forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const userId = button.getAttribute('data-id');
|
||||
fetch('/delete', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': token
|
||||
},
|
||||
body: JSON.stringify({ userId })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
alert(data.message);
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('.admin-button').forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const userId = button.getAttribute('data-id');
|
||||
fetch('/make-admin', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': token
|
||||
},
|
||||
body: JSON.stringify({ userId })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
alert(data.message);
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const logoutButton = document.getElementById('logout-button');
|
||||
logoutButton.addEventListener('click', () => {
|
||||
localStorage.removeItem('token');
|
||||
window.location.href = 'login.html';
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
const checkTokenValidity = () => {
|
||||
const token = localStorage.getItem('token');
|
||||
if (!token) return false;
|
||||
|
||||
return fetch('/users/me', {
|
||||
headers: {
|
||||
'Authorization': token
|
||||
}
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
localStorage.removeItem('token');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.catch(() => {
|
||||
localStorage.removeItem('token');
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const token = localStorage.getItem('token');
|
||||
const loginLink = document.getElementById('login-link');
|
||||
const registerLink = document.getElementById('register-link');
|
||||
const profileLink = document.getElementById('profile-link');
|
||||
const adminLink = document.getElementById('admin-link');
|
||||
const logoutButton = document.getElementById('logout-button');
|
||||
|
||||
if (token) {
|
||||
const isValid = await checkTokenValidity();
|
||||
if (!isValid) {
|
||||
window.location.href = 'login.html';
|
||||
return;
|
||||
}
|
||||
|
||||
loginLink.style.display = 'none';
|
||||
registerLink.style.display = 'none';
|
||||
profileLink.style.display = 'block';
|
||||
logoutButton.style.display = 'block';
|
||||
|
||||
fetch('/users/me', {
|
||||
headers: {
|
||||
'Authorization': token
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(user => {
|
||||
const welcomeMessage = document.getElementById('welcome-message');
|
||||
if (welcomeMessage) {
|
||||
welcomeMessage.textContent = `Bonjour ${user.email}`;
|
||||
}
|
||||
if (user.status === 'admin') {
|
||||
adminLink.style.display = 'block';
|
||||
}
|
||||
});
|
||||
|
||||
logoutButton.addEventListener('click', () => {
|
||||
localStorage.removeItem('token');
|
||||
window.location.href = 'index.html';
|
||||
});
|
||||
} else {
|
||||
loginLink.style.display = 'block';
|
||||
registerLink.style.display = 'block';
|
||||
profileLink.style.display = 'none';
|
||||
adminLink.style.display = 'none';
|
||||
logoutButton.style.display = 'none';
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Site de Streaming</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Site de Streaming</h1>
|
||||
<nav>
|
||||
<a href="index.html">Accueil</a>
|
||||
<a href="login.html" id="login-link">Connexion</a>
|
||||
<a href="register.html" id="register-link">Inscription</a>
|
||||
<a href="profile.html" id="profile-link" style="display: none;">Profil</a>
|
||||
<a href="admin.html" id="admin-link" style="display: none;">Administration</a>
|
||||
<button id="logout-button" style="display: none;">Déconnexion</button>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<h2 id="welcome-message"></h2>
|
||||
<div id="movies-grid">
|
||||
<!-- Grille des films/séries -->
|
||||
</div>
|
||||
</main>
|
||||
<script src="auth.js"></script>
|
||||
<script src="scripts.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Connexion</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Connexion</h1>
|
||||
<nav>
|
||||
<a href="index.html">Accueil</a>
|
||||
<a href="login.html" id="login-link">Connexion</a>
|
||||
<a href="register.html" id="register-link">Inscription</a>
|
||||
<button id="logout-button" style="display: none;">Déconnexion</button>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<form id="login-form" class="auth-form">
|
||||
<label for="email">Email :</label>
|
||||
<input type="email" id="email" name="email" required>
|
||||
<label for="password">Mot de passe :</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
<button type="submit">Connexion</button>
|
||||
</form>
|
||||
</main>
|
||||
<script src="auth.js"></script>
|
||||
<script src="login.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
document.getElementById('login-form').addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
const email = document.getElementById('email').value;
|
||||
const password = document.getElementById('password').value;
|
||||
|
||||
fetch('/login', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ email, password })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.token) {
|
||||
localStorage.setItem('token', data.token);
|
||||
window.location.href = 'index.html';
|
||||
} else {
|
||||
alert('Email ou mot de passe incorrect');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Détails du Film</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Détails du Film</h1>
|
||||
<nav>
|
||||
<a href="index.html">Accueil</a>
|
||||
<a href="login.html" id="login-link">Connexion</a>
|
||||
<a href="register.html" id="register-link">Inscription</a>
|
||||
<button id="logout-button" style="display: none;">Déconnexion</button>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<div id="movie-details">
|
||||
<!-- Détails du film -->
|
||||
</div>
|
||||
<video id="movie-video" controls>
|
||||
<source id="movie-source" type="video/mp4">
|
||||
Votre navigateur ne supporte pas la lecture de vidéos.
|
||||
</video>
|
||||
</main>
|
||||
<script src="auth.js"></script>
|
||||
<script src="movie.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,44 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const movieTitle = urlParams.get('title');
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
if (!token) {
|
||||
alert('Vous devez avoir un compte pour voir ce film.');
|
||||
window.location.href = 'login.html';
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/users/me', {
|
||||
headers: {
|
||||
'Authorization': token
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(user => {
|
||||
console.log(user)
|
||||
if (user.status !== 'approved' && user.status !== 'admin') {
|
||||
alert('Votre compte n\'a pas encore été approuvé par un administrateur.');
|
||||
window.location.href = 'index.html';
|
||||
} else {
|
||||
fetch(`/movie/${encodeURIComponent(movieTitle)}`, {
|
||||
headers: {
|
||||
'Authorization': token
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(movie => {
|
||||
const movieDetails = document.getElementById('movie-details');
|
||||
movieDetails.innerHTML = `
|
||||
<h2>${movie.title}</h2>
|
||||
<p>${movie.description}</p>
|
||||
<img src="${movie.cover}" alt="${movie.title}">
|
||||
`;
|
||||
const movieSource = document.getElementById('movie-source');
|
||||
movieSource.src = movie.video;
|
||||
const movieVideo = document.getElementById('movie-video');
|
||||
movieVideo.load();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profil Utilisateur</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Profil Utilisateur</h1>
|
||||
<nav>
|
||||
<a href="index.html">Accueil</a>
|
||||
<a href="login.html" id="login-link">Connexion</a>
|
||||
<a href="register.html" id="register-link">Inscription</a>
|
||||
<a href="profile.html" id="profile-link" style="display: none;">Profil</a>
|
||||
<a href="admin.html" id="admin-link" style="display: none;">Administration</a>
|
||||
<button id="logout-button" style="display: none;">Déconnexion</button>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<div id="profile-details">
|
||||
<!-- Détails du profil utilisateur -->
|
||||
</div>
|
||||
</main>
|
||||
<script src="auth.js"></script>
|
||||
<script src="profile.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,23 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const token = localStorage.getItem('token');
|
||||
|
||||
if (!token) {
|
||||
alert('Vous devez être connecté pour accéder à votre profil.');
|
||||
window.location.href = 'login.html';
|
||||
return;
|
||||
}
|
||||
|
||||
fetch('/profile', {
|
||||
headers: {
|
||||
'Authorization': token
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(user => {
|
||||
const profileDetails = document.getElementById('profile-details');
|
||||
profileDetails.innerHTML = `
|
||||
<h2>Profil de ${user.email}</h2>
|
||||
<p>Status: ${user.status}</p>
|
||||
`;
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Inscription</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Inscription</h1>
|
||||
<nav>
|
||||
<a href="index.html">Accueil</a>
|
||||
<a href="login.html" id="login-link">Connexion</a>
|
||||
<a href="register.html" id="register-link">Inscription</a>
|
||||
<button id="logout-button" style="display: none;">Déconnexion</button>
|
||||
</nav>
|
||||
</header>
|
||||
<main>
|
||||
<form id="register-form" class="auth-form">
|
||||
<label for="email">Email :</label>
|
||||
<input type="email" id="email" name="email" required>
|
||||
<label for="password">Mot de passe :</label>
|
||||
<input type="password" id="password" name="password" required>
|
||||
<button type="submit">Inscription</button>
|
||||
</form>
|
||||
</main>
|
||||
<script src="auth.js"></script>
|
||||
<script src="register.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
document.getElementById('register-form').addEventListener('submit', function(event) {
|
||||
event.preventDefault();
|
||||
const email = document.getElementById('email').value;
|
||||
const password = document.getElementById('password').value;
|
||||
|
||||
fetch('/register', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ email, password })
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.token) {
|
||||
localStorage.setItem('token', data.token);
|
||||
window.location.href = 'index.html';
|
||||
} else {
|
||||
alert('Erreur lors de l\'inscription');
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fetch('/movies')
|
||||
.then(response => response.json())
|
||||
.then(movies => {
|
||||
const moviesGrid = document.getElementById('movies-grid');
|
||||
movies.forEach(movie => {
|
||||
const movieElement = document.createElement('div');
|
||||
movieElement.classList.add('movie');
|
||||
movieElement.innerHTML = `
|
||||
<img src="${movie.cover}" alt="${movie.title}">
|
||||
<h3>${movie.title}</h3>
|
||||
`;
|
||||
movieElement.addEventListener('click', () => {
|
||||
window.location.href = `movie.html?title=${encodeURIComponent(movie.title)}`;
|
||||
});
|
||||
moviesGrid.appendChild(movieElement);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
nav a {
|
||||
color: #fff;
|
||||
margin: 0 1rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
nav button {
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.auth-form {
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
padding: 1rem;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.auth-form label {
|
||||
display: block;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.auth-form input {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.auth-form button {
|
||||
width: 100%;
|
||||
padding: 0.5rem;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#movies-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.movie {
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.movie img {
|
||||
max-width: 100%;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#movie-details {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#movie-video {
|
||||
display: block;
|
||||
margin: 2rem auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
const bcrypt = require('bcrypt');
|
||||
const jwt = require('jsonwebtoken');
|
||||
const db = require('./database');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const app = express();
|
||||
const port = 3000;
|
||||
|
||||
app.use(bodyParser.json());
|
||||
app.use(express.static('public'));
|
||||
app.use('/movies', express.static(path.join(__dirname, 'movies')));
|
||||
|
||||
const authenticateToken = (req, res, next) => {
|
||||
const token = req.headers['authorization'];
|
||||
if (!token) return res.sendStatus(401);
|
||||
|
||||
jwt.verify(token, 'secret_key', (err, user) => {
|
||||
if (err) return res.sendStatus(403);
|
||||
req.user = user;
|
||||
next();
|
||||
});
|
||||
};
|
||||
|
||||
const checkApproval = (req, res, next) => {
|
||||
db.get(`SELECT status FROM users WHERE id = ?`, [req.user.id], (err, user) => {
|
||||
if (err || !user || (user.status !== 'approved' && user.status !== 'admin')) {
|
||||
return res.status(403).json({ message: 'Votre compte n\'a pas encore été approuvé par un administrateur.' });
|
||||
}
|
||||
next();
|
||||
});
|
||||
};
|
||||
|
||||
const checkAdmin = (req, res, next) => {
|
||||
db.get(`SELECT status FROM users WHERE id = ?`, [req.user.id], (err, user) => {
|
||||
if (err || !user || user.status !== 'admin') {
|
||||
return res.status(403).json({ message: 'Accès réservé aux administrateurs.' });
|
||||
}
|
||||
next();
|
||||
});
|
||||
};
|
||||
|
||||
// Route pour afficher la liste des films
|
||||
app.get('/movies', (req, res) => {
|
||||
const moviesDir = path.join(__dirname, 'movies');
|
||||
fs.readdir(moviesDir, (err, files) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ message: 'Erreur lors de la lecture des films' });
|
||||
}
|
||||
|
||||
const movies = files.map(file => {
|
||||
const moviePath = path.join(moviesDir, file);
|
||||
const movieData = JSON.parse(fs.readFileSync(path.join(moviePath, 'info.json')));
|
||||
return {
|
||||
title: movieData.title,
|
||||
cover: `/movies/${file}/cover.jpg`
|
||||
};
|
||||
});
|
||||
|
||||
res.json(movies);
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/movie/:title', (req, res) => {
|
||||
const movieTitle = req.params.title;
|
||||
const moviesDir = path.join(__dirname, 'movies');
|
||||
fs.readdir(moviesDir, (err, files) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ message: 'Erreur lors de la lecture des films' });
|
||||
}
|
||||
|
||||
const movieFile = files.find(file => {
|
||||
const moviePath = path.join(moviesDir, file);
|
||||
const movieData = JSON.parse(fs.readFileSync(path.join(moviePath, 'info.json')));
|
||||
return movieData.title === movieTitle;
|
||||
});
|
||||
|
||||
if (!movieFile) {
|
||||
return res.status(404).json({ message: 'Film non trouvé' });
|
||||
}
|
||||
|
||||
const moviePath = path.join(moviesDir, movieFile);
|
||||
const movieData = JSON.parse(fs.readFileSync(path.join(moviePath, 'info.json')));
|
||||
movieData.cover = `/movies/${movieFile}/cover.jpg`;
|
||||
movieData.video = `/movies/${movieFile}/video.mp4`;
|
||||
|
||||
res.json(movieData);
|
||||
});
|
||||
});
|
||||
|
||||
// Route pour gérer l'inscription des utilisateurs
|
||||
app.post('/register', (req, res) => {
|
||||
const { email, password } = req.body;
|
||||
const hashedPassword = bcrypt.hashSync(password, 10);
|
||||
|
||||
db.run(`INSERT INTO users (email, password) VALUES (?, ?)`, [email, hashedPassword], function(err) {
|
||||
if (err) {
|
||||
return res.status(500).json({ message: 'Erreur lors de l\'inscription' });
|
||||
}
|
||||
|
||||
const userId = this.lastID;
|
||||
const token = jwt.sign({ id: userId }, 'secret_key', { expiresIn: '1h' });
|
||||
res.status(201).json({ message: 'Utilisateur inscrit avec succès', token });
|
||||
});
|
||||
});
|
||||
|
||||
// Route pour gérer la connexion des utilisateurs
|
||||
app.post('/login', (req, res) => {
|
||||
const { email, password } = req.body;
|
||||
|
||||
db.get(`SELECT * FROM users WHERE email = ?`, [email], (err, user) => {
|
||||
if (err || !user || !bcrypt.compareSync(password, user.password)) {
|
||||
return res.status(401).json({ message: 'Email ou mot de passe incorrect' });
|
||||
}
|
||||
|
||||
const token = jwt.sign({ id: user.id }, 'secret_key', { expiresIn: '1h' });
|
||||
res.json({ token });
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/users/me', authenticateToken, (req, res) => {
|
||||
db.get(`SELECT email, status FROM users WHERE id = ?`, [req.user.id], (err, user) => {
|
||||
if (err || !user) {
|
||||
return res.status(500).json({ message: 'Erreur lors de la récupération des informations utilisateur' });
|
||||
}
|
||||
res.json(user);
|
||||
});
|
||||
});
|
||||
|
||||
// Route pour récupérer tous les utilisateurs
|
||||
app.get('/users', authenticateToken, checkAdmin, (req, res) => {
|
||||
db.all(`SELECT id, email, status FROM users`, (err, users) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ message: 'Erreur lors de la récupération des utilisateurs' });
|
||||
}
|
||||
res.json(users);
|
||||
});
|
||||
});
|
||||
|
||||
// Route pour approuver un utilisateur
|
||||
app.post('/approve', authenticateToken, checkAdmin, (req, res) => {
|
||||
const { userId } = req.body;
|
||||
db.run(`UPDATE users SET status = 'approved' WHERE id = ?`, [userId], function(err) {
|
||||
if (err) {
|
||||
return res.status(500).json({ message: 'Erreur lors de l\'approbation de l\'utilisateur' });
|
||||
}
|
||||
res.json({ message: 'Utilisateur approuvé avec succès' });
|
||||
});
|
||||
});
|
||||
|
||||
// Route pour supprimer un utilisateur
|
||||
app.post('/delete', authenticateToken, checkAdmin, (req, res) => {
|
||||
const { userId } = req.body;
|
||||
db.run(`DELETE FROM users WHERE id = ?`, [userId], function(err) {
|
||||
if (err) {
|
||||
return res.status(500).json({ message: 'Erreur lors de la suppression de l\'utilisateur' });
|
||||
}
|
||||
res.json({ message: 'Utilisateur supprimé avec succès' });
|
||||
});
|
||||
});
|
||||
|
||||
// Route pour promouvoir un utilisateur en administrateur
|
||||
app.post('/make-admin', authenticateToken, checkAdmin, (req, res) => {
|
||||
const { userId } = req.body;
|
||||
db.run(`UPDATE users SET status = 'admin' WHERE id = ?`, [userId], function(err) {
|
||||
if (err) {
|
||||
return res.status(500).json({ message: 'Erreur lors de la promotion de l\'utilisateur' });
|
||||
}
|
||||
res.json({ message: 'Utilisateur promu administrateur avec succès' });
|
||||
});
|
||||
});
|
||||
|
||||
// Route pour lire les fichiers vidéo
|
||||
app.get('/video/:filename', authenticateToken, checkApproval, (req, res) => {
|
||||
const filePath = path.join(__dirname, 'movies', req.params.filename, 'video.mp4');
|
||||
const stat = fs.statSync(filePath);
|
||||
const fileSize = stat.size;
|
||||
const range = req.headers.range;
|
||||
|
||||
if (range) {
|
||||
const parts = range.replace(/bytes=/, "").split("-");
|
||||
const start = parseInt(parts[0], 10);
|
||||
const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1;
|
||||
const chunksize = (end - start) + 1;
|
||||
const file = fs.createReadStream(filePath, { start, end });
|
||||
const head = {
|
||||
'Content-Range': `bytes ${start}-${end}/${fileSize}`,
|
||||
'Accept-Ranges': 'bytes',
|
||||
'Content-Length': chunksize,
|
||||
'Content-Type': 'video/mp4',
|
||||
};
|
||||
res.writeHead(206, head);
|
||||
file.pipe(res);
|
||||
} else {
|
||||
const head = {
|
||||
'Content-Length': fileSize,
|
||||
'Content-Type': 'video/mp4',
|
||||
};
|
||||
res.writeHead(200, head);
|
||||
fs.createReadStream(filePath).pipe(res);
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/profile', authenticateToken, (req, res) => {
|
||||
db.get(`SELECT email, status FROM users WHERE id = ?`, [req.user.id], (err, user) => {
|
||||
if (err || !user) {
|
||||
return res.status(500).json({ message: 'Erreur lors de la récupération des informations utilisateur' });
|
||||
}
|
||||
res.json(user);
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Serveur démarré sur http://localhost:${port}`);
|
||||
});
|
||||
Reference in New Issue
Block a user