跳转至

创建 / 维护用户(写系统库)

目标:Agent 直接写数据库 创建或维护前台用户(登录账号 + 用户档案 + 部门角色绑定)。知识以本文为准。不走管理端 UI、不调 REST。

REQUIRED SUB-SKILL: 写库成功后必须用 rebuild-index 的 clear_cache.py 刷新缓存。禁止只 INSERT 就声称完成。

术语:

说法 落点
用户名 / 账号 / loginno T_ACCOUNT.LOGINNO(登录名)
显示名 / 姓名 T_USER.NAME(未给则 = 用户名)
所属角色 workspace role/{名}.role 的 id → T_USER_DEPARTMENT_ROLE_SET.ROLEID
所在部门 系统库 T_DEPARTMENT 的 id → 绑定表 DEPARTMENTID + T_USER.DEFAULTDEPARTMENT
系统库 Java Spring Boot 服务的 spring.datasource(usercenter / lite / runtime 连的那套库)
应用库 软件 .datasource 指向的业务库(TLK_ 等)。**禁止**当作用户库

角色本体在 workspace 文件,不在 t_role。历史 INSERT INTO t_role 已失效。


硬性规则:默认授予「工作台」员工角色

创建的用户需要默认授予「工作台」应用的员工角色。 无例外。

项 值
软件 desk.application(<name>desk</name>,<description>工作台</description>)
角色文件 desk.application/role/员工.role(<name>员工</name>,defaultRole=true)
绑定 再写一行 T_USER_DEPARTMENT_ROLE_SET,ROLEID = 该文件根属性 id(须读文件,禁止把「员工」当 ROLEID)
部门 与本次用户的 DEPARTMENTID 相同

与 --app-dir 业务角色**并存**(两行;若业务角色已经是工作台员工则只保留一行,勿重复插)。

禁止:

  • 只绑业务软件角色、漏绑工作台员工(前台无「发起新建 / 我的待办 / 经办跟踪」等 desk 入口)
  • 维护用户时 DELETE 掉工作台员工行,或把全部绑定「替换」成仅业务角色
  • 找不到 desk.application/role/员工.role 仍声称创建完成(停手问用户)

定位 desk.application:优先 --app-dir 的**同级目录** desk.application;再沿父目录查找 storage/workspace/desk.application。用 <description>工作台</description> 或 <name>desk</name> 确认,不要凭目录名猜测其它软件。

写库成功后 clear_cache.py 须对 业务 --app-dir 与 desk.application 都执行(未改 XML 不必 rebuild index)。


产出物

部分 落库 说明
登录凭证 T_ACCOUNT LOGINNO 全局唯一;密码为密文 LOGINPWD
用户档案 T_USER 属企业域;ACCOUNTID → 账户;DEFAULTDEPARTMENT 必填
部门-角色 T_USER_DEPARTMENT_ROLE_SET 三元组 (USERID, DEPARTMENTID, ROLEID);无此行则前台看不到非系统软件。创建用户必须额外授予「工作台」应用的员工角色(可与业务角色并存,多行)

同 LOGINNO 已有账户时**复用** T_ACCOUNT(一账户可对应多域多个 T_USER)。

推荐脚本(本目录):

python "<skill-dir>/scripts/create_user.py" --loginno zhangsan --name 张三 --role 员工 --department 研发部 --app-dir "<某个.application绝对路径>"
# 未传 --password 时 LOGINPWD 使用 admin1 的 123456 密文(见下)

连接参数未给齐时脚本会按下文「定位系统库」尝试读取;仍不确定则**停止并问用户**。


何时用 / 不用

用:新建测试账号;给已有用户改部门/角色/密码/姓名;用户说「按用户名、角色、部门创建用户」。

不用:生成 .role 文件(用 role 技能);改业务表 TLK_*(那是应用库);走管理端/REST 创建(本技能只写库)。


门禁(写库前必须齐)

缺一则询问,禁止猜测后直接 INSERT:

  1. 用户名(loginno)
  2. 所属角色(名称或 id)+ 角色所在 软件 .application 路径(用来读 .role 的 id,并给 clear_cache 用)
  3. 所在部门(名称或 id)
  4. 密码:未给则默认明文 123456(写入下文固定密文)。其它明文须加密或从已有账号复制。禁止把明文写入 LOGINPWD
  5. 系统库连接:按「定位系统库」;无法唯一确定时必须问用户(JDBC URL 或 host/port/库名/账号/密码)

可选:显示名(默认=用户名)、企业域(默认可从部门 DOMAIN_ID 推导)、邮箱/手机。


定位系统库(禁止用应用 .datasource)

用户中心表由 平台全局库 管理,对应正在跑的 Java Spring Boot 服务(常见 obpm-lite 8888,或 obpm-usercenter / obpm-runtime)。**不要**打开 {软件}.application/datasource/*.datasource 当作用户库——那是创建应用时的业务库,即使碰巧同一 MySQL 实例,连接来源也必须是服务配置。

按序尝试:

  1. 用户已给出 JDBC / host+port+库名+账号
  2. 正在使用的服务配置:obpm-lite → obpm-lite/src/main/resources/application.properties 的 spring.datasource.url;微服务则看 usercenter(或 runtime)对应 application.properties
  3. 环境变量:DB_HOST、DB_PORT、DB_USERNAME、DB_PASSWORD(缺省常见 localhost / 3307 / root / Teemlink2010,仅作候选,须能连上并验表)

Lite 样例(仓库默认,部署可能不同):

jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3307}/obpm_lite?...
spring.datasource.username=${DB_USERNAME:root}
spring.datasource.password=${DB_PASSWORD:Teemlink2010}

验库(必须先跑,失败即连错库):

SHOW TABLES LIKE 'T_USER';
SHOW TABLES LIKE 'T_ACCOUNT';
SHOW TABLES LIKE 'T_USER_DEPARTMENT_ROLE_SET';
SHOW TABLES LIKE 'T_DEPARTMENT';
SHOW TABLES LIKE 'T_DOMAIN';

五张都在 → 系统库。只有 TLK_* / 没有 T_ACCOUNT → 应用库,停手。候选连接 ≥2 条且验库都过、或一条都不过 → 问用户。


解析角色 / 部门 / 域

角色 id(workspace,不是库表)

读 {软件}.application/role/{角色名}.role 根属性 id。可按 <name> 匹配。多个 .role 重名或找不到 → 问用户。**禁止**把角色名写入 ROLEID。

部门 id(系统库)

SELECT ID, NAME, DOMAIN_ID, VALID
FROM T_DEPARTMENT
WHERE NAME = '{部门名}' AND (VALID = 1 OR VALID IS NULL);

0 行 / 多行(跨域重名)→ 问用户。不要自动建部门。

企业域

优先部门的 DOMAIN_ID。否则 SELECT ID, NAME FROM T_DOMAIN:仅 1 行可用;多行 → 问用户。


创建 vs 维护

SELECT u.ID, u.NAME, u.DOMAINID, u.ACCOUNTID, u.DEFAULTDEPARTMENT, a.LOGINNO
FROM T_USER u
JOIN T_ACCOUNT a ON u.ACCOUNTID = a.ID
WHERE a.LOGINNO = '{loginno}' AND u.DOMAINID = '{domainId}';
结果 动作
0 行 创建:账户(按 loginno 复用或新建)+ 用户 + 绑定
1 行 维护:改姓名/部门/角色/密码(只改用户明确要改的字段)
多行 停手问用户

另:SELECT ID, LOGINNO FROM T_ACCOUNT WHERE LOGINNO = '{loginno}' —— 已有账户则复用 ID,只补本域 T_USER。


写库约定

主键:Sequence.getSequence() 风格 19 位字母数字,或 __ + 短 UUID;库内不冲突即可。T_USER_DEPARTMENT_ROLE_SET.ID 同样生成(hbm 虽标 uuid,批量插入用 Sequence)。

表名以 Hibernate 为准:T_ACCOUNT / T_USER / T_USER_DEPARTMENT_ROLE_SET(MySQL 大小写不敏感时 t_user 亦可)。

布尔用 0/1。STATUS=1(在职有效)、LOCKFLAG=1(未锁)、ORDERBYNO=10000、PERMISSION_TYPE='public'、ISFIRSTLOGIN=1(新建)。

NAME_LETTER:中文用拼音首字母(如张三→zs);英文用小写字母。可空,但列表排序会受影响。

密码(LOGINPWD)

必须写密文,禁止明文。默认加密模式 0:Security.encryptPassword(Blowfish-CBC)。

优先:复制已知账号密文。 安装包内置前台账号 admin1 明文为 123456,其 T_ACCOUNT.LOGINPWD 可直接复用(Blowfish 带随机 IV,同明文每次加密结果不同,但同一密文可反复登录):

来源 loginno 明文 LOGINPWD(原样写入)
admin1 123456 77e558a1dd70259b8b10219707b8d54c0cec5d7b3fb3a200

新建用户未指定密码、或密码就是 123456 时:直接写入上表密文,不必再加密、不必连 admin1 现查。

其它明文:--copy-password-from {已有loginno}(明文须与源账号相同),或脚本按模式 0 加密(需 pycryptodome)。模式 1 为 SHA1 小写 hex。

创建 SQL(事务内按序)

1. T_ACCOUNT(loginno 尚不存在时):

INSERT INTO T_ACCOUNT (ID, LOGINNO, LOGINPWD, EMAIL, TELEPHONE, TELEPHONE2, ISFIRSTLOGIN)
VALUES ('{accountId}', '{loginno}', '77e558a1dd70259b8b10219707b8d54c0cec5d7b3fb3a200', NULL, NULL, NULL, 1);
-- 上式为明文 123456(admin1 密文);其它密码替换 LOGINPWD

2. T_USER:

INSERT INTO T_USER (
  ID, NAME, NAME_LETTER, STATUS, DOMAINID, DEFAULTDEPARTMENT, ACCOUNTID,
  LEVELS, DEPARTMENTUSER, USEIM, ORDERBYNO, LOCKFLAG, PERMISSION_TYPE,
  LIAISON_OFFICER, TELEPHONEPUBLIC, TELEPHONEPUBLIC2, EMAILPUBLIC, USERINFOPUBLIC,
  LASTMODIFYTIME
) VALUES (
  '{userId}', '{name}', '{nameLetter}', 1, '{domainId}', '{deptId}', '{accountId}',
  0, 0, 0, 10000, 1, 'public',
  0, 0, 0, 0, 1,
  NOW()
);

3. T_USER_DEPARTMENT_ROLE_SET(可多角色则多行;**至少**业务角色 + 工作台员工,已重合则一行):

INSERT INTO T_USER_DEPARTMENT_ROLE_SET (ID, USERID, DEPARTMENTID, ROLEID)
VALUES ('{setId}', '{userId}', '{deptId}', '{roleId}');
-- 默认再插工作台员工(ROLEID 读 desk.application/role/员工.role 根属性 id)
INSERT INTO T_USER_DEPARTMENT_ROLE_SET (ID, USERID, DEPARTMENTID, ROLEID)
VALUES ('{setIdDesk}', '{userId}', '{deptId}', '{deskEmployeeRoleId}');

三步同一事务。失败回滚。不要只插用户不插绑定。创建必须含工作台员工绑定。

维护 SQL

  • 改部门:UPDATE T_USER SET DEFAULTDEPARTMENT='{deptId}', LASTMODIFYTIME=NOW() WHERE ID='{userId}';该用户全部绑定行的 DEPARTMENTID 一并改到新部门(UPDATE T_USER_DEPARTMENT_ROLE_SET SET DEPARTMENTID=... WHERE USERID=...)
  • 改角色:为新 ROLEID 补一行或改对应行;**不得删除**工作台员工绑定
  • 改姓名:UPDATE T_USER SET NAME=..., NAME_LETTER=...
  • 改密码:UPDATE T_ACCOUNT SET LOGINPWD='{encrypted}' WHERE ID='{accountId}'
  • 不要无故新建第二个同域同 loginno 用户
  • 维护结束时仍须保证存在工作台员工绑定(缺则补插)

Agent 步骤(按序)

1. 收齐门禁五项;缺则问
2. 定位并验系统库;不确定则问(禁止用 .datasource)
3. 解析业务 roleId、deptId、domainId;再解析 desk.application/role/员工.role → deskEmployeeRoleId
4. 按 loginno+domain 判断创建或维护
5. 事务写 T_ACCOUNT → T_USER → T_USER_DEPARTMENT_ROLE_SET(业务角色 + 工作台员工)
6. 向用户摘要:loginno、userId、accountId、部门、业务角色 id、工作台员工角色 id、创建还是更新
7. REQUIRED:对业务软件与 desk.application 都执行
   python "<rebuild-index>/scripts/clear_cache.py" "<软件.application绝对路径>"
   只清缓存即可(未改模板 XML,不必 rebuild pid.index)。按 .done/.failed 判定
8. 失败(.failed / 超时)必须警告;成功才可声称完成

clear_cache 会按 applicationId 清设计时对象缓存,并做附属全局清理(含 MyCache / 权限等)。监视进程须为 Runtime / Manager / Job;Designer 不处理 .sync/。


校验与常见错误

问题 处理
连的是应用库 验表失败;改用 Spring spring.datasource,或问用户
明文密码 无法登录;123456 用 admin1 密文;其它用加密或 copy-from
未绑部门角色 前台看不到非系统软件;补 T_USER_DEPARTMENT_ROLE_SET + DEFAULTDEPARTMENT
未绑工作台员工 无「发起新建 / 我的待办」等 desk 入口;补 desk.application/role/员工.role 的 id
维护时删光其它绑定 会丢掉工作台员工;只 upsert,不整表替换
ROLEID 写成角色名 绑定无效;用 .role 根属性 id
跳过 clear_cache 运行时可能仍用旧用户/权限缓存
INSERT t_role 无效;角色在 role/*.role
同域 loginno 重复再 INSERT 应走维护
部门不存在就手建 先问用户

与其它技能边界

内容 本文 其它
系统库用户/账户/部门角色绑定 ✓
企业域绑定软件(t_domain.bind_applications) bind-domain-application
.role 文件、permissions generate-role-file
应用 .datasource / TLK_ 禁止当作用户库 generate-datasource-file
写库后清缓存 必做,调用 clear_cache rebuild-index
测试账号文档 USER.md 可提示补 run-testcase