package repository import ( "context" "errors" "time" libmongo "gateway/internal/library/mongo" permission "gateway/internal/model/permission/domain" "gateway/internal/model/permission/domain/entity" "gateway/internal/model/permission/domain/enum" domrepo "gateway/internal/model/permission/domain/repository" "go.mongodb.org/mongo-driver/v2/bson" mongodriver "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" ) // PermissionRepositoryParam configures the Mongo permission repository. type PermissionRepositoryParam struct { Conf *libmongo.Conf } type permissionRepository struct { db libmongo.DocumentDBUseCase } // NewPermissionRepository creates a Mongo-backed PermissionRepository. func NewPermissionRepository(param PermissionRepositoryParam) domrepo.PermissionRepository { documentDB, err := libmongo.NewDocumentDB(param.Conf, entity.Permission{}.CollectionName()) if err != nil { panic(err) } return &permissionRepository{db: documentDB} } func (r *permissionRepository) Insert(ctx context.Context, perm *entity.Permission) error { now := time.Now().UTC().UnixMilli() if perm.ID.IsZero() { perm.ID = bson.NewObjectID() } if perm.CreateAt == 0 { perm.CreateAt = now } if perm.UpdateAt == 0 { perm.UpdateAt = now } _, err := r.db.GetClient().InsertOne(ctx, perm) if err != nil { if mongodriver.IsDuplicateKeyError(err) { return permission.ErrPermissionDup } return err } return nil } func (r *permissionRepository) UpsertByName(ctx context.Context, perm *entity.Permission) error { now := time.Now().UTC().UnixMilli() if perm.UpdateAt == 0 { perm.UpdateAt = now } filter := bson.M{permission.BSONFieldName: perm.Name} set := bson.M{ permission.BSONFieldParent: perm.Parent, permission.BSONFieldName: perm.Name, permission.BSONFieldHTTPMethods: perm.HTTPMethods, permission.BSONFieldHTTPPath: perm.HTTPPath, permission.BSONFieldStatus: perm.Status, permission.BSONFieldType: perm.Type, permission.BSONFieldUpdateAt: perm.UpdateAt, } insert := bson.M{ permission.BSONFieldCreateAt: now, } update := bson.M{ bsonOpSet: set, bsonOpSetOnInsert: insert, } _, err := r.db.GetClient().UpdateOne(ctx, filter, update, options.UpdateOne().SetUpsert(true)) return err } func (r *permissionRepository) UpdateStatus(ctx context.Context, id string, status enum.Status) error { objID, err := bson.ObjectIDFromHex(id) if err != nil { return permission.ErrPermissionNotFound } now := time.Now().UTC().UnixMilli() filter := bson.M{permission.BSONFieldID: objID} set := bson.M{ permission.BSONFieldStatus: status, permission.BSONFieldUpdateAt: now, } res, err := r.db.GetClient().UpdateOne(ctx, filter, bson.M{bsonOpSet: set}) if err != nil { return err } if res.MatchedCount == 0 { return permission.ErrPermissionNotFound } return nil } func (r *permissionRepository) GetByID(ctx context.Context, id string) (*entity.Permission, error) { objID, err := bson.ObjectIDFromHex(id) if err != nil { return nil, permission.ErrPermissionNotFound } var doc entity.Permission if err := r.db.GetClient().FindOne(ctx, &doc, bson.M{permission.BSONFieldID: objID}); err != nil { if errors.Is(err, mongodriver.ErrNoDocuments) { return nil, permission.ErrPermissionNotFound } return nil, err } return &doc, nil } func (r *permissionRepository) GetByName(ctx context.Context, name string) (*entity.Permission, error) { var doc entity.Permission if err := r.db.GetClient().FindOne(ctx, &doc, bson.M{permission.BSONFieldName: name}); err != nil { if errors.Is(err, mongodriver.ErrNoDocuments) { return nil, permission.ErrPermissionNotFound } return nil, err } return &doc, nil } func (r *permissionRepository) GetAll(ctx context.Context, status *enum.Status) ([]*entity.Permission, error) { q := bson.M{} if status != nil { q[permission.BSONFieldStatus] = *status } opts := options.Find().SetSort(bson.D{{Key: permission.BSONFieldName, Value: 1}}) var docs []*entity.Permission if err := r.db.GetClient().Find(ctx, &docs, q, opts); err != nil { return nil, err } return docs, nil } func (r *permissionRepository) GetByIDs(ctx context.Context, ids []string) ([]*entity.Permission, error) { if len(ids) == 0 { return nil, nil } objIDs := make([]bson.ObjectID, 0, len(ids)) for _, id := range ids { objID, err := bson.ObjectIDFromHex(id) if err != nil { continue } objIDs = append(objIDs, objID) } if len(objIDs) == 0 { return nil, nil } q := bson.M{permission.BSONFieldID: bson.M{bsonOpIn: objIDs}} var docs []*entity.Permission if err := r.db.GetClient().Find(ctx, &docs, q); err != nil { return nil, err } return docs, nil } func (r *permissionRepository) GetByNames(ctx context.Context, names []string) ([]*entity.Permission, error) { if len(names) == 0 { return nil, nil } q := bson.M{permission.BSONFieldName: bson.M{bsonOpIn: names}} var docs []*entity.Permission if err := r.db.GetClient().Find(ctx, &docs, q); err != nil { return nil, err } return docs, nil } // Index20260521001UP ensures permissions collection indexes exist. func (r *permissionRepository) Index20260521001UP(ctx context.Context) error { if err := r.db.PopulateIndex(ctx, permission.BSONFieldName, 1, true); err != nil { return err } if err := r.db.PopulateIndex(ctx, permission.BSONFieldParent, 1, false); err != nil { return err } if err := r.db.PopulateIndex(ctx, permission.BSONFieldStatus, 1, false); err != nil { return err } return r.db.PopulateIndex(ctx, permission.BSONFieldType, 1, false) } var _ domrepo.PermissionRepository = (*permissionRepository)(nil)