feat(account): GET /me user endpoint only, disable cache and extra routers
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
5
src/presentation/schemas/__init__.py
Normal file
5
src/presentation/schemas/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from src.presentation.schemas.phone import SetPhoneRequest
|
||||
from src.presentation.schemas.bank import BankUpdateRequest, BankConfirmRequest
|
||||
from src.presentation.schemas.crypto_wallet import CryptoWalletConfirmRequest
|
||||
from src.presentation.schemas.password import ChangePasswordConfirmRequest
|
||||
from src.presentation.schemas.email import ChangeEmailConfirmOldRequest, ChangeEmailCompleteRequest
|
||||
110
src/presentation/schemas/bank.py
Normal file
110
src/presentation/schemas/bank.py
Normal file
@@ -0,0 +1,110 @@
|
||||
import re
|
||||
from typing import Self
|
||||
from pydantic import BaseModel, field_validator, model_validator
|
||||
|
||||
|
||||
class BankUpdateRequest(BaseModel):
|
||||
bik: str | None = None
|
||||
account_number: str | None = None
|
||||
card_number: str | None = None
|
||||
|
||||
@model_validator(mode='after')
|
||||
def at_least_one(self) -> Self:
|
||||
if not any([self.bik, self.account_number, self.card_number]):
|
||||
raise ValueError('At least one field is required')
|
||||
return self
|
||||
|
||||
@field_validator('bik')
|
||||
@classmethod
|
||||
def validate_bik(cls, v: str | None) -> str | None:
|
||||
if v is None:
|
||||
return None
|
||||
v = v.strip()
|
||||
if not re.match(r'^\d{9}$', v):
|
||||
raise ValueError('BIK must be exactly 9 digits')
|
||||
return v
|
||||
|
||||
@field_validator('account_number')
|
||||
@classmethod
|
||||
def validate_account_number(cls, v: str | None) -> str | None:
|
||||
if v is None:
|
||||
return None
|
||||
v = v.strip()
|
||||
if not re.match(r'^\d{20}$', v):
|
||||
raise ValueError('Account number must be exactly 20 digits')
|
||||
return v
|
||||
|
||||
@field_validator('card_number')
|
||||
@classmethod
|
||||
def validate_card_number(cls, v: str | None) -> str | None:
|
||||
if v is None:
|
||||
return None
|
||||
v = re.sub(r'[\s\-]', '', v)
|
||||
if not re.match(r'^\d{13,19}$', v):
|
||||
raise ValueError('Card number must be 13-19 digits')
|
||||
if not cls._luhn_check(v):
|
||||
raise ValueError('Invalid card number (Luhn check failed)')
|
||||
return v
|
||||
|
||||
@staticmethod
|
||||
def _luhn_check(number: str) -> bool:
|
||||
digits = [int(d) for d in number]
|
||||
odd_digits = digits[-1::-2]
|
||||
even_digits = digits[-2::-2]
|
||||
total = sum(odd_digits)
|
||||
for d in even_digits:
|
||||
total += sum(divmod(d * 2, 10))
|
||||
return total % 10 == 0
|
||||
|
||||
|
||||
class BankConfirmRequest(BaseModel):
|
||||
code: str
|
||||
bik: str | None = None
|
||||
account_number: str | None = None
|
||||
card_number: str | None = None
|
||||
|
||||
@model_validator(mode='after')
|
||||
def at_least_one_field(self) -> Self:
|
||||
if not any([self.bik, self.account_number, self.card_number]):
|
||||
raise ValueError('At least one bank field is required')
|
||||
return self
|
||||
|
||||
@field_validator('code')
|
||||
@classmethod
|
||||
def validate_code(cls, v: str) -> str:
|
||||
v = v.strip()
|
||||
if not re.match(r'^\d{6}$', v):
|
||||
raise ValueError('Code must be exactly 6 digits')
|
||||
return v
|
||||
|
||||
@field_validator('bik')
|
||||
@classmethod
|
||||
def validate_bik(cls, v: str | None) -> str | None:
|
||||
if v is None:
|
||||
return None
|
||||
v = v.strip()
|
||||
if not re.match(r'^\d{9}$', v):
|
||||
raise ValueError('BIK must be exactly 9 digits')
|
||||
return v
|
||||
|
||||
@field_validator('account_number')
|
||||
@classmethod
|
||||
def validate_account_number(cls, v: str | None) -> str | None:
|
||||
if v is None:
|
||||
return None
|
||||
v = v.strip()
|
||||
if not re.match(r'^\d{20}$', v):
|
||||
raise ValueError('Account number must be exactly 20 digits')
|
||||
return v
|
||||
|
||||
@field_validator('card_number')
|
||||
@classmethod
|
||||
def validate_card_number(cls, v: str | None) -> str | None:
|
||||
if v is None:
|
||||
return None
|
||||
v = re.sub(r'[\s\-]', '', v)
|
||||
if not re.match(r'^\d{13,19}$', v):
|
||||
raise ValueError('Card number must be 13-19 digits')
|
||||
if not BankUpdateRequest._luhn_check(v):
|
||||
raise ValueError('Invalid card number (Luhn check failed)')
|
||||
return v
|
||||
23
src/presentation/schemas/crypto_wallet.py
Normal file
23
src/presentation/schemas/crypto_wallet.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import re
|
||||
from pydantic import BaseModel, field_validator
|
||||
|
||||
|
||||
class CryptoWalletConfirmRequest(BaseModel):
|
||||
code: str
|
||||
wallet_address: str
|
||||
|
||||
@field_validator('code')
|
||||
@classmethod
|
||||
def validate_code(cls, v: str) -> str:
|
||||
v = v.strip()
|
||||
if not re.match(r'^\d{6}$', v):
|
||||
raise ValueError('Code must be exactly 6 digits')
|
||||
return v
|
||||
|
||||
@field_validator('wallet_address')
|
||||
@classmethod
|
||||
def validate_tron_address(cls, v: str) -> str:
|
||||
v = v.strip()
|
||||
if not re.match(r'^T[1-9A-HJ-NP-Za-km-z]{33}$', v):
|
||||
raise ValueError('Invalid TRON wallet address')
|
||||
return v
|
||||
35
src/presentation/schemas/email.py
Normal file
35
src/presentation/schemas/email.py
Normal file
@@ -0,0 +1,35 @@
|
||||
import re
|
||||
from pydantic import BaseModel, field_validator
|
||||
|
||||
|
||||
class ChangeEmailConfirmOldRequest(BaseModel):
|
||||
code: str
|
||||
new_email: str
|
||||
|
||||
@field_validator('code')
|
||||
@classmethod
|
||||
def validate_code(cls, v: str) -> str:
|
||||
v = v.strip()
|
||||
if not re.match(r'^\d{6}$', v):
|
||||
raise ValueError('Code must be exactly 6 digits')
|
||||
return v
|
||||
|
||||
@field_validator('new_email')
|
||||
@classmethod
|
||||
def validate_new_email(cls, v: str) -> str:
|
||||
v = v.strip().lower()
|
||||
if not re.match(r'^[^@\s]+@[^@\s]+\.[^@\s]+$', v):
|
||||
raise ValueError('Invalid email address')
|
||||
return v
|
||||
|
||||
|
||||
class ChangeEmailCompleteRequest(BaseModel):
|
||||
code: str
|
||||
|
||||
@field_validator('code')
|
||||
@classmethod
|
||||
def validate_code(cls, v: str) -> str:
|
||||
v = v.strip()
|
||||
if not re.match(r'^\d{6}$', v):
|
||||
raise ValueError('Code must be exactly 6 digits')
|
||||
return v
|
||||
30
src/presentation/schemas/password.py
Normal file
30
src/presentation/schemas/password.py
Normal file
@@ -0,0 +1,30 @@
|
||||
import re
|
||||
from typing import Self
|
||||
from pydantic import BaseModel, field_validator, model_validator
|
||||
|
||||
|
||||
class ChangePasswordConfirmRequest(BaseModel):
|
||||
code: str
|
||||
new_password: str
|
||||
confirm_password: str
|
||||
|
||||
@model_validator(mode='after')
|
||||
def passwords_match(self) -> Self:
|
||||
if self.new_password != self.confirm_password:
|
||||
raise ValueError('Passwords do not match')
|
||||
return self
|
||||
|
||||
@field_validator('code')
|
||||
@classmethod
|
||||
def validate_code(cls, v: str) -> str:
|
||||
v = v.strip()
|
||||
if not re.match(r'^\d{6}$', v):
|
||||
raise ValueError('Code must be exactly 6 digits')
|
||||
return v
|
||||
|
||||
@field_validator('new_password')
|
||||
@classmethod
|
||||
def validate_new_password(cls, v: str) -> str:
|
||||
if len(v) < 8:
|
||||
raise ValueError('Password must be at least 8 characters')
|
||||
return v
|
||||
17
src/presentation/schemas/phone.py
Normal file
17
src/presentation/schemas/phone.py
Normal file
@@ -0,0 +1,17 @@
|
||||
import re
|
||||
from pydantic import BaseModel, field_validator
|
||||
from src.application.domain.exceptions import ApplicationException
|
||||
|
||||
|
||||
class SetPhoneRequest(BaseModel):
|
||||
phone: str
|
||||
|
||||
@field_validator('phone')
|
||||
@classmethod
|
||||
def validate_russian_phone(cls, v: str) -> str:
|
||||
cleaned = re.sub(r'[\s\-\(\)]', '', v)
|
||||
pattern = r'^(\+7|8)\d{10}$'
|
||||
if not re.match(pattern, cleaned):
|
||||
raise ApplicationException(message='Invalid Russian phone number', status_code=429)
|
||||
normalized = '+7' + cleaned[-10:]
|
||||
return normalized
|
||||
Reference in New Issue
Block a user