57 lines
2.1 KiB
Python
57 lines
2.1 KiB
Python
r"""Gemeinsame DB-Zugriffe (Benutzer + Admin-Bootstrap)."""
|
||
import pymysql
|
||
|
||
from db import get_connection
|
||
from config import Config
|
||
from auth import hash_password
|
||
|
||
|
||
def get_user_by_username(username: str) -> dict | None:
|
||
with get_connection() as conn:
|
||
with conn.cursor() as cur:
|
||
cur.execute("SELECT * FROM users WHERE username = %s", (username,))
|
||
return cur.fetchone()
|
||
|
||
|
||
def get_user_by_id(user_id: int) -> dict | None:
|
||
with get_connection() as conn:
|
||
with conn.cursor() as cur:
|
||
cur.execute("SELECT * FROM users WHERE id = %s", (user_id,))
|
||
return cur.fetchone()
|
||
|
||
|
||
def create_user(username: str, password: str, email: str = "", is_admin: bool = False) -> None:
|
||
salt, password_hash = hash_password(password)
|
||
with get_connection() as conn:
|
||
with conn.cursor() as cur:
|
||
cur.execute(
|
||
"INSERT INTO users (username, email, salt, password_hash, is_admin) "
|
||
"VALUES (%s, %s, %s, %s, %s)",
|
||
(username, email, salt, password_hash, 1 if is_admin else 0),
|
||
)
|
||
|
||
|
||
def ensure_admin(app):
|
||
"""Legt beim ersten Start den Admin an, falls er nicht existiert.
|
||
|
||
Race-sicher: Da Gunicorn mehrere Worker startet, rufen alle zugleich
|
||
create_app() auf. Die Prüfung + Einfügen ist deshalb nicht atomar –
|
||
ein IntegrityError (Duplicate key) wird daher toleriert, wenn ein
|
||
anderer Worker den Admin bereits angelegt hat.
|
||
"""
|
||
with app.app_context():
|
||
with get_connection() as conn:
|
||
with conn.cursor() as cur:
|
||
cur.execute(
|
||
"SELECT COUNT(*) AS c FROM users WHERE username = %s",
|
||
(Config.ADMIN_USERNAME,),
|
||
)
|
||
count = cur.fetchone()["c"]
|
||
if count == 0:
|
||
try:
|
||
create_user(Config.ADMIN_USERNAME, Config.ADMIN_PASSWORD, is_admin=True)
|
||
print(f"Admin-Benutzer '{Config.ADMIN_USERNAME}' angelegt.")
|
||
except pymysql.err.IntegrityError:
|
||
# Ein anderer Worker hat den Admin bereits erstellt.
|
||
pass
|