2025-12-20 00:01:08 +07:00

147 lines
4.1 KiB
Go

// internal/models/user.go - FIXED VERSION
package models
import (
"lost-and-found/internal/utils"
"time"
"gorm.io/gorm"
)
// User represents a user in the system
type User struct {
ID uint `gorm:"primaryKey" json:"id"`
Name string `gorm:"type:varchar(100);not null" json:"name"`
Email string `gorm:"type:varchar(100);uniqueIndex;not null" json:"email"`
Password string `gorm:"type:varchar(255);not null" json:"-"`
NRP string `gorm:"type:varchar(20)" json:"nrp"` // ✅ Plain text
Phone string `gorm:"type:varchar(20)" json:"phone"` // ✅ Plain text
RoleID uint `gorm:"not null;default:3" json:"role_id"`
Role Role `gorm:"foreignKey:RoleID" json:"role,omitempty"`
Status string `gorm:"type:varchar(20);default:'active'" json:"status"`
LastLogin *time.Time `json:"last_login"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}
// TableName specifies the table name
func (User) TableName() string {
return "users"
}
// User status constants
const (
UserStatusActive = "active"
UserStatusBlocked = "blocked"
)
// IsActive checks if user is active
func (u *User) IsActive() bool {
return u.Status == UserStatusActive
}
// IsBlocked checks if user is blocked
func (u *User) IsBlocked() bool {
return u.Status == UserStatusBlocked
}
// IsAdmin checks if user is admin
func (u *User) IsAdmin() bool {
return u.Role.Name == "admin"
}
// IsManager checks if user is manager
func (u *User) IsManager() bool {
return u.Role.Name == "manager"
}
func (u *User) HasPermission(permissionSlug string) bool {
// Jika Role atau Permissions belum di-load, return false (fail safe)
if u.Role.ID == 0 {
return false
}
// Admin (Role ID 1) biasanya bypass semua check, tapi sebaiknya tetap cek list
// untuk konsistensi database.
for _, perm := range u.Role.Permissions {
if perm.Slug == permissionSlug {
return true
}
}
return false
}
// IsUser checks if user is regular user
func (u *User) IsUser() bool {
return u.Role.Name == "user"
}
// UserResponse represents user data for API responses
type UserResponse struct {
ID uint `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
NRP string `json:"nrp,omitempty"` // ✅ Langsung dari database
Phone string `json:"phone,omitempty"` // ✅ Langsung dari database
Role string `json:"role"`
Status string `json:"status"`
LastLogin *time.Time `json:"last_login,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
// ✅ ToResponse converts User to UserResponse dengan DEKRIPSI
func (u *User) ToResponse() UserResponse {
response := UserResponse{
ID: u.ID,
Name: u.Name,
Email: u.Email,
NRP: u.NRP, // ✅ Langsung assign
Phone: u.Phone, // ✅ Langsung assign
Status: u.Status,
LastLogin: u.LastLogin,
CreatedAt: u.CreatedAt,
}
// Set role name
if u.Role.ID != 0 {
response.Role = u.Role.Name
}
// ✅ DEKRIPSI NRP
if u.NRP != "" {
decryptedNRP, err := utils.DecryptString(u.NRP)
if err == nil {
response.NRP = decryptedNRP
} else {
// Jika dekripsi gagal, kembalikan nilai asli (untuk backward compatibility)
response.NRP = u.NRP
}
}
// ✅ DEKRIPSI Phone
if u.Phone != "" {
decryptedPhone, err := utils.DecryptString(u.Phone)
if err == nil {
response.Phone = decryptedPhone
} else {
// Jika dekripsi gagal, kembalikan nilai asli (untuk backward compatibility)
response.Phone = u.Phone
}
}
return response
}
// ✅ ToPublicResponse - untuk public access (hide sensitive data)
func (u *User) ToPublicResponse() UserResponse {
return UserResponse{
ID: u.ID,
Name: u.Name,
Role: u.Role.Name,
Status: u.Status,
CreatedAt: u.CreatedAt,
// NRP & Phone tidak disertakan untuk security
}
}