84 lines
2.7 KiB
Python
84 lines
2.7 KiB
Python
--- 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/<int:galerie_id>/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/<int:galerie_id>/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/<int:oeuvre_id>/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)
|
|
|