backend/pkg/permission/repository/role.go

234 lines
5.8 KiB
Go
Raw Normal View History

2025-10-03 08:38:12 +00:00
package repository
import (
"backend/pkg/library/errs/code"
"backend/pkg/permission/domain"
"backend/pkg/permission/domain/permission"
"context"
"errors"
"go.mongodb.org/mongo-driver/v2/mongo/options"
"time"
"backend/pkg/library/errs"
"backend/pkg/library/mongo"
"backend/pkg/permission/domain/entity"
"backend/pkg/permission/domain/repository"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/mon"
"go.mongodb.org/mongo-driver/v2/bson"
mongodriver "go.mongodb.org/mongo-driver/v2/mongo"
)
type RoleRepositoryParam struct {
Conf *mongo.Conf
CacheConf cache.CacheConf
DBOpts []mon.Option
CacheOpts []cache.Option
}
type RoleRepository struct {
DB mongo.DocumentDBWithCacheUseCase
}
// NewRoleRepository 創建角色倉庫實例
func NewRoleRepository(param RoleRepositoryParam) repository.RoleRepository {
e := entity.Role{}
documentDB, err := mongo.MustDocumentDBWithCache(
param.Conf,
e.CollectionName(),
param.CacheConf,
param.DBOpts,
param.CacheOpts,
)
if err != nil {
panic(err)
}
return &RoleRepository{
DB: documentDB,
}
}
func (repo *RoleRepository) Create(ctx context.Context, role *entity.Role) error {
now := time.Now()
role.CreateTime = now
role.UpdateTime = now
id := bson.NewObjectID()
role.ID = id
rk := domain.GetRoleRedisKeyRedisKey(id.Hex())
_, err := repo.DB.InsertOne(ctx, rk, role)
if err != nil {
// 檢查是否為重複鍵錯誤
if mongodriver.IsDuplicateKeyError(err) {
return errs.ResourceAlreadyExist(role.ClientID)
}
return errs.DBErrorWithScope(code.CloudEPPermission, err.Error())
}
return nil
}
func (repo *RoleRepository) GetByID(ctx context.Context, id string) (*entity.Role, error) {
var role entity.Role
objID, err := bson.ObjectIDFromHex(id)
if err != nil {
return nil, err
}
rk := domain.GetRoleRedisKeyRedisKey(id)
err = repo.DB.FindOne(ctx, rk, &role, bson.M{"client_id": objID})
if err != nil {
if errors.Is(err, mongodriver.ErrNoDocuments) {
return nil, errs.ResourceNotFoundWithScope(
code.CloudEPPermission,
domain.FailedToGetRoleByID,
"failed to get role by id")
}
return nil, errs.DBErrorWithScope(code.CloudEPPermission, err.Error())
}
return &role, nil
}
func (repo *RoleRepository) GetByUID(ctx context.Context, uid string) (*entity.Role, error) {
var role entity.Role
rk := domain.GetRoleRedisKeyRedisKey(uid)
err := repo.DB.FindOne(ctx, rk, &role, bson.M{"uid": uid, "status": permission.StatusActive})
if err != nil {
if errors.Is(err, mongodriver.ErrNoDocuments) {
return nil, errs.ResourceNotFoundWithScope(
code.CloudEPPermission,
domain.FailedToGetByUID,
"failed to get role by uid")
}
return nil, errs.DBErrorWithScope(code.CloudEPPermission, err.Error())
}
return &role, nil
}
func (repo *RoleRepository) GetByClientAndName(ctx context.Context, clientID, name string) (*entity.Role, error) {
filter := bson.M{
"client_id": clientID,
"name": name,
"status": permission.StatusActive,
}
var role entity.Role
err := repo.DB.GetClient().FindOne(ctx, &role, filter)
if err != nil {
if errors.Is(err, mongodriver.ErrNoDocuments) {
return nil, errs.ResourceNotFoundWithScope(
code.CloudEPPermission, domain.FailedToGetByClientAndName, "failed to get by client and name")
}
return nil, errs.DBErrorWithScope(code.CloudEPPermission, err.Error())
}
return &role, nil
}
func (repo *RoleRepository) Update(ctx context.Context, id string, role *entity.Role) error {
role.UpdateTime = time.Now()
objID, err := bson.ObjectIDFromHex(id)
if err != nil {
return err
}
update := bson.M{
"$set": bson.M{
"name": role.Name,
"status": role.Status,
"permissions": role.Permissions,
"update_time": role.UpdateTime,
},
}
rk := domain.GetRoleRedisKeyRedisKey(id)
_, err = repo.DB.UpdateOne(ctx, rk, bson.M{"_id": objID}, update)
if err != nil {
return errs.DBErrorWithScope(code.CloudEPPermission, err.Error())
}
return nil
}
func (repo *RoleRepository) Delete(ctx context.Context, id string) error {
rk := domain.GetRoleRedisKeyRedisKey(id)
objID, err := bson.ObjectIDFromHex(id)
if err != nil {
return err
}
gc, err := repo.GetByID(ctx, id)
if err != nil {
return err
}
rk = domain.GetRoleRedisKeyRedisKey(gc.UID)
err = repo.DB.DelCache(ctx, rk)
if err != nil {
return err
}
_, err = repo.DB.DeleteOne(ctx, rk, bson.M{"_id": objID})
if err != nil {
return errs.DBErrorWithScope(code.CloudEPPermission, err.Error())
}
return nil
}
func (repo *RoleRepository) List(ctx context.Context, filter repository.RoleFilter) ([]*entity.Role, error) {
query := bson.M{}
if filter.ClientID != "" {
query["client_id"] = filter.ClientID
}
if filter.Status != nil {
query["status"] = *filter.Status
}
var roles []*entity.Role
err := repo.DB.GetClient().Find(ctx, &roles, query,
options.Find().SetLimit(int64(filter.Limit)),
options.Find().SetSkip(int64(filter.Skip)),
)
if err != nil {
return nil, errs.DBErrorWithScope(code.CloudEPPermission, err.Error())
}
return roles, nil
}
func (repo *RoleRepository) GetRolesByClientID(ctx context.Context, clientID string) ([]*entity.Role, error) {
status := permission.StatusActive
filter := repository.RoleFilter{
ClientID: clientID,
Status: &status,
}
return repo.List(ctx, filter)
}
// Index20241226001UP 創建索引
func (repo *RoleRepository) Index20241226001UP(ctx context.Context) (*mongodriver.Cursor, error) {
// 等價於 db.account.createIndex({ "login_id": 1, "platform": 1}, {unique: true})
repo.DB.PopulateMultiIndex(ctx, []string{
"client_id",
"name",
}, []int32{1, 1}, true)
// 等價於 db.account.createIndex({"create_at": 1})
repo.DB.PopulateIndex(ctx, "uid", 1, true)
repo.DB.PopulateIndex(ctx, "status", 1, false)
return repo.DB.GetClient().Indexes().List(ctx)
}