183 lines
4.9 KiB
Go
183 lines
4.9 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"
|
||
|
|
"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"
|
||
|
|
)
|
||
|
|
|
||
|
|
// RoleMappingRepositoryParam configures the Mongo role mapping repository.
|
||
|
|
type RoleMappingRepositoryParam struct {
|
||
|
|
Conf *libmongo.Conf
|
||
|
|
}
|
||
|
|
|
||
|
|
type roleMappingRepository struct {
|
||
|
|
db libmongo.DocumentDBUseCase
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewRoleMappingRepository creates a Mongo-backed RoleMappingRepository.
|
||
|
|
func NewRoleMappingRepository(param RoleMappingRepositoryParam) domrepo.RoleMappingRepository {
|
||
|
|
documentDB, err := libmongo.NewDocumentDB(param.Conf, entity.RoleMapping{}.CollectionName())
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
return &roleMappingRepository{db: documentDB}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *roleMappingRepository) Insert(ctx context.Context, rm *entity.RoleMapping) error {
|
||
|
|
now := time.Now().UTC().UnixMilli()
|
||
|
|
if rm.ID.IsZero() {
|
||
|
|
rm.ID = bson.NewObjectID()
|
||
|
|
}
|
||
|
|
if rm.CreateAt == 0 {
|
||
|
|
rm.CreateAt = now
|
||
|
|
}
|
||
|
|
if rm.UpdateAt == 0 {
|
||
|
|
rm.UpdateAt = now
|
||
|
|
}
|
||
|
|
_, err := r.db.GetClient().InsertOne(ctx, rm)
|
||
|
|
if err != nil {
|
||
|
|
if mongodriver.IsDuplicateKeyError(err) {
|
||
|
|
return permission.ErrRoleMappingDuplicate
|
||
|
|
}
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *roleMappingRepository) Upsert(ctx context.Context, rm *entity.RoleMapping) error {
|
||
|
|
now := time.Now().UTC().UnixMilli()
|
||
|
|
if rm.UpdateAt == 0 {
|
||
|
|
rm.UpdateAt = now
|
||
|
|
}
|
||
|
|
filter := bson.M{
|
||
|
|
permission.BSONFieldTenantID: rm.TenantID,
|
||
|
|
permission.BSONFieldExternalSource: rm.ExternalSource,
|
||
|
|
permission.BSONFieldExternalKey: rm.ExternalKey,
|
||
|
|
}
|
||
|
|
set := bson.M{
|
||
|
|
permission.BSONFieldInternalRoleID: rm.InternalRoleID,
|
||
|
|
permission.BSONFieldInternalRoleKey: rm.InternalRoleKey,
|
||
|
|
permission.BSONFieldUpdateAt: rm.UpdateAt,
|
||
|
|
}
|
||
|
|
insert := bson.M{
|
||
|
|
permission.BSONFieldTenantID: rm.TenantID,
|
||
|
|
permission.BSONFieldExternalSource: rm.ExternalSource,
|
||
|
|
permission.BSONFieldExternalKey: rm.ExternalKey,
|
||
|
|
permission.BSONFieldCreateAt: now,
|
||
|
|
}
|
||
|
|
_, err := r.db.GetClient().UpdateOne(ctx, filter,
|
||
|
|
bson.M{bsonOpSet: set, bsonOpSetOnInsert: insert},
|
||
|
|
options.UpdateOne().SetUpsert(true))
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *roleMappingRepository) Delete(
|
||
|
|
ctx context.Context,
|
||
|
|
tenantID string,
|
||
|
|
source enum.RoleSource,
|
||
|
|
externalKey string,
|
||
|
|
) error {
|
||
|
|
filter := bson.M{
|
||
|
|
permission.BSONFieldTenantID: tenantID,
|
||
|
|
permission.BSONFieldExternalSource: source,
|
||
|
|
permission.BSONFieldExternalKey: externalKey,
|
||
|
|
}
|
||
|
|
res, err := r.db.GetClient().DeleteOne(ctx, filter)
|
||
|
|
if err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if res == 0 {
|
||
|
|
return permission.ErrRoleMappingNotFound
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *roleMappingRepository) DeleteByRole(ctx context.Context, tenantID, roleID string) (int64, error) {
|
||
|
|
filter := bson.M{
|
||
|
|
permission.BSONFieldTenantID: tenantID,
|
||
|
|
permission.BSONFieldInternalRoleID: roleID,
|
||
|
|
}
|
||
|
|
return r.db.GetClient().DeleteMany(ctx, filter)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *roleMappingRepository) GetByExternal(
|
||
|
|
ctx context.Context,
|
||
|
|
tenantID string,
|
||
|
|
source enum.RoleSource,
|
||
|
|
externalKey string,
|
||
|
|
) (*entity.RoleMapping, error) {
|
||
|
|
filter := bson.M{
|
||
|
|
permission.BSONFieldTenantID: tenantID,
|
||
|
|
permission.BSONFieldExternalSource: source,
|
||
|
|
permission.BSONFieldExternalKey: externalKey,
|
||
|
|
}
|
||
|
|
var doc entity.RoleMapping
|
||
|
|
if err := r.db.GetClient().FindOne(ctx, &doc, filter); err != nil {
|
||
|
|
if errors.Is(err, mongodriver.ErrNoDocuments) {
|
||
|
|
return nil, permission.ErrRoleMappingNotFound
|
||
|
|
}
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return &doc, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *roleMappingRepository) ListByTenant(
|
||
|
|
ctx context.Context,
|
||
|
|
tenantID string,
|
||
|
|
source *enum.RoleSource,
|
||
|
|
offset, limit int64,
|
||
|
|
) ([]*entity.RoleMapping, int64, error) {
|
||
|
|
q := bson.M{permission.BSONFieldTenantID: tenantID}
|
||
|
|
if source != nil {
|
||
|
|
q[permission.BSONFieldExternalSource] = *source
|
||
|
|
}
|
||
|
|
total, err := r.db.GetClient().CountDocuments(ctx, q)
|
||
|
|
if err != nil {
|
||
|
|
return nil, 0, err
|
||
|
|
}
|
||
|
|
if limit <= 0 {
|
||
|
|
limit = 50
|
||
|
|
}
|
||
|
|
if limit > 200 {
|
||
|
|
limit = 200
|
||
|
|
}
|
||
|
|
opts := options.Find().
|
||
|
|
SetSkip(offset).
|
||
|
|
SetLimit(limit).
|
||
|
|
SetSort(bson.D{{Key: permission.BSONFieldCreateAt, Value: -1}})
|
||
|
|
var docs []*entity.RoleMapping
|
||
|
|
if err := r.db.GetClient().Find(ctx, &docs, q, opts); err != nil {
|
||
|
|
return nil, 0, err
|
||
|
|
}
|
||
|
|
return docs, total, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Index20260521001UP ensures role_mappings collection indexes exist.
|
||
|
|
func (r *roleMappingRepository) Index20260521001UP(ctx context.Context) error {
|
||
|
|
if err := r.db.PopulateMultiIndex(ctx,
|
||
|
|
[]string{
|
||
|
|
permission.BSONFieldTenantID,
|
||
|
|
permission.BSONFieldExternalSource,
|
||
|
|
permission.BSONFieldExternalKey,
|
||
|
|
},
|
||
|
|
[]int32{1, 1, 1}, true); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return r.db.PopulateMultiIndex(ctx,
|
||
|
|
[]string{permission.BSONFieldTenantID, permission.BSONFieldInternalRoleID},
|
||
|
|
[]int32{1, 1}, false)
|
||
|
|
}
|
||
|
|
|
||
|
|
var _ domrepo.RoleMappingRepository = (*roleMappingRepository)(nil)
|