fix: resolve backend CI errors for MyPy and Ruff

- Fix PyPNGImage save() method call (remove format parameter)
- Fix return type annotation in is_mfa_required()
- Remove unused imports and reorder imports
- Update timezone imports from timezone to UTC
- Fix test assertions formatting

Frontend CI fixes to follow in subsequent commit

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
pull/22455/head
k-brahma-claude 10 months ago
parent 9202c05d4c
commit 1bdbbb7140

@ -14,8 +14,6 @@ from controllers.console.auth.error import (
EmailPasswordLoginLimitError,
InvalidEmailError,
InvalidTokenError,
MFARequiredError,
MFATokenRequiredError,
)
from controllers.console.error import (
AccountBannedError,

@ -1,12 +1,8 @@
from typing import cast
import flask_login
from flask import request
from flask_restful import Resource, reqparse
from controllers.console.auth.error import (
TokenValidationError,
)
from controllers.console.wraps import account_initialization_required
from libs.login import login_required
from models.account import Account

@ -389,7 +389,8 @@ api.add_resource(EducationAutoCompleteApi, "/account/education/autocomplete")
# api.add_resource(AccountEmailVerifyApi, '/account/email-verify')
# MFA endpoints
from controllers.console.auth.mfa import MFASetupInitApi, MFASetupCompleteApi, MFADisableApi, MFAStatusApi
from controllers.console.auth.mfa import MFADisableApi, MFASetupCompleteApi, MFASetupInitApi, MFAStatusApi
api.add_resource(MFAStatusApi, "/account/mfa/status")
api.add_resource(MFASetupInitApi, "/account/mfa/setup")
api.add_resource(MFASetupCompleteApi, "/account/mfa/setup/complete")

@ -2,13 +2,10 @@ import base64
import io
import json
import secrets
from datetime import datetime, timezone
from typing import Optional
from datetime import UTC, datetime
import pyotp
import qrcode
from sqlalchemy import and_
from sqlalchemy.orm import Session
from models.account import Account, AccountMFASettings
from models.engine import db
@ -53,7 +50,7 @@ class MFAService:
# Convert to base64
buffer = io.BytesIO()
img.save(buffer, format='PNG')
img.save(buffer)
img_str = base64.b64encode(buffer.getvalue()).decode()
return f"data:image/png;base64,{img_str}"
@ -120,7 +117,7 @@ class MFAService:
# Enable MFA
mfa_settings.enabled = True
mfa_settings.backup_codes = json.dumps(backup_codes)
mfa_settings.setup_at = datetime.now(timezone.utc)
mfa_settings.setup_at = datetime.now(UTC)
db.session.commit()
@ -176,7 +173,7 @@ class MFAService:
def is_mfa_required(account: Account) -> bool:
"""Check if MFA is required for this account."""
mfa_settings = db.session.query(AccountMFASettings).filter_by(account_id=account.id).first()
return mfa_settings and mfa_settings.enabled and mfa_settings.secret is not None
return bool(mfa_settings and mfa_settings.enabled and mfa_settings.secret is not None)
@staticmethod
def authenticate_with_mfa(account: Account, token: str) -> bool:

@ -1,14 +1,8 @@
import json
import sys
import pytest
from unittest.mock import Mock, patch
from datetime import datetime
from flask import Flask
from flask_restful import Api
from controllers.console.auth.login import LoginApi
from models.account import Account, AccountMFASettings
class TestLoginMFAIntegration:
@ -292,8 +286,8 @@ class TestMFAEndToEndFlow:
@patch('services.mfa_service.db.session')
def test_complete_mfa_setup_flow(self, mock_session, mock_gen_codes, mock_verify, mock_gen_qr, mock_gen_secret):
"""Test complete MFA setup flow from init to completion."""
from services.mfa_service import MFAService
from models.account import Account
from services.mfa_service import MFAService
# Mock account
account = Mock(spec=Account)

@ -1,7 +1,8 @@
import pytest
from datetime import datetime, timezone
from datetime import UTC, datetime
from unittest.mock import patch
import pytest
from services.account_service import AccountService
from services.mfa_service import MFAService
@ -71,7 +72,7 @@ class TestMFAEndpoints:
with patch.object(MFAService, 'setup_mfa') as mock_setup:
mock_setup.return_value = {
"backup_codes": ["CODE1", "CODE2", "CODE3", "CODE4", "CODE5", "CODE6", "CODE7", "CODE8"],
"setup_at": datetime(2024, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
"setup_at": datetime(2024, 1, 1, 0, 0, 0, tzinfo=UTC)
}
response = test_client.post(
@ -97,7 +98,8 @@ class TestMFAEndpoints:
assert response.status_code == 400
data = response.json
assert "message" in data and "TOTP token is required" in data["message"]
assert "message" in data
assert "TOTP token is required" in data["message"]
def test_mfa_setup_complete_invalid_token(self, test_client, setup_account, auth_header):
"""Test MFA setup completion with invalid token."""

@ -1,7 +1,5 @@
import json
from unittest import mock
from models.account import Account
from services.mfa_service import MFAService
@ -12,7 +10,7 @@ class TestMFASimpleIntegration:
"""Test MFA setup flow end-to-end."""
# Step 1: Check initial MFA status
response = test_client.get(
f"/console/api/account/mfa/status",
"/console/api/account/mfa/status",
headers=auth_header
)
assert response.status_code == 200
@ -21,7 +19,7 @@ class TestMFASimpleIntegration:
# Step 2: Initialize MFA setup
response = test_client.post(
f"/console/api/account/mfa/setup",
"/console/api/account/mfa/setup",
headers=auth_header
)
assert response.status_code == 200
@ -33,7 +31,7 @@ class TestMFASimpleIntegration:
# Step 3: Complete MFA setup with mocked TOTP
with mock.patch.object(MFAService, 'verify_totp', return_value=True):
response = test_client.post(
f"/console/api/account/mfa/setup/complete",
"/console/api/account/mfa/setup/complete",
headers=auth_header,
json={"totp_token": "123456"}
)
@ -44,7 +42,7 @@ class TestMFASimpleIntegration:
# Step 4: Verify MFA is now enabled
response = test_client.get(
f"/console/api/account/mfa/status",
"/console/api/account/mfa/status",
headers=auth_header
)
assert response.status_code == 200
@ -55,7 +53,7 @@ class TestMFASimpleIntegration:
"""Test MFA disable flow."""
# First check MFA status and disable if already enabled
response = test_client.get(
f"/console/api/account/mfa/status",
"/console/api/account/mfa/status",
headers=auth_header
)
assert response.status_code == 200
@ -65,7 +63,7 @@ class TestMFASimpleIntegration:
# MFA is already enabled, disable it first with mocked password verification
with mock.patch('libs.password.compare_password', return_value=True):
response = test_client.post(
f"/console/api/account/mfa/disable",
"/console/api/account/mfa/disable",
headers=auth_header,
json={"password": "any_password"} # Password doesn't matter, it's mocked
)
@ -75,14 +73,14 @@ class TestMFASimpleIntegration:
with mock.patch.object(MFAService, 'verify_totp', return_value=True):
# Initialize setup
response = test_client.post(
f"/console/api/account/mfa/setup",
"/console/api/account/mfa/setup",
headers=auth_header
)
assert response.status_code == 200
# Complete setup
response = test_client.post(
f"/console/api/account/mfa/setup/complete",
"/console/api/account/mfa/setup/complete",
headers=auth_header,
json={"totp_token": "123456"}
)
@ -91,7 +89,7 @@ class TestMFASimpleIntegration:
# Now disable MFA with mocked password verification
with mock.patch('libs.password.compare_password', return_value=True):
response = test_client.post(
f"/console/api/account/mfa/disable",
"/console/api/account/mfa/disable",
headers=auth_header,
json={"password": "any_password"} # Password doesn't matter, it's mocked
)
@ -101,7 +99,7 @@ class TestMFASimpleIntegration:
# Verify MFA is disabled
response = test_client.get(
f"/console/api/account/mfa/status",
"/console/api/account/mfa/status",
headers=auth_header
)
assert response.status_code == 200

@ -1,9 +1,7 @@
import json
import unittest
from datetime import datetime
from unittest.mock import Mock, patch
from datetime import datetime, timezone
import pytest
from models.account import Account, AccountMFASettings
from services.mfa_service import MFAService

Loading…
Cancel
Save