chore(lint): make ruff happy
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
[GeoIP] Scheduled Update Service
|
||||
Periodically update the MaxMind GeoIP database
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
from app.config import settings
|
||||
from app.dependencies.geoip import get_geoip_helper
|
||||
from app.dependencies.scheduler import get_scheduler
|
||||
@@ -18,11 +20,11 @@ async def update_geoip_database():
|
||||
try:
|
||||
logger.info("[GeoIP] Starting scheduled GeoIP database update...")
|
||||
geoip = get_geoip_helper()
|
||||
|
||||
|
||||
# Run the synchronous update method in a background thread
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, lambda: geoip.update(force=False))
|
||||
|
||||
|
||||
logger.info("[GeoIP] Scheduled GeoIP database update completed successfully")
|
||||
except Exception as e:
|
||||
logger.error(f"[GeoIP] Scheduled GeoIP database update failed: {e}")
|
||||
@@ -33,20 +35,21 @@ def schedule_geoip_updates():
|
||||
Schedule the GeoIP database update task
|
||||
"""
|
||||
scheduler = get_scheduler()
|
||||
|
||||
|
||||
# Use settings to configure the update time: update once a week
|
||||
scheduler.add_job(
|
||||
update_geoip_database,
|
||||
'cron',
|
||||
"cron",
|
||||
day_of_week=settings.geoip_update_day,
|
||||
hour=settings.geoip_update_hour,
|
||||
minute=0,
|
||||
id='geoip_weekly_update',
|
||||
name='Weekly GeoIP database update',
|
||||
replace_existing=True
|
||||
id="geoip_weekly_update",
|
||||
name="Weekly GeoIP database update",
|
||||
replace_existing=True,
|
||||
)
|
||||
|
||||
|
||||
logger.info(
|
||||
f"[GeoIP] Scheduled update task registered: "
|
||||
f"every week on day {settings.geoip_update_day} at {settings.geoip_update_hour}:00"
|
||||
f"every week on day {settings.geoip_update_day} "
|
||||
f"at {settings.geoip_update_hour}:00"
|
||||
)
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
[GeoIP] Initialization Service
|
||||
Initialize the GeoIP database when the application starts
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
|
||||
from app.dependencies.geoip import get_geoip_helper
|
||||
from app.log import logger
|
||||
|
||||
|
||||
async def init_geoip():
|
||||
"""
|
||||
Asynchronously initialize the GeoIP database
|
||||
@@ -14,11 +18,11 @@ async def init_geoip():
|
||||
try:
|
||||
geoip = get_geoip_helper()
|
||||
logger.info("[GeoIP] Initializing GeoIP database...")
|
||||
|
||||
|
||||
# Run the synchronous update method in a background thread
|
||||
loop = asyncio.get_event_loop()
|
||||
await loop.run_in_executor(None, geoip.update)
|
||||
|
||||
|
||||
logger.info("[GeoIP] GeoIP database initialization completed")
|
||||
except Exception as e:
|
||||
logger.error(f"[GeoIP] GeoIP database initialization failed: {e}")
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
用户登录记录服务
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
from fastapi import Request
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
from app.database.user_login_log import UserLoginLog
|
||||
from app.dependencies.geoip import get_geoip_helper, get_client_ip, normalize_ip
|
||||
from app.dependencies.geoip import get_client_ip, get_geoip_helper, normalize_ip
|
||||
from app.log import logger
|
||||
|
||||
from fastapi import Request
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
|
||||
|
||||
class LoginLogService:
|
||||
"""用户登录记录服务"""
|
||||
|
||||
|
||||
@staticmethod
|
||||
async def record_login(
|
||||
db: AsyncSession,
|
||||
@@ -23,11 +25,11 @@ class LoginLogService:
|
||||
request: Request,
|
||||
login_success: bool = True,
|
||||
login_method: str = "password",
|
||||
notes: Optional[str] = None
|
||||
notes: str | None = None,
|
||||
) -> UserLoginLog:
|
||||
"""
|
||||
记录用户登录信息
|
||||
|
||||
|
||||
Args:
|
||||
db: 数据库会话
|
||||
user_id: 用户ID
|
||||
@@ -35,17 +37,17 @@ class LoginLogService:
|
||||
login_success: 登录是否成功
|
||||
login_method: 登录方式
|
||||
notes: 备注信息
|
||||
|
||||
|
||||
Returns:
|
||||
UserLoginLog: 登录记录对象
|
||||
"""
|
||||
# 获取客户端IP并标准化格式
|
||||
raw_ip = get_client_ip(request)
|
||||
ip_address = normalize_ip(raw_ip)
|
||||
|
||||
|
||||
# 获取User-Agent
|
||||
user_agent = request.headers.get("User-Agent", "")
|
||||
|
||||
|
||||
# 创建基本的登录记录
|
||||
login_log = UserLoginLog(
|
||||
user_id=user_id,
|
||||
@@ -54,20 +56,19 @@ class LoginLogService:
|
||||
login_time=datetime.utcnow(),
|
||||
login_success=login_success,
|
||||
login_method=login_method,
|
||||
notes=notes
|
||||
notes=notes,
|
||||
)
|
||||
|
||||
|
||||
# 异步获取GeoIP信息
|
||||
try:
|
||||
geoip = get_geoip_helper()
|
||||
|
||||
|
||||
# 在后台线程中运行GeoIP查询(避免阻塞)
|
||||
loop = asyncio.get_event_loop()
|
||||
geo_info = await loop.run_in_executor(
|
||||
None,
|
||||
lambda: geoip.lookup(ip_address)
|
||||
None, lambda: geoip.lookup(ip_address)
|
||||
)
|
||||
|
||||
|
||||
if geo_info:
|
||||
login_log.country_code = geo_info.get("country_iso", "")
|
||||
login_log.country_name = geo_info.get("country_name", "")
|
||||
@@ -75,7 +76,7 @@ class LoginLogService:
|
||||
login_log.latitude = geo_info.get("latitude", "")
|
||||
login_log.longitude = geo_info.get("longitude", "")
|
||||
login_log.time_zone = geo_info.get("time_zone", "")
|
||||
|
||||
|
||||
# 处理 ASN(可能是字符串,需要转换为整数)
|
||||
asn_value = geo_info.get("asn")
|
||||
if asn_value is not None:
|
||||
@@ -83,42 +84,47 @@ class LoginLogService:
|
||||
login_log.asn = int(asn_value)
|
||||
except (ValueError, TypeError):
|
||||
login_log.asn = None
|
||||
|
||||
|
||||
login_log.organization = geo_info.get("organization", "")
|
||||
|
||||
logger.debug(f"GeoIP lookup for {ip_address}: {geo_info.get('country_name', 'Unknown')}")
|
||||
|
||||
logger.debug(
|
||||
f"GeoIP lookup for {ip_address}: "
|
||||
f"{geo_info.get('country_name', 'Unknown')}"
|
||||
)
|
||||
else:
|
||||
logger.warning(f"GeoIP lookup failed for {ip_address}")
|
||||
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"GeoIP lookup error for {ip_address}: {e}")
|
||||
|
||||
|
||||
# 保存到数据库
|
||||
db.add(login_log)
|
||||
await db.commit()
|
||||
await db.refresh(login_log)
|
||||
|
||||
logger.info(f"Login recorded for user {user_id} from {ip_address} ({login_method})")
|
||||
|
||||
logger.info(
|
||||
f"Login recorded for user {user_id} from {ip_address} ({login_method})"
|
||||
)
|
||||
return login_log
|
||||
|
||||
|
||||
@staticmethod
|
||||
async def record_failed_login(
|
||||
db: AsyncSession,
|
||||
request: Request,
|
||||
attempted_username: Optional[str] = None,
|
||||
attempted_username: str | None = None,
|
||||
login_method: str = "password",
|
||||
notes: Optional[str] = None
|
||||
notes: str | None = None,
|
||||
) -> UserLoginLog:
|
||||
"""
|
||||
记录失败的登录尝试
|
||||
|
||||
|
||||
Args:
|
||||
db: 数据库会话
|
||||
request: HTTP请求对象
|
||||
attempted_username: 尝试登录的用户名
|
||||
login_method: 登录方式
|
||||
notes: 备注信息
|
||||
|
||||
|
||||
Returns:
|
||||
UserLoginLog: 登录记录对象
|
||||
"""
|
||||
@@ -129,17 +135,19 @@ class LoginLogService:
|
||||
request=request,
|
||||
login_success=False,
|
||||
login_method=login_method,
|
||||
notes=f"Failed login attempt: {attempted_username}" if attempted_username else "Failed login attempt"
|
||||
notes=f"Failed login attempt: {attempted_username}"
|
||||
if attempted_username
|
||||
else "Failed login attempt",
|
||||
)
|
||||
|
||||
|
||||
def get_request_info(request: Request) -> dict:
|
||||
"""
|
||||
提取请求的详细信息
|
||||
|
||||
|
||||
Args:
|
||||
request: HTTP请求对象
|
||||
|
||||
|
||||
Returns:
|
||||
dict: 包含请求信息的字典
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user