refactor: config + lldaplib 收敛到 LLDAP 形态(读只读、删 OpenLDAP 写路径与密码包)

- config 重写:删 user-ou/inactive-ou/group-root-* / group-object-class /
  group-member-attr / initial-password;新增 lldap 写通道 + webhook + confirm-base-url
  + 两套 schedule + guard
- ldaplib 收拢为只读:属性常量/DN 归入 attrs.go;删 ops.go 写路径与 internal/password
- config.example.yml 重写成 LLDAP 形态
- 组命名修订(呼应 AGENTS.md 约束12):用部门稳定索引 cn=<dept_id> 做组身份,
  mirror_departments 增 group_id 列并跨快照保留,可读中文名只走 DB 展示
This commit is contained in:
2026-09-29 23:48:49 +08:00
parent 10ed3984dc
commit 979a98d502
16 changed files with 387 additions and 1031 deletions
+7 -7
View File
@@ -22,16 +22,16 @@ func mirrorUser(uid, email, deptID string) *store.MirrorUser {
}
}
func mirrorDept(id, name, pinyin, dn string, level int, parent string) *store.MirrorDepartment {
func mirrorDept(id, name, dn string, level int, parent string) *store.MirrorDepartment {
return &store.MirrorDepartment{
DeptID: id, Name: name, PinyinName: pinyin, DN: dn, Level: level, ParentID: parent,
DeptID: id, Name: name, DN: dn, Level: level, ParentID: parent,
}
}
// TestBuildFromMirrorUserDN 验证用户 DN 固定挂在 ou=people 下,不再有离职 OU。
func TestBuildFromMirrorUserDN(t *testing.T) {
depts := []*store.MirrorDepartment{
mirrorDept("od-root", "Acme", "Acme", "cn=Acme,ou=groups,dc=example,dc=com", 0, ""),
mirrorDept("od-root", "Acme", "cn=od-root,ou=groups,dc=example,dc=com", 0, ""),
}
users := []*store.MirrorUser{mirrorUser("alice", "alice@example.com", "od-root")}
@@ -51,8 +51,8 @@ func TestBuildFromMirrorUserDN(t *testing.T) {
// TestBuildFromMirrorGroupMembers 验证成员关系按用户所属部门归集到对应的组。
func TestBuildFromMirrorGroupMembers(t *testing.T) {
depts := []*store.MirrorDepartment{
mirrorDept("od-root", "Acme", "Acme", "cn=Acme,ou=groups,dc=example,dc=com", 0, ""),
mirrorDept("od-rd", "研发部", "Acme.yanfabu", "cn=Acme.yanfabu,ou=groups,dc=example,dc=com", 1, "od-root"),
mirrorDept("od-root", "Acme", "cn=od-root,ou=groups,dc=example,dc=com", 0, ""),
mirrorDept("od-rd", "研发部", "cn=od-rd,ou=groups,dc=example,dc=com", 1, "od-root"),
}
users := []*store.MirrorUser{
mirrorUser("alice", "alice@example.com", "od-rd"),
@@ -83,8 +83,8 @@ func TestBuildFromMirrorGroupMembers(t *testing.T) {
func TestBuildFromMirrorGroupOrderIsParentFirst(t *testing.T) {
depts := []*store.MirrorDepartment{
// 刻意让子部门先给出,验证 BuildFromMirror 内部仍按 Level 排回父先于子。
mirrorDept("od-rd", "研发部", "Acme.yanfabu", "cn=Acme.yanfabu,ou=groups,dc=example,dc=com", 1, "od-root"),
mirrorDept("od-root", "Acme", "Acme", "cn=Acme,ou=groups,dc=example,dc=com", 0, ""),
mirrorDept("od-rd", "研发部", "cn=od-rd,ou=groups,dc=example,dc=com", 1, "od-root"),
mirrorDept("od-root", "Acme", "cn=od-root,ou=groups,dc=example,dc=com", 0, ""),
}
st := BuildFromMirror(nil, depts, "dc=example,dc=com")