1- """Auth routes: register, login, refresh, me."""
1+ """Auth routes: register, login, refresh, me.
2+
3+ HTTP wiring only -- credentials, tokens and account state are decided
4+ in ``controllers.accounts``.
5+ """
26
37from __future__ import annotations
48
5- import jwt as pyjwt
6- from fastapi import APIRouter , Depends , HTTPException , Query , status
9+ from fastapi import APIRouter , Depends , Query , status
710from fastapi .security import HTTPAuthorizationCredentials , HTTPBearer
8- from sqlalchemy import select
911from sqlalchemy .orm import Session
1012
11- from ..infra .security import (
12- create_access_token ,
13- create_refresh_token ,
14- decode_token ,
15- hash_password ,
16- verify_password ,
17- )
18- from ..models import User , new_id
19- from ..models .db import commit_now , get_db
13+ from ..controllers import accounts
14+ from ..models import User
15+ from ..models .db import get_db
2016from ..validation .schemas import RefreshIn , RegisterIn , TokenPair , UserOut
2117
2218router = APIRouter (prefix = "/auth" , tags = ["auth" ])
2319_bearer = HTTPBearer (auto_error = False )
2420
2521
26- def _user_for_token (db : Session , token : str | None ) -> User :
27- """Shared bearer-token validation for header and query-param auth."""
28- if not token :
29- raise HTTPException (status .HTTP_401_UNAUTHORIZED , "missing bearer token" )
30- try :
31- payload = decode_token (token , expected_type = "access" )
32- except pyjwt .PyJWTError as exc :
33- raise HTTPException (status .HTTP_401_UNAUTHORIZED , f"invalid token: { exc } " ) from exc
34- user = db .get (User , payload ["sub" ])
35- if user is None or not user .is_active :
36- raise HTTPException (status .HTTP_401_UNAUTHORIZED , "unknown or inactive user" )
37- return user
38-
39-
4022def authenticate_user (
4123 db : Session = Depends (get_db ),
4224 credentials : HTTPAuthorizationCredentials | None = Depends (_bearer ),
@@ -49,69 +31,46 @@ def authenticate_user(
4931 ``access_token`` query parameter.
5032 """
5133 header_token = credentials .credentials if credentials is not None else None
52- return _user_for_token (db , header_token or access_token )
34+ return accounts .user_for_access_token (db , header_token or access_token )
35+
36+
37+ def require_admin (user : User = Depends (authenticate_user )) -> User :
38+ return accounts .require_admin (user )
5339
5440
5541def _token_pair (user : User ) -> TokenPair :
56- return TokenPair (
57- access_token = create_access_token (user .id ),
58- refresh_token = create_refresh_token (user .id ),
42+ access , refresh_token = accounts .token_pair (user )
43+ return TokenPair (access_token = access , refresh_token = refresh_token )
44+
45+
46+ def _user_out (user : User ) -> UserOut :
47+ return UserOut (
48+ id = user .id ,
49+ email = user .email ,
50+ is_active = user .is_active ,
51+ is_admin = user .is_admin ,
52+ created_at = user .created_at ,
5953 )
6054
6155
6256@router .post ("/register" , response_model = TokenPair , status_code = status .HTTP_201_CREATED )
6357def register (body : RegisterIn , db : Session = Depends (get_db )) -> TokenPair :
64- exists = db .scalar (select (User ).where (User .email == body .email ))
65- if exists is not None :
66- raise HTTPException (status .HTTP_409_CONFLICT , "email already registered" )
67- user = User (
68- id = new_id ("usr" ),
69- email = body .email ,
70- password_hash = hash_password (body .password ),
71- )
72- db .add (user )
73- db .flush ()
74- commit_now (db )
75- return _token_pair (user )
58+ return _token_pair (accounts .register (db , body .email , body .password ))
7659
7760
7861@router .post ("/login" , response_model = TokenPair )
7962def login (body : RegisterIn , db : Session = Depends (get_db )) -> TokenPair :
80- user = db .scalar (select (User ).where (User .email == body .email ))
81- if user is None or not verify_password (body .password , user .password_hash ):
82- raise HTTPException (status .HTTP_401_UNAUTHORIZED , "invalid email or password" )
83- if not user .is_active :
84- raise HTTPException (status .HTTP_403_FORBIDDEN , "account disabled" )
85- return _token_pair (user )
63+ return _token_pair (accounts .login (db , body .email , body .password ))
8664
8765
8866@router .post ("/refresh" , response_model = TokenPair )
8967def refresh (body : RefreshIn , db : Session = Depends (get_db )) -> TokenPair :
90- try :
91- payload = decode_token (body .refresh_token , expected_type = "refresh" )
92- except pyjwt .PyJWTError as exc :
93- raise HTTPException (status .HTTP_401_UNAUTHORIZED , f"invalid token: { exc } " ) from exc
94- user = db .get (User , payload ["sub" ])
95- if user is None or not user .is_active :
96- raise HTTPException (status .HTTP_401_UNAUTHORIZED , "unknown or inactive user" )
97- return _token_pair (user )
68+ return _token_pair (accounts .user_for_refresh_token (db , body .refresh_token ))
9869
9970
10071@router .get ("/me" , response_model = UserOut )
10172def me (user : User = Depends (authenticate_user )) -> UserOut :
102- return UserOut (
103- id = user .id ,
104- email = user .email ,
105- is_active = user .is_active ,
106- is_admin = user .is_admin ,
107- created_at = user .created_at ,
108- )
109-
110-
111- def require_admin (user : User = Depends (authenticate_user )) -> User :
112- if not user .is_admin :
113- raise HTTPException (status .HTTP_403_FORBIDDEN , "admin required" )
114- return user
73+ return _user_out (user )
11574
11675
11776@router .get ("/admin-check" )
0 commit comments