package models import ( "time" "gorm.io/gorm" ) // UserRoles is stored as JSON array of strings. // Typescript: type type UserRoles []string // Typescript: type type UsersShort []UserShort type User struct { ID int `json:"id" gorm:"primaryKey"` Email string `json:"email" gorm:"uniqueIndex;size:255"` Name string `json:"name" gorm:"size:255"` Password string `json:"password" gorm:"size:255"` Roles UserRoles `json:"roles" gorm:"type:text;serializer:json"` Types UserTypes `json:"types" gorm:"type:text;serializer:json"` Status UserStatus `json:"status" gorm:"type:text;default:'pending'"` ActivatedAt *time.Time `json:"activatedAt" ts:"type=Date"` UUID string `json:"uuid" gorm:"size:36"` 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"` CreatedAt time.Time `json:"createdAt" ts:"type=Date"` UpdatedAt time.Time `json:"updatedAt" ts:"type=Date"` DeletedAt gorm.DeletedAt `json:"-" gorm:"index" ts:"type=Date"` } // UserCreateInput captures the minimal payload to create a user. // Typescript: interface type UserCreateInput 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"` Roles UserRoles `json:"roles"` Status UserStatus `json:"status"` Types UserTypes `json:"types"` Avatar *string `json:"avatar"` Details *UserDetailsShort `json:"details" ` Preferences *UserPreferencesShort `json:"preferences" ` } // UserTypes is stored as JSON array (e.g. ["internal","external"]). type UserTypes []string // UserShort is a lightweight representation of User without sensitive data. // Typescript: interface type UserShort struct { Email string `json:"email" ` Name string `json:"name" ` Roles UserRoles `json:"roles" ` Status UserStatus `json:"status" ` UUID string `json:"uuid" ` Details *UserDetailsShort `json:"details" ` Preferences *UserPreferencesShort `json:"preferences" ` Avatar *string `json:"avatar" ` } // ToUserShort maps a User to the lightweight view. func ToUserShort(u *User) UserShort { if u == nil { return UserShort{} } return UserShort{ Email: u.Email, Name: u.Name, Roles: u.Roles, Status: u.Status, UUID: u.UUID, Details: ToUserDetailsShort(u.Details), Preferences: ToUserPreferencesShort(u.Preferences), Avatar: u.Avatar, } } // ToUserDetailsShort maps UserDetails to the short version. func ToUserDetailsShort(d *UserDetails) *UserDetailsShort { if d == nil { return nil } return &UserDetailsShort{ Title: d.Title, FirstName: d.FirstName, LastName: d.LastName, Address: d.Address, City: d.City, ZipCode: d.ZipCode, Country: d.Country, Phone: d.Phone, } } // ToUserPreferencesShort maps UserPreferences to the short version. func ToUserPreferencesShort(p *UserPreferences) *UserPreferencesShort { if p == nil { return nil } return &UserPreferencesShort{ UseIdle: p.UseIdle, IdleTimeout: p.IdleTimeout, UseIdlePassword: p.UseIdlePassword, IdlePin: p.IdlePin, UseDirectLogin: p.UseDirectLogin, UseQuadcodeLogin: p.UseQuadcodeLogin, SendNoticesMail: p.SendNoticesMail, Language: p.Language, } } // UserPreferences holds per-user settings stored as JSON. type UserPreferences struct { ID int `json:"id" gorm:"primaryKey"` UserID int `json:"userId" gorm:"index"` 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" ts:"type=Date"` UpdatedAt time.Time `json:"updatedAt" ts:"type=Date"` } // UserPreferences holds per-user settings stored as JSON. // Typescript: interface type UserPreferencesShort struct { 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 int `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"` CreatedAt time.Time `json:"createdAt" ts:"type=Date"` UpdatedAt time.Time `json:"updatedAt" ts:"type=Date"` } // UserDetails holds optional profile data. // Typescript: interface type UserDetailsShort struct { 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"` } // Session tracks logins with browser metadata. type Session struct { ID int `json:"id" gorm:"primaryKey"` UserID *int `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=Date" gorm:"index"` IPAddress string `json:"ipAddress" gorm:"size:64"` UserAgent string `json:"userAgent" gorm:"size:512"` CreatedAt time.Time `json:"createdAt" ts:"type=Date"` UpdatedAt time.Time `json:"updatedAt" ts:"type=Date"` DeletedAt gorm.DeletedAt `json:"-" gorm:"index" ` } type PasswordResetToken struct { ID int `json:"id" gorm:"primaryKey"` UserID int `json:"userId" gorm:"index"` TokenHash string `json:"-" gorm:"size:64;uniqueIndex"` ExpiresAt time.Time `json:"expiresAt" ts:"type=Date" gorm:"index"` UsedAt *time.Time `json:"usedAt" ts:"type=Date"` CreatedAt time.Time `json:"createdAt" ts:"type=Date"` UpdatedAt time.Time `json:"updatedAt" 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" )