Skip to content

Roceann/Next-Step

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

121 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Next-Step - Présentation globale

Description

Next-Step est un projet "Job Board" (plateforme d'offres d'emploi) composé d'un frontend en Next.js et d'un backend en Flask. Il utilise PostgreSQL pour la base de données et MinIO pour le stockage des fichiers (CV, photos, logos, lettres de motivation).

Tech Stack et pourquoi ce choix

  • Frontend : Next.js — routage simple, riche écosystème React.
  • Backend : Flask — léger, adapté aux APIs.
  • Base de données : PostgreSQL — fiable et supporte UUID.
  • Stockage : MinIO — stockage d'objets pour fichiers volumineux, interface graphique.
  • Auth & sécurité : JWT + Flask-Bcrypt — auth sans état et mots de passe hachés.
  • ORM : Flask-SQLAlchemy — mapping Python ↔ Postgres et création automatique des tables.

Step 0 — Lancement & stack (installation rapide)

Liens officiels pour l'installation de toutes les prérequis du projet :

0.0) Cloner le projet

Clonez le dépôt si ce n'est pas déjà fait :

git clone https://github.com/EpitechMscProPromo2028/T-WEB-501-PAR_1
cd T-WEB-501-PAR_1

0.1) Démarrer les services Docker (Postgres + MinIO)

Depuis la racine du projet (là où se trouve docker-compose.yml, donc juste après avoir fait cd T-WEB-501-PAR_1), lancez :

sudo docker compose up -d

Si cette commande ne fonctionne pas, la commande doit probablement être :

sudo docker-compose up -d

(La commande peut varier selon votre OS — voir la documentation Docker ci-dessus.)

0.2) Fichier d'environnement et lien avec la configuration

Créez flask/.env contenant :

DATABASE_URL=postgresql+psycopg://user:password@localhost:5432/webapp
MINIO_ENDPOINT=localhost:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin123
MINIO_BUCKET=documents
MINIO_SECURE=False
SECRET_KEY=une_clé_secrète_pour_votre_environnement

Le fichier .env contient les variables lues par l'application. Le fichier flask/config.py utilise python-dotenv et os.environ.get(...) pour peupler Config (ex. Config.SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')). Modifier .env change uniquement la configuration sans toucher au code.

  • DATABASE_URL : connexion à Postgres.
  • MINIO_* : connexion à MinIO.
  • SECRET_KEY : clé secrète pour JWT (générer une valeur aléatoire et secrète).

Pour générer rapidement une SECRET_KEY :

python3 -c "import os; print(os.urandom(24).hex())"

(La commande peut varier selon l'OS — voir la documentation Python.)

0.3) Préparer et lancer le backend (Flask)

Toujours depuis la racine du projet :

python3 -m venv .venv
source .venv/bin/activate
pip install -r flask/requirements.txt
python3 flask/app.py

Ces commandes créent/activent un environnement virtuel, installent les dépendances Python et démarrent le serveur Flask (par défaut sur http://localhost:5001).

0.4) Préparer et lancer le frontend (Next.js)

Dans un autre terminal :

cd next-step
npm install
npm run dev

Le serveur de développement Next.js écoute par défaut sur http://localhost:3000.


Step 1

Base de Données

Cette base de données PostgreSQL a été conçue pour fonctionner sans aucune configuration manuelle. Elle se déploie automatiquement via Docker et s'initialise lors du premier lancement de l'application Flask. L'objectif est d'avoir un système de données opérationnel immédiatement, avec toutes les tables et relations créées automatiquement par SQLAlchemy.

Architecture Docker

L'environnement utilise Docker Compose pour isoler et orchestrer les services de base de données. Cette approche garantit un environnement reproductible, simplifie le déploiement et évite les conflits de versions entre les différents environnements de développement.

PostgreSQL

  • Base : webapp
  • Utilisateur : user / password
  • Port : 5432 (mappé sur l'hôte)

MinIO (Stockage document)

  • Ports : 9000 (API) / 9001 (Console Web (admin))
  • Accès : minioadmin / minioadmin123

Choix des UUID

Les identifiants utilisent des UUID v4 plutôt que des entiers auto-incrémentés. Cette approche garantit des identifiants uniques et imprévisibles, empêchant ainsi de deviner les IDs d'autres enregistrements par simple incrémentation. Les UUID sont également plus scalables car ils peuvent être générés côté application sans conflit, même avec plusieurs bases de données distribuées.

Sécurité des Mots de Passe

Les mots de passe sont sécurisés avec Flask-Bcrypt qui utilise l'algorithme bcrypt pour le hachage. Les mots de passe ne sont jamais stockés en clair dans la base de données - seuls les hashs sont conservés. Le modèle People propose deux méthodes :

  • set_password(password) : hache et stocke le mot de passe
  • check_password(password) : vérifie si le mot de passe correspond au hash stocké

Initialisation Automatique Flask (app.py)

app.config['SQLALCHEMY_DATABASE_URI'] = Config.SQLALCHEMY_DATABASE_URI
db.init_app(app)

# Import des modèles
from models.people import People
from models.companies import Companies
# ...

# Création automatique des tables
with app.app_context():
    db.create_all()  # Analyse les modèles et crée le schéma

Flask-SQLAlchemy analyse automatiquement :

  • Les classes de modèles
  • Les relations entre les tables (ForeignKey, relationship)
  • Les liens entre les données
  • Génère les CREATE TABLE correspondants

Tables

Schéma de la base de données

Table Contenu Relations
people Profils utilisateurs (UUID, nom, email, CV, photo) → education, experience, skills, candidatures
companies Entreprises (UUID, nom, logo, email) → ads
ads Offres (UUID, titre, description, salaire) company_id, category_id
category Catégories d'emploi (UUID, nom) → ads
candidatures Postulations (person_id, ads_id, date) people ↔ ads
education Formations (person_id, école, dates) → people
experience Expériences pro (person_id, entreprise, dates) → people
skills Compétences (person_id, nom) → people

Stockage MinIOS3

MinIO sert de serveur de stockage de document pour gérer tous les fichiers de l'application. Ce choix permet de séparer les documents/images (images, PDFs) de la base de données relationnelle, offrant une meilleure performance et une scalabilité native avec distribution et réplication.

Les fichiers sont organisés dans un bucket principal documents avec des dossiers spécifiques : CV_fichier pour les CVs, Photo_de_profile pour les photos de profil, Logo_entreprise pour les logos des entreprises, et Lettre_de_motivation pour les lettres de motivation. Cette configuration se met en place automatiquement au démarrage.

Implémentation Flask-SQLAlchemy

Exemple avec la table Skills qui démontre l'utilisation des UUID et des relations :

class Skills(db.Model):
    __tablename__ = 'skills'
    
    id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    person_id = db.Column(UUID(as_uuid=True), ForeignKey('people.id'), nullable=False)
    name = db.Column(db.String(100), nullable=False)
    
    person = db.relationship('People', backref=db.backref('skills'))

Flask-SQLAlchemy génère automatiquement les liaisons entre les tables. La relation backref permet d'accéder aux compétences depuis un objet People via person.skills.

Technologies

  • Flask-SQLAlchemy : ORM Python ↔ PostgreSQL
  • UUID : Identifiants cryptographiquement sûrs
  • Docker Compose : Orchestration multi-conteneurs
  • MinIO : Stockage de document
  • Flask-Bcrypt : Hachage sécurisé des mots de passe

Step 2

Dans cette étape, nous avons développé le composant AdsCard.jsx pour afficher les offres d'emploi sous forme de cartes.

Chaque carte inclut :

  • Le titre de l'annonce
  • Le type de contrat et la catégorie, affichés dans des bulles colorées
  • La description de l'offre, tronquée si elle est trop longue
  • Un bouton "Plus d'informations" (actuellement non fonctionnel)

Le composant utilise Tailwind CSS pour le style et FontAwesome pour les icônes. On a également ajouté des données fictives dans page.js pour simuler quatre offres d'emploi et vérifier le bon fonctionnement des cartes.

Step 3

Dans cette étape, nous avons rendu le bouton "Plus d'informations" fonctionnel dans le composant AdsCard.jsx. En utilisant l'état React (useState), le bouton permet désormais de basculer entre l'affichage condensé et l'affichage complet des détails de l'offre sans recharger la page.

Fonctionnalités ajoutées :

  • Un clic sur le bouton "Plus d'informations" révèle les détails supplémentaires (entreprise, localisation, salaire, durée, diplôme requis) avec une animation fluide.
  • La description complète est affichée uniquement en mode étendu, et la description tronquée est cachée.
  • Le bouton change de texte et d'icône (flèche vers le haut/bas) selon l'état d'expansion.

Step 4

API REST Flask

Cette API REST sert de backend pour Next-Step, offrant toutes les fonctionnalités nécessaires pour gérer les utilisateurs, entreprises, offres d'emploi et candidatures. L'architecture modulaire basée sur des blueprints Flask garantit une séparation claire des responsabilités et facilite la maintenance du code.

Architecture API

L'API utilise une architecture Blueprint qui organise les routes par domaine fonctionnel. Chaque blueprint gère un aspect spécifique de l'application :

from routes import (
    ads_bp, candidatures_bp, category_bp, companies_bp, 
    education_bp, experience_bp, file_bp, people_bp, search_bp, skills_bp
)

app.register_blueprint(file_bp)  # Gestion des fichiers
app.register_blueprint(search_bp)  # Recherche avancée

Cette approche permet de grouper logiquement les endpoints et d'appliquer des middlewares spécifiques par domaine.

Endpoints Principaux

Gestion des Offres

  • GET /ads/<uuid> : Récupérer une offre spécifique
  • POST /ads : Créer une nouvelle offre d'emploi
  • PUT /ads/<uuid> : Modifier une offre existante
  • DELETE /ads/<uuid> : Supprimer une offre

Recherche Avancée

GET /search?sector_activity=IT&post_title=Developer&salary_min=50000&salary_max=80000

Le moteur de recherche utilise SQLAlchemy Query Builder avec jointures pour filtrer les offres selon multiple critères : secteur, titre, diplôme requis, et fourchette salariale.

Gestion des Fichiers

  • GET /file/profile_photo/<uuid> : Accès sécurisé aux photos de profil
  • GET /file/cv/<uuid> : Téléchargement des CVs
  • GET /file/company_logo/<uuid> : Logos des entreprises

Technologies Core

Flask-CORS

Cross-Origin Resource Sharing activé pour permettre les requêtes depuis le frontend Next.js hébergé sur un port différent :

from flask_cors import CORS
CORS(app)  # Autorise toutes les origines en développement

Validation et Sérialisation

Les données sont validées côté client (frontend) avec des champs required, puis traitées par des fonctions utilitaires comme return_ad() qui standardise le format de réponse JSON :

def return_ad(ad):
    return {
        "id": str(ad.id),
        "title": ad.title,
        "description": ad.description,
        "salary": ad.salary,
        "category_id": str(ad.category_id)
    }

Gestion d'Erreurs

Système unifié de gestion d'exceptions avec rollback automatique des transactions :

try:
    db.session.add(user)
    db.session.commit()
    return jsonify({"message": "Success"}), 201
except Exception as e:
    db.session.rollback()
    return jsonify({"error": str(e)}), 500

Service MinIO

MinIO S3 intégré via un service dédié pour la gestion centralisée des fichiers :

def upload_file(file_data, folder, entity_id):
    client = Minio(Config.MINIO_ENDPOINT, ...)
    file_name_store = f"{folder}/{entity_id}{file_data.filename}"
    client.put_object(Config.MINIO_BUCKET, file_name_store, file_data)

Les fichiers sont organisés par type (CV_fichier/, Photo_de_profile/, Logo_entreprise/) avec des URLs pré-signées pour l'accès sécurisé.

Configuration Environment

Variables d'environnement centralisées via python-dotenv :

class Config:
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
    SECRET_KEY = os.environ.get('SECRET_KEY')
    MINIO_ENDPOINT = os.environ.get('MINIO_ENDPOINT')

Cette approche sépare la configuration du code et facilite le déploiement multi-environnements.

Exemple d'Usage

Recherche d'Offres

GET /search?post_title=Developer&salary_min=50000

Cet endpoint retourne toutes les offres contenant "Developer" dans le titre avec un salaire minimum de 50 000€, démontrant la simplicité d'utilisation de l'API.

Technologies

  • Flask-SQLAlchemy : ORM avec support UUID natif
  • Flask-CORS : Communication cross-origin
  • MinIO Python SDK : Stockage S3-compatible
  • python-dotenv : Configuration d'environnement

Step 6

Authentification JWT

Le système d'authentification utilise le blueprint auth_bp avec JSON Web Tokens pour sécuriser l'API sans état de session côté serveur.

Authentification par Token

L'authentification par token remplace les sessions traditionnelles par des jetons cryptographiques. Après connexion, le serveur génère un token JWT contenant les informations utilisateur. Cette approche sans état améliore la scalabilité, la sécurité cryptographique et les performances en évitant les requêtes base de données répétées.

Configuration JWT

Le système utilise une clé secrète définie dans les variables d'environnement :

# .env
SECRET_KEY=your-super-secret-key-here

# config.py
SECRET_KEY = os.environ.get('SECRET_KEY')

Cette clé signe et valide tous les tokens JWT générés par l'application.

Endpoints

Inscription

POST /auth/register
{
  "email": "user@example.com",
  "password": "password123",
  "first_name": "John",
  "last_name": "Doe"
}

Supporte l'upload simultané de fichiers (CV, photo de profil) et génère automatiquement un token JWT.

Connexion

POST /auth/login
{
  "email": "user@example.com",
  "password": "password123"
}

Sécurité

Flask-Bcrypt hache les mots de passe avec l'algorithme bcrypt - aucun mot de passe en clair n'est stocké :

def set_password(self, password):
    self.password_hash = bcrypt.generate_password_hash(password).decode('utf-8')

Les tokens JWT incluent l'ID utilisateur et sont signés avec la clé secrète pour validation côté client.

Technologies

  • Flask-JWT : Authentification sans état
  • Flask-Bcrypt : Hachage sécurisé
  • MinIO Integration : Upload de fichiers

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •