package useCases import ( "RenewCMS/internal/domain/audit" "RenewCMS/internal/domain/author" "RenewCMS/internal/domain/image" "RenewCMS/internal/domain/user" "errors" "strconv" "strings" ) const authorChangeSeparator = ", " type AuthorCaller struct { UserID uint32 Role user.Role } func isAdminRole(role user.Role) bool { return role == user.RoleOwner || role == user.RoleAdmin } func (c AuthorCaller) isAdmin() bool { return isAdminRole(c.Role) } func authorTarget(a author.Author) audit.Target { return audit.NewTarget(audit.TargetAuthor, a.ID, a.Name) } func isSlugTaken(authors author.Repository, slug string) (bool, error) { _, err := authors.GetBySlug(slug) if errors.Is(err, author.ErrAuthorNotFound) { return false, nil } return err == nil, err } func ensureUserCanBeLinked(users user.Repository, authors author.Repository, userID uint32) error { if _, err := users.Get(userID); err != nil { return err } _, err := authors.GetByUserID(userID) if err == nil { return author.ErrUserAlreadyLinked } if errors.Is(err, author.ErrAuthorNotFound) { return nil } return err } func withUserEmail(users user.Repository, a author.Author) author.Author { a.UserEmail = nil if a.UserID == nil { return a } linked, err := users.Get(*a.UserID) if err != nil { return a } email := linked.Email a.UserEmail = &email return a } func linksLabel(links []author.SocialLink) string { labels := make([]string, 0, len(links)) for _, link := range links { labels = append(labels, link.Type+": "+link.URL) } return strings.Join(labels, authorChangeSeparator) } func websiteLabel(website *string) string { if website == nil { return "" } return *website } func usernameLabel(users user.Repository, id *uint32) string { if id == nil { return "" } found, err := users.Get(*id) if err != nil { return strconv.FormatUint(uint64(*id), 10) } return found.Username } func sameID(a *uint32, b *uint32) bool { if a == nil || b == nil { return a == b } return *a == *b } func authorChanges(users user.Repository, images image.Repository, before author.Author, after author.Author) []audit.Change { changes := []audit.Change{} changes = appendTextChange(changes, audit.FieldName, before.Name, after.Name) changes = appendTextChange(changes, audit.FieldSlug, before.Slug, after.Slug) changes = appendTextChange(changes, audit.FieldBio, before.Bio, after.Bio) changes = appendTextChange(changes, audit.FieldWebsite, websiteLabel(before.Website), websiteLabel(after.Website)) changes = appendTextChange(changes, audit.FieldSocialLinks, linksLabel(before.SocialLinks), linksLabel(after.SocialLinks)) if !sameID(before.AvatarID, after.AvatarID) { changes = append(changes, audit.TextChange(audit.FieldAvatar, imageLabel(images, before.AvatarID), imageLabel(images, after.AvatarID))) } if !sameID(before.UserID, after.UserID) { changes = append(changes, audit.TextChange(audit.FieldUser, usernameLabel(users, before.UserID), usernameLabel(users, after.UserID))) } return changes }