diff --git a/internal/auth/auth_test.go b/internal/auth/auth_test.go index 422875b8..544d6cf5 100644 --- a/internal/auth/auth_test.go +++ b/internal/auth/auth_test.go @@ -29,6 +29,7 @@ func TestPasswordCrypto(t *testing.T) { func TestAuthStoreMemory_Operations(t *testing.T) { cfg := &config.Config{ + Env: "dev", AdminUsername: "superadmin", AdminPassword: "admin-test-pass-999", AuthRegistrationEnabled: true, diff --git a/internal/auth/store.go b/internal/auth/store.go index 781bcf3b..1ae25e08 100644 --- a/internal/auth/store.go +++ b/internal/auth/store.go @@ -76,40 +76,46 @@ func NewMemoryStore(cfg *config.Config) *MemoryStore { } store.nextID = 2 - // 2. 初始化标准测试用户 (统一初始密码: 123456) - defaultPassHash, _ := HashPassword("123456") - seedUsers := []struct { - id int64 - username string - name string - roleID string - position string - dept string - employeeID string - }{ - {2, "zhanggong", "张工", "role-engineer", "方案工程师", "骨科耗材研发组", "RD-001"}, - {3, "lizhuguan", "李主管", "role-tech-lead", "技术主管", "骨科耗材研发组", "RD-002"}, - {4, "wangzong", "王总监", "role-director", "研发总监", "研发中心", "RD-003"}, - {5, "guest", "访客", "role-guest", "待指派", "外协中心", "EXT-999"}, + // 2. 标准测试用户仅 dev/test 环境种子化;生产不得携带固定密码演示账号 + env := "" + if cfg != nil { + env = cfg.Env } - - 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 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-engineer", "方案工程师", "骨科耗材研发组", "RD-001"}, + {3, "lizhuguan", "李主管", "role-tech-lead", "技术主管", "骨科耗材研发组", "RD-002"}, + {4, "wangzong", "王总监", "role-director", "研发总监", "研发中心", "RD-003"}, + {5, "guest", "访客", "role-guest", "待指派", "外协中心", "EXT-999"}, } - if su.id >= store.nextID { - store.nextID = su.id + 1 + + 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 + } } } diff --git a/internal/auth/store_test.go b/internal/auth/store_test.go new file mode 100644 index 00000000..19342b4b --- /dev/null +++ b/internal/auth/store_test.go @@ -0,0 +1,49 @@ +package auth_test + +import ( + "context" + "testing" + + "chat-agent-system/internal/auth" + "chat-agent-system/internal/config" +) + +func TestMemoryStore_DevEnvSeedsDemoUsers(t *testing.T) { + cfg := &config.Config{Env: "dev", AdminPassword: "admin-test-pass-999"} + store := auth.NewMemoryStore(cfg) + ctx := context.Background() + + user, err := store.GetUserByUsername(ctx, "zhanggong") + if err != nil { + t.Fatalf("expected zhanggong in dev env: %v", err) + } + if user.RoleID != "role-engineer" { + t.Fatalf("unexpected role: %s", user.RoleID) + } +} + +func TestMemoryStore_MainEnvNoSeedUsers(t *testing.T) { + cfg := &config.Config{ + Env: "main", + AdminPassword: "secure-main-admin-pass-xyz", + } + store := auth.NewMemoryStore(cfg) + ctx := context.Background() + + if _, err := store.GetUserByUsername(ctx, "zhanggong"); err == nil { + t.Fatal("main env must not seed zhanggong demo user") + } + if _, err := store.GetUserByUsername(ctx, "guest"); err == nil { + t.Fatal("main env must not seed guest demo user") + } + admin, err := store.GetUserByUsername(ctx, cfg.AdminUsername) + if err != nil && cfg.AdminUsername == "" { + admin, err = store.GetUserByUsername(ctx, "admin") + } + if err != nil { + t.Fatalf("admin account should still exist: %v", err) + } + if admin.RoleID != "role-admin" { + t.Fatalf("expected role-admin, got %s", admin.RoleID) + } +} diff --git a/internal/server/auth_middleware.go b/internal/server/auth_middleware.go index 30e4eb4c..f2f3abbf 100644 --- a/internal/server/auth_middleware.go +++ b/internal/server/auth_middleware.go @@ -6,7 +6,14 @@ import ( ) func (s *Server) allowLegacyTestPrincipal() bool { - return s.cfg != nil && s.cfg.AllowInMemory && s.cfg.ContextDbHost == "" + if s.cfg == nil { + return false + } + env := s.cfg.Env + if env != "dev" && env != "test" && env != "" { + return false + } + return s.cfg.AllowInMemory && s.cfg.ContextDbHost == "" } func isPublicRoute(method, path string) bool { diff --git a/internal/server/test_auth_helpers.go b/internal/server/test_auth_helpers.go index 474883cf..5d8867e5 100644 --- a/internal/server/test_auth_helpers.go +++ b/internal/server/test_auth_helpers.go @@ -5,7 +5,6 @@ import ( "encoding/json" "net/http" "net/http/httptest" - "strconv" "testing" "chat-agent-system/internal/auth" @@ -47,7 +46,7 @@ func withBearerAuth(req *http.Request, token string) { req.Header.Set("Authorization", "Bearer "+token) } -// withUserIDAuth 为请求附加 X-User-ID(用户必须已存在于 auth store)。 -func withUserIDAuth(req *http.Request, userID int64) { - req.Header.Set("X-User-ID", strconv.FormatInt(userID, 10)) +// withBearerToken 为请求附加 Authorization Bearer Token(Phase 0:不再使用 X-User-ID)。 +func withBearerToken(req *http.Request, token string) { + req.Header.Set("Authorization", "Bearer "+token) }