106 lines
3.0 KiB
Go
106 lines
3.0 KiB
Go
|
|
package repository
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
libmongo "gateway/internal/library/mongo"
|
||
|
|
member "gateway/internal/model/member/domain"
|
||
|
|
"gateway/internal/model/member/domain/entity"
|
||
|
|
domrepo "gateway/internal/model/member/domain/repository"
|
||
|
|
|
||
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||
|
|
mongodriver "go.mongodb.org/mongo-driver/v2/mongo"
|
||
|
|
)
|
||
|
|
|
||
|
|
// IdentityRepositoryParam configures the Mongo identity repository.
|
||
|
|
type IdentityRepositoryParam struct {
|
||
|
|
Conf *libmongo.Conf
|
||
|
|
}
|
||
|
|
|
||
|
|
type identityRepository struct {
|
||
|
|
db libmongo.DocumentDBUseCase
|
||
|
|
}
|
||
|
|
|
||
|
|
// NewIdentityRepository creates a Mongo-backed IdentityRepository.
|
||
|
|
func NewIdentityRepository(param IdentityRepositoryParam) domrepo.IdentityRepository {
|
||
|
|
documentDB, err := libmongo.NewDocumentDB(param.Conf, entity.Identity{}.CollectionName())
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
return &identityRepository{db: documentDB}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *identityRepository) Insert(ctx context.Context, identity *entity.Identity) error {
|
||
|
|
now := time.Now().UTC().UnixMilli()
|
||
|
|
if identity.ID.IsZero() {
|
||
|
|
identity.ID = bson.NewObjectID()
|
||
|
|
}
|
||
|
|
if identity.CreateAt == 0 {
|
||
|
|
identity.CreateAt = now
|
||
|
|
}
|
||
|
|
if identity.UpdateAt == 0 {
|
||
|
|
identity.UpdateAt = now
|
||
|
|
}
|
||
|
|
_, err := r.db.GetClient().InsertOne(ctx, identity)
|
||
|
|
if err != nil {
|
||
|
|
if mongodriver.IsDuplicateKeyError(err) {
|
||
|
|
return member.ErrDuplicateMember
|
||
|
|
}
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *identityRepository) GetByZitadelUserID(ctx context.Context, tenantID, zitadelUserID string) (*entity.Identity, error) {
|
||
|
|
return r.findOne(ctx, bson.M{
|
||
|
|
member.BSONFieldTenantID: tenantID,
|
||
|
|
member.BSONFieldZitadelUserID: zitadelUserID,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *identityRepository) GetByExternalID(ctx context.Context, tenantID, externalID string) (*entity.Identity, error) {
|
||
|
|
return r.findOne(ctx, bson.M{
|
||
|
|
member.BSONFieldTenantID: tenantID,
|
||
|
|
member.BSONFieldExternalID: externalID,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *identityRepository) GetByUID(ctx context.Context, tenantID, uid string) (*entity.Identity, error) {
|
||
|
|
return r.findOne(ctx, bson.M{
|
||
|
|
member.BSONFieldTenantID: tenantID,
|
||
|
|
member.BSONFieldUID: uid,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (r *identityRepository) findOne(ctx context.Context, filter bson.M) (*entity.Identity, error) {
|
||
|
|
var doc entity.Identity
|
||
|
|
if err := r.db.GetClient().FindOne(ctx, &doc, filter); err != nil {
|
||
|
|
if errors.Is(err, mongodriver.ErrNoDocuments) {
|
||
|
|
return nil, member.ErrNotFound
|
||
|
|
}
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return &doc, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// Index20260520001UP ensures identities collection indexes exist.
|
||
|
|
func (r *identityRepository) Index20260520001UP(ctx context.Context) error {
|
||
|
|
if err := r.db.PopulateMultiIndex(ctx,
|
||
|
|
[]string{member.BSONFieldTenantID, member.BSONFieldZitadelUserID},
|
||
|
|
[]int32{1, 1}, true); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
if err := r.db.PopulateMultiIndex(ctx,
|
||
|
|
[]string{member.BSONFieldTenantID, member.BSONFieldUID},
|
||
|
|
[]int32{1, 1}, false); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
return r.db.PopulateMultiIndex(ctx,
|
||
|
|
[]string{member.BSONFieldTenantID, member.BSONFieldExternalID},
|
||
|
|
[]int32{1, 1}, false)
|
||
|
|
}
|
||
|
|
|
||
|
|
var _ domrepo.IdentityRepository = (*identityRepository)(nil)
|