206 lines
5.1 KiB
Go
206 lines
5.1 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"permission/reborn/domain/entity"
|
|
"permission/reborn/domain/errors"
|
|
"permission/reborn/domain/repository"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type roleRepository struct {
|
|
db *gorm.DB
|
|
}
|
|
|
|
// NewRoleRepository 建立角色 Repository
|
|
func NewRoleRepository(db *gorm.DB) repository.RoleRepository {
|
|
return &roleRepository{db: db}
|
|
}
|
|
|
|
func (r *roleRepository) Create(ctx context.Context, role *entity.Role) error {
|
|
if err := role.Validate(); err != nil {
|
|
return errors.Wrap(errors.ErrCodeInvalidInput, "invalid role data", err)
|
|
}
|
|
|
|
if err := r.db.WithContext(ctx).Create(role).Error; err != nil {
|
|
return errors.Wrap(errors.ErrCodeDBQuery, "failed to create role", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *roleRepository) Update(ctx context.Context, role *entity.Role) error {
|
|
if err := role.Validate(); err != nil {
|
|
return errors.Wrap(errors.ErrCodeInvalidInput, "invalid role data", err)
|
|
}
|
|
|
|
result := r.db.WithContext(ctx).
|
|
Model(&entity.Role{}).
|
|
Where("uid = ? AND status != ?", role.UID, entity.StatusDeleted).
|
|
Updates(map[string]interface{}{
|
|
"name": role.Name,
|
|
"status": role.Status,
|
|
})
|
|
|
|
if result.Error != nil {
|
|
return errors.Wrap(errors.ErrCodeDBQuery, "failed to update role", result.Error)
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return errors.ErrRoleNotFound
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *roleRepository) Delete(ctx context.Context, uid string) error {
|
|
result := r.db.WithContext(ctx).
|
|
Model(&entity.Role{}).
|
|
Where("uid = ?", uid).
|
|
Update("status", entity.StatusDeleted)
|
|
|
|
if result.Error != nil {
|
|
return errors.Wrap(errors.ErrCodeDBQuery, "failed to delete role", result.Error)
|
|
}
|
|
|
|
if result.RowsAffected == 0 {
|
|
return errors.ErrRoleNotFound
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *roleRepository) Get(ctx context.Context, id int64) (*entity.Role, error) {
|
|
var role entity.Role
|
|
err := r.db.WithContext(ctx).
|
|
Where("id = ? AND status != ?", id, entity.StatusDeleted).
|
|
First(&role).Error
|
|
|
|
if err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return nil, errors.ErrRoleNotFound
|
|
}
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to get role", err)
|
|
}
|
|
|
|
return &role, nil
|
|
}
|
|
|
|
func (r *roleRepository) GetByUID(ctx context.Context, uid string) (*entity.Role, error) {
|
|
var role entity.Role
|
|
err := r.db.WithContext(ctx).
|
|
Where("uid = ? AND status != ?", uid, entity.StatusDeleted).
|
|
First(&role).Error
|
|
|
|
if err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return nil, errors.ErrRoleNotFound
|
|
}
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to get role by uid", err)
|
|
}
|
|
|
|
return &role, nil
|
|
}
|
|
|
|
func (r *roleRepository) GetByUIDs(ctx context.Context, uids []string) ([]*entity.Role, error) {
|
|
if len(uids) == 0 {
|
|
return []*entity.Role{}, nil
|
|
}
|
|
|
|
var roles []*entity.Role
|
|
err := r.db.WithContext(ctx).
|
|
Where("uid IN ? AND status != ?", uids, entity.StatusDeleted).
|
|
Find(&roles).Error
|
|
|
|
if err != nil {
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to get roles by uids", err)
|
|
}
|
|
|
|
return roles, nil
|
|
}
|
|
|
|
func (r *roleRepository) List(ctx context.Context, filter repository.RoleFilter) ([]*entity.Role, error) {
|
|
query := r.buildQuery(ctx, filter)
|
|
|
|
var roles []*entity.Role
|
|
if err := query.Find(&roles).Error; err != nil {
|
|
return nil, errors.Wrap(errors.ErrCodeDBQuery, "failed to list roles", err)
|
|
}
|
|
|
|
return roles, nil
|
|
}
|
|
|
|
func (r *roleRepository) Page(ctx context.Context, filter repository.RoleFilter, page, size int) ([]*entity.Role, int64, error) {
|
|
query := r.buildQuery(ctx, filter)
|
|
|
|
// 計算總數
|
|
var total int64
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, 0, errors.Wrap(errors.ErrCodeDBQuery, "failed to count roles", err)
|
|
}
|
|
|
|
// 分頁查詢
|
|
var roles []*entity.Role
|
|
offset := (page - 1) * size
|
|
if err := query.Offset(offset).Limit(size).Find(&roles).Error; err != nil {
|
|
return nil, 0, errors.Wrap(errors.ErrCodeDBQuery, "failed to page roles", err)
|
|
}
|
|
|
|
return roles, total, nil
|
|
}
|
|
|
|
func (r *roleRepository) Exists(ctx context.Context, uid string) (bool, error) {
|
|
var count int64
|
|
err := r.db.WithContext(ctx).
|
|
Model(&entity.Role{}).
|
|
Where("uid = ? AND status != ?", uid, entity.StatusDeleted).
|
|
Count(&count).Error
|
|
|
|
if err != nil {
|
|
return false, errors.Wrap(errors.ErrCodeDBQuery, "failed to check role exists", err)
|
|
}
|
|
|
|
return count > 0, nil
|
|
}
|
|
|
|
func (r *roleRepository) NextID(ctx context.Context) (int64, error) {
|
|
var role entity.Role
|
|
err := r.db.WithContext(ctx).
|
|
Order("id DESC").
|
|
Limit(1).
|
|
First(&role).Error
|
|
|
|
if err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return 1, nil
|
|
}
|
|
return 0, errors.Wrap(errors.ErrCodeDBQuery, "failed to get next id", err)
|
|
}
|
|
|
|
return role.ID + 1, nil
|
|
}
|
|
|
|
func (r *roleRepository) buildQuery(ctx context.Context, filter repository.RoleFilter) *gorm.DB {
|
|
query := r.db.WithContext(ctx).
|
|
Model(&entity.Role{}).
|
|
Where("status != ?", entity.StatusDeleted)
|
|
|
|
if filter.ClientID > 0 {
|
|
query = query.Where("client_id = ?", filter.ClientID)
|
|
}
|
|
|
|
if filter.UID != "" {
|
|
query = query.Where("uid = ?", filter.UID)
|
|
}
|
|
|
|
if filter.Name != "" {
|
|
query = query.Where("name LIKE ?", "%"+filter.Name+"%")
|
|
}
|
|
|
|
if filter.Status != nil {
|
|
query = query.Where("status = ?", *filter.Status)
|
|
}
|
|
|
|
return query
|
|
}
|