package models import ( "fmt" "time" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" ) type RoleName string const ( RoleSystemAdmin RoleName = "system_admin" RoleAdmin RoleName = "admin" RoleUser RoleName = "user" ) func (r RoleName) String() string { return string(r) } func (r RoleName) Rank() int { switch r { case RoleSystemAdmin: return 3 case RoleAdmin: return 2 case RoleUser: return 1 default: return 0 } } func (r RoleName) CanManage(target RoleName) bool { return r.Rank() > target.Rank() } func ParseRoleName(s string) (RoleName, error) { switch s { case "system_admin": return RoleSystemAdmin, nil case "admin": return RoleAdmin, nil case "user": return RoleUser, nil default: return "", fmt.Errorf("unknown role: %s", s) } } type Role struct { ID int32 `json:"id" gorm:"primaryKey;autoIncrement"` Name string `json:"name" gorm:"uniqueIndex;size:32;not null"` Description *string `json:"description"` Permissions string `json:"permissions" gorm:"type:jsonb;default:'[]'"` CreatedAt time.Time `json:"created_at"` Users []User `json:"-" gorm:"foreignKey:RoleID"` } func (r *Role) NameEnum() RoleName { role, _ := ParseRoleName(r.Name) return role } type User struct { ID string `json:"id" gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` Username string `json:"username" gorm:"uniqueIndex;size:32;not null"` Email *string `json:"email" gorm:"uniqueIndex;size:128"` PasswordHash string `json:"-" gorm:"size:255"` RoleID int32 `json:"role_id" gorm:"not null"` Role Role `json:"role,omitempty" gorm:"foreignKey:RoleID;references:ID"` Status string `json:"status" gorm:"size:16;default:active"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } type PublicUserInfo struct { ID string `json:"id"` Username string `json:"username"` Email *string `json:"email"` Role RoleName `json:"role"` Status string `json:"status"` CreatedAt time.Time `json:"created_at"` } func (u *User) ToPublicInfo() PublicUserInfo { return PublicUserInfo{ ID: u.ID, Username: u.Username, Email: u.Email, Role: u.Role.NameEnum(), Status: u.Status, CreatedAt: u.CreatedAt, } } func AutoMigrate(db *gorm.DB) error { return db.AutoMigrate(&Role{}, &User{}) } func SeedRoles(db *gorm.DB) error { roles := []Role{ {Name: string(RoleSystemAdmin), Description: strPtr("系统管理员,可管理管理员与系统配置"), Permissions: `["*"]`}, {Name: string(RoleAdmin), Description: strPtr("管理员,可管理普通用户"), Permissions: `["users.read", "users.write", "users.create"]`}, {Name: string(RoleUser), Description: strPtr("普通用户,可访问业务功能"), Permissions: `["dashboard.read", "profile.write"]`}, } for _, role := range roles { var existing Role if err := db.Where("name = ?", role.Name).First(&existing).Error; err != nil { if err == gorm.ErrRecordNotFound { if err := db.Create(&role).Error; err != nil { return err } } else { return err } } } return nil } // SeedSystemAdmin 在没有 system_admin 用户时创建默认系统管理员账号。 func SeedSystemAdmin(db *gorm.DB) error { var existing User if err := db.Where("username = ?", "system_admin").First(&existing).Error; err == nil { return nil } else if err != gorm.ErrRecordNotFound { return err } var role Role if err := db.Where("name = ?", RoleSystemAdmin).First(&role).Error; err != nil { return err } hash, err := bcrypt.GenerateFromPassword([]byte("system_admin"), bcrypt.DefaultCost) if err != nil { return err } return db.Create(&User{ Username: "system_admin", PasswordHash: string(hash), RoleID: role.ID, Status: "active", }).Error } func strPtr(s string) *string { return &s }