Billing implements reserve -> commit -> refund against bl_quota and bl_ledger with row-level locking and idempotency keys; the refund commits on its own transaction so a failed request cannot silently keep a user's quota. Task implements the unified task centre over the state machine. Identity issues and resolves users. Remaining domains are placeholders whose READMEs state what belongs there and what must not.
39 lines
1.0 KiB
Python
Executable File
39 lines
1.0 KiB
Python
Executable File
"""Data access for the identity domain. **Only this module may touch id_* tables.**"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from packages.shared.models import Consent, User, UserIdentity
|
|
|
|
|
|
async def get_user(session: AsyncSession, user_id: int) -> User | None:
|
|
return await session.get(User, user_id)
|
|
|
|
|
|
async def find_identity(
|
|
session: AsyncSession, *, provider: str, union_id: str
|
|
) -> UserIdentity | None:
|
|
result = await session.execute(
|
|
select(UserIdentity).where(
|
|
UserIdentity.provider == provider, UserIdentity.union_id == union_id
|
|
)
|
|
)
|
|
return result.scalar_one_or_none()
|
|
|
|
|
|
def add_user(session: AsyncSession, user: User) -> User:
|
|
session.add(user)
|
|
return user
|
|
|
|
|
|
def add_identity(session: AsyncSession, identity: UserIdentity) -> UserIdentity:
|
|
session.add(identity)
|
|
return identity
|
|
|
|
|
|
def add_consent(session: AsyncSession, consent: Consent) -> Consent:
|
|
session.add(consent)
|
|
return consent
|