182 lines
6.4 KiB
Go
182 lines
6.4 KiB
Go
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:"-"`
|
|
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:"-"`
|
|
}
|
|
|
|
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"`
|
|
}
|