Add validation to mailman service

Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Sacha Al Himdani
2026-03-13 15:28:10 +01:00
parent 7ed9c6c2e6
commit dc8e6d0817
5 changed files with 137 additions and 25 deletions

View File

@@ -30,6 +30,13 @@ import (
"go.probo.inc/probo/pkg/gid"
"go.probo.inc/probo/pkg/mail"
"go.probo.inc/probo/pkg/page"
"go.probo.inc/probo/pkg/validator"
)
const (
updateTitleMaxLength = 200
updateBodyMaxLength = 50000
subscriberFullNameMaxLength = 200
)
const (
@@ -51,6 +58,56 @@ func NewService(pgClient *pg.Client, fm *filemanager.Service, tokenSecret string
return &Service{pg: pgClient, fm: fm, tokenSecret: tokenSecret, apiBaseURL: apiBaseURL, bucket: bucket, encryptionKey: encryptionKey, logger: logger}
}
type (
CreateMailingListUpdateRequest struct {
MailingListID gid.GID
Title string
Body string
}
UpdateMailingListUpdateRequest struct {
ID gid.GID
Title *string
Body *string
}
CreateSubscriberRequest struct {
MailingListID gid.GID
Email mail.Addr
FullName string
}
)
func (r *CreateMailingListUpdateRequest) Validate() error {
v := validator.New()
v.Check(r.MailingListID, "mailing_list_id", validator.Required(), validator.GID(coredata.MailingListEntityType))
v.Check(r.Title, "title", validator.Required(), validator.SafeTextNoNewLine(updateTitleMaxLength))
v.Check(r.Body, "body", validator.Required(), validator.SafeText(updateBodyMaxLength))
return v.Error()
}
func (r *UpdateMailingListUpdateRequest) Validate() error {
v := validator.New()
v.Check(r.ID, "id", validator.Required(), validator.GID(coredata.MailingListUpdateEntityType))
v.Check(r.Title, "title", validator.SafeTextNoNewLine(updateTitleMaxLength))
v.Check(r.Body, "body", validator.SafeText(updateBodyMaxLength))
return v.Error()
}
func (r *CreateSubscriberRequest) Validate() error {
v := validator.New()
v.Check(r.MailingListID, "mailing_list_id", validator.Required(), validator.GID(coredata.MailingListEntityType))
v.Check(r.Email, "email", validator.Required(), validator.NotEmpty())
v.Check(r.FullName, "full_name", validator.Required(), validator.SafeTextNoNewLine(subscriberFullNameMaxLength))
return v.Error()
}
func (s *Service) UpdateMailingList(
ctx context.Context,
id gid.GID,
@@ -116,10 +173,16 @@ func (s *Service) GetSubscriber(
func (s *Service) CreateSubscriber(
ctx context.Context,
mailingListID gid.GID,
email mail.Addr,
fullName string,
req *CreateSubscriberRequest,
) (*coredata.MailingListSubscriber, error) {
if err := req.Validate(); err != nil {
return nil, fmt.Errorf("invalid request: %w", err)
}
mailingListID := req.MailingListID
email := req.Email
fullName := req.FullName
scope := coredata.NewScopeFromObjectID(mailingListID)
emailRecord, err := s.buildConfirmationMail(ctx, mailingListID, email, fullName)
if err != nil {
@@ -334,18 +397,21 @@ func (s *Service) ListSubscribers(
func (s *Service) CreateMailingListUpdate(
ctx context.Context,
mailingListID gid.GID,
title string,
body string,
req *CreateMailingListUpdateRequest,
) (*coredata.MailingListUpdate, error) {
if err := req.Validate(); err != nil {
return nil, fmt.Errorf("invalid request: %w", err)
}
mailingListID := req.MailingListID
scope := coredata.NewScopeFromObjectID(mailingListID)
now := time.Now()
mlu := &coredata.MailingListUpdate{
ID: gid.New(scope.GetTenantID(), coredata.MailingListUpdateEntityType),
MailingListID: mailingListID,
Title: title,
Body: body,
Title: req.Title,
Body: req.Body,
Status: coredata.MailingListUpdateStatusDraft,
CreatedAt: now,
UpdatedAt: now,
@@ -406,17 +472,19 @@ func (s *Service) GetMailingListUpdate(
func (s *Service) UpdateMailingListUpdate(
ctx context.Context,
id gid.GID,
title string,
body string,
req *UpdateMailingListUpdateRequest,
) (*coredata.MailingListUpdate, error) {
scope := coredata.NewScopeFromObjectID(id)
if err := req.Validate(); err != nil {
return nil, fmt.Errorf("invalid request: %w", err)
}
scope := coredata.NewScopeFromObjectID(req.ID)
var mlu coredata.MailingListUpdate
err := s.pg.WithConn(
ctx,
func(conn pg.Conn) error {
if err := mlu.LoadByID(ctx, conn, scope, id); err != nil {
if err := mlu.LoadByID(ctx, conn, scope, req.ID); err != nil {
if errors.Is(err, coredata.ErrResourceNotFound) {
return ErrMailingListUpdateNotFound
}
@@ -427,8 +495,12 @@ func (s *Service) UpdateMailingListUpdate(
return ErrMailingListUpdateAlreadySent
}
mlu.Title = title
mlu.Body = body
if req.Title != nil {
mlu.Title = *req.Title
}
if req.Body != nil {
mlu.Body = *req.Body
}
mlu.UpdatedAt = time.Now()
if err := mlu.Update(ctx, conn, scope); err != nil {