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 PermissionRepositoryParam struct { Conf *mongo.Conf CacheConf cache.CacheConf DBOpts []mon.Option CacheOpts []cache.Option } type PermissionRepository struct { DB mongo.DocumentDBWithCacheUseCase } // NewPermissionRepository 創建權限倉庫實例 func NewPermissionRepository(param PermissionRepositoryParam) repository.PermissionRepository { e := entity.Permission{} documentDB, err := mongo.MustDocumentDBWithCache( param.Conf, e.CollectionName(), param.CacheConf, param.DBOpts, param.CacheOpts, ) if err != nil { panic(err) } return &PermissionRepository{ DB: documentDB, } } func (repo *PermissionRepository) Create(ctx context.Context, permission *entity.Permission) error { now := time.Now() permission.CreateTime = now permission.UpdateTime = now id := bson.NewObjectID() permission.ID = id rk := domain.GetPermissionRedisKey(id.Hex()) _, err := repo.DB.InsertOne(ctx, rk, permission) if err != nil { // 檢查是否為重複鍵錯誤 if mongodriver.IsDuplicateKeyError(err) { return errs.ResourceAlreadyExist(permission.ID.Hex()) } return errs.DBErrorWithScope(code.CloudEPPermission, err.Error()) } return nil } func (repo *PermissionRepository) GetByID(ctx context.Context, id string) (*entity.Permission, error) { var p entity.Permission objID, err := bson.ObjectIDFromHex(id) if err != nil { return nil, err } rk := domain.GetPermissionRedisKey(objID.Hex()) err = repo.DB.FindOne(ctx, rk, &p, bson.M{"_id": objID}) if err != nil { if errors.Is(err, mongodriver.ErrNoDocuments) { return nil, errs.ResourceNotFoundWithScope( code.CloudEPPermission, domain.FailedToGetPermission, "failed to get permission by id") } return nil, errs.DBErrorWithScope(code.CloudEPPermission, err.Error()) } return &p, nil } func (repo *PermissionRepository) GetByKey(ctx context.Context, httpMethod, httpPath string) (*entity.Permission, error) { filter := bson.M{ "http_method": httpMethod, "http_path": httpPath, "status": permission.StatusActive, } var p entity.Permission err := repo.DB.GetClient().FindOne(ctx, &p, filter) if err != nil { if errors.Is(err, mongodriver.ErrNoDocuments) { return nil, errs.ResourceNotFoundWithScope( code.CloudEPPermission, domain.FailedToGetPermissionByKey, "failed to get permission by key") } return nil, errs.DBErrorWithScope(code.CloudEPPermission, err.Error()) } return &p, nil } func (repo *PermissionRepository) Update(ctx context.Context, id string, permission *entity.Permission) error { permission.UpdateTime = time.Now() update := bson.M{ "$set": bson.M{ "parent_id": permission.ParentID, "name": permission.Name, "http_method": permission.HTTPMethod, "http_path": permission.HTTPPath, "status": permission.Status, "type": permission.Type, "update_time": permission.UpdateTime, }, } rk := domain.GetPermissionRedisKey(id) objID, err := bson.ObjectIDFromHex(id) if err != nil { return err } _, 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 *PermissionRepository) Delete(ctx context.Context, id string) error { rk := domain.GetPermissionRedisKey(id) objID, err := bson.ObjectIDFromHex(id) 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 *PermissionRepository) List(ctx context.Context, filter repository.PermissionFilter) ([]*entity.Permission, error) { query := bson.M{} if filter.Status != nil { query["status"] = *filter.Status } if filter.Type != nil { query["type"] = *filter.Type } if filter.ParentID != nil { query["parent_id"] = *filter.ParentID } var permissions []*entity.Permission err := repo.DB.GetClient().Find(ctx, &permissions, 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 permissions, nil } func (repo *PermissionRepository) GetActivePermissions(ctx context.Context) ([]*entity.Permission, error) { status := permission.StatusActive filter := repository.PermissionFilter{ Status: &status, } return repo.List(ctx, filter) } // Index20241226001UP 創建索引 func (repo *PermissionRepository) Index20241226001UP(ctx context.Context) (*mongodriver.Cursor, error) { // 等價於 db.account.createIndex({ "login_id": 1, "platform": 1}, {unique: true}) repo.DB.PopulateMultiIndex(ctx, []string{ "http_method", "http_path", }, []int32{1, 1}, true) // 等價於 db.account.createIndex({"create_at": 1}) repo.DB.PopulateIndex(ctx, "name", 1, false) repo.DB.PopulateIndex(ctx, "status", 1, false) repo.DB.PopulateIndex(ctx, "type", 1, false) return repo.DB.GetClient().Indexes().List(ctx) }