Files
Agent-System/internal/auth/bootstrap.go
T
weichen f97ed2dd98 feat(auth): persist sessions and accounts via PostgresAuthStore
Add PgStore with hashed token sessions, IAM bootstrap, and store factory wiring; remove in-memory token map and allow_dev_switch from login payload.
2026-09-12 01:39:31 +00:00

115 lines
3.2 KiB
Go

package auth
import (
"context"
"fmt"
"github.com/jackc/pgx/v5/pgxpool"
"chat-agent-system/internal/config"
)
// BootstrapAdminFromConfig 确保配置的管理员账户在 PG 中存在且具备 role-admin。
func BootstrapAdminFromConfig(ctx context.Context, store AuthStore, cfg *config.Config) error {
if store == nil || cfg == nil {
return nil
}
adminUser := cfg.AdminUsername
adminPass := cfg.AdminPassword
if adminUser == "" {
adminUser = "admin"
}
if adminPass == "" {
return nil
}
existing, err := store.GetUserByUsername(ctx, adminUser)
if err == nil && existing != nil {
if existing.RoleID != "role-admin" {
_, _ = store.UpdateUserRole(ctx, existing.ID, "role-admin", "系统管理员")
}
if existing.PasswordHash == "" {
hash, hashErr := HashPassword(adminPass)
if hashErr != nil {
return hashErr
}
_, err = store.UpdateUserPassword(ctx, existing.ID, hash, false)
return err
}
return nil
}
hash, err := HashPassword(adminPass)
if err != nil {
return fmt.Errorf("bootstrap admin hash: %w", err)
}
_, err = store.CreateUser(ctx, &UserAccount{
Username: adminUser,
Name: "系统管理员",
PasswordHash: hash,
Status: StatusActive,
MustChangePassword: false,
RoleID: "role-admin",
Position: "系统管理员",
Department: "系统运维部",
EmployeeID: "SYS-000",
})
return err
}
// BootstrapDevSeedUsers 在 dev/test 环境补齐演示账号(与 MemoryStore 种子对齐)。
func BootstrapDevSeedUsers(ctx context.Context, store AuthStore, cfg *config.Config) error {
if store == nil || cfg == nil {
return nil
}
if cfg.Env != "dev" && cfg.Env != "test" && cfg.Env != "" {
return nil
}
seeds := []struct {
username string
name string
roleID string
position string
dept string
empID string
}{
{"zhanggong", "张工", "role-engineer", "方案工程师", "骨科耗材研发组", "RD-001"},
{"lizhuguan", "李主管", "role-tech-lead", "技术主管", "骨科耗材研发组", "RD-002"},
{"wangzong", "王总监", "role-director", "研发总监", "研发中心", "RD-003"},
{"guest", "访客", "role-guest", "待指派", "外协中心", "EXT-999"},
}
passHash, err := HashPassword("123456")
if err != nil {
return err
}
for _, su := range seeds {
if _, err := store.GetUserByUsername(ctx, su.username); err == nil {
continue
}
_, err := store.CreateUser(ctx, &UserAccount{
Username: su.username,
Name: su.name,
PasswordHash: passHash,
Status: StatusActive,
RoleID: su.roleID,
Position: su.position,
Department: su.dept,
EmployeeID: su.empID,
})
if err != nil {
return fmt.Errorf("seed user %s: %w", su.username, err)
}
}
return nil
}
// BootstrapIAM 在 PG IAM 就绪后执行管理员与 dev 种子初始化。
func BootstrapIAM(ctx context.Context, pool *pgxpool.Pool, store AuthStore, cfg *config.Config) error {
if !IAMTablesReady(ctx, pool) {
return nil
}
if err := BootstrapAdminFromConfig(ctx, store, cfg); err != nil {
return err
}
return BootstrapDevSeedUsers(ctx, store, cfg)
}