import os import uuid import json # J'ai ajouté 'request' aux imports from flask import Flask, redirect, url_for, jsonify, session, render_template, request from flask_sqlalchemy import SQLAlchemy from authlib.integrations.flask_client import OAuth app = Flask(__name__) ANNOUNCE_FILE = os.path.join(os.path.dirname(__file__), "annonces.json") # Ta config DB actuelle app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://flaskuser:flaskpass@mariadb/flaskdb' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.secret_key = os.environ.get("SECRET_KEY", "dev-key") db = SQLAlchemy(app) # --- MODELE DE DONNEES POUR LES BLOCS --- class Block(db.Model): id = db.Column(db.Integer, primary_key=True) block_type = db.Column(db.String(50)) # ex: 'iframe', 'buttons', 'html' column_name = db.Column(db.String(20)) # ex: 'left', 'center', 'right' position = db.Column(db.Integer) # pour l'ordre (0, 1, 2...) data = db.Column(db.Text) # Contenu JSON (url, titre, etc.) def to_dict(self): return { "id": self.id, "type": self.block_type, "column": self.column_name, "position": self.position, "data": json.loads(self.data) if self.data else {} } # Création des tables si elles n'existent pas with app.app_context(): db.create_all() # ... (Ici, garde ta configuration OAUTH et tes routes Login/Logout/Auth inchangées) ... # ... (Garde aussi tes fonctions load_announces, save_announces etc.) ... oauth = OAuth(app) keycloak = oauth.register( name='keycloak', client_id='flask-app', client_secret='T5G5jzCBiphnBNh9uuj0f6YNc9HrP8r4', server_metadata_url='https://keycloak.ninolbt.com/realms/gesthub/.well-known/openid-configuration', client_kwargs={'scope': 'openid profile email'} ) @app.route('/') def index(): user = session.get('user') if user: return render_template('view/index.html', user=user) return redirect(url_for('login')) @app.route('/login') def login(): nonce = uuid.uuid4().hex session['nonce'] = nonce redirect_uri = url_for('auth', _external=True, _scheme='https') return keycloak.authorize_redirect(redirect_uri, nonce=nonce) @app.route('/auth') def auth(): token = keycloak.authorize_access_token() nonce = session.pop('nonce', None) userinfo = keycloak.parse_id_token(token, nonce=nonce) session['user'] = userinfo session["id_token"] = token.get("id_token") return redirect('/') @app.route("/logout") def logout(): id_token = session.get("id_token") session.clear() return redirect( f"https://keycloak.ninolbt.com/realms/gesthub/protocol/openid-connect/logout" f"?post_logout_redirect_uri=https://dashboard.ninolbt.com" f"&id_token_hint={id_token}" ) # --- API LAYOUT (Gestion des Blocs) --- @app.route('/api/layout', methods=['GET']) def get_layout(): # Récupère tous les blocs triés par position blocks = Block.query.order_by(Block.position).all() return jsonify([b.to_dict() for b in blocks]) @app.route('/api/layout/save', methods=['POST']) def save_layout(): # Sauvegarde l'ordre et la colonne après un drag & drop user = session.get("user") if not user or "/admin" not in user.get("groups", []): return jsonify({"error": "Unauthorized"}), 403 layout_data = request.json # Liste de {id, column, position} for item in layout_data: block = Block.query.get(item['id']) if block: block.column_name = item['column'] block.position = item['position'] db.session.commit() return jsonify({"status": "saved"}) @app.route('/api/block/add', methods=['POST']) def add_block(): user = session.get("user") if not user or "/admin" not in user.get("groups", []): return jsonify({"error": "Unauthorized"}), 403 data = request.json new_block = Block( block_type=data.get('type'), column_name=data.get('column', 'center'), position=99, # Ajoute à la fin par défaut data=json.dumps(data.get('data', {})) ) db.session.add(new_block) db.session.commit() return jsonify(new_block.to_dict()) @app.route('/api/block/', methods=['DELETE']) def delete_block(block_id): user = session.get("user") if not user or "/admin" not in user.get("groups", []): return jsonify({"error": "Unauthorized"}), 403 block = Block.query.get(block_id) if block: db.session.delete(block) db.session.commit() return jsonify({"status": "deleted"}) return jsonify({"error": "not found"}), 404 # --- API ANNONCES (Tes routes existantes) --- # ... (Colle ici tes routes /api/annonces existantes, elles sont très bien) ... # ... (N'oublie pas la route /api/is_admin) ... @app.route("/api/is_admin") def is_admin(): user = session.get("user") # Sécurité : si pas de user, renvoie false if not user: return jsonify({"admin": False}) return jsonify({"admin": "/admin" in user.get("groups", [])}) if __name__ == '__main__': app.run(host='0.0.0.0', debug=True)