Files
Agent-System/internal/auth/store.go
T
weichenandCursor 90f77eac93 feat(authz): implement six-phase permissions, settings and workflow v2
Close P0 auth gaps for lineage/runs, stage ABAC fail-closed, and
project:create; add IAM migrations 00021-23, me settings APIs, schema v2
manifests, orchestrator skeleton, and gate A regression coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-13 02:50:23 +00:00

281 lines
7.5 KiB
Go

package auth
import (
"context"
"fmt"
"strings"
"sync"
"time"
"chat-agent-system/internal/config"
)
// AuthStore 用户与认证配置存储接口
type AuthStore interface {
GetUserByUsername(ctx context.Context, username string) (*UserAccount, error)
GetUserByID(ctx context.Context, id int64) (*UserAccount, error)
CreateUser(ctx context.Context, user *UserAccount) (*UserAccount, error)
UpdateUser(ctx context.Context, user *UserAccount) (*UserAccount, error)
UpdateUserRole(ctx context.Context, id int64, roleID, position string) (*UserAccount, error)
UpdateUserStatus(ctx context.Context, id int64, status AccountStatus) (*UserAccount, error)
UpdateUserPassword(ctx context.Context, id int64, passwordHash string, mustChangePassword bool) (*UserAccount, error)
ListUsers(ctx context.Context) ([]*UserAccount, error)
GetConfig(ctx context.Context) (SystemAuthConfig, error)
UpdateConfig(ctx context.Context, cfg SystemAuthConfig) error
}
// MemoryStore 内存与并发安全存储实现
type MemoryStore struct {
mu sync.RWMutex
users map[int64]*UserAccount
nextID int64
cfg SystemAuthConfig
}
// NewMemoryStore 初始化并载入初始系统管理员与基线用户
func NewMemoryStore(cfg *config.Config) *MemoryStore {
store := &MemoryStore{
users: make(map[int64]*UserAccount),
nextID: 1,
cfg: SystemAuthConfig{
AllowRegistration: true,
RequireApproval: false,
},
}
if cfg != nil {
store.cfg.AllowRegistration = cfg.AuthRegistrationEnabled
store.cfg.RequireApproval = cfg.AuthRequireApproval
}
now := time.Now().Format("2006-01-02 15:04:05")
// 1. 初始化 .env 系统超级管理员
adminUser := "admin"
adminPass := "admin-secret-password-123"
if cfg != nil && cfg.AdminUsername != "" {
adminUser = cfg.AdminUsername
}
if cfg != nil && cfg.AdminPassword != "" {
adminPass = cfg.AdminPassword
}
adminHash, _ := HashPassword(adminPass)
store.users[1] = &UserAccount{
ID: 1,
Username: adminUser,
Name: "系统管理员",
PasswordHash: adminHash,
Status: StatusActive,
MustChangePassword: false,
RoleID: "role-admin",
Position: "系统管理员",
Department: "系统运维部",
EmployeeID: "SYS-000",
CreatedAt: now,
UpdatedAt: now,
}
store.nextID = 2
// 2. 标准测试用户仅 dev/test 环境种子化;生产不得携带固定密码演示账号
env := ""
if cfg != nil {
env = cfg.Env
}
if env == "dev" || env == "test" || env == "" {
defaultPassHash, _ := HashPassword("123456")
seedUsers := []struct {
id int64
username string
name string
roleID string
position string
dept string
employeeID string
}{
{2, "zhanggong", "张工", "role-tech-lead", "技术主管", "骨科耗材研发组", "RD-001"},
{3, "lizhuguan", "李主管", "role-tech-lead", "技术主管", "骨科耗材研发组", "RD-002"},
{4, "wangzong", "王总监", "role-director", "研发总监", "研发中心", "RD-003"},
{5, "guest", "访客", "role-guest", "待指派", "外协中心", "EXT-999"},
}
for _, su := range seedUsers {
store.users[su.id] = &UserAccount{
ID: su.id,
Username: su.username,
Name: su.name,
PasswordHash: defaultPassHash,
Status: StatusActive,
MustChangePassword: false,
RoleID: su.roleID,
Position: su.position,
Department: su.dept,
EmployeeID: su.employeeID,
CreatedAt: now,
UpdatedAt: now,
}
if su.id >= store.nextID {
store.nextID = su.id + 1
}
}
}
return store
}
// GetUserByUsername 根据用户名查询
func (s *MemoryStore) GetUserByUsername(ctx context.Context, username string) (*UserAccount, error) {
s.mu.RLock()
defer s.mu.RUnlock()
for _, u := range s.users {
if strings.EqualFold(u.Username, username) {
copy := *u
return &copy, nil
}
}
return nil, fmt.Errorf("user not found: %s", username)
}
// GetUserByID 根据用户ID查询
func (s *MemoryStore) GetUserByID(ctx context.Context, id int64) (*UserAccount, error) {
s.mu.RLock()
defer s.mu.RUnlock()
u, exists := s.users[id]
if !exists {
return nil, fmt.Errorf("user not found: %d", id)
}
copy := *u
return &copy, nil
}
// CreateUser 创建新用户账号
func (s *MemoryStore) CreateUser(ctx context.Context, user *UserAccount) (*UserAccount, error) {
s.mu.Lock()
defer s.mu.Unlock()
for _, existing := range s.users {
if strings.EqualFold(existing.Username, user.Username) {
return nil, fmt.Errorf("username already exists: %s", user.Username)
}
}
user.ID = s.nextID
s.nextID++
now := time.Now().Format("2006-01-02 15:04:05")
if user.CreatedAt == "" {
user.CreatedAt = now
}
user.UpdatedAt = now
copied := *user
s.users[user.ID] = &copied
result := *user
return &result, nil
}
// UpdateUser 更新用户基础资料
func (s *MemoryStore) UpdateUser(ctx context.Context, user *UserAccount) (*UserAccount, error) {
s.mu.Lock()
defer s.mu.Unlock()
existing, ok := s.users[user.ID]
if !ok {
return nil, fmt.Errorf("user not found: %d", user.ID)
}
existing.Name = user.Name
existing.Department = user.Department
existing.EmployeeID = user.EmployeeID
existing.Email = user.Email
existing.Avatar = user.Avatar
existing.UpdatedAt = time.Now().Format("2006-01-02 15:04:05")
copy := *existing
return &copy, nil
}
// UpdateUserRole 更新用户职位与全局角色
func (s *MemoryStore) UpdateUserRole(ctx context.Context, id int64, roleID, position string) (*UserAccount, error) {
s.mu.Lock()
defer s.mu.Unlock()
existing, ok := s.users[id]
if !ok {
return nil, fmt.Errorf("user not found: %d", id)
}
existing.RoleID = roleID
existing.Position = position
existing.UpdatedAt = time.Now().Format("2006-01-02 15:04:05")
copy := *existing
return &copy, nil
}
// UpdateUserStatus 更新用户账号状态
func (s *MemoryStore) UpdateUserStatus(ctx context.Context, id int64, status AccountStatus) (*UserAccount, error) {
s.mu.Lock()
defer s.mu.Unlock()
existing, ok := s.users[id]
if !ok {
return nil, fmt.Errorf("user not found: %d", id)
}
existing.Status = status
existing.UpdatedAt = time.Now().Format("2006-01-02 15:04:05")
copy := *existing
return &copy, nil
}
// UpdateUserPassword 更新用户密码并置位/复位首次强制改密
func (s *MemoryStore) UpdateUserPassword(ctx context.Context, id int64, passwordHash string, mustChangePassword bool) (*UserAccount, error) {
s.mu.Lock()
defer s.mu.Unlock()
existing, ok := s.users[id]
if !ok {
return nil, fmt.Errorf("user not found: %d", id)
}
existing.PasswordHash = passwordHash
existing.MustChangePassword = mustChangePassword
existing.UpdatedAt = time.Now().Format("2006-01-02 15:04:05")
copy := *existing
return &copy, nil
}
// ListUsers 列出所有用户
func (s *MemoryStore) ListUsers(ctx context.Context) ([]*UserAccount, error) {
s.mu.RLock()
defer s.mu.RUnlock()
list := make([]*UserAccount, 0, len(s.users))
for _, u := range s.users {
copy := *u
// 脱敏密码哈希
copy.PasswordHash = ""
list = append(list, &copy)
}
return list, nil
}
// GetConfig 获取准入配置
func (s *MemoryStore) GetConfig(ctx context.Context) (SystemAuthConfig, error) {
s.mu.RLock()
defer s.mu.RUnlock()
return s.cfg, nil
}
// UpdateConfig 更新准入配置
func (s *MemoryStore) UpdateConfig(ctx context.Context, cfg SystemAuthConfig) error {
s.mu.Lock()
defer s.mu.Unlock()
s.cfg = cfg
return nil
}