feat: Authors feature backend (and upgraded deprecated mods)
This commit is contained in:
1 parent
a11338094e
commit
b34a173d83
103 files changed
+6454
-240
No files matched your search
@@ -0,0 +1,106 @@
|
||||
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)
|
||||
}
|
||||
Reference in new issue
Block a user