Andrei Neagoie Python ((new)) [ 90% Validated ]

def check_rate_limit(self, key: str) -> bool: """ Check if rate limit is exceeded for given key Args: key: Identifier for rate limiting (e.g., email or IP) Returns: True if under limit, False if exceeded Raises: RateLimitExceededError: If rate limit is exceeded """ now = time.time() # Clean up old attempts if key in self.attempts: self.attempts[key] = [ attempt_time for attempt_time in self.attempts[key] if now - attempt_time < self.window_seconds ] # Check if limit exceeded if len(self.attempts.get(key, [])) >= self.max_attempts: wait_time = self.window_seconds - (now - self.attempts[key][0]) raise RateLimitExceededError( f"Too many attempts. Please try again in int(wait_time) seconds" ) return True

def login(self, email: str, password: str, ip_address: str) -> Tuple[str, User]: """ Authenticate user and return JWT token Args: email: User's email password: User's password ip_address: Client IP for rate limiting Returns: Tuple of (jwt_token, user_object) Raises: UserNotFoundError: If user doesn't exist InvalidPasswordError: If password is incorrect RateLimitExceededError: If too many attempts """ # Check rate limit by IP self.rate_limiter.check_rate_limit(ip_address) self.rate_limiter.record_attempt(ip_address) # Find user user = self.users.get(email) if not user: raise UserNotFoundError("User not found") # Check if account is locked if user.is_locked(): remaining = (user.locked_until - datetime.utcnow()).seconds raise AuthenticationError(f"Account locked. Try again in remaining seconds") # Verify password if not self.password_hasher.verify_password(password, user.password_hash): user.failed_attempts += 1 # Lock account if max attempts exceeded if user.failed_attempts >= self.max_failed_attempts: user.locked_until = datetime.utcnow() + timedelta(minutes=self.lockout_minutes) raise AuthenticationError( f"Too many failed attempts. Account locked for self.lockout_minutes minutes" ) raise InvalidPasswordError("Invalid password") # Successful login - reset failed attempts and update last login user.failed_attempts = 0 user.last_login = datetime.utcnow() # Generate token token = self.token_manager.generate_token(user.user_id, user.email) return token, user andrei neagoie python

def test_account_lockout(self, auth_service): auth_service.register_user("test@example.com", "ValidPass123!") # Try wrong password 5 times (max_failed_attempts=5) for _ in range(5): with pytest.raises(InvalidPasswordError): auth_service.login("test@example.com", "wrong", "127.0.0.1") # Next attempt should lock account with pytest.raises(AuthenticationError, match="Account locked"): auth_service.login("test@example.com", "ValidPass123!", "127.0.0.1") def check_rate_limit(self, key: str) -&gt; bool: """ Check

def validate_token(self, token: str) -> Dict: """ Validate and decode JWT token Args: token: JWT token string Returns: Decoded token payload Raises: AuthenticationError: If token is invalid or expired """ try: payload = jwt.decode( token, self.secret_key, algorithms=['HS256'] ) return payload except ExpiredSignatureError: raise AuthenticationError("Token has expired") except InvalidTokenError as e: raise AuthenticationError(f"Invalid token: str(e)") class RateLimiter: """Simple in-memory rate limiter for authentication attempts""" Account locked for self

def test_login_wrong_password(self, auth_service): auth_service.register_user("test@example.com", "ValidPass123!") with pytest.raises(InvalidPasswordError): auth_service.login("test@example.com", "WrongPass456!", "192.168.1.1")

@staticmethod def _validate_password_strength(password: str) -> None: """ Validate password meets security requirements Requirements: - Minimum 8 characters - At least 1 uppercase letter - At least 1 lowercase letter - At least 1 digit - At least 1 special character Raises: ValidationError: If password doesn't meet requirements """ if len(password) < 8: raise ValidationError("Password must be at least 8 characters long") if not re.search(r'[A-Z]', password): raise ValidationError("Password must contain at least one uppercase letter") if not re.search(r'[a-z]', password): raise ValidationError("Password must contain at least one lowercase letter") if not re.search(r'\d', password): raise ValidationError("Password must contain at least one digit") if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password): raise ValidationError("Password must contain at least one special character") class TokenManager: """Handles JWT token creation and validation"""