107 lines
2.9 KiB
Go
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)
|
|
}
|