Files
RenewCMS/internal/infrastructure/useCases/CreateAuthor.go
T

107 lines
2.9 KiB
Go

package useCases
import (
"RenewCMS/internal/domain/audit"
"RenewCMS/internal/domain/author"
"RenewCMS/internal/domain/image"
"RenewCMS/internal/domain/user"
"context"
"strings"
)
type CreateAuthorUseCase struct {
authors author.Repository
users user.Repository
images image.Repository
recorder audit.Recorder
}
type CreateAuthorCommand struct {
Name string
Slug string
Bio string
AvatarID *uint32
Website *string
SocialLinks []author.SocialLink
UserID *uint32
}
func NewCreateAuthorUseCase(authors author.Repository, users user.Repository, images image.Repository, recorder audit.Recorder) *CreateAuthorUseCase {
return &CreateAuthorUseCase{authors: authors, users: users, images: images, recorder: recorder}
}
func (u *CreateAuthorUseCase) Create(ctx context.Context, command CreateAuthorCommand) (author.Author, error) {
command.Name = strings.TrimSpace(command.Name)
event := audit.NewEvent(audit.ActionAuthorCreate, audit.CategoryAuthors)
event.Target = audit.Target{Type: audit.TargetAuthor, Name: command.Name}
created, err := u.create(command)
if err != nil {
recordFailure(ctx, u.recorder, event, err)
return author.Author{}, err
}
event.Target = authorTarget(created)
u.recorder.Record(ctx, event)
return withUserEmail(u.users, created), nil
}
func (u *CreateAuthorUseCase) create(command CreateAuthorCommand) (author.Author, error) {
website, err := validateAuthorContent(command.Bio, command.Website, command.SocialLinks)
if err != nil {
return author.Author{}, err
}
if err := ensureImageExists(u.images, command.AvatarID); err != nil {
return author.Author{}, err
}
if command.UserID != nil {
if err := ensureUserCanBeLinked(u.users, u.authors, *command.UserID); err != nil {
return author.Author{}, err
}
}
slug, err := u.slugFor(command)
if err != nil {
return author.Author{}, err
}
links := command.SocialLinks
if links == nil {
links = []author.SocialLink{}
}
return u.authors.Create(author.Author{
Name: command.Name,
Slug: slug,
Bio: command.Bio,
AvatarID: command.AvatarID,
Website: website,
SocialLinks: links,
UserID: command.UserID,
IsLinked: command.UserID != nil,
})
}
func (u *CreateAuthorUseCase) slugFor(command CreateAuthorCommand) (string, error) {
slug := command.Slug
if slug == "" {
slug = author.GenerateSlug(command.Name)
}
if !author.IsValidSlug(slug) {
return "", author.ErrInvalidSlug
}
taken, err := isSlugTaken(u.authors, slug)
if err != nil {
return "", err
}
if taken {
return "", author.ErrSlugTaken
}
return slug, nil
}
func validateAuthorContent(bio string, website *string, links []author.SocialLink) (*string, error) {
if err := author.ValidateBio(bio); err != nil {
return nil, err
}
if err := author.ValidateLinks(links); err != nil {
return nil, err
}
return author.NormalizeWebsite(website)
}