SA-005 addressed by updateing ratelimiting
Build LinkLog Development Image / development-image (push) Successful in 8s
Build LinkLog Development Image / development-image (push) Successful in 8s
This commit is contained in:
+14
-4
@@ -3,7 +3,7 @@
|
||||
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from pydantic import BaseModel
|
||||
|
||||
from backend.app.api.dependencies import get_current_user
|
||||
@@ -17,6 +17,7 @@ from backend.app.services.token_service import issue_token, revoke_token, valida
|
||||
from backend.app.services.otp_service import verify_code
|
||||
from backend.app.services.secret_store import decrypt_secret
|
||||
from backend.app.services.email_addresses import verify_user_email_address
|
||||
from backend.app.services.login_throttle import check_login_allowed, clear_login_failures, record_login_failure
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -35,10 +36,17 @@ class PasswordResetRequest(BaseModel):
|
||||
|
||||
|
||||
@router.post('/login')
|
||||
def login(payload: LoginRequest):
|
||||
user = authenticate_user(payload.email.strip(), payload.password)
|
||||
def login(payload: LoginRequest, request: Request):
|
||||
email = payload.email.strip()
|
||||
ip_address = request.client.host if request.client else 'unknown'
|
||||
retry_after = check_login_allowed(ip_address, email)
|
||||
if retry_after is not None:
|
||||
raise HTTPException(status_code=429, detail='Too many failed login attempts. Try again later.', headers={'Retry-After': str(retry_after)})
|
||||
|
||||
user = authenticate_user(email, payload.password)
|
||||
if user is None:
|
||||
reset_user = find_user(payload.email.strip())
|
||||
record_login_failure(ip_address, email)
|
||||
reset_user = find_user(email)
|
||||
if reset_user and reset_user['email_verified'] and smtp_configured():
|
||||
try:
|
||||
token = create_reset_token(reset_user['id'])
|
||||
@@ -50,8 +58,10 @@ def login(payload: LoginRequest):
|
||||
if not user['email_verified']:
|
||||
raise HTTPException(status_code=403, detail='Email address is not verified')
|
||||
if user['otp_enabled'] and not verify_code(decrypt_secret(user['otp_secret']), payload.otp):
|
||||
record_login_failure(ip_address, email)
|
||||
raise HTTPException(status_code=401, detail='One-time password required or invalid')
|
||||
|
||||
clear_login_failures(ip_address, email)
|
||||
token_data = issue_token(user['id'], user['username'])
|
||||
return {
|
||||
'access_token': token_data['access_token'],
|
||||
|
||||
Reference in New Issue
Block a user