Skip to content
Merged

sync #63

Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,3 @@ REDIS_PASSWORD=''
REDIS_DATABASE=0
# Token
TOKEN_SECRET_KEY='1VkVF75nsNABBjK_7-qz7GtzNy3AMvktc9TCPwKczCk'
# Opera Log
OPERA_LOG_ENCRYPT_SECRET_KEY='d77b25790a804c2b4a339dd0207941e4cefa5751935a33735bc73bb7071a005b'
2 changes: 1 addition & 1 deletion backend/app/admin/model/login_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class LoginLog(DataClassBase):
country: Mapped[str | None] = mapped_column(sa.String(64), comment='国家')
region: Mapped[str | None] = mapped_column(sa.String(64), comment='地区')
city: Mapped[str | None] = mapped_column(sa.String(64), comment='城市')
user_agent: Mapped[str | None] = mapped_column(sa.String(256), comment='请求头')
user_agent: Mapped[str | None] = mapped_column(sa.String(512), comment='请求头')
os: Mapped[str | None] = mapped_column(sa.String(64), comment='操作系统')
browser: Mapped[str | None] = mapped_column(sa.String(64), comment='浏览器')
device: Mapped[str | None] = mapped_column(sa.String(64), comment='设备')
Expand Down
2 changes: 1 addition & 1 deletion backend/app/admin/service/auth_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ async def logout(*, request: Request, response: Response) -> None:
await redis_client.delete(f'{settings.TOKEN_REDIS_PREFIX}:{user_id}:{session_uuid}')
await redis_client.delete(f'{settings.TOKEN_EXTRA_INFO_REDIS_PREFIX}:{user_id}:{session_uuid}')
if refresh_token:
await redis_client.delete(f'{settings.TOKEN_REFRESH_REDIS_PREFIX}:{user_id}:{refresh_token}')
await redis_client.delete(f'{settings.TOKEN_REFRESH_REDIS_PREFIX}:{user_id}:{session_uuid}')


auth_service: AuthService = AuthService()
3 changes: 1 addition & 2 deletions backend/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,8 @@ def setup_env_file() -> bool:
redis_password = Prompt.ask('Redis 密码(留空表示无密码)', password=True, default='')
redis_db = Prompt.ask('Redis 数据库编号', default='0')

console.print('生成 Token 和操作日志密钥...', style='white')
console.print('生成 Token 密钥...', style='white')
token_secret = secrets.token_urlsafe(32)
opera_log_secret = secrets.token_hex(32)

console.print('写入 .env 文件...', style='white')
env_content = env_content.replace("DATABASE_TYPE='postgresql'", f"DATABASE_TYPE='{db_type}'")
Expand Down
4 changes: 4 additions & 0 deletions backend/common/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from asyncio import Queue

from backend.common.log import log


async def batch_dequeue(queue: Queue, max_items: int, timeout: float) -> list:
"""
Expand All @@ -23,5 +25,7 @@ async def collector() -> None:
await asyncio.wait_for(collector(), timeout=timeout)
except asyncio.TimeoutError:
pass
except Exception as e:
log.error(f'队列批量获取失败: {e}')

return items
8 changes: 2 additions & 6 deletions backend/core/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Settings(BaseSettings):
# 数据库
DATABASE_ECHO: bool | Literal['debug'] = False
DATABASE_POOL_ECHO: bool | Literal['debug'] = False
DATABASE_SCHEMA: str = 'fba-simple'
DATABASE_SCHEMA: str = 'fba-slim'
DATABASE_CHARSET: str = 'utf8mb4'
DATABASE_PK_MODE: Literal['autoincrement', 'snowflake'] = 'autoincrement'

Expand Down Expand Up @@ -165,9 +165,6 @@ class Settings(BaseSettings):
LOG_ACCESS_FILENAME: str = 'fba_access.log'
LOG_ERROR_FILENAME: str = 'fba_error.log'

# .env 操作日志
OPERA_LOG_ENCRYPT_SECRET_KEY: str # secrets.token_hex(32)

# 操作日志
OPERA_LOG_PATH_EXCLUDE: list[str] = [
'/favicon.ico',
Expand All @@ -179,8 +176,7 @@ class Settings(BaseSettings):
f'{FASTAPI_API_V1_PATH}/oauth2/google/callback',
f'{FASTAPI_API_V1_PATH}/oauth2/linux-do/callback',
]
OPERA_LOG_ENCRYPT_TYPE: int = 1 # 0: AES (性能损耗); 1: md5; 2: ItsDangerous; 3: 不加密, others: 替换为 ******
OPERA_LOG_ENCRYPT_KEY_INCLUDE: list[str] = [ # 将加密接口入参参数对应的值
OPERA_LOG_REDACT_KEYS: list[str] = [
'password',
'old_password',
'new_password',
Expand Down
24 changes: 7 additions & 17 deletions backend/middleware/opera_log_middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from backend.app.admin.schema.opera_log import CreateOperaLogParam
from backend.app.admin.service.opera_log_service import opera_log_service
from backend.common.context import ctx
from backend.common.enums import OperaLogCipherType, StatusType
from backend.common.enums import StatusType
from backend.common.log import log
from backend.common.prometheus.instruments import (
PROMETHEUS_EXCEPTION_COUNTER,
Expand All @@ -25,7 +25,6 @@
from backend.common.response.response_code import StandardResponseCode
from backend.core.conf import settings
from backend.database.db import async_db_session
from backend.utils.encrypt import AESCipher, ItsDCipher, Md5Cipher
from backend.utils.trace_id import get_request_trace_id


Expand Down Expand Up @@ -208,20 +207,9 @@ def desensitization(args: dict[str, Any]) -> dict[str, Any]:
:param args: 需要脱敏的参数字典
:return:
"""
for key, value in args.items():
if key in settings.OPERA_LOG_ENCRYPT_KEY_INCLUDE:
match settings.OPERA_LOG_ENCRYPT_TYPE:
case OperaLogCipherType.aes:
args[key] = (AESCipher(settings.OPERA_LOG_ENCRYPT_SECRET_KEY).encrypt(value)).hex()
case OperaLogCipherType.md5:
args[key] = Md5Cipher.encrypt(value)
case OperaLogCipherType.itsdangerous:
args[key] = ItsDCipher(settings.OPERA_LOG_ENCRYPT_SECRET_KEY).encrypt(value)
case OperaLogCipherType.plan:
pass
case _:
args[key] = '******'

for key in args:
if key in settings.OPERA_LOG_REDACT_KEYS:
args[key] = '[REDACTED]'
return args

@classmethod
Expand All @@ -239,6 +227,8 @@ async def consumer(cls) -> None:
log.info('自动执行【操作日志批量创建】任务...')
async with async_db_session.begin() as db:
await opera_log_service.bulk_create(db=db, objs=logs)
except Exception as e:
log.error(f'操作日志入库失败,丢失 {len(logs)} 条日志: {e}')
finally:
if not cls.opera_log_queue.empty():
for _ in range(len(logs)):
cls.opera_log_queue.task_done()
Loading