173 lines
4.6 KiB
Go
173 lines
4.6 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"permission/reborn/domain/entity"
|
|
"permission/reborn/domain/errors"
|
|
"permission/reborn/domain/repository"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type userRoleRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewUserRoleRepository 建立使用者角色 Repository
|
|
func NewUserRoleRepository(db *gorm.DB) repository.UserRoleRepository {
|
|
return &userRoleRepository{db: db}
|
|
}
|
|
|
|
func (r *userRoleRepository) Create(ctx context.Context, userRole *entity.UserRole) error {
|
|
if err := userRole.Validate(); err != nil {
|
|
return errors.Wrap(errors.ErrCodeInvalidInput, "invalid user role data", err)
|
|
}
|
|
|
|
if err := r.db.WithContext(ctx).Create(userRole).Error; err != nil {
|
|
return errors.Wrap(errors.ErrCodeDBQuery, "failed to create user role", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *userRoleRepository) Update(ctx context.Context, uid, roleID string) (*entity.UserRole, error) {
|
|
var userRole entity.UserRole
|
|
|
|
result := r.db.WithContext(ctx).
|
|
Model(&userRole).
|
|
Where("uid = ? AND status != ?", uid, entity.StatusDeleted).
|
|
Update("role_id", roleID)
|
|
|
|
if result.Error != nil {
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to update user role", result.Error)
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return nil, errors.ErrUserRoleNotFound
|
|
}
|
|
|
|
// 重新查詢更新後的資料
|
|
if err := r.db.WithContext(ctx).Where("uid = ?", uid).First(&userRole).Error; err != nil {
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to get updated user role", err)
|
|
}
|
|
|
|
return &userRole, nil
|
|
}
|
|
|
|
func (r *userRoleRepository) Delete(ctx context.Context, uid string) error {
|
|
result := r.db.WithContext(ctx).
|
|
Model(&entity.UserRole{}).
|
|
Where("uid = ?", uid).
|
|
Update("status", entity.StatusDeleted)
|
|
|
|
if result.Error != nil {
|
|
return errors.Wrap(errors.ErrCodeDBQuery, "failed to delete user role", result.Error)
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return errors.ErrUserRoleNotFound
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *userRoleRepository) Get(ctx context.Context, uid string) (*entity.UserRole, error) {
|
|
var userRole entity.UserRole
|
|
err := r.db.WithContext(ctx).
|
|
Where("uid = ? AND status != ?", uid, entity.StatusDeleted).
|
|
First(&userRole).Error
|
|
|
|
if err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return nil, errors.ErrUserRoleNotFound
|
|
}
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to get user role", err)
|
|
}
|
|
|
|
return &userRole, nil
|
|
}
|
|
|
|
func (r *userRoleRepository) GetByRoleID(ctx context.Context, roleID string) ([]*entity.UserRole, error) {
|
|
var userRoles []*entity.UserRole
|
|
err := r.db.WithContext(ctx).
|
|
Where("role_id = ? AND status != ?", roleID, entity.StatusDeleted).
|
|
Find(&userRoles).Error
|
|
|
|
if err != nil {
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to get user roles by role id", err)
|
|
}
|
|
|
|
return userRoles, nil
|
|
}
|
|
|
|
func (r *userRoleRepository) List(ctx context.Context, filter repository.UserRoleFilter) ([]*entity.UserRole, error) {
|
|
query := r.buildQuery(ctx, filter)
|
|
|
|
var userRoles []*entity.UserRole
|
|
if err := query.Find(&userRoles).Error; err != nil {
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to list user roles", err)
|
|
}
|
|
|
|
return userRoles, nil
|
|
}
|
|
|
|
// CountByRoleID 統計每個角色的使用者數量 (批量查詢,避免 N+1)
|
|
func (r *userRoleRepository) CountByRoleID(ctx context.Context, roleIDs []string) (map[string]int, error) {
|
|
if len(roleIDs) == 0 {
|
|
return make(map[string]int), nil
|
|
}
|
|
|
|
var counts []entity.RoleUserCount
|
|
err := r.db.WithContext(ctx).
|
|
Model(&entity.UserRole{}).
|
|
Select("role_id, COUNT(*) as count").
|
|
Where("role_id IN ? AND status != ?", roleIDs, entity.StatusDeleted).
|
|
Group("role_id").
|
|
Find(&counts).Error
|
|
|
|
if err != nil {
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to count users by role id", err)
|
|
}
|
|
|
|
result := make(map[string]int)
|
|
for _, c := range counts {
|
|
result[c.RoleID] = c.Count
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (r *userRoleRepository) Exists(ctx context.Context, uid string) (bool, error) {
|
|
var count int64
|
|
err := r.db.WithContext(ctx).
|
|
Model(&entity.UserRole{}).
|
|
Where("uid = ? AND status != ?", uid, entity.StatusDeleted).
|
|
Count(&count).Error
|
|
|
|
if err != nil {
|
|
return false, errors.Wrap(errors.ErrCodeDBQuery, "failed to check user role exists", err)
|
|
}
|
|
|
|
return count > 0, nil
|
|
}
|
|
|
|
func (r *userRoleRepository) buildQuery(ctx context.Context, filter repository.UserRoleFilter) *gorm.DB {
|
|
query := r.db.WithContext(ctx).
|
|
Model(&entity.UserRole{}).
|
|
Where("status != ?", entity.StatusDeleted)
|
|
|
|
if filter.Brand != "" {
|
|
query = query.Where("brand = ?", filter.Brand)
|
|
}
|
|
|
|
if filter.RoleID != "" {
|
|
query = query.Where("role_id = ?", filter.RoleID)
|
|
}
|
|
|
|
if filter.Status != nil {
|
|
query = query.Where("status = ?", *filter.Status)
|
|
}
|
|
|
|
return query
|
|
}
|