package useCases import ( "RenewCMS/internal/domain/audit" "RenewCMS/internal/domain/image" "RenewCMS/internal/domain/site" "context" ) type UpdateSiteUseCase struct { siteRepository site.Repository imageRepository image.Repository recorder audit.Recorder } func NewUpdateSiteUseCase(siteRepository site.Repository, imageRepository image.Repository, recorder audit.Recorder) *UpdateSiteUseCase { return &UpdateSiteUseCase{siteRepository, imageRepository, recorder} } func (u *UpdateSiteUseCase) Update(ctx context.Context, id uint32, patch site.Patch) (site.Site, error) { before, err := u.siteRepository.Get(id) if err != nil { return site.Site{}, err } event := audit.NewEvent(audit.ActionSiteEdit, audit.CategorySites) event.Target = siteTarget(before) after, err := u.apply(before, patch) if err != nil { recordFailure(ctx, u.recorder, event, err) return site.Site{}, err } changes := u.changes(before, after) if len(changes) == 0 { return before, nil } saved, err := u.siteRepository.Update(after) if err != nil { recordFailure(ctx, u.recorder, event, err) return site.Site{}, err } event.Target = siteTarget(saved) event.Changes = changes u.recorder.Record(ctx, event) return saved, nil } func (u *UpdateSiteUseCase) apply(before site.Site, patch site.Patch) (site.Site, error) { after := before if patch.IsDefault != nil { return site.Site{}, site.ErrUseSetDefault } if patch.Key != nil && *patch.Key != before.Key { return site.Site{}, site.ErrKeyImmutable } if patch.Name != nil { after.Name = *patch.Name } if patch.BaseURL != nil { baseURL, err := site.NormalizeBaseURL(*patch.BaseURL) if err != nil { return site.Site{}, err } after.BaseURL = baseURL } if patch.DefaultRobots != nil { after.DefaultRobots = *patch.DefaultRobots } if patch.Locale.Set { locale, err := site.NormalizeLocale(patch.Locale.Value) if err != nil { return site.Site{}, err } after.Locale = locale } if patch.DefaultSocialImageID.Set { if err := ensureImageExists(u.imageRepository, patch.DefaultSocialImageID.Value); err != nil { return site.Site{}, err } after.DefaultSocialImageID = patch.DefaultSocialImageID.Value } return after, nil } func (u *UpdateSiteUseCase) changes(before site.Site, after site.Site) []audit.Change { changes := []audit.Change{} changes = appendTextChange(changes, audit.FieldName, before.Name, after.Name) changes = appendTextChange(changes, audit.FieldBaseURL, before.BaseURL, after.BaseURL) changes = appendTextChange(changes, audit.FieldDefaultRobots, before.DefaultRobots, after.DefaultRobots) changes = appendTextChange(changes, audit.FieldLocale, localeLabel(before.Locale), localeLabel(after.Locale)) if !sameImage(before.DefaultSocialImageID, after.DefaultSocialImageID) { changes = append(changes, audit.TextChange(audit.FieldSocialImage, imageLabel(u.imageRepository, before.DefaultSocialImageID), imageLabel(u.imageRepository, after.DefaultSocialImageID))) } return changes } func appendTextChange(changes []audit.Change, field string, before string, after string) []audit.Change { if before == after { return changes } return append(changes, audit.TextChange(field, before, after)) } func sameImage(a *uint32, b *uint32) bool { if a == nil || b == nil { return a == b } return *a == *b }