131 lines
3.3 KiB
Go
131 lines
3.3 KiB
Go
package processor
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"eslogad-be/internal/entities"
|
|
|
|
"github.com/google/uuid"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type UserRoleProcessor interface {
|
|
AssignRoleToUser(ctx context.Context, userID, roleID uuid.UUID) error
|
|
RemoveRoleFromUser(ctx context.Context, userID, roleID uuid.UUID) error
|
|
GetUserRoles(ctx context.Context, userID uuid.UUID) ([]entities.Role, error)
|
|
HasRole(ctx context.Context, userID uuid.UUID, roleCode string) (bool, error)
|
|
ReplaceUserRole(ctx context.Context, userID, roleID uuid.UUID) error
|
|
}
|
|
|
|
type UserRoleProcessorImpl struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
func NewUserRoleProcessor(db *gorm.DB) *UserRoleProcessorImpl {
|
|
return &UserRoleProcessorImpl{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
type UserRoleEntry struct {
|
|
ID uuid.UUID `gorm:"type:uuid;primary_key;default:gen_random_uuid()"`
|
|
UserID uuid.UUID `gorm:"type:uuid;not null"`
|
|
RoleID uuid.UUID `gorm:"type:uuid;not null"`
|
|
AssignedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
|
|
RemovedAt *time.Time
|
|
}
|
|
|
|
func (UserRoleEntry) TableName() string {
|
|
return "user_role"
|
|
}
|
|
|
|
func (p *UserRoleProcessorImpl) AssignRoleToUser(ctx context.Context, userID, roleID uuid.UUID) error {
|
|
var existingEntry UserRoleEntry
|
|
err := p.db.WithContext(ctx).
|
|
Where("user_id = ? AND role_id = ? AND removed_at IS NULL", userID, roleID).
|
|
First(&existingEntry).Error
|
|
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
|
|
if err != gorm.ErrRecordNotFound {
|
|
return err
|
|
}
|
|
|
|
newEntry := UserRoleEntry{
|
|
UserID: userID,
|
|
RoleID: roleID,
|
|
AssignedAt: time.Now(),
|
|
}
|
|
|
|
return p.db.WithContext(ctx).Create(&newEntry).Error
|
|
}
|
|
|
|
func (p *UserRoleProcessorImpl) RemoveRoleFromUser(ctx context.Context, userID, roleID uuid.UUID) error {
|
|
now := time.Now()
|
|
return p.db.WithContext(ctx).
|
|
Model(&UserRoleEntry{}).
|
|
Where("user_id = ? AND role_id = ? AND removed_at IS NULL", userID, roleID).
|
|
Update("removed_at", now).Error
|
|
}
|
|
|
|
func (p *UserRoleProcessorImpl) GetUserRoles(ctx context.Context, userID uuid.UUID) ([]entities.Role, error) {
|
|
var roles []entities.Role
|
|
err := p.db.WithContext(ctx).
|
|
Table("roles as r").
|
|
Select("r.*").
|
|
Joins("JOIN user_role ur ON ur.role_id = r.id AND ur.removed_at IS NULL").
|
|
Where("ur.user_id = ?", userID).
|
|
Find(&roles).Error
|
|
return roles, err
|
|
}
|
|
|
|
func (p *UserRoleProcessorImpl) HasRole(ctx context.Context, userID uuid.UUID, roleCode string) (bool, error) {
|
|
var count int64
|
|
err := p.db.WithContext(ctx).
|
|
Table("user_role as ur").
|
|
Joins("JOIN roles r ON r.id = ur.role_id").
|
|
Where("ur.user_id = ? AND r.code = ? AND ur.removed_at IS NULL", userID, roleCode).
|
|
Count(&count).Error
|
|
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return count > 0, nil
|
|
}
|
|
|
|
func (p *UserRoleProcessorImpl) ReplaceUserRole(ctx context.Context, userID uuid.UUID, roleID uuid.UUID) error {
|
|
return p.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
|
// Delete old role
|
|
if err := tx.Where("user_id = ?", userID).
|
|
Delete(&UserRoleEntry{}).Error; err != nil {
|
|
return err
|
|
}
|
|
|
|
// Check if new role already exists
|
|
var existingEntry UserRoleEntry
|
|
err := tx.Where("user_id = ?", userID).
|
|
First(&existingEntry).Error
|
|
|
|
if err == nil {
|
|
// Role already assigned
|
|
return nil
|
|
}
|
|
|
|
if err != gorm.ErrRecordNotFound {
|
|
return err
|
|
}
|
|
|
|
// Assign new role
|
|
newEntry := UserRoleEntry{
|
|
UserID: userID,
|
|
RoleID: roleID,
|
|
AssignedAt: time.Now(),
|
|
}
|
|
|
|
return tx.Create(&newEntry).Error
|
|
})
|
|
} |