import reflex as rx from passlib.context import CryptContext from ..models import User, Configuration from sqlmodel import select pwd_context = CryptContext(schemes=["argon2"], deprecated="auto") class AuthState(rx.State): username: str = "" password: str = "" confirm_password: str = "" is_logged_in: bool = False # Wizard Config Fields setup_api_key: str = "" setup_input_folder: str = "" setup_philosophy: str = "" def check_login(self): """Validates credentials.""" with rx.session() as session: user = session.exec(select(User).where(User.username == self.username)).first() if user and pwd_context.verify(self.password, user.password_hash): self.is_logged_in = True return rx.redirect("/") return rx.window_alert("Invalid credentials.") def logout(self): self.is_logged_in = False self.username = "" self.password = "" return rx.redirect("/login") def create_admin_account(self): """Creates the initial admin account during wizard setup.""" if self.password != self.confirm_password: return rx.window_alert("Passwords do not match.") if len(self.password) < 8: return rx.window_alert("Password must be at least 8 characters.") hashed = pwd_context.hash(self.password) user = User(username=self.username, password_hash=hashed) # Also save the initial config config = Configuration( gemini_api_key=self.setup_api_key, input_folder=self.setup_input_folder, philosophy=self.setup_philosophy, is_configured=True ) with rx.session() as session: session.add(user) session.add(config) session.commit() self.is_logged_in = True return rx.redirect("/") def on_load_check(self): """Redirects to setup if no user exists, or login if not authenticated.""" with rx.session() as session: user = session.exec(select(User)).first() if not user: return rx.redirect("/setup") elif not self.is_logged_in: return rx.redirect("/login")