package repository import ( "backend/pkg/library/errs/code" "backend/pkg/permission/domain" "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 ClientRepositoryParam struct { Conf *mongo.Conf CacheConf cache.CacheConf DBOpts []mon.Option CacheOpts []cache.Option } type ClientRepository struct { DB mongo.DocumentDBWithCacheUseCase } // NewClientRepository 創建客戶端倉庫實例 func NewClientRepository(param ClientRepositoryParam) repository.ClientRepository { e := entity.Client{} documentDB, err := mongo.MustDocumentDBWithCache( param.Conf, e.CollectionName(), param.CacheConf, param.DBOpts, param.CacheOpts, ) if err != nil { panic(err) } return &ClientRepository{ DB: documentDB, } } func (repo *ClientRepository) Create(ctx context.Context, client *entity.Client) error { now := time.Now() client.CreateTime = now client.UpdateTime = now id := bson.NewObjectID() client.ID = id rk := domain.GeClientRedisKey(id.Hex()) _, err := repo.DB.InsertOne(ctx, rk, client) if err != nil { // 檢查是否為重複鍵錯誤 if mongodriver.IsDuplicateKeyError(err) { return errs.ResourceAlreadyExist(client.ClientID) } return errs.DBErrorWithScope(code.CloudEPPermission, err.Error()) } return nil } func (repo *ClientRepository) GetByID(ctx context.Context, id string) (*entity.Client, error) { var client entity.Client objID, err := bson.ObjectIDFromHex(id) if err != nil { return nil, err } rk := domain.GeClientRedisKey(objID.Hex()) err = repo.DB.FindOne(ctx, rk, &client, bson.M{"_id": objID}) if err != nil { if errors.Is(err, mongodriver.ErrNoDocuments) { return nil, errs.ResourceNotFoundWithScope( code.CloudEPPermission, domain.FailedToGetByID, "failed to get client by id") } return nil, errs.DBErrorWithScope(code.CloudEPPermission, err.Error()) } return &client, nil } func (repo *ClientRepository) GetByClientID(ctx context.Context, clientID string) (*entity.Client, error) { var client entity.Client rk := domain.GeClientRedisKey(clientID) err := repo.DB.FindOne(ctx, rk, &client, bson.M{"client_id": clientID}) if err != nil { if errors.Is(err, mongodriver.ErrNoDocuments) { return nil, errs.ResourceNotFoundWithScope( code.CloudEPPermission, domain.FailedToGetByClientID, "failed to get client by client id") } return nil, errs.DBErrorWithScope(code.CloudEPPermission, err.Error()) } return &client, nil } func (repo *ClientRepository) Update(ctx context.Context, id string, client *entity.Client) error { client.UpdateTime = time.Now() objID, err := bson.ObjectIDFromHex(id) if err != nil { return err } update := bson.M{ "$set": bson.M{ "name": client.Name, "secret": client.Secret, "status": client.Status, "update_time": client.UpdateTime, }, } gc, err := repo.GetByID(ctx, id) if err != nil { return err } rk := domain.GeClientRedisKey(objID.Hex()) _, err = repo.DB.UpdateOne(ctx, rk, bson.M{"_id": objID}, update) if err != nil { return errs.DBErrorWithScope(code.CloudEPPermission, err.Error()) } rk = domain.GeClientRedisKey(gc.ClientID) err = repo.DB.DelCache(ctx, rk) if err != nil { return err } return nil } func (repo *ClientRepository) Delete(ctx context.Context, id string) error { objID, err := bson.ObjectIDFromHex(id) if err != nil { return err } gc, err := repo.GetByID(ctx, id) if err != nil { return err } rk := domain.GeClientRedisKey(gc.ClientID) err = repo.DB.DelCache(ctx, rk) if err != nil { return err } rk = domain.GeClientRedisKey(objID.Hex()) _, err = repo.DB.DeleteOne(ctx, rk, bson.M{"_id": objID}) if err != nil { return errs.DBErrorWithScope(code.CloudEPPermission, err.Error()) } return nil } func (repo *ClientRepository) List(ctx context.Context, filter repository.ClientFilter) ([]*entity.Client, error) { query := bson.M{} if filter.Status != nil { query["status"] = *filter.Status } var clients []*entity.Client err := repo.DB.GetClient().Find(ctx, query, &clients, options.Find().SetLimit(int64(filter.Limit)), options.Find().SetSkip(int64(filter.Skip)), ) if err != nil { return nil, errs.DBErrorWithScope(code.CloudEPPermission, err.Error()) } return clients, nil } // Index20241226001UP 創建索引 func (repo *ClientRepository) Index20241226001UP(ctx context.Context) (*mongodriver.Cursor, error) { repo.DB.PopulateIndex(ctx, "client_id", 1, true) repo.DB.PopulateIndex(ctx, "status", 1, false) return repo.DB.GetClient().Indexes().List(ctx) }