feat: invite management API: DELETE /v1/user/invite/:id (204, cancels a pending invite) and POST /v1/user/invite/:id/renew (200, new code, expires_at = now+3d, created_at = now, resends the invitation email, old link dead)

This commit is contained in:
fsylvain committed 2026-09-30 01:36:43 +02:00
1 parent 461e93e3b5
commit 153fd8719a
18 files changed
+1147 -44

No files matched your search

@@ -0,0 +1,59 @@
package useCases
import (
"RenewCMS/internal/domain/hash"
"RenewCMS/internal/domain/invite"
"RenewCMS/internal/domain/mail"
"RenewCMS/internal/domain/user"
"fmt"
"strings"
"github.com/google/uuid"
)
const inviteTemplateName = "invitation"
type MailInviteData struct {
Host string
VerificationCode string
Email string
InvitedBy string
}
func (d MailInviteData) Subject() string {
inviter := strings.NewReplacer("\r", " ", "\n", " ").Replace(d.InvitedBy)
return inviter + " invited you to RenewCMS"
}
type inviteMailer struct {
mailRepository mail.Repository
publicURL string
}
func (m inviteMailer) send(email string, rawCode string, inviter user.User) error {
if err := m.mailRepository.Send(email, inviteTemplateName, MailInviteData{
Host: m.publicURL,
VerificationCode: rawCode,
Email: email,
InvitedBy: inviterName(inviter),
}); err != nil {
return fmt.Errorf("%w: %w", invite.ErrInviteEmailNotSent, err)
}
return nil
}
func newInviteCode(hasher hash.Hasher) (string, string, error) {
rawCode := uuid.NewString()
hashedCode, err := hasher.Hash(rawCode)
if err != nil {
return "", "", err
}
return rawCode, hashedCode, nil
}
func inviterName(inviter user.User) string {
if inviter.DisplayName != "" {
return inviter.DisplayName
}
return inviter.Username
}