194 lines
6.2 KiB
Go
194 lines
6.2 KiB
Go
package mongo
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/tech/sendico/payments/storage"
|
|
"github.com/tech/sendico/payments/storage/model"
|
|
"github.com/tech/sendico/payments/storage/mongo/store"
|
|
quotestorage "github.com/tech/sendico/payments/storage/quote"
|
|
quotemongo "github.com/tech/sendico/payments/storage/quote/mongo"
|
|
"github.com/tech/sendico/pkg/auth"
|
|
"github.com/tech/sendico/pkg/db"
|
|
"github.com/tech/sendico/pkg/db/repository"
|
|
"github.com/tech/sendico/pkg/merrors"
|
|
"github.com/tech/sendico/pkg/mlogger"
|
|
"github.com/tech/sendico/pkg/mservice"
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
)
|
|
|
|
// Store implements storage.Repository backed by MongoDB.
|
|
type Store struct {
|
|
logger mlogger.Logger
|
|
ping func(context.Context) error
|
|
|
|
payments storage.PaymentsStore
|
|
methods storage.PaymentMethodsStore
|
|
quotes quotestorage.QuotesStore
|
|
routes storage.RoutesStore
|
|
plans storage.PlanTemplatesStore
|
|
}
|
|
|
|
type paymentMethodsConfig struct {
|
|
enforcer auth.Enforcer
|
|
permissionRef bson.ObjectID
|
|
}
|
|
|
|
type options struct {
|
|
quoteRetention time.Duration
|
|
paymentMethodsAuth *paymentMethodsConfig
|
|
}
|
|
|
|
// Option configures the Mongo-backed payments repository.
|
|
type Option func(*options)
|
|
|
|
// WithQuoteRetention sets how long payment quote records are retained after expiry.
|
|
func WithQuoteRetention(retention time.Duration) Option {
|
|
return func(opts *options) {
|
|
opts.quoteRetention = retention
|
|
}
|
|
}
|
|
|
|
// WithPaymentMethodsAuth enables the payment-methods store and permission checks.
|
|
func WithPaymentMethodsAuth(enforcer auth.Enforcer, permissionRef bson.ObjectID) Option {
|
|
return func(opts *options) {
|
|
opts.paymentMethodsAuth = &paymentMethodsConfig{
|
|
enforcer: enforcer,
|
|
permissionRef: permissionRef,
|
|
}
|
|
}
|
|
}
|
|
|
|
// New constructs a Mongo-backed payments repository from a Mongo connection.
|
|
func New(logger mlogger.Logger, conn *db.MongoConnection, opts ...Option) (*Store, error) {
|
|
if conn == nil {
|
|
return nil, merrors.InvalidArgument("payments.storage.mongo: connection is nil")
|
|
}
|
|
paymentsRepo := repository.CreateMongoRepository(conn.Database(), (&model.Payment{}).Collection())
|
|
quotesRepo := repository.CreateMongoRepository(conn.Database(), (&model.PaymentQuoteRecord{}).Collection())
|
|
routesRepo := repository.CreateMongoRepository(conn.Database(), (&model.PaymentRoute{}).Collection())
|
|
plansRepo := repository.CreateMongoRepository(conn.Database(), (&model.PaymentPlanTemplate{}).Collection())
|
|
methodsRepo := repository.CreateMongoRepository(conn.Database(), mservice.PaymentMethods)
|
|
|
|
return newWithRepository(logger, conn.Ping, paymentsRepo, methodsRepo, quotesRepo, routesRepo, plansRepo, opts...)
|
|
}
|
|
|
|
// NewWithRepository constructs a payments repository using the provided primitives.
|
|
func NewWithRepository(logger mlogger.Logger, ping func(context.Context) error, paymentsRepo repository.Repository, quotesRepo repository.Repository, routesRepo repository.Repository, plansRepo repository.Repository, opts ...Option) (*Store, error) {
|
|
return newWithRepository(logger, ping, paymentsRepo, nil, quotesRepo, routesRepo, plansRepo, opts...)
|
|
}
|
|
|
|
func newWithRepository(
|
|
logger mlogger.Logger,
|
|
ping func(context.Context) error,
|
|
paymentsRepo, methodsRepo, quotesRepo, routesRepo, plansRepo repository.Repository,
|
|
opts ...Option,
|
|
) (*Store, error) {
|
|
if ping == nil {
|
|
return nil, merrors.InvalidArgument("payments.storage.mongo: ping func is nil")
|
|
}
|
|
if paymentsRepo == nil {
|
|
return nil, merrors.InvalidArgument("payments.storage.mongo: payments repository is nil")
|
|
}
|
|
if quotesRepo == nil {
|
|
return nil, merrors.InvalidArgument("payments.storage.mongo: quotes repository is nil")
|
|
}
|
|
if routesRepo == nil {
|
|
return nil, merrors.InvalidArgument("payments.storage.mongo: routes repository is nil")
|
|
}
|
|
if plansRepo == nil {
|
|
return nil, merrors.InvalidArgument("payments.storage.mongo: plan templates repository is nil")
|
|
}
|
|
|
|
cfg := options{}
|
|
for _, opt := range opts {
|
|
if opt != nil {
|
|
opt(&cfg)
|
|
}
|
|
}
|
|
|
|
childLogger := logger.Named("storage").Named("mongo")
|
|
paymentsStore, err := store.NewPayments(childLogger, paymentsRepo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
quotesRepoStore, err := quotemongo.NewWithRepository(childLogger, ping, quotesRepo, quotemongo.WithQuoteRetention(cfg.quoteRetention))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
routesStore, err := store.NewRoutes(childLogger, routesRepo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
plansStore, err := store.NewPlanTemplates(childLogger, plansRepo)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var methodsStore storage.PaymentMethodsStore
|
|
if cfg.paymentMethodsAuth != nil {
|
|
if methodsRepo == nil {
|
|
return nil, merrors.InvalidArgument("payments.storage.mongo: payment methods repository is nil")
|
|
}
|
|
if cfg.paymentMethodsAuth.enforcer == nil {
|
|
return nil, merrors.InvalidArgument("payments.storage.mongo: payment methods enforcer is nil")
|
|
}
|
|
if cfg.paymentMethodsAuth.permissionRef == bson.NilObjectID {
|
|
return nil, merrors.InvalidArgument("payments.storage.mongo: payment methods permission reference is required")
|
|
}
|
|
|
|
methodsStore, err = store.NewPaymentMethods(childLogger, methodsRepo, cfg.paymentMethodsAuth.enforcer, cfg.paymentMethodsAuth.permissionRef)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
result := &Store{
|
|
logger: childLogger,
|
|
ping: ping,
|
|
payments: paymentsStore,
|
|
methods: methodsStore,
|
|
quotes: quotesRepoStore.Quotes(),
|
|
routes: routesStore,
|
|
plans: plansStore,
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// Ping verifies connectivity with the backing database.
|
|
func (s *Store) Ping(ctx context.Context) error {
|
|
if s.ping == nil {
|
|
return merrors.InvalidArgument("payments.storage.mongo: ping func is nil")
|
|
}
|
|
return s.ping(ctx)
|
|
}
|
|
|
|
// Payments returns the payments store.
|
|
func (s *Store) Payments() storage.PaymentsStore {
|
|
return s.payments
|
|
}
|
|
|
|
// PaymentMethods returns the payment-methods store.
|
|
func (s *Store) PaymentMethods() storage.PaymentMethodsStore {
|
|
return s.methods
|
|
}
|
|
|
|
// Quotes returns the quotes store.
|
|
func (s *Store) Quotes() quotestorage.QuotesStore {
|
|
return s.quotes
|
|
}
|
|
|
|
// Routes returns the routing store.
|
|
func (s *Store) Routes() storage.RoutesStore {
|
|
return s.routes
|
|
}
|
|
|
|
// PlanTemplates returns the plan templates store.
|
|
func (s *Store) PlanTemplates() storage.PlanTemplatesStore {
|
|
return s.plans
|
|
}
|
|
|
|
var _ storage.Repository = (*Store)(nil)
|