mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-10-26 21:41:57 -06:00
Implement operator login service and fix static root
This commit is contained in:
72
Data/Engine/builders/operator_auth.py
Normal file
72
Data/Engine/builders/operator_auth.py
Normal file
@@ -0,0 +1,72 @@
|
||||
"""Builders for operator authentication payloads."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from dataclasses import dataclass
|
||||
from typing import Mapping
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class OperatorLoginRequest:
|
||||
"""Normalized operator login credentials."""
|
||||
|
||||
username: str
|
||||
password_sha512: str
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class OperatorMFAVerificationRequest:
|
||||
"""Normalized MFA verification payload."""
|
||||
|
||||
pending_token: str
|
||||
code: str
|
||||
|
||||
|
||||
def _sha512_hex(raw: str) -> str:
|
||||
digest = hashlib.sha512()
|
||||
digest.update(raw.encode("utf-8"))
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def build_login_request(payload: Mapping[str, object]) -> OperatorLoginRequest:
|
||||
"""Validate and normalize the login *payload*."""
|
||||
|
||||
username = str(payload.get("username") or "").strip()
|
||||
password_sha512 = str(payload.get("password_sha512") or "").strip().lower()
|
||||
password = payload.get("password")
|
||||
|
||||
if not username:
|
||||
raise ValueError("username is required")
|
||||
|
||||
if password_sha512:
|
||||
normalized_hash = password_sha512
|
||||
else:
|
||||
if not isinstance(password, str) or not password:
|
||||
raise ValueError("password is required")
|
||||
normalized_hash = _sha512_hex(password)
|
||||
|
||||
return OperatorLoginRequest(username=username, password_sha512=normalized_hash)
|
||||
|
||||
|
||||
def build_mfa_request(payload: Mapping[str, object]) -> OperatorMFAVerificationRequest:
|
||||
"""Validate and normalize the MFA verification *payload*."""
|
||||
|
||||
pending_token = str(payload.get("pending_token") or "").strip()
|
||||
raw_code = str(payload.get("code") or "").strip()
|
||||
digits = "".join(ch for ch in raw_code if ch.isdigit())
|
||||
|
||||
if not pending_token:
|
||||
raise ValueError("pending_token is required")
|
||||
if len(digits) < 6:
|
||||
raise ValueError("code must contain 6 digits")
|
||||
|
||||
return OperatorMFAVerificationRequest(pending_token=pending_token, code=digits)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"OperatorLoginRequest",
|
||||
"OperatorMFAVerificationRequest",
|
||||
"build_login_request",
|
||||
"build_mfa_request",
|
||||
]
|
||||
Reference in New Issue
Block a user