user.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. package models
  2. import (
  3. "encoding/json"
  4. "time"
  5. "gorm.io/gorm"
  6. "golang.org/x/crypto/bcrypt"
  7. )
  8. // User represents a user in the system
  9. type User struct {
  10. ID int64 `gorm:"column:rowid;primaryKey;autoIncrement" json:"id"` // Unique identifier
  11. Username string `json:"username" gorm:"uniqueIndex;not null"` // Username
  12. Email string `json:"email" gorm:"uniqueIndex;not null"` // User's email address
  13. Password string `json:"password,omitempty" gorm:"not null"` // Password (hashed)
  14. Role string `json:"role" gorm:"default:'user'"` // User role
  15. PreferencesJSON string `json:"-" gorm:"column:preferences;type:text"` // User preferences stored as JSON string
  16. Preferences UserPreferences `json:"preferences" gorm:"-"` // User preferences (transient field)
  17. CreatedAt time.Time `json:"createdAt" gorm:"autoCreateTime"` // Creation timestamp
  18. UpdatedAt time.Time `json:"updatedAt" gorm:"autoUpdateTime"` // Last update timestamp
  19. DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` // Soft delete support
  20. }
  21. // UserPreferences represents user-specific settings
  22. type UserPreferences struct {
  23. Theme string `json:"theme"` // User's theme preference
  24. Notifications bool `json:"notifications"` // Notification preference
  25. DashboardLayout interface{} `json:"dashboardLayout,omitempty"` // Optional dashboard layout
  26. }
  27. // BeforeSave hook runs before saving a User - handles password hashing and preferences serialization
  28. func (u *User) BeforeSave(tx *gorm.DB) error {
  29. // Only hash password if it's provided and not already hashed
  30. if u.Password != "" && len(u.Password) < 60 { // bcrypt hashes are typically 60 characters
  31. hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
  32. if err != nil {
  33. return err
  34. }
  35. u.Password = string(hashedPassword)
  36. }
  37. // Serialize preferences to JSON
  38. preferencesData, err := json.Marshal(u.Preferences)
  39. if err != nil {
  40. return err
  41. }
  42. u.PreferencesJSON = string(preferencesData)
  43. return nil
  44. }
  45. // AfterFind hook deserializes JSON preferences after fetching from database
  46. func (u *User) AfterFind(tx *gorm.DB) error {
  47. if u.PreferencesJSON != "" {
  48. return json.Unmarshal([]byte(u.PreferencesJSON), &u.Preferences)
  49. }
  50. return nil
  51. }
  52. // CheckPassword verifies if the provided password matches the hashed one
  53. func (u *User) CheckPassword(password string) bool {
  54. err := bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
  55. return err == nil
  56. }
  57. type UserRole string
  58. const (
  59. Admin UserRole = "admin"
  60. Developer UserRole = "developer"
  61. Viewer UserRole = "viewer"
  62. )