#from .model import db, User from .token_service import generate_token, expiration from .email_service import send_user_created_email from config_loader import load_config from .db import get_pool import bcrypt from werkzeug.security import generate_password_hash, check_password_hash config = load_config() def authenticate_user(username: str, password: str): print("LOGIN TRY:", username, password) sql = """ SELECT password_hash FROM app_users WHERE email = :1 \ """ pool = get_pool() with pool.acquire() as conn: with conn.cursor() as cur: cur.execute(sql, [username]) row = cur.fetchone() # print("ROW:", row) if not row: # print("USER NOT FOUND") return False stored_hash = row[0] # print("HASH:", stored_hash) ok = check_password_hash(stored_hash, password) # print("MATCH:", ok) return ok def create_user(username: str, password: str): hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode() sql = """ INSERT INTO app_users (username, password_hash) VALUES (:1, :2) \ """ pool = get_pool() with pool.acquire() as conn: with conn.cursor() as cur: cur.execute(sql, [username, hashed]) conn.commit() def _default_name(email: str) -> str: return (email or "").split("@")[0] def signup_user(email: str, name: str = ""): if not email: raise ValueError("Email required") email = email.lower().strip() name = name or email.split("@")[0] token = generate_token() pool = get_pool() sql_check = """ SELECT id FROM app_users WHERE email = :1 \ """ sql_insert = """ INSERT INTO app_users (name,email,user_role,active,reset_token,reset_expire,must_change_password) VALUES (:1,:2,'user',1,:3,:4,1) \ """ sql_update = """ UPDATE app_users SET reset_token=:1, reset_expire=:2, must_change_password=1 WHERE email=:3 \ """ with pool.acquire() as conn: with conn.cursor() as cur: cur.execute(sql_check, [email]) row = cur.fetchone() if not row: cur.execute(sql_insert, [name, email, token, expiration()]) else: cur.execute(sql_update, [token, expiration(), email]) conn.commit() link = f"{config.app_base}:{config.service_port}/admin/users/set-password/{token}" dev_link = send_user_created_email(email, link, name) return dev_link or link def list_users(): sql = """ SELECT id, name, email, user_role, active FROM app_users ORDER BY name \ """ pool = get_pool() with pool.acquire() as conn: with conn.cursor() as cur: cur.execute(sql) cols = [c[0].lower() for c in cur.description] return [dict(zip(cols, r)) for r in cur.fetchall()] def create_user(name, email, role, active, token): sql = """ INSERT INTO app_users (name,email,user_role,active,reset_token,reset_expire,must_change_password) VALUES (:1,:2,:3,:4,:5,SYSTIMESTAMP + INTERVAL '1' DAY,1) \ """ pool = get_pool() with pool.acquire() as conn: with conn.cursor() as cur: cur.execute(sql, [name, email, role, active, token]) conn.commit() def update_user(user_id, name, email, role, active): sql = """ UPDATE app_users SET name=:1, email=:2, user_role=:3, active=:4 WHERE id=:5 \ """ pool = get_pool() with pool.acquire() as conn: with conn.cursor() as cur: cur.execute(sql, [name, email, role, active, user_id]) conn.commit() def delete_user(user_id): sql = "DELETE FROM app_users WHERE id=:1" pool = get_pool() with pool.acquire() as conn: with conn.cursor() as cur: cur.execute(sql, [user_id]) conn.commit() def get_user_by_token(token): sql = """ SELECT id, reset_expire FROM app_users WHERE reset_token=:1 \ """ pool = get_pool() with pool.acquire() as conn: with conn.cursor() as cur: cur.execute(sql, [token]) row = cur.fetchone() if not row: return None return {"id": row[0], "expire": row[1]} def set_password_service(user_id, pwd): hashed = generate_password_hash(pwd) sql = """ UPDATE app_users SET password_hash=:1, must_change_password=0, reset_token=NULL, reset_expire=NULL WHERE id=:2 \ """ pool = get_pool() with pool.acquire() as conn: with conn.cursor() as cur: cur.execute(sql, [hashed, user_id]) conn.commit()