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)