finai/backend/app/services/user_service.py

140 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from datetime import datetime
from sqlalchemy import select
from sqlalchemy.orm import Session
from app.models import JobTitle, Permission, Role, User
DEFAULT_ROLES = {
"employee": "普通员工",
"admin": "业务管理员",
"system_admin": "系统管理员",
}
# 业务职级预设。用户在个人资料里选的头衔。跟制度里的分组名不一定字面一致,
# 字面不一致时必须在 JOB_TITLE_GROUP_ALIASES 里加映射,否则 chat.py 拿 job_title
# 做子串匹配会全部落空LLM 反问澄清。
DEFAULT_JOB_TITLES: list[str] = [
"董事长",
"总经理",
"领导班子副职",
"总助级",
"中层干部正职及相当职级人员",
"中层干部副职及相当职级人员",
"教授级高工及相当职称人员",
"普通员工",
]
# 业务职级 -> 制度里"按职级分组"分组名的关键词列表。
# 制度里分组常写作"总院领导班子正职"这种复合词,用户选的却是"董事长"这种具体头衔,
# chat.py 会拿这里的关键词代替原 job_title 做子串规则("包含任一关键词")。
# 未在此表的 job_title 回退成拿它本身做子串匹配(老行为)。
# 加/改字典项时,同步维护此表;关键词要够特异,避免误命中相邻分组
# (例如"正职"太泛,会同时命中"领导班子正职"和"中层正职")。
JOB_TITLE_GROUP_ALIASES: dict[str, list[str]] = {
"董事长": ["领导班子正职"],
"总经理": ["领导班子正职"],
"领导班子副职": ["领导班子副职"],
"总助级": ["总助级"],
"中层干部正职及相当职级人员": ["中层正职", "中层干部正职"],
"中层干部副职及相当职级人员": ["中层副职", "中层干部副职"],
"教授级高工及相当职称人员": ["教授级高工"],
"普通员工": ["普通员工"],
}
# 页面级权限code -> (显示名, 模块)
DEFAULT_PAGE_PERMISSIONS: dict[str, tuple[str, str]] = {
"page.chat": ("智能问答", "page"),
"page.documents": ("知识文档", "page"),
"page.audit": ("问答审计", "page"),
"page.analytics": ("数据分析", "page"),
"page.settings": ("系统设置", "page"),
}
# 角色 -> 页面权限 code 列表
DEFAULT_ROLE_PAGE_PERMISSIONS: dict[str, list[str]] = {
"employee": ["page.chat"],
"admin": ["page.chat", "page.documents", "page.audit", "page.analytics"],
"system_admin": list(DEFAULT_PAGE_PERMISSIONS.keys()),
}
def _ensure_page_permissions(db: Session) -> dict[str, Permission]:
existing = {p.code: p for p in db.scalars(select(Permission)).all()}
for code, (name, module) in DEFAULT_PAGE_PERMISSIONS.items():
if code not in existing:
p = Permission(code=code, name=name, module=module)
db.add(p)
existing[code] = p
db.flush()
return existing
def ensure_roles(db: Session) -> None:
perms = _ensure_page_permissions(db)
existing_roles = {role.code: role for role in db.scalars(select(Role)).all()}
for code, name in DEFAULT_ROLES.items():
role = existing_roles.get(code)
if role is None:
role = Role(code=code, name=name)
db.add(role)
existing_roles[code] = role
db.flush()
# 只补齐默认页面权限,不覆盖管理员后续在后台自定义的权限
for code, page_codes in DEFAULT_ROLE_PAGE_PERMISSIONS.items():
role = existing_roles.get(code)
if role is None:
continue
current = {p.code for p in role.permissions}
for page_code in page_codes:
if page_code not in current and page_code in perms:
role.permissions.append(perms[page_code])
db.flush()
def ensure_job_titles(db: Session) -> None:
"""把 DEFAULT_JOB_TITLES 里没入库的补进去;已存在的保留,不覆盖启用状态/顺序。"""
existing = {jt.name for jt in db.scalars(select(JobTitle)).all()}
for idx, name in enumerate(DEFAULT_JOB_TITLES):
if name in existing:
continue
db.add(JobTitle(name=name, sort_order=idx, is_active=True))
db.flush()
def ensure_default_admin(db: Session) -> User:
ensure_roles(db)
ensure_job_titles(db)
user = db.scalar(select(User).where(User.phone == "13800000000"))
if user:
return user
role = db.scalar(select(Role).where(Role.code == "system_admin"))
user = User(phone="13800000000", name="系统管理员", department="财务部", is_superuser=True)
if role:
user.roles.append(role)
db.add(user)
db.flush()
return user
def get_or_create_login_user(db: Session, phone: str) -> User:
ensure_roles(db)
user = db.scalar(select(User).where(User.phone == phone))
if user:
user.last_login_at = datetime.utcnow()
return user
role = db.scalar(select(Role).where(Role.code == "employee"))
user = User(phone=phone, name=f"用户{phone[-4:]}", status="active", last_login_at=datetime.utcnow())
if role:
user.roles.append(role)
db.add(user)
db.flush()
return user
def apply_roles(db: Session, user: User, role_codes: list[str]) -> None:
ensure_roles(db)
roles = db.scalars(select(Role).where(Role.code.in_(role_codes))).all() if role_codes else []
user.roles = list(roles)