package users import ( "time" "github.com/google/uuid" "gorm.io/gorm" ) // BeforeCreate will set a UUID rather than numeric ID. func (base *User) BeforeCreate(tx *gorm.DB) error { if base.ID == "" { id, err := uuid.NewRandom() if err != nil { return err } base.ID = id.String() } return nil } type User struct { ID string `json:"id" gorm:"type:uuid;primary_key;"` Email string `json:"email" gorm:"uniqueIndex;size:255"` Name string `json:"name" gorm:"size:255"` Password string `json:"-" gorm:"size:255"` Permission string `json:"permission"` Type UserType `json:"type"` Status UserStatus `json:"status" gorm:"type:text;default:'pending'"` Details *UserDetails `json:"details" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` Preferences *UserPreferences `json:"preferences" gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` Avatar *string `json:"avatar" gorm:"size:512"` ActivatedAt *time.Time `json:"activatedAt" ts:"type=Nullable"` CreatedAt *time.Time `json:"createdAt,omitempty" ts:"type=Date"` UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` DeletedAt *gorm.DeletedAt `json:"-" gorm:"index" ` } type UpdateUserProfileRequest struct { ID string `json:"id"` Email string `json:"email"` Name string `json:"name"` Permission string `json:"permission"` Type UserType `json:"type"` Status UserStatus `json:"status"` } type UpdateUserAvatarRequest struct { ID string `json:"id" validate:"required,uuid4"` Img []byte `json:"img"` } // UserPreferences holds per-user settings stored as JSON. type UserPreferences struct { ID int `json:"id" gorm:"primaryKey"` UserID string `json:"userId" gorm:"type:uuid;column:user_foreign_key;not null;"` UseIdle bool `json:"useIdle"` IdleTimeout int `json:"idleTimeout"` UseIdlePassword bool `json:"useIdlePassword"` IdlePin string `json:"idlePin"` UseDirectLogin bool `json:"useDirectLogin"` UseQuadcodeLogin bool `json:"useQuadcodeLogin"` SendNoticesMail bool `json:"sendNoticesMail"` Language string `json:"language"` CreatedAt *time.Time `json:"createdAt,omitempty" ts:"type=Date"` UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` } type UpdateUserPreferencesRequest struct { ID int `json:"id"` UserID string `json:"userId"` UseIdle bool `json:"useIdle"` IdleTimeout int `json:"idleTimeout"` UseIdlePassword bool `json:"useIdlePassword"` IdlePin string `json:"idlePin"` UseDirectLogin bool `json:"useDirectLogin"` UseQuadcodeLogin bool `json:"useQuadcodeLogin"` SendNoticesMail bool `json:"sendNoticesMail"` Language string `json:"language"` } // UserDetails holds optional profile data. type UserDetails struct { ID int `json:"id" gorm:"primaryKey"` UserID string `json:"userId" gorm:"type:uuid;column:user_foreign_key;not null;"` Title string `json:"title"` FirstName string `json:"firstName"` LastName string `json:"lastName"` Address string `json:"address"` City string `json:"city"` ZipCode string `json:"zipCode"` Country string `json:"country"` Phone string `json:"phone"` CreatedAt *time.Time `json:"createdAt,omitempty" ts:"type=Date"` UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` } type UpdateUserDetailsRequest struct { ID int `json:"id"` UserID string `json:"userId" gorm:"index"` Title string `json:"title"` FirstName string `json:"firstName"` LastName string `json:"lastName"` Address string `json:"address"` City string `json:"city"` ZipCode string `json:"zipCode"` Country string `json:"country"` Phone string `json:"phone"` } // UserDetails holds optional profile data. // Session tracks logins with browser metadata. type Session struct { ID int `gorm:"primaryKey"` UserID *string `json:"userId" gorm:"index"` Username string `json:"username" gorm:"size:255"` AccessTokenHash string `json:"-" gorm:"size:128;index"` RefreshTokenHash string `json:"-" gorm:"size:128;index"` ExpiresAt time.Time `json:"expiresAt" ts:"type=Nullable" gorm:"index"` IPAddress string `json:"ipAddress" gorm:"size:64"` UserAgent string `json:"userAgent" gorm:"size:512"` CreatedAt time.Time `json:"createdAt,omitempty" ts:"type=Date"` UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` DeletedAt *gorm.DeletedAt `json:"-" gorm:"index" ` } type PasswordResetToken struct { ID int `gorm:"primaryKey"` UserID string `json:"userId" gorm:"index"` TokenHash string `json:"-" gorm:"size:64;uniqueIndex"` ExpiresAt time.Time `json:"expiresAt,omitempty" ts:"type=Date" gorm:"index"` UsedAt *time.Time `json:"usedAt,omitempty" ts:"type=Date"` CreatedAt *time.Time `json:"createdAt" ts:"type=Date"` UpdatedAt *time.Time `json:"updatedAt,omitempty" ts:"type=Date"` DeletedAt *gorm.DeletedAt `json:"-" gorm:"index"` } // UserStatus represents lifecycle state of a user. type UserStatus string // Typescript: enum=UserStatus const ( UserStatusPending UserStatus = "pending" UserStatusActive UserStatus = "active" UserStatusDisabled UserStatus = "disabled" ) // UserTypes represents different types of a user. type UserType string // Typescript: enum=UserTypes const ( UserTypeInternal UserType = "internal" UserTypeExternal UserType = "external" UserTypeSurveyor UserType = "surveyor" ) type LoginRequest struct { Username string `json:"username" validate:"required,email"` Password string `json:"password" validate:"required,min=8,max=128"` } type RefreshRequest struct { RefreshToken string `json:"refresh_token"` } type ForgotPasswordRequest struct { Email string `json:"email" validate:"required,email"` } type ResetPasswordRequest struct { Token string `json:"token" validate:"required,min=20,max=255"` Password string `json:"password" validate:"required,min=8,max=128"` } type UpdatePasswordRequest struct { ID string `json:"id" validate:"required,uuid4"` Password string `json:"password" validate:"required,min=8,max=128"` } type UpdateUserRequest struct { ID string `json:"id" validate:"required,uuid4"` Name string `json:"name" validate:"required,min=1,max=255"` Email string `json:"email" validate:"required,email"` Password string `json:"password" validate:"omitempty,min=8,max=128"` Permission string `json:"permission"` Status UserStatus `json:"status"` Type UserType `json:"type"` } // UserCreateRequest captures the minimal payload to create a user. type UserCreateRequest struct { Name string `json:"name" validate:"required,min=1,max=255"` Email string `json:"email" validate:"required,email"` Password string `json:"password" validate:"required,min=8,max=128"` Permission string `json:"permission"` Status UserStatus `json:"status"` Type UserType `json:"type"` Avatar *string `json:"avatar,omitempty"` Details *UserDetails `json:"details,omitempty"` Preferences *UserPreferences `json:"preferences,omitempty"` }