package identity import ( "context" "time" db "git.sendico.io/tech/sxchnge/shared/database" deps "git.sendico.io/tech/sxchnge/shared/database/dependencies" "git.sendico.io/tech/sxchnge/shared/database/repository" "git.sendico.io/tech/sxchnge/shared/database/source" "go.mongodb.org/mongo-driver/v2/bson" ) type Store interface { Get(context.Context, bson.ObjectID) (*Binding, error) Create(context.Context, *Binding) error Claim(context.Context, bson.ObjectID, string) (bool, error) Bind(context.Context, bson.ObjectID, string, string) error Accept(context.Context, bson.ObjectID, string, Receipt) error } type mongoStore struct{ records repository.Repository } func OpenStore(factory db.Factory) (Store, error) { d, err := deps.ResolveDependencies(factory) if err != nil { return nil, err } return &mongoStore{records: repository.CreateRepository(source.Majority(d.Database), "signup_facts")}, nil } func (s *mongoStore) Get(ctx context.Context, id bson.ObjectID) (*Binding, error) { b := &Binding{} err := s.records.Get(ctx, id, b) return b, err } func (s *mongoStore) Create(ctx context.Context, b *Binding) error { return s.records.Insert(ctx, b, nil) } func scoped(id bson.ObjectID, namespace string) repository.FilterQuery { return repository.IDFilter(id).Filter(repository.Field("namespace"), namespace) } func (s *mongoStore) Claim(ctx context.Context, id bson.ObjectID, namespace string) (bool, error) { query := scoped(id, namespace).Filter(repository.Field("registering"), false).Filter(repository.Field("subjectRef"), "") return s.records.PatchOneByFilter(ctx, query, repository.Patch().Set(repository.Field("registering"), true).Set(repository.Field("registeringAt"), time.Now().UTC()), &Binding{}) } func (s *mongoStore) Bind(ctx context.Context, id bson.ObjectID, namespace, subject string) error { query := scoped(id, namespace).Filter(repository.Field("registering"), true).Filter(repository.Field("subjectRef"), "") matched, err := s.records.PatchOneByFilter(ctx, query, repository.Patch().Set(repository.Field("subjectRef"), subject).Set(repository.Field("registering"), false), &Binding{}) if err != nil { return err } if !matched { return unavailable() } return nil } func (s *mongoStore) Accept(ctx context.Context, id bson.ObjectID, namespace string, receipt Receipt) error { query := scoped(id, namespace).Filter(repository.Field("subjectRef"), receipt.SubjectRef) matched, err := s.records.PatchOneByFilter(ctx, query, repository.Patch().Set(repository.Field("receipt"), receipt), &Binding{}) if err != nil { return err } if !matched { return unavailable() } return nil }