193 lines
5.2 KiB
Go
193 lines
5.2 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"time"
|
|
|
|
libmongo "gateway/internal/library/mongo"
|
|
permission "gateway/internal/model/permission/domain"
|
|
"gateway/internal/model/permission/domain/entity"
|
|
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"
|
|
)
|
|
|
|
// RoleRepositoryParam configures the Mongo role repository.
|
|
type RoleRepositoryParam struct {
|
|
Conf *libmongo.Conf
|
|
}
|
|
|
|
type roleRepository struct {
|
|
db libmongo.DocumentDBUseCase
|
|
}
|
|
|
|
// NewRoleRepository creates a Mongo-backed RoleRepository.
|
|
func NewRoleRepository(param RoleRepositoryParam) domrepo.RoleRepository {
|
|
documentDB, err := libmongo.NewDocumentDB(param.Conf, entity.Role{}.CollectionName())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return &roleRepository{db: documentDB}
|
|
}
|
|
|
|
func (r *roleRepository) Insert(ctx context.Context, role *entity.Role) error {
|
|
now := time.Now().UTC().UnixMilli()
|
|
if role.ID.IsZero() {
|
|
role.ID = bson.NewObjectID()
|
|
}
|
|
if role.CreateAt == 0 {
|
|
role.CreateAt = now
|
|
}
|
|
if role.UpdateAt == 0 {
|
|
role.UpdateAt = now
|
|
}
|
|
_, err := r.db.GetClient().InsertOne(ctx, role)
|
|
if err != nil {
|
|
if mongodriver.IsDuplicateKeyError(err) {
|
|
return permission.ErrRoleDuplicate
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *roleRepository) GetByID(ctx context.Context, tenantID, id string) (*entity.Role, error) {
|
|
objID, err := bson.ObjectIDFromHex(id)
|
|
if err != nil {
|
|
return nil, permission.ErrRoleNotFound
|
|
}
|
|
var doc entity.Role
|
|
filter := bson.M{
|
|
permission.BSONFieldID: objID,
|
|
permission.BSONFieldTenantID: tenantID,
|
|
}
|
|
if err := r.db.GetClient().FindOne(ctx, &doc, filter); err != nil {
|
|
if errors.Is(err, mongodriver.ErrNoDocuments) {
|
|
return nil, permission.ErrRoleNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
return &doc, nil
|
|
}
|
|
|
|
func (r *roleRepository) GetByKey(ctx context.Context, tenantID, key string) (*entity.Role, error) {
|
|
var doc entity.Role
|
|
filter := bson.M{
|
|
permission.BSONFieldTenantID: tenantID,
|
|
permission.BSONFieldKey: key,
|
|
}
|
|
if err := r.db.GetClient().FindOne(ctx, &doc, filter); err != nil {
|
|
if errors.Is(err, mongodriver.ErrNoDocuments) {
|
|
return nil, permission.ErrRoleNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
return &doc, nil
|
|
}
|
|
|
|
func (r *roleRepository) ListByTenant(ctx context.Context, tenantID string) ([]*entity.Role, error) {
|
|
q := bson.M{permission.BSONFieldTenantID: tenantID}
|
|
opts := options.Find().SetSort(bson.D{
|
|
{Key: permission.BSONFieldIsSystem, Value: -1},
|
|
{Key: permission.BSONFieldKey, Value: 1},
|
|
})
|
|
var docs []*entity.Role
|
|
if err := r.db.GetClient().Find(ctx, &docs, q, opts); err != nil {
|
|
return nil, err
|
|
}
|
|
return docs, nil
|
|
}
|
|
|
|
func (r *roleRepository) ListByTenantAndIDs(ctx context.Context, tenantID string, ids []string) ([]*entity.Role, 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.BSONFieldTenantID: tenantID,
|
|
permission.BSONFieldID: bson.M{bsonOpIn: objIDs},
|
|
}
|
|
var docs []*entity.Role
|
|
if err := r.db.GetClient().Find(ctx, &docs, q); err != nil {
|
|
return nil, err
|
|
}
|
|
return docs, nil
|
|
}
|
|
|
|
func (r *roleRepository) Update(ctx context.Context, tenantID, id string, update *domrepo.RoleUpdate) (*entity.Role, error) {
|
|
if update == nil {
|
|
return r.GetByID(ctx, tenantID, id)
|
|
}
|
|
objID, err := bson.ObjectIDFromHex(id)
|
|
if err != nil {
|
|
return nil, permission.ErrRoleNotFound
|
|
}
|
|
now := time.Now().UTC().UnixMilli()
|
|
set := bson.M{permission.BSONFieldUpdateAt: now}
|
|
if update.DisplayName != nil {
|
|
set[permission.BSONFieldDisplayName] = *update.DisplayName
|
|
}
|
|
if update.Status != nil {
|
|
set[permission.BSONFieldStatus] = *update.Status
|
|
}
|
|
filter := bson.M{
|
|
permission.BSONFieldID: objID,
|
|
permission.BSONFieldTenantID: tenantID,
|
|
}
|
|
var doc entity.Role
|
|
opts := options.FindOneAndUpdate().SetReturnDocument(options.After)
|
|
if err := r.db.GetClient().FindOneAndUpdate(ctx, &doc, filter, bson.M{bsonOpSet: set}, opts); err != nil {
|
|
if errors.Is(err, mongodriver.ErrNoDocuments) {
|
|
return nil, permission.ErrRoleNotFound
|
|
}
|
|
return nil, err
|
|
}
|
|
return &doc, nil
|
|
}
|
|
|
|
func (r *roleRepository) Delete(ctx context.Context, tenantID, id string) error {
|
|
objID, err := bson.ObjectIDFromHex(id)
|
|
if err != nil {
|
|
return permission.ErrRoleNotFound
|
|
}
|
|
filter := bson.M{
|
|
permission.BSONFieldID: objID,
|
|
permission.BSONFieldTenantID: tenantID,
|
|
}
|
|
res, err := r.db.GetClient().DeleteOne(ctx, filter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if res == 0 {
|
|
return permission.ErrRoleNotFound
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Index20260521001UP ensures roles collection indexes exist.
|
|
func (r *roleRepository) Index20260521001UP(ctx context.Context) error {
|
|
if err := r.db.PopulateMultiIndex(ctx,
|
|
[]string{permission.BSONFieldTenantID, permission.BSONFieldKey},
|
|
[]int32{1, 1}, true); err != nil {
|
|
return err
|
|
}
|
|
return r.db.PopulateMultiIndex(ctx,
|
|
[]string{permission.BSONFieldTenantID, permission.BSONFieldIsSystem},
|
|
[]int32{1, 1}, false)
|
|
}
|
|
|
|
var _ domrepo.RoleRepository = (*roleRepository)(nil)
|