package model import ( "time" "git.ma-al.com/goc_daniel/b2b/app/delivery/middleware/perms" "gorm.io/gorm" ) // User represents a user in the system type Customer struct { ID uint `gorm:"primaryKey" json:"id"` Email string `gorm:"uniqueIndex;not null;size:255" json:"email"` Password string `gorm:"size:255" json:"-"` // Hashed password, not exposed in JSON FirstName string `gorm:"size:100" json:"first_name"` LastName string `gorm:"size:100" json:"last_name"` RoleID uint `gorm:"column:role_id;not null;default:1" json:"-"` Role *Role `gorm:"foreignKey:RoleID" json:"role,omitempty"` Provider AuthProvider `gorm:"type:varchar(20);default:'local'" json:"provider"` ProviderID string `gorm:"size:255" json:"provider_id,omitempty"` // ID from OAuth provider AvatarURL string `gorm:"size:500" json:"avatar_url,omitempty"` IsActive bool `gorm:"default:true" json:"is_active"` EmailVerified bool `gorm:"default:false" json:"email_verified"` EmailVerificationToken string `gorm:"size:255" json:"-"` EmailVerificationExpires *time.Time `json:"-"` PasswordResetToken string `gorm:"size:255" json:"-"` PasswordResetExpires *time.Time `json:"-"` WebdavToken string `gorm:"size:255" json:"-"` WebdavExpires *time.Time `json:"-"` LastPasswordResetRequest *time.Time `json:"-"` LastLoginAt *time.Time `json:"last_login_at,omitempty"` LangID uint `gorm:"default:2" json:"lang_id"` // User's preferred language CountryID uint `gorm:"default:2" json:"country_id"` // User's selected country Country *Country `gorm:"foreignKey:CountryID" json:"country,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` IsNoVat bool `gorm:"default:false" json:"is_no_vat"` } func (u *Customer) HasPermission(permission perms.Permission) bool { for _, p := range u.Role.Permissions { if p.Name == permission { return true } } return false } // AuthProvider represents the authentication provider type AuthProvider string const ( ProviderLocal AuthProvider = "local" ProviderGoogle AuthProvider = "google" ) // TableName specifies the table name for User model func (Customer) TableName() string { return "b2b_customers" } // FullName returns the user's full name func (u *Customer) FullName() string { if u.FirstName == "" && u.LastName == "" { return u.Email } return u.FirstName + " " + u.LastName } // UserSession represents a user session for JWT claims type UserSession struct { UserID uint `json:"user_id"` Email string `json:"email"` Username string `json:"username"` RoleID uint `json:"role_id"` RoleName string `json:"role_name"` LangID uint `json:"lang_id"` CountryID uint `json:"country_id"` IsActive bool `json:"is_active"` Permissions []perms.Permission `json:"permissions"` } func (us *UserSession) HasPermission(permission perms.Permission) bool { for _, p := range us.Permissions { if p == permission { return true } } return false } type UserLocale struct { // User is the Target user if present, otherwise same as Original. // User ought to be used in applications User *Customer // Original user is the one associated with auth token OriginalUser *Customer // Importantly, lang_id used in application is stored as OriginalUser.LangID } // ToSession converts User to UserSession func (u *Customer) ToSession() *UserSession { return &UserSession{ UserID: u.ID, Email: u.Email, RoleID: u.Role.ID, RoleName: u.Role.Name, Permissions: BuildPermissionSlice(u), LangID: u.LangID, CountryID: u.CountryID, IsActive: u.IsActive, } } func BuildPermissionSlice(user *Customer) []perms.Permission { var perms []perms.Permission for _, p := range user.Role.Permissions { perms = append(perms, p.Name) } return perms } // LoginRequest represents the login form data type LoginRequest struct { Email string `json:"email" form:"email"` Password string `json:"password" form:"password"` LangID *uint `json:"lang_id" form:"lang_id"` } // RegisterRequest represents the initial registration form data type RegisterRequest struct { ErrorMsg string `form:"error_msg" json:"error_msg"` Email string `json:"email" form:"email"` Password string `json:"password" form:"password"` ConfirmPassword string `json:"confirm_password" form:"confirm_password"` FirstName string `json:"first_name" form:"first_name"` LastName string `json:"last_name" form:"last_name"` LangID uint `form:"lang_id" json:"lang_id"` CountryID uint `form:"country_id" json:"country_id"` } // CompleteRegistrationRequest represents the completion of registration with email verification type CompleteRegistrationRequest struct { Token string `json:"token" form:"token"` } // ResetPasswordRequest represents the reset password form data type ResetPasswordRequest struct { Token string `json:"token" form:"token"` Password string `json:"password" form:"password"` } // AuthResponse represents the authentication response type AuthResponse struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` ExpiresIn int `json:"expires_in"` User *UserSession `json:"user"` } // RefreshToken represents an opaque refresh token stored in the database type RefreshToken struct { ID uint `gorm:"primaryKey" json:"-"` CustomerID uint `gorm:"not null;index" json:"-"` TokenHash string `gorm:"size:64;uniqueIndex;not null" json:"-"` // SHA-256 hex of the raw token ExpiresAt time.Time `gorm:"not null" json:"-"` CreatedAt time.Time `json:"-"` } // TableName specifies the table name for RefreshToken model func (RefreshToken) TableName() string { return "b2b_refresh_tokens" } type UserInList struct { UserID uint `gorm:"primaryKey;column:id" json:"user_id"` Email string `gorm:"column:email" json:"email"` FirstName string `gorm:"column:first_name" json:"first_name"` LastName string `gorm:"column:last_name" json:"last_name"` }