This commit is contained in:
fengchuanhn@gmail.com
2026-05-22 18:13:07 +08:00
parent 80958994a2
commit 9526c0cb1b
2 changed files with 49 additions and 0 deletions

View File

@@ -22,13 +22,19 @@ async def register(
db: DbSession, db: DbSession,
redis: RedisClient, redis: RedisClient,
device_serial: str | None = Header(default=None, convert_underscores=False), device_serial: str | None = Header(default=None, convert_underscores=False),
oem_id: str | None = Header(default=None, convert_underscores=False),
agent_id: str | None = Header(default=None, convert_underscores=False),
) -> ApiResponse[TokenResponse]: ) -> ApiResponse[TokenResponse]:
try: try:
parsed_oem_id = auth_service.parse_id_header(oem_id, field_name="oem_id")
parsed_agent_id = auth_service.parse_id_header(agent_id, field_name="agent_id")
result = await auth_service.register_user( result = await auth_service.register_user(
db, db,
username=body.username, username=body.username,
password=body.password, password=body.password,
device_serial=device_serial, device_serial=device_serial,
oem_id=parsed_oem_id,
agent_id=parsed_agent_id,
) )
except auth_service.AuthError as exc: except auth_service.AuthError as exc:
return ApiResponse(ok=False, message=exc.message) return ApiResponse(ok=False, message=exc.message)

View File

@@ -4,6 +4,7 @@ from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from app.config import get_settings from app.config import get_settings
from app.core.roles import ROLE_AGENT, ROLE_OEM
from app.core.heartbeat_verify import compute_server_verify_code from app.core.heartbeat_verify import compute_server_verify_code
from app.core.security import ( from app.core.security import (
create_access_token, create_access_token,
@@ -29,6 +30,40 @@ def _normalize_device_serial(value: str | None) -> str:
return value.strip()[:255] return value.strip()[:255]
def parse_id_header(value: str | None, *, field_name: str) -> int | None:
if value is None or not str(value).strip():
return None
try:
parsed = int(str(value).strip())
except ValueError as exc:
raise AuthError(f"{field_name} 无效") from exc
if parsed < 1:
raise AuthError(f"{field_name} 无效")
return parsed
async def _validate_register_owner_ids(
db: AsyncSession,
*,
oem_id: int | None,
agent_id: int | None,
) -> tuple[int | None, int | None]:
resolved_oem_id = oem_id
if agent_id is not None:
agent = await db.get(User, agent_id)
if agent is None or agent.role_id != ROLE_AGENT:
raise AuthError("代理无效")
if resolved_oem_id is None:
resolved_oem_id = agent.oem_id
elif agent.oem_id != resolved_oem_id:
raise AuthError("代理与 OEM 不匹配")
if resolved_oem_id is not None:
oem = await db.get(User, resolved_oem_id)
if oem is None or oem.role_id != ROLE_OEM:
raise AuthError("OEM 无效")
return resolved_oem_id, agent_id
def _vip_is_active(vip_end_time: datetime | None) -> bool: def _vip_is_active(vip_end_time: datetime | None) -> bool:
if vip_end_time is None: if vip_end_time is None:
return False return False
@@ -61,6 +96,8 @@ async def register_user(
username: str, username: str,
password: str, password: str,
device_serial: str | None = None, device_serial: str | None = None,
oem_id: int | None = None,
agent_id: int | None = None,
) -> TokenResponse: ) -> TokenResponse:
existing = await db.scalar(select(User).where(User.username == username)) existing = await db.scalar(select(User).where(User.username == username))
if existing is not None: if existing is not None:
@@ -72,12 +109,18 @@ async def register_user(
if bound is not None: if bound is not None:
raise AuthError("该电脑已绑定其它用户") raise AuthError("该电脑已绑定其它用户")
resolved_oem_id, resolved_agent_id = await _validate_register_owner_ids(
db, oem_id=oem_id, agent_id=agent_id
)
user = User( user = User(
username=username, username=username,
password_hash=hash_password(password), password_hash=hash_password(password),
role_id=0, role_id=0,
phone=None, phone=None,
device_serial=serial, device_serial=serial,
oem_id=resolved_oem_id,
agent_id=resolved_agent_id,
) )
db.add(user) db.add(user)
await db.flush() await db.flush()