diff --git a/pkg/coredata/migrations/20260225T000000Z.sql b/pkg/coredata/migrations/20260225T000000Z.sql index a4348e8eb..06a4da771 100644 --- a/pkg/coredata/migrations/20260225T000000Z.sql +++ b/pkg/coredata/migrations/20260225T000000Z.sql @@ -4,8 +4,7 @@ CREATE TABLE mailing_lists ( organization_id TEXT NOT NULL REFERENCES organizations(id) ON UPDATE CASCADE ON DELETE CASCADE, reply_to CITEXT, created_at TIMESTAMP WITH TIME ZONE NOT NULL, - updated_at TIMESTAMP WITH TIME ZONE NOT NULL, - UNIQUE (organization_id) + updated_at TIMESTAMP WITH TIME ZONE NOT NULL ); CREATE TYPE mailing_list_subscriber_status AS ENUM ( diff --git a/pkg/mailman/service.go b/pkg/mailman/service.go index 50aa0a5b1..a90d5c520 100644 --- a/pkg/mailman/service.go +++ b/pkg/mailman/service.go @@ -35,26 +35,18 @@ func NewService(pgClient *pg.Client) *Service { return &Service{pg: pgClient} } -func (s *Service) WithTenant(tenantID gid.TenantID) *TenantService { - return &TenantService{pg: s.pg, scope: coredata.NewScope(tenantID)} -} - -type TenantService struct { - pg *pg.Client - scope coredata.Scoper -} - -func (s *TenantService) UpdateMailingList( +func (s *Service) UpdateMailingList( ctx context.Context, id gid.GID, replyTo *mail.Addr, ) (*coredata.MailingList, error) { - var ml coredata.MailingList + scope := coredata.NewScopeFromObjectID(id) + ml := coredata.MailingList{} err := s.pg.WithConn( ctx, func(conn pg.Conn) error { - if err := ml.LoadByID(ctx, conn, s.scope, id); err != nil { + if err := ml.LoadByID(ctx, conn, scope, id); err != nil { if errors.Is(err, coredata.ErrResourceNotFound) { return ErrMailingListNotFound } @@ -64,7 +56,7 @@ func (s *TenantService) UpdateMailingList( ml.ReplyTo = replyTo ml.UpdatedAt = time.Now() - if err := ml.Update(ctx, conn, s.scope); err != nil { + if err := ml.Update(ctx, conn, scope); err != nil { return fmt.Errorf("cannot update mailing list: %w", err) } @@ -78,17 +70,18 @@ func (s *TenantService) UpdateMailingList( return &ml, nil } -func (s *TenantService) GetSubscriber( +func (s *Service) GetSubscriber( ctx context.Context, mailingListID gid.GID, email mail.Addr, ) (*coredata.MailingListSubscriber, error) { - var subscriber coredata.MailingListSubscriber + scope := coredata.NewScopeFromObjectID(mailingListID) + subscriber := coredata.MailingListSubscriber{} err := s.pg.WithConn( ctx, func(conn pg.Conn) error { - if err := subscriber.LoadByMailingListIDAndEmail(ctx, conn, s.scope, mailingListID, email); err != nil { + if err := subscriber.LoadByMailingListIDAndEmail(ctx, conn, scope, mailingListID, email); err != nil { return fmt.Errorf("cannot load mailing list subscriber: %w", err) } @@ -105,16 +98,17 @@ func (s *TenantService) GetSubscriber( return &subscriber, nil } -func (s *TenantService) CreateSubscriber( +func (s *Service) CreateSubscriber( ctx context.Context, mailingListID gid.GID, email mail.Addr, fullName string, ) (*coredata.MailingListSubscriber, error) { + scope := coredata.NewScopeFromObjectID(mailingListID) now := time.Now() subscriber := &coredata.MailingListSubscriber{ - ID: gid.New(s.scope.GetTenantID(), coredata.MailingListSubscriberEntityType), + ID: gid.New(scope.GetTenantID(), coredata.MailingListSubscriberEntityType), MailingListID: mailingListID, FullName: fullName, Email: email, @@ -126,13 +120,13 @@ func (s *TenantService) CreateSubscriber( err := s.pg.WithConn( ctx, func(conn pg.Conn) error { - var ml coredata.MailingList - if err := ml.LoadByID(ctx, conn, s.scope, mailingListID); err != nil { + ml := coredata.MailingList{} + if err := ml.LoadByID(ctx, conn, scope, mailingListID); err != nil { return fmt.Errorf("cannot load mailing list: %w", err) } subscriber.OrganizationID = ml.OrganizationID - if err := subscriber.Insert(ctx, conn, s.scope); err != nil { + if err := subscriber.Insert(ctx, conn, scope); err != nil { if errors.Is(err, coredata.ErrResourceAlreadyExists) { return ErrSubscriberAlreadyExist } @@ -149,15 +143,17 @@ func (s *TenantService) CreateSubscriber( return subscriber, nil } -func (s *TenantService) DeleteSubscriber( +func (s *Service) DeleteSubscriber( ctx context.Context, id gid.GID, ) error { + scope := coredata.NewScopeFromObjectID(id) + err := s.pg.WithConn( ctx, func(conn pg.Conn) error { subscriber := coredata.MailingListSubscriber{ID: id} - if err := subscriber.Delete(ctx, conn, s.scope); err != nil { + if err := subscriber.Delete(ctx, conn, scope); err != nil { return fmt.Errorf("cannot delete mailing list subscriber: %w", err) } return nil @@ -170,17 +166,18 @@ func (s *TenantService) DeleteSubscriber( return nil } -func (s *TenantService) CountSubscribers( +func (s *Service) CountSubscribers( ctx context.Context, mailingListID gid.GID, ) (int, error) { - var count int + scope := coredata.NewScopeFromObjectID(mailingListID) + count := 0 err := s.pg.WithConn( ctx, func(conn pg.Conn) (err error) { subscribers := coredata.MailingListSubscribers{} - count, err = subscribers.CountByMailingListID(ctx, conn, s.scope, mailingListID) + count, err = subscribers.CountByMailingListID(ctx, conn, scope, mailingListID) if err != nil { return fmt.Errorf("cannot count mailing list subscribers: %w", err) } @@ -194,17 +191,18 @@ func (s *TenantService) CountSubscribers( return count, nil } -func (s *TenantService) ListSubscribers( +func (s *Service) ListSubscribers( ctx context.Context, mailingListID gid.GID, cursor *page.Cursor[coredata.MailingListSubscriberOrderField], ) (*page.Page[*coredata.MailingListSubscriber, coredata.MailingListSubscriberOrderField], error) { - var subscribers coredata.MailingListSubscribers + scope := coredata.NewScopeFromObjectID(mailingListID) + subscribers := coredata.MailingListSubscribers{} err := s.pg.WithConn( ctx, func(conn pg.Conn) error { - if err := subscribers.LoadByMailingListID(ctx, conn, s.scope, mailingListID, cursor); err != nil { + if err := subscribers.LoadByMailingListID(ctx, conn, scope, mailingListID, cursor); err != nil { return fmt.Errorf("cannot load mailing list subscribers: %w", err) } return nil diff --git a/pkg/server/api/console/v1/resolver.go b/pkg/server/api/console/v1/resolver.go index d97debb2d..f9bdf4af8 100644 --- a/pkg/server/api/console/v1/resolver.go +++ b/pkg/server/api/console/v1/resolver.go @@ -202,9 +202,6 @@ func (r *Resolver) ProboService(ctx context.Context, tenantID gid.TenantID) *pro return r.probo.WithTenant(tenantID) } -func (r *Resolver) MailmanService(ctx context.Context, tenantID gid.TenantID) *mailman.TenantService { - return r.mailman.WithTenant(tenantID) -} func (r *Resolver) Permission(ctx context.Context, obj types.Node, action string) (bool, error) { return r.authorize(ctx, obj.GetID(), action) == nil, nil diff --git a/pkg/server/api/console/v1/v1_resolver.go b/pkg/server/api/console/v1/v1_resolver.go index 52952b367..cdaf182ea 100644 --- a/pkg/server/api/console/v1/v1_resolver.go +++ b/pkg/server/api/console/v1/v1_resolver.go @@ -1537,7 +1537,7 @@ func (r *mailingListResolver) Subscribers(ctx context.Context, obj *types.Mailin cursor := types.NewCursor(first, after, last, before, pageOrderBy) - result, err := r.MailmanService(ctx, obj.ID.TenantID()).ListSubscribers(ctx, obj.ID, cursor) + result, err := r.mailman.ListSubscribers(ctx, obj.ID, cursor) if err != nil { r.logger.ErrorCtx(ctx, "cannot list mailing list subscribers", log.Error(err)) return nil, gqlutils.Internal(ctx) @@ -1554,7 +1554,7 @@ func (r *mailingListSubscriberConnectionResolver) TotalCount(ctx context.Context switch obj.Resolver.(type) { case *mailingListResolver: - count, err := r.MailmanService(ctx, obj.ParentID.TenantID()).CountSubscribers(ctx, obj.ParentID) + count, err := r.mailman.CountSubscribers(ctx, obj.ParentID) if err != nil { r.logger.ErrorCtx(ctx, "cannot count mailing list subscribers", log.Error(err)) return 0, gqlutils.Internal(ctx) @@ -2034,7 +2034,7 @@ func (r *mutationResolver) UpdateMailingList(ctx context.Context, input types.Up return nil, err } - ml, err := r.MailmanService(ctx, input.ID.TenantID()).UpdateMailingList(ctx, input.ID, input.ReplyTo) + ml, err := r.mailman.UpdateMailingList(ctx, input.ID, input.ReplyTo) if err != nil { r.logger.ErrorCtx(ctx, "cannot update mailing list", log.Error(err)) return nil, gqlutils.Internal(ctx) @@ -2051,7 +2051,7 @@ func (r *mutationResolver) CreateMailingListSubscriber(ctx context.Context, inpu return nil, err } - subscriber, err := r.MailmanService(ctx, input.MailingListID.TenantID()).CreateSubscriber(ctx, input.MailingListID, input.Email, input.FullName) + subscriber, err := r.mailman.CreateSubscriber(ctx, input.MailingListID, input.Email, input.FullName) if err != nil { r.logger.ErrorCtx(ctx, "cannot create mailing list subscriber", log.Error(err)) return nil, gqlutils.Internal(ctx) @@ -2068,7 +2068,7 @@ func (r *mutationResolver) DeleteMailingListSubscriber(ctx context.Context, inpu return nil, err } - if err := r.MailmanService(ctx, input.ID.TenantID()).DeleteSubscriber(ctx, input.ID); err != nil { + if err := r.mailman.DeleteSubscriber(ctx, input.ID); err != nil { r.logger.ErrorCtx(ctx, "cannot delete mailing list subscriber", log.Error(err)) return nil, gqlutils.Internal(ctx) } diff --git a/pkg/server/api/trust/v1/resolver.go b/pkg/server/api/trust/v1/resolver.go index 1a60bd517..8b7bd7bb2 100644 --- a/pkg/server/api/trust/v1/resolver.go +++ b/pkg/server/api/trust/v1/resolver.go @@ -100,6 +100,3 @@ func (r *Resolver) TrustService(ctx context.Context, tenantID gid.TenantID) *tru return r.trust.WithTenant(tenantID) } -func (r *Resolver) MailmanService(ctx context.Context, tenantID gid.TenantID) *mailman.TenantService { - return r.mailman.WithTenant(tenantID) -} diff --git a/pkg/server/api/trust/v1/v1_resolver.go b/pkg/server/api/trust/v1/v1_resolver.go index ce0974612..32aaebf5c 100644 --- a/pkg/server/api/trust/v1/v1_resolver.go +++ b/pkg/server/api/trust/v1/v1_resolver.go @@ -702,13 +702,12 @@ func (r *mutationResolver) SubscribeToMailingList(ctx context.Context) (*types.S return nil, gqlutils.NotFoundf(ctx, "mailing list not found") } - mlSvc := r.MailmanService(ctx, trustCenter.ID.TenantID()) identity := authn.IdentityFromContext(ctx) - subscriber, err := mlSvc.CreateSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress, identity.FullName) + subscriber, err := r.mailman.CreateSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress, identity.FullName) if err != nil { if errors.Is(err, mailman.ErrSubscriberAlreadyExist) { - subscriber, err = mlSvc.GetSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress) + subscriber, err = r.mailman.GetSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress) if err != nil { r.logger.ErrorCtx(ctx, "cannot get existing mailing list subscription", log.Error(err)) return nil, gqlutils.Internal(ctx) @@ -731,10 +730,9 @@ func (r *mutationResolver) UnsubscribeFromMailingList(ctx context.Context) (*typ return nil, gqlutils.NotFoundf(ctx, "mailing list not found") } - mlSvc := r.MailmanService(ctx, trustCenter.ID.TenantID()) identity := authn.IdentityFromContext(ctx) - subscriber, err := mlSvc.GetSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress) + subscriber, err := r.mailman.GetSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress) if err != nil { r.logger.ErrorCtx(ctx, "cannot get mailing list subscription", log.Error(err)) return nil, gqlutils.Internal(ctx) @@ -743,7 +741,7 @@ func (r *mutationResolver) UnsubscribeFromMailingList(ctx context.Context) (*typ return nil, gqlutils.NotFoundf(ctx, "mailing list subscription not found") } - if err := mlSvc.DeleteSubscriber(ctx, subscriber.ID); err != nil { + if err := r.mailman.DeleteSubscriber(ctx, subscriber.ID); err != nil { r.logger.ErrorCtx(ctx, "cannot unsubscribe from mailing list", log.Error(err)) return nil, gqlutils.Internal(ctx) } @@ -1052,7 +1050,7 @@ func (r *trustCenterResolver) ViewerSubscription(ctx context.Context, obj *types return nil, nil } - subscriber, err := r.MailmanService(ctx, trustCenter.ID.TenantID()).GetSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress) + subscriber, err := r.mailman.GetSubscriber(ctx, *trustCenter.MailingListID, identity.EmailAddress) if err != nil { r.logger.ErrorCtx(ctx, "cannot get mailing list subscription", log.Error(err)) return nil, gqlutils.Internal(ctx)