From 2057d693cd0b411a9c468ddec6f3732ec7117e03 Mon Sep 17 00:00:00 2001 From: jfgiraud Date: Wed, 22 Jul 2026 16:37:53 +0200 Subject: [PATCH] Initial commit - Bolsa app avec Tailwind et authentification --- .gitignore | 20 +++ Dockerfile | 9 ++ app/__init__.py | 38 +++++ app/routes.py | 56 +++++++ app/static/images/GFBlancLogo.png | Bin 0 -> 63122 bytes app/static/images/favicon.png | Bin 0 -> 630 bytes app/templates/base.html | 204 ++++++++++++++++++++++++ app/templates/gestion_utilisateurs.html | 45 ++++++ app/templates/index.html | 58 +++++++ app/templates/menu.html | 73 +++++++++ create_user.py | 31 ++++ create_user.txt | 5 + docker-compose.yml | 51 ++++++ run.py | 4 + 14 files changed, 594 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 app/__init__.py create mode 100644 app/routes.py create mode 100644 app/static/images/GFBlancLogo.png create mode 100644 app/static/images/favicon.png create mode 100644 app/templates/base.html create mode 100644 app/templates/gestion_utilisateurs.html create mode 100644 app/templates/index.html create mode 100644 app/templates/menu.html create mode 100644 create_user.py create mode 100644 create_user.txt create mode 100644 docker-compose.yml create mode 100644 run.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..362ccfc --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +# Environnement virtuel +venv/ +env/ +ENV/ + +# Cache Python +__pycache__/ +*.py[cod] +*$py.class + +# Fichiers de configuration IDE / Système +.vscode/ +.idea/ +.DS_Store + +# Fichiers de base de données locaux (si applicable) +*.sqlite3 + +# Base de données MySQL Docker +mysql_data/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..34eba76 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.11-slim + +WORKDIR /app + +RUN pip install --no-cache-dir flask flask-sqlalchemy pymysql cryptography + +EXPOSE 5000 + +CMD ["python", "run.py"] diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..26b6cd9 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,38 @@ +import time +from flask import Flask, render_template +from flask_sqlalchemy import SQLAlchemy +from sqlalchemy.exc import OperationalError + +db = SQLAlchemy() + +def create_app(): + app = Flask(__name__) + app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://jfgiraud:lyon4@db/bolsa' + app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False + app.config['SECRET_KEY'] = 'votre_cle_secrete_tres_securisee_jfgiraud04051963++fin' + + db.init_app(app) + + # Tentative de connexion et création des tables au démarrage du conteneur + with app.app_context(): + max_retries = 15 + delay = 2 + for i in range(max_retries): + try: + db.create_all() + print("Base de données connectée et tables initialisées avec succès.") + break + except OperationalError as e: + print(f"Tentative {i+1}/{max_retries} : MySQL n'est pas encore prêt. Nouvelle tentative dans {delay}s...") + time.sleep(delay) + else: + raise Exception("Impossible d'initialiser la base de données après plusieurs tentatives.") + + # Enregistrement des routes (Blueprint) + from app.routes import main + app.register_blueprint(main) + + return app + +# Expose 'app' pour que run.py puisse l'importer directement +app = create_app() \ No newline at end of file diff --git a/app/routes.py b/app/routes.py new file mode 100644 index 0000000..8538f78 --- /dev/null +++ b/app/routes.py @@ -0,0 +1,56 @@ +from flask import Blueprint, render_template, request, redirect, url_for, session, flash +from werkzeug.security import check_password_hash +from sqlalchemy import text +from app import db +from datetime import datetime + +main = Blueprint('main', __name__) + +@main.route('/', methods=['GET', 'POST']) +def index(): + if 'user_id' in session: + return redirect(url_for('main.menu')) + + if 'login_attempts' not in session: + session['login_attempts'] = 0 + + if request.method == 'POST': + user_login = request.form.get('login') + user_pass = request.form.get('pass') + + query = text("SELECT id, pass AS user_pass, nom, prenom FROM login WHERE login = :login AND actif = 1") + result = db.session.execute(query, {"login": user_login}).fetchone() + + if result and check_password_hash(result.user_pass, user_pass): + session.pop('login_attempts', None) + session['user_id'] = result.id + session['user_name'] = f"{result.prenom} {result.nom}" + return redirect(url_for('main.menu')) + else: + session['login_attempts'] += 1 + + if session['login_attempts'] >= 3: + session.pop('login_attempts', None) + return redirect('https://giraud-finance.com') + + essais_restants = 3 - session['login_attempts'] + flash(f"Identifiant ou mot de passe incorrect. Il vous reste {essais_restants} essai(s).", "danger") + + return render_template('index.html') + +@main.route('/menu') +def menu(): + if 'user_id' not in session: + return redirect(url_for('main.index')) + return render_template('menu.html') + +@main.route('/logout') +def logout(): + session.clear() + return redirect(url_for('main.index')) + +@main.route('/gestion-utilisateurs') +def gestion_utilisateurs(): + if 'user_id' not in session: + return redirect(url_for('main.index')) + return render_template('gestion_utilisateurs.html') \ No newline at end of file diff --git a/app/static/images/GFBlancLogo.png b/app/static/images/GFBlancLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..beebbdc835054832a5b92348b8752f2622f88636 GIT binary patch literal 63122 zcmeFYbx>T*w>CPsyZa!)WpD}Zt`RJR!QCOayE_C6p5X2-!QF$qLvWXG^1eSib-$`x zr|v!foneNW-M#wh)z6Zay(dgnSq2T67#RQnpvlQfssjK}d64gVnDCJQtKQ#x0RX%q z_jj63>fkRxI|o}6b1P$@lbf9}(Ad@71ORYdEK4(w-{x}&dcDLIfaXCU?eDTEB-y`v zAg8V_ENSjnG)Y^gikI{EWwV94lNhlD#5mP{v6}i&O4N* zwmJHOKGOlSb9FEAgborOMy~UCJi^}n0=H*+|8nnrMcwe__;bM1y@$D^EeV37JY7HO z-B-tFMc`43;MaY7yR*ICF!qMqHg9d^wF1mopKuLTllB@f?_tT8d5WuZCM*#Op}-Qu zo!1v&+-LBst(@d z#;s7^tXt=wKXDZViq6xfXPj-`CoDy&~V26U|szgg+v%_fbRU2L5jEavWoa zJ3-8&=a|_p@Sey(`)MxukiH{qEW@nT`+=$cnamf{-qw(VJ;6`auwK*9jG>M&EHB|( zm#A`ofgEzK*5U{U-b38B>r`7);m_M;qXS36Git14Cb9z>v)B@7adnY0K5i~%9rhZF z(dFi-G|Qq7me%j-1+;Anv`WgjZQIbs^_E-R9er9K_lrzb=iE=qJbrtj+6WN3*52|GT|EEJR&kXQAjjnaFdbLeYxn zaGj2Ai}xd0M>YO8746rXd!KRbr$KFZ&H|jJic))XOA!glt}q5uBjzO8zH|;C&AT!G ze)Xxm83xl@-cR5#t+e=>JPv92;jlrQr=%7iM>!F7i zSO&B@9$3dAu7Pu6c=8JRhgCPH6`#BtheUIgtw=(Zq2C${$=I}M9ENdI>Ijx+r66~l z!rn^DZ#DHG>9lQtv^oYK^jus-V1Z=i5wJKb;=~_0cX3!dGnL6IA&@ceZ^JE zeA@ni>g-Yj(y8#+wuvHj))SqUX6NIVa%1-Q(yn*YHZA5~+>GQmTbZLTtro%_t1Dhg zHJmRsp`PQ%PS0GD&*U1BO#N94{wBqQY8fGrT^_-j&D~fy>V(LRRy&_*T}Ez3GQhqq zcc~r_@uI^bT&on7aLj!APR{(xP~i?|x7xLuU~75JVbivI5+d

%6uvJYHk5eV1Rf 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�X*k{^+762}=)+>B90cwxj;G_w?_s&q;KB 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 QkpKVy07*qoM6N<$f-OlOxc~qF literal 0 HcmV?d00001 diff --git a/app/templates/base.html b/app/templates/base.html new file mode 100644 index 0000000..7e694b1 --- /dev/null +++ b/app/templates/base.html @@ -0,0 +1,204 @@ + + + + + + {% block title %}Bolsa App{% endblock %} + + + + + + + + + +

+ + + + +
+

Bolsa

+
+ + +
+
+ Paris : --:--:-- + +
+
+ New-York : --:--:-- + +
+ {% if session.get('user_id') %} + + {% endif %} +
+
+ + +
+ {% block content %}{% endblock %} +
+ + +
+ +
+ + +
+

copyright © Jean-François GIRAUD - Giraud Finance - 2026

+
+ + +
+ {% if session.get('user_id') %} +
+ {{ session.get('user_name') }} +
+
+ {{ session.get('user_ip', 'IP inconnue') }} +
+ {% endif %} +
+
+ + + {% if session.get('user_id') %} + + {% endif %} + + + + + diff --git a/app/templates/gestion_utilisateurs.html b/app/templates/gestion_utilisateurs.html new file mode 100644 index 0000000..66e2180 --- /dev/null +++ b/app/templates/gestion_utilisateurs.html @@ -0,0 +1,45 @@ +{% extends "base.html" %} {% block title %}Gestion des utilisateurs - Bolsa{% +endblock %} {% block header_title %}Gestion utilisateurs{% endblock %} {% block +content %} +
+ +
+ +
+
+

+ Administration des utilisateurs +

+

+ Gérez les accès et les comptes autorisés de l'application. +

+
+ + Retour au menu + +
+ + +
+

+ Module de gestion des utilisateurs en cours de chargement... +

+
+ + +
+ Positions en bourse : Accès sécurisé. Veillez à fermer votre session après + chaque utilisation. +
+
+
+{% endblock %} diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..711ff33 --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,58 @@ +{% extends "base.html" %} {% block title %}Connexion - Bolsa{% endblock %} {% +block content %} +
+
+

+ Connexion +

+ + + {% with messages = get_flashed_messages() %} {% if messages %} +
+ {% for message in messages %} {{ message }} {% endfor %} +
+ {% endif %} {% endwith %} + +
+
+ + +
+ +
+ + +
+ + +
+
+
+{% endblock %} diff --git a/app/templates/menu.html b/app/templates/menu.html new file mode 100644 index 0000000..0c134ee --- /dev/null +++ b/app/templates/menu.html @@ -0,0 +1,73 @@ +{% extends "base.html" %} {% block title %}Menu - Bolsa{% endblock %} {% block +header_title %}Tableau de bord{% endblock %} {% block content %} +
+ +
+ +

Espace de gestion

+

+ Accédez aux fonctions clés de l'application financière. +

+ + + + + +
+ Positions en bourse : Accès sécurisé. Veillez à fermer votre session après + chaque utilisation. +
+
+
+{% endblock %} diff --git a/create_user.py b/create_user.py new file mode 100644 index 0000000..bbe0360 --- /dev/null +++ b/create_user.py @@ -0,0 +1,31 @@ +from werkzeug.security import generate_password_hash +from sqlalchemy import text +from app import app, db + +with app.app_context(): + # Définition des informations de l'utilisateur + login_name = "jfgiraud" + nom = "GIRAUD" + prenom = "Jean-François" + mail = "jfgiraud@giraud-finance.com" + # Génération du hash sécurisé pour le mot de passe "lyon4" + hashed_password = generate_password_hash("lyon4") + + # Requête d'insertion + query = text(""" + INSERT INTO login (login, nom, prenom, mail, pass, actif) + VALUES (:login, :nom, :prenom, :mail, :pass, 1) + ON DUPLICATE KEY UPDATE + pass = :pass, nom = :nom, prenom = :prenom, mail = :mail, actif = 1 + """) + + db.session.execute(query, { + "login": login_name, + "nom": nom, + "prenom": prenom, + "mail": mail, + "pass": hashed_password + }) + db.session.commit() + + print(f"Utilisateur '{login_name}' créé/mis à jour avec succès avec un mot de passe haché !") \ No newline at end of file diff --git a/create_user.txt b/create_user.txt new file mode 100644 index 0000000..01e0502 --- /dev/null +++ b/create_user.txt @@ -0,0 +1,5 @@ +Pour exécuter ce script directement à l'intérieur du conteneur web utiliser la commande suivante dans votre terminal : + +docker compose exec web python create_user.py + +Une fois cette commande passée, vous pourrez vous connecter sur votre page d'accueil avec le login jfgiraud et le mot de passe lyon4. \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e0e7d51 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,51 @@ +services: + db: + image: mysql:8.0 + environment: + MYSQL_ROOT_PASSWORD: sysadm-1963 + MYSQL_DATABASE: bolsa + MYSQL_USER: jfgiraud + MYSQL_PASSWORD: lyon4 + volumes: + - db_data:/var/lib/mysql + healthcheck: + test: + [ + "CMD", + "mysqladmin", + "ping", + "-h", + "127.0.0.1", + "-u", + "root", + "-psysadm-1963", + ] + interval: 3s + timeout: 3s + retries: 10 + + web: + build: . + command: python run.py + volumes: + - .:/app + ports: + - "5000:5000" + environment: + - DATABASE_URL=mysql+pymysql://jfgiraud:lyon4@db/bolsa + depends_on: + db: + condition: service_healthy + + phpmyadmin: + image: phpmyadmin/phpmyadmin + ports: + - "8080:80" + environment: + PMA_HOST: db + MYSQL_ROOT_PASSWORD: sysadm-1963 + depends_on: + - db + +volumes: + db_data: diff --git a/run.py b/run.py new file mode 100644 index 0000000..7592ef5 --- /dev/null +++ b/run.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000, debug=True) \ No newline at end of file