Backend : Node.js avec Express.
js et MongoDB
Pour le backend, nous utiliserons Node.js avec le framework Express.js pour l'API et Mongoose pour
interagir avec MongoDB.
1. Initialisation du Projet Node.js
Naviguez dans le dossier filmflex/ et exécutez :
Bash
npm init -y
npm install express mongoose dotenv bcryptjs jsonwebtoken
express : Framework web pour Node.js.
mongoose : ODM (Object Data Modeling) pour MongoDB, facilitant l'interaction avec la base
de données.
dotenv : Pour charger les variables d'environnement (ex: votre chaîne de connexion
MongoDB).
bcryptjs : Pour hacher les mots de passe de manière sécurisée.
jsonwebtoken : Pour l'authentification basée sur les tokens (JWT).
2. .env (Variables d'Environnement)
Créez un fichier .env à la racine de votre projet :
MONGO_URI=mongodb://localhost:27017/filmflexbd
JWT_SECRET=supersecretjwtkey (changez cette clé !)
3. server.js (Serveur Express)
JavaScript
require('dotenv').config(); // Charge les variables d'environnement
const express = require('express');
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const path = require('path');
const app = express();
const PORT = process.env.PORT || 5000;
// Middleware pour parser le JSON
app.use(express.json());
// Servir les fichiers statiques du dossier 'public'
app.use(express.static(path.join(__dirname, 'public')));
// Connexion à la base de données MongoDB
mongoose.connect(process.env.MONGO_URI)
.then(() => console.log('Connecté à MongoDB : filmflexbd'))
.catch(err => console.error('Erreur de connexion à MongoDB:', err));
// --- Schémas et Modèles Mongoose ---
// Schéma Utilisateur
const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true },
createdAt: { type: Date, default: Date.now }
});
// Hashage du mot de passe avant de sauvegarder
userSchema.pre('save', async function(next) {
if (!this.isModified('password')) {
return next();
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
});
const User = mongoose.model('User', userSchema);
// Schéma Film/Série (simplifié)
const contentSchema = new mongoose.Schema({
title: { type: String, required: true },
description: { type: String, required: true },
imageUrl: { type: String, required: true },
type: { type: String, enum: ['movie', 'series'], required: true }, // 'movie' ou 'series'
genre: [String],
releaseYear: Number,
rating: Number,
// ... d'autres champs pertinents
});
const Content = mongoose.model('Content', contentSchema);
// --- Routes d'API ---
// Route d'Inscription
app.post('/api/register', async (req, res) => {
const { username, email, password } = req.body;
try {
let user = await User.findOne({ email });
if (user) {
return res.status(400).json({ message: 'L\'utilisateur avec cet email existe déjà.' });
user = new User({ username, email, password });
await user.save();
res.status(201).json({ message: 'Inscription réussie !' });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Erreur serveur lors de l\'inscription.' });
});
// Route de Connexion
app.post('/api/login', async (req, res) => {
const { email, password } = req.body;
try {
const user = await User.findOne({ email });
if (!user) {
return res.status(400).json({ message: 'Identifiants invalides.' });
const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(400).json({ message: 'Identifiants invalides.' });
// Générer un token JWT
const token = jwt.sign(
{ id: user._id, username: user.username },
process.env.JWT_SECRET,
{ expiresIn: '1h' } // Token expire après 1 heure
);
res.json({ message: 'Connexion réussie !', token });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Erreur serveur lors de la connexion.' });
});
// Middleware d'authentification (pour les routes protégées)
const auth = (req, res, next) => {
const token = req.header('x-auth-token'); // Récupérer le token depuis l'en-tête
if (!token) {
return res.status(401).json({ message: 'Pas de token, autorisation refusée.' });
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded; // Ajoute les infos de l'utilisateur décodées à la requête
next();
} catch (error) {
res.status(401).json({ message: 'Token non valide.' });
};
// Exemple de route protégée (nécessite d'être connecté)
app.get('/api/protected', auth, (req, res) => {
res.json({ message: `Bienvenue ${req.user.username}, vous êtes connecté et accédez à une
ressource protégée !` });
});
// Routes pour les films et séries
app.get('/api/movies', async (req, res) => {
try {
const movies = await Content.find({ type: 'movie' });
res.json(movies);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Erreur lors de la récupération des films.' });
});
app.get('/api/series', async (req, res) => {
try {
const series = await Content.find({ type: 'series' });
res.json(series);
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Erreur lors de la récupération des séries.' });
});
// Ajout de contenu (exemple, peut être protégé par un rôle admin)
app.post('/api/content', auth, async (req, res) => {
const { title, description, imageUrl, type, genre, releaseYear, rating } = req.body;
try {
const newContent = new Content({
title, description, imageUrl, type, genre, releaseYear, rating
});
await newContent.save();
res.status(201).json({ message: 'Contenu ajouté avec succès !', content: newContent });
} catch (error) {
console.error(error);
res.status(500).json({ message: 'Erreur lors de l\'ajout du contenu.' });
});
// --- Gestion des Paiements (Concepteuel) ---
// Pour les modes de paiement comme Orange Money, MTN MoMo, PayPal, vous devrez intégrer
// les API de ces services. C'est une partie très complexe et sensible.
// Voici un exemple conceptuel de route de paiement :
app.post('/api/payment/orange-money', auth, async (req, res) => {
const { amount, phoneNumber } = req.body;
// Logique d'intégration avec l'API Orange Money
// Cela impliquerait d'envoyer une requête à l'API d'Orange Money,
// de gérer les callbacks (webhook) pour confirmer le paiement.
console.log(`Tentative de paiement Orange Money de ${amount} avec ${phoneNumber}`);
res.status(200).json({ message: 'Paiement Orange Money initié. En attente de confirmation...' });
});
app.post('/api/payment/mtn-momo', auth, async (req, res) => {
const { amount, phoneNumber } = req.body;
// Logique d'intégration avec l'API MTN MoMo
console.log(`Tentative de paiement MTN MoMo de ${amount} avec ${phoneNumber}`);
res.status(200).json({ message: 'Paiement MTN MoMo initié. En attente de confirmation...' });
});
app.post('/api/payment/paypal', auth, async (req, res) => {
const { amount } = req.body;
// Logique d'intégration avec l'API PayPal (SDK côté serveur)
// Cela générerait un lien de paiement PayPal ou une transaction directe.
console.log(`Tentative de paiement PayPal de ${amount}`);
res.status(200).json({ message: 'Paiement PayPal initié. Redirection vers PayPal...' });
});
// Route par défaut pour toutes les autres requêtes (pour les SPA)
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
// Démarrer le serveur
app.listen(PORT, () => {
console.log(`Serveur démarré sur http://localhost:${PORT}`);
});
Fonctionnement Global et Étapes Suivantes
1. Démarrer MongoDB : Assurez-vous que votre serveur MongoDB est en cours d'exécution
(par défaut sur mongodb://localhost:27017).
2. Démarrer le Backend :
Bash
cd filmflex
node server.js
Le serveur écoutera sur http://localhost:5000.
3. Accéder au Site : Ouvrez votre navigateur et allez sur http://localhost:5000.
Prochaines Étapes Cruciales pour un Vrai Site :
Gestion des Erreurs Robuste : Ajouter plus de gestion des erreurs côté client et serveur.
Validation des Entrées : Valider toutes les données envoyées par l'utilisateur (backend et
frontend).
Sécurité :
o Implémenter des mesures de sécurité supplémentaires (CORS, CSRF, XSS).
o Ne jamais exposer les clés API sensibles côté client.
Gestion des Sessions/Tokens : Affiner la gestion des tokens JWT, y compris le
rafraîchissement des tokens.
Déploiement : Apprendre à déployer votre application sur un serveur (Heroku, Vercel, Netlify
pour le frontend, AWS, DigitalOcean pour le backend).
Contenu Dynamique : Remplir votre base de données filmflexbd avec de vraies données de
films et séries.
Interface Utilisateur Avancée :
o Ajouter des fonctionnalités de recherche et de filtrage.
o Créer des pages de détails pour chaque film/série.
o Implémenter un lecteur vidéo.
Intégration des Paiements Réels : C'est une étape majeure et délicate. Vous devrez vous
inscrire auprès d'Orange Money, MTN MoMo, et PayPal pour obtenir leurs API et
documentations techniques, puis les intégrer de manière sécurisée.
Dashboards Admin : Pour gérer le contenu (ajouter, modifier, supprimer films/séries).
Ce guide vous donne une base solide et les concepts clés pour construire votre site "FilmFlex". La
réalisation complète demandera un apprentissage approfondi de chaque technologie mentionnée.
N'hésitez pas à poser des questions si vous avez besoin de précisions sur des parties spécifiques !
Sources