Add Prepaid users and activate button
This commit is contained in:
86
db/models.py
86
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
|
||||
|
||||
69
main.py
69
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)
|
||||
|
||||
@@ -24,7 +24,75 @@
|
||||
{% block content %}{% endblock %} {% if user %} {% if 'Fachschaft'
|
||||
in user.groups %}
|
||||
<p>Du bist Teil der Fachschaft Informatik.</p>
|
||||
{% endif %} {% if 'Fachschaft Admins' in user.groups %}
|
||||
<p>Füge Nutzer zur Prepaid Liste hinzu:</p>
|
||||
<form
|
||||
method="post"
|
||||
action="/add_prepaid_user"
|
||||
style="
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
align-items: center;
|
||||
margin-bottom: 1em;
|
||||
background: var(--hellgrau);
|
||||
padding: 1em;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||
max-width: 600px;
|
||||
"
|
||||
>
|
||||
<label
|
||||
for="username"
|
||||
style="margin: 0 0.5em 0 0; font-weight: bold"
|
||||
>Username:</label
|
||||
>
|
||||
<input
|
||||
id="username"
|
||||
type="text"
|
||||
name="username"
|
||||
placeholder="Username"
|
||||
required
|
||||
style="
|
||||
padding: 0.5em;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
"
|
||||
/>
|
||||
<label
|
||||
for="start_money"
|
||||
style="margin: 0 0.5em 0 0; font-weight: bold"
|
||||
>Start Money (€):</label
|
||||
>
|
||||
<input
|
||||
id="start_money"
|
||||
type="number"
|
||||
name="start_money"
|
||||
placeholder="Start Money"
|
||||
step="0.01"
|
||||
required
|
||||
style="
|
||||
padding: 0.5em;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
width: 100px;
|
||||
"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
style="
|
||||
padding: 0.5em 1em;
|
||||
background: rgb(0, 97, 143);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
"
|
||||
>
|
||||
Add User
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% if 'Fachschaft Admins' in user.groups %}
|
||||
<h2>Admin Interface</h2>
|
||||
<p>Ausgleichszahlung:</p>
|
||||
<p>
|
||||
@@ -100,7 +168,8 @@
|
||||
Pay Up
|
||||
</button>
|
||||
</form>
|
||||
<p>Users in database:</p>
|
||||
<h3>Postpaid Liste</h3>
|
||||
<p>Users in postpaid database:</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -143,6 +212,57 @@
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<p>(De-)Activate User</p>
|
||||
<form
|
||||
method="post"
|
||||
action="/toggle_activated_user_postpaid"
|
||||
style="
|
||||
display: flex;
|
||||
gap: 1em;
|
||||
align-items: center;
|
||||
margin-bottom: 1em;
|
||||
background: var(--hellgrau);
|
||||
padding: 1em;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
|
||||
max-width: 600px;
|
||||
"
|
||||
>
|
||||
<label
|
||||
for="activate-username"
|
||||
style="margin: 0 0.5em 0 0; font-weight: bold"
|
||||
>Username:</label
|
||||
>
|
||||
<select
|
||||
id="activate-username"
|
||||
name="username"
|
||||
required
|
||||
style="
|
||||
padding: 0.5em;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
"
|
||||
>
|
||||
{% for db_user in users %}
|
||||
<option value="{{ db_user.username }}">
|
||||
{{ db_user.username }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button
|
||||
type="submit"
|
||||
style="
|
||||
padding: 0.5em 1em;
|
||||
background: rgb(0, 97, 143);
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
"
|
||||
>
|
||||
Toggle Activation
|
||||
</button>
|
||||
</form>
|
||||
<p>Set user money:</p>
|
||||
<form
|
||||
method="post"
|
||||
@@ -213,6 +333,66 @@
|
||||
Set Money
|
||||
</button>
|
||||
</form>
|
||||
<h3>Prepaid Liste</h3>
|
||||
<p>Users in prepaid database:</p>
|
||||
<table>
|
||||
<thread>
|
||||
<tr>
|
||||
<th style="padding: 0.5em 1em">ID</th>
|
||||
<th style="padding: 0.5em 1em">Username</th>
|
||||
<th style="padding: 0.5em 1em">Key</th>
|
||||
<th style="padding: 0.5em 1em">Postpaid_User ID</th>
|
||||
<th style="padding: 0.5em 1em">Money (€)</th>
|
||||
<th style="padding: 0.5em 1em">Activated</th>
|
||||
<th style="padding: 0.5em 1em">last drink</th>
|
||||
</tr>
|
||||
</thread>
|
||||
<tbody>
|
||||
{% if db_users_prepaid %}
|
||||
{% for prepaid_user_i in db_users_prepaid %}
|
||||
<tr
|
||||
{%
|
||||
if
|
||||
prepaid_user_i.money
|
||||
<=0
|
||||
%}
|
||||
style="background-color: rgba(179, 6, 44, 0.5)"
|
||||
{%
|
||||
endif
|
||||
%}
|
||||
>
|
||||
<td style="padding: 0.5em 1em">
|
||||
{{ prepaid_user_i.id }}
|
||||
</td>
|
||||
<td style="padding: 0.5em 1em">
|
||||
{{ prepaid_user_i.username }}
|
||||
</td>
|
||||
<td style="padding: 0.5em 1em">
|
||||
{{ prepaid_user_i.user_key }}
|
||||
</td>
|
||||
<td style="padding: 0.5em 1em">
|
||||
{{ prepaid_user_i.postpaid_user_id }}
|
||||
</td>
|
||||
<td style="padding: 0.5em 1em">
|
||||
{{ prepaid_user_i.money / 100 }}
|
||||
</td>
|
||||
<td style="padding: 0.5em 1em">
|
||||
{{ prepaid_user_i.activated }}
|
||||
</td>
|
||||
<td style="padding: 0.5em 1em">
|
||||
{{ prepaid_user_i.last_drink }}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="7" style="text-align: center">
|
||||
No users in prepaid database
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %} {% endif %}
|
||||
</main>
|
||||
</body>
|
||||
|
||||
Reference in New Issue
Block a user