--- user_api/app.py --- from flask import Flask, jsonify, request, abort from flask_sqlalchemy import SQLAlchemy import requests import jwt app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../db.sqlite' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) # Configuration Keycloak KEYCLOAK_URL = "http://localhost:8080" REALM = "myrealm" CLIENT_ID = "myclient" class Visite(db.Model): id = db.Column(db.Integer, primary_key=True) galerie_id = db.Column(db.Integer, nullable=False) class Critique(db.Model): id = db.Column(db.Integer, primary_key=True) oeuvre_id = db.Column(db.Integer, nullable=False) texte = db.Column(db.Text, nullable=False) username = db.Column(db.String(100), nullable=False) def verify_token(auth_header): if not auth_header.startswith("Bearer "): return None token = auth_header.split(" ")[1] try: jwks_url = f"{KEYCLOAK_URL}/realms/{REALM}/protocol/openid-connect/certs" jwks = requests.get(jwks_url).json() public_keys = {k['kid']: jwt.algorithms.RSAAlgorithm.from_jwk(k) for k in jwks['keys']} unverified = jwt.decode(token, options={"verify_signature": False}) kid = unverified['kid'] decoded = jwt.decode(token, key=public_keys[kid], algorithms=['RS256'], audience=CLIENT_ID) return decoded['preferred_username'] except Exception as e: print(f"JWT verification failed: {e}") return None @app.before_request def authenticate(): auth = request.headers.get("Authorization", "") user = verify_token(auth) if not user: return jsonify({"error": "Unauthorized"}), 403 request.user = user @app.route("/", methods=["GET"]) def index(): return f"User API - Authenticated as {request.user}", 200 @app.route("/galerie//entrer", methods=["POST"]) def entrer_galerie(galerie_id): visite = Visite(galerie_id=galerie_id) db.session.add(visite) db.session.commit() return jsonify({"message": "Entré dans la galerie"}), 201 @app.route("/galerie//sortir", methods=["POST"]) def sortir_galerie(galerie_id): Visite.query.filter_by(galerie_id=galerie_id).delete() db.session.commit() return jsonify({"message": "Sorti de la galerie"}), 200 @app.route("/oeuvre//critiquer", methods=["POST"]) def critiquer_oeuvre(oeuvre_id): data = request.get_json() if not data or not data.get("texte"): abort(400) critique = Critique(oeuvre_id=oeuvre_id, texte=data["texte"], username=request.user) db.session.add(critique) db.session.commit() return jsonify({"message": "Critique ajoutée"}), 201 if __name__ == "__main__": with app.app_context(): db.create_all() app.run(port=5002)