Skip to content

Commit 2c2333f

Browse files
committed
feat: add csrf
1 parent 9e5cf3c commit 2c2333f

1 file changed

Lines changed: 76 additions & 0 deletions

File tree

app/services/account.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from datetime import UTC, datetime, timedelta
2+
3+
from pydantic import BaseModel
4+
5+
from app.configs import config
6+
from app.extensions.ext_database import db
7+
from app.extensions.ext_redis import redis_client
8+
from app.libs.helper import naive_utc_now
9+
from app.models.account import (
10+
Account,
11+
AccountStatus,
12+
)
13+
from app.services.passport import PassportService
14+
from app.services.token import TokenService
15+
16+
17+
class TokenPair(BaseModel):
18+
access_token: str
19+
refresh_token: str
20+
csrf_token: str
21+
22+
23+
class AccountService:
24+
@staticmethod
25+
def _get_refresh_token_key(refresh_token: str) -> str:
26+
return f"{config.REFRESH_TOKEN_PREFIX}{refresh_token}"
27+
28+
@staticmethod
29+
def _get_account_refresh_token_key(account_id: str) -> str:
30+
return f"{config.ACCOUNT_REFRESH_TOKEN_PREFIX}{account_id}"
31+
32+
@staticmethod
33+
def store_refresh_token(refresh_token: str, account_id: str):
34+
redis_client.setex(AccountService._get_refresh_token_key(refresh_token), config.REFRESH_TOKEN_EXPIRE_DAYS,
35+
account_id)
36+
redis_client.setex(
37+
AccountService._get_account_refresh_token_key(account_id), config.REFRESH_TOKEN_EXPIRE_DAYS, refresh_token
38+
)
39+
40+
@staticmethod
41+
def get_account_jwt_token(account: Account) -> str:
42+
exp_dt = datetime.now(UTC) + timedelta(minutes=config.ACCESS_TOKEN_EXPIRE_MINUTES)
43+
exp = int(exp_dt.timestamp())
44+
payload = {
45+
"user_id": account.id,
46+
"exp": exp,
47+
"iss": config.EDITION,
48+
"sub": "Console API Passport",
49+
}
50+
51+
token: str = PassportService().issue(payload)
52+
return token
53+
54+
@staticmethod
55+
def update_login_info(account: Account, *, ip_address: str):
56+
account.last_login_at = naive_utc_now()
57+
account.last_login_ip = ip_address
58+
db.session.add(account)
59+
db.session.commit()
60+
61+
@staticmethod
62+
def login(account: Account, ip_address: str | None = None) -> TokenPair:
63+
if ip_address:
64+
AccountService.update_login_info(account=account, ip_address=ip_address)
65+
66+
if account.status == AccountStatus.PENDING:
67+
account.status = AccountStatus.ACTIVE
68+
db.session.commit()
69+
70+
access_token = AccountService.get_account_jwt_token(account=account)
71+
refresh_token = TokenService().generate_refresh_token()
72+
csrf_token = TokenService().generate_csrf_token(account.id)
73+
74+
AccountService.store_refresh_token(refresh_token, account.id)
75+
76+
return TokenPair(access_token=access_token, refresh_token=refresh_token, csrf_token=csrf_token)

0 commit comments

Comments
 (0)