diff --git a/db/models.py b/db/models.py index da22e9a..c2ff2a8 100644 --- a/db/models.py +++ b/db/models.py @@ -16,6 +16,7 @@ Functions: - drink_postpaid_user(user_id: int) -> int: Deducts 100 units from the specified postpaid user's balance and records a drink entry. Raises HTTPException if the user is not found or if the drink entry could not be created. Returns the number of rows affected by the drink entry insertion. """ +import secrets from sqlalchemy import create_engine, text from fastapi import HTTPException @@ -42,7 +43,7 @@ with engine.connect() as conn: user_key TEXT NOT NULL UNIQUE, postpaid_user_id INTEGER NOT NULL, money INT DEFAULT 0, - activated BOOLEAN DEFAULT 0, + activated BOOLEAN DEFAULT 1, last_drink TIMESTAMP DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (postpaid_user_id) REFERENCES users_postpaid(id) ) @@ -172,6 +173,10 @@ def drink_postpaid_user(user_id: int): int: The number of rows affected by the drink entry insertion (should be 1 on success). """ + activated = get_postpaid_user(user_id)["activated"] + if not activated: + raise HTTPException(status_code=403, detail="User not activated") + prev_money = get_postpaid_user(user_id)["money"] t = text("UPDATE users_postpaid SET money = :money, last_drink = CURRENT_TIMESTAMP WHERE id = :id") with engine.connect() as connection: @@ -187,3 +192,82 @@ def drink_postpaid_user(user_id: int): raise HTTPException(status_code=500, detail="Failed to create drink entry") connection.commit() return result.rowcount + +def toggle_activate_postpaid_user(user_id: int): + prev_activated = get_postpaid_user(user_id)["activated"] + t = text("UPDATE users_postpaid SET activated = :activated WHERE id = :id") + with engine.connect() as connection: + result = connection.execute(t, {"id": user_id, "activated": not prev_activated}) + if result.rowcount == 0: + raise HTTPException(status_code=404, detail="User not found") + connection.commit() + return result.rowcount + + +def get_prepaid_user(user_id: int): + t = text("SELECT id, username, user_key, postpaid_user_id, money, activated, last_drink FROM users_prepaid WHERE id = :id") + user_db = {} + with engine.connect() as connection: + result = connection.execute(t, {"id": user_id}).fetchone() + if result: + user_db["id"] = result[0] + user_db["username"] = result[1] + user_db["user_key"] = result[2] + user_db["postpaid_user_id"] = result[3] + user_db["money"] = result[4] + user_db["activated"] = result[5] + user_db["last_drink"] = result[6] + else: + raise HTTPException(status_code=404, detail="User not found") + return user_db + +def get_prepaid_user_by_username(username: str): + """ + Retrieve a prepaid user from the database by their username. + Args: + username (str): The username of the user to retrieve. + Returns: + dict: A dictionary containing the user's id, username, money, activated status, and last_drink timestamp. + Raises: + HTTPException: If no user with the given username is found, raises a 404 HTTPException. + """ + + t = text("SELECT id, username, user_key, postpaid_user_id, money, activated, last_drink FROM users_prepaid WHERE username = :username") + user_db = {} + with engine.connect() as connection: + result = connection.execute(t, {"username": username}).fetchone() + if result: + user_db["id"] = result[0] + user_db["username"] = result[1] + user_db["user_key"] = result[2] + user_db["postpaid_user_id"] = result[3] + user_db["money"] = result[4] + user_db["activated"] = result[5] + user_db["last_drink"] = result[6] + else: + raise HTTPException(status_code=404, detail="User not found") + return user_db + +def create_prepaid_user(prepaid_username: str, postpaid_user_id: int, start_money: int = 0): + prepaid_key = secrets.token_urlsafe(6) + t = text("INSERT INTO users_prepaid (username, user_key, postpaid_user_id, money) VALUES (:username, :user_key, :postpaid_user_id, :start_money)") + with engine.connect() as connection: + + # Check if user already exists in prepaid + sel = text("SELECT * FROM users_prepaid WHERE username = :username") + if connection.execute(sel, {"username": prepaid_username}).fetchone(): + raise HTTPException(status_code=400, detail="User already exists") + + result = connection.execute( + t, + { + "username": str(prepaid_username), + "user_key": str(prepaid_key), + "postpaid_user_id": int(postpaid_user_id), + "start_money": int(start_money), + }) + if result.rowcount == 0: + raise HTTPException(status_code=500, detail="Failed to create user") + connection.commit() + + return result.lastrowid diff --git a/main.py b/main.py index 6266c53..ae6edb2 100644 --- a/main.py +++ b/main.py @@ -12,6 +12,10 @@ from db.models import get_postpaid_user from db.models import get_postpaid_user_by_username from db.models import set_postpaid_user_money from db.models import drink_postpaid_user +from db.models import toggle_activate_postpaid_user +from db.models import get_prepaid_user +from db.models import get_prepaid_user_by_username +from db.models import create_prepaid_user from auth.session import get_current_user @@ -41,6 +45,7 @@ def home(request: Request): if not user_db_id or not user_authentik: raise HTTPException(status_code=404, detail="User nicht gefunden") users = None + db_users_prepaid = None if ADMIN_GROUP in user_authentik["groups"]: with engine.connect() as conn: t = text("SELECT id FROM users_postpaid") @@ -51,8 +56,24 @@ def home(request: Request): user_db = get_postpaid_user(row[0]) if user_db: users.append(user_db) + t = text("SELECT id FROM users_prepaid") + result = conn.execute(t).fetchall() + print(f"Result: {result}") + if result: + db_users_prepaid = [] + for row in result: + prepaid_user = get_prepaid_user(row[0]) + if prepaid_user: + db_users_prepaid.append(prepaid_user) db_user = get_postpaid_user(user_db_id) - return templates.TemplateResponse("index.html", {"request": request, "user": user_authentik, "users": users, "user_db_id": user_db_id, "db_user": db_user}) + print("db_users_prepaid", db_users_prepaid) + return templates.TemplateResponse("index.html", { + "request": request, + "user": user_authentik, + "users": users, + "user_db_id": user_db_id, + "db_user": db_user, + "db_users_prepaid": db_users_prepaid}) @app.get("/login", response_class=HTMLResponse) def login_form(request: Request): @@ -145,5 +166,51 @@ def payup(request: Request, username: str = Form(...), money: float = Form(...)) set_postpaid_user_money(current_user_db_id, current_user_money - money*100) return RedirectResponse(url="/", status_code=303) +@app.post("/toggle_activated_user_postpaid") +def toggle_activated_user_postpaid(request: Request, username: str = Form(...)): + user_auth = request.session.get("user_authentik") + if not user_auth or ADMIN_GROUP not in user_auth["groups"]: + raise HTTPException(status_code=403, detail="Nicht erlaubt") + + user_db_id = get_postpaid_user_by_username(username)["id"] + if not user_db_id: + raise HTTPException(status_code=404, detail="User nicht gefunden") + + toggle_activate_postpaid_user(user_db_id) + + return RedirectResponse(url="/", status_code=303) + + +@app.post("/add_prepaid_user") +def add_prepaid_user(request: Request, username: str = Form(...), start_money: float = Form(...)): + active_user_auth = request.session.get("user_authentik") + active_user_db_id = request.session.get("user_db_id") + if not active_user_auth or ADMIN_GROUP not in active_user_auth["groups"]: + raise HTTPException(status_code=403, detail="Nicht erlaubt") + if not active_user_db_id: + raise HTTPException(status_code=404, detail="Aktueller User nicht gefunden") + if not username: + raise HTTPException(status_code=400, detail="Username ist leer") + + user_exists = False + try: + get_postpaid_user_by_username(username) + user_exists = True + get_prepaid_user_by_username(username) + user_exists = True + except HTTPException: + pass + + if user_exists: + raise HTTPException(status_code=400, detail="User existiert bereits") + + create_prepaid_user(username, active_user_db_id, int(start_money*100)) + + prev_money = get_postpaid_user(active_user_db_id)["money"] + set_postpaid_user_money(active_user_db_id, prev_money - int(start_money*100)) + + return RedirectResponse(url="/", status_code=303) + + if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000) diff --git a/templates/base.html b/templates/base.html index 80d03de..6b39af0 100644 --- a/templates/base.html +++ b/templates/base.html @@ -24,7 +24,75 @@ {% block content %}{% endblock %} {% if user %} {% if 'Fachschaft' in user.groups %}
Du bist Teil der Fachschaft Informatik.
- {% endif %} {% if 'Fachschaft Admins' in user.groups %} +Füge Nutzer zur Prepaid Liste hinzu:
+ + {% endif %} + {% if 'Fachschaft Admins' in user.groups %}Ausgleichszahlung:
@@ -100,7 +168,8 @@ Pay Up -
Users in database:
+Users in postpaid database:
(De-)Activate User
+Set user money:
+Users in prepaid database:
+| ID | +Username | +Key | +Postpaid_User ID | +Money (€) | +Activated | +last drink | +
|---|---|---|---|---|---|---|
| + {{ prepaid_user_i.id }} + | ++ {{ prepaid_user_i.username }} + | ++ {{ prepaid_user_i.user_key }} + | ++ {{ prepaid_user_i.postpaid_user_id }} + | ++ {{ prepaid_user_i.money / 100 }} + | ++ {{ prepaid_user_i.activated }} + | ++ {{ prepaid_user_i.last_drink }} + | +
| + No users in prepaid database + | +||||||