| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- """用户摘要、组织解析与列表查询。"""
- from __future__ import annotations
- from sqlalchemy import func, or_, select
- from dms.common.enums import AllowedModule, EnabledStatus, RoleCode
- from dms.common.errors import InvalidArgumentError, ResourceNotFoundError
- from dms.common.pagination import PageRequest, page_result
- from dms.common.response import serialize_id
- from dms.extensions import db
- from dms.models import Organization, User
- ALLOWED_MODULES = {
- RoleCode.USER: [AllowedModule.DOCUMENT_BROWSER.value],
- RoleCode.ADMIN: [
- AllowedModule.DOCUMENT_BROWSER.value,
- AllowedModule.BACKEND_MANAGEMENT.value,
- AllowedModule.AUDIT_LOG.value,
- ],
- }
- def effective_organization(user: User) -> tuple[int | None, str | None]:
- if user.organization_id is not None:
- organization = db.session.scalar(
- select(Organization).where(
- Organization.id == user.organization_id,
- Organization.is_deleted.is_(False),
- Organization.status == EnabledStatus.ENABLED.value,
- )
- )
- if organization is not None:
- return organization.id, organization.org_name
- return user.organization_id, user.organization_name
- def user_summary(user: User) -> dict[str, object]:
- organization_id, organization_name = effective_organization(user)
- return {
- "id": serialize_id(user.id),
- "username": user.username,
- "realName": user.real_name,
- "organizationId": serialize_id(organization_id),
- "organizationName": organization_name,
- "roleCode": user.role_code,
- "securityLevel": user.security_level,
- "status": user.status,
- "allowedModules": ALLOWED_MODULES[RoleCode(user.role_code)],
- }
- def parse_string_id(raw_value: str | None, *, name: str) -> int | None:
- if raw_value is None or raw_value == "":
- return None
- if not raw_value.isdecimal() or int(raw_value) <= 0:
- raise InvalidArgumentError(f"{name}必须是正整数形式的字符串ID")
- return int(raw_value)
- def _descendant_ids(root_id: int) -> set[int]:
- organizations = db.session.scalars(
- select(Organization).where(Organization.is_deleted.is_(False))
- ).all()
- if not any(item.id == root_id for item in organizations):
- raise ResourceNotFoundError("组织不存在")
- children: dict[int | None, list[int]] = {}
- for item in organizations:
- if item.status == EnabledStatus.ENABLED.value:
- children.setdefault(item.parent_id, []).append(item.id)
- found = {root_id}
- pending = [root_id]
- while pending:
- current = pending.pop()
- for child_id in children.get(current, []):
- if child_id not in found:
- found.add(child_id)
- pending.append(child_id)
- return found
- def list_users(
- *,
- organization_id: int | None,
- include_descendants: bool,
- keyword: str | None,
- status: str | None,
- page_request: PageRequest,
- ) -> dict[str, object]:
- filters = [User.is_deleted.is_(False)]
- if organization_id is not None:
- organization_ids = (
- _descendant_ids(organization_id)
- if include_descendants
- else {organization_id}
- )
- filters.append(User.organization_id.in_(organization_ids))
- if keyword:
- pattern = f"%{keyword.strip()}%"
- filters.append(or_(User.username.like(pattern), User.real_name.like(pattern)))
- if status:
- try:
- normalized_status = EnabledStatus(status).value
- except ValueError as exc:
- raise InvalidArgumentError("status必须是ENABLED或DISABLED") from exc
- filters.append(User.status == normalized_status)
- total = db.session.scalar(select(func.count(User.id)).where(*filters)) or 0
- users = db.session.scalars(
- select(User)
- .where(*filters)
- .order_by(User.real_name.asc(), User.id.asc())
- .offset(page_request.offset)
- .limit(page_request.page_size)
- ).all()
- return page_result(
- [user_summary(user) for user in users],
- page=page_request.page,
- page_size=page_request.page_size,
- total=total,
- )
|