账号体系
单一来源 shared_auth.users
所有账号数据集中在 shared_auth 库的 users 表。两个应用(robovan / nempoi)各自连两个库:自己的业务库 + shared_auth。
sql
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
username TEXT UNIQUE, -- 可空(纯飞书账号无 username)
password_hash TEXT, -- 可空(纯飞书账号无密码)
display_name TEXT,
feishu_user_id TEXT UNIQUE, -- 飞书 OAuth 绑定
token_version INTEGER DEFAULT 0, -- 改密/改角色后 +1 → 旧 session 立即失效
robovan_role TEXT, -- superadmin/management/operations/finance/sales/pending
nempoi_role TEXT, -- superadmin/admin/customer
nempoi_organization_id INTEGER, -- nempoi customer 必填
nempoi_nem_token TEXT, -- per-admin NEM 凭据
nempoi_nem_token_synced_at TIMESTAMPTZ,
nempoi_nem_token_sync_key TEXT UNIQUE,
is_root_owner BOOLEAN DEFAULT FALSE, -- 根超管:全系统唯一
created_at TIMESTAMPTZ,
last_login_at TIMESTAMPTZ
);角色字段
| 字段 | 含义 | 取值 |
|---|---|---|
robovan_role | 在运力管理的角色 | superadmin / management / operations / finance / sales / pending / NULL |
nempoi_role | 在 NEMPOI 的角色 | superadmin / admin / customer / NULL |
is_root_owner | 是否根超管 | TRUE / FALSE |
NULL 表示不能登录该 app。例如某 user 仅有 robovan_role='operations',那他打开 nempoi.zephyrian.site 即使带 cookie 也会被拒绝(nempoi auth 校验 nempoi_role IS NOT NULL)。
根超管(is_root_owner)
- 整个系统只有一个(初始为 evan)
- 自动视为两边 app 的 superadmin(无需显式分配 robovan_role / nempoi_role)
- 普通 superadmin 不能修改 / 删除 / 改密 根超管账号
- 根超管自己可改自己
身份合并(同一人在两边都有)
如果一个员工既需要管 fleet 又需要管 NEMPOI,就给他设两个角色:
sql
UPDATE users SET robovan_role='operations', nempoi_role='admin' WHERE username='xxx';cookie 跨子域共享后,登录一次,两边都能用。
操作入口
门户超管面板 → 账号管理 提供完整 CRUD UI:
- 列出所有 user(根超管置顶 + 高亮)
- 增删改 + 双角色编辑 + 密码重置
- nempoi customer 必须绑定 organization_id