Errors for performer/studio non-unique names (#4178)

* Errors for performer/studio non-unique names
---------
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
Flashy78 2023-10-15 23:26:43 -07:00 committed by GitHub
parent 2fd7141f0f
commit 789de2d5f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 99 additions and 0 deletions

View File

@ -108,6 +108,10 @@ func (r *mutationResolver) PerformerCreate(ctx context.Context, input models.Per
if err := r.withTxn(ctx, func(ctx context.Context) error {
qb := r.repository.Performer
if err := performer.EnsureNameUnique(ctx, newPerformer.Name, newPerformer.Disambiguation, qb); err != nil {
return err
}
err = qb.Create(ctx, &newPerformer)
if err != nil {
return err
@ -224,6 +228,10 @@ func (r *mutationResolver) PerformerUpdate(ctx context.Context, input models.Per
return fmt.Errorf("performer with id %d not found", performerID)
}
if err := performer.EnsureUpdateNameUnique(ctx, existing, updatedPerformer.Name, updatedPerformer.Disambiguation, qb); err != nil {
return err
}
if err := performer.ValidateDeathDate(existing, input.Birthdate, input.DeathDate); err != nil {
return err
}
@ -336,6 +344,10 @@ func (r *mutationResolver) BulkPerformerUpdate(ctx context.Context, input BulkPe
return fmt.Errorf("performer with id %d not found", performerID)
}
if err := performer.EnsureUpdateNameUnique(ctx, existing, updatedPerformer.Name, updatedPerformer.Disambiguation, qb); err != nil {
return err
}
err = performer.ValidateDeathDate(existing, input.Birthdate, input.DeathDate)
if err != nil {
return err

View File

@ -61,6 +61,10 @@ func (r *mutationResolver) StudioCreate(ctx context.Context, input models.Studio
if err := r.withTxn(ctx, func(ctx context.Context) error {
qb := r.repository.Studio
if err := studio.EnsureStudioNameUnique(ctx, 0, newStudio.Name, qb); err != nil {
return err
}
if len(input.Aliases) > 0 {
if err := studio.EnsureAliasesUnique(ctx, 0, input.Aliases, qb); err != nil {
return err

76
pkg/performer/update.go Normal file
View File

@ -0,0 +1,76 @@
package performer
import (
"context"
"fmt"
"github.com/stashapp/stash/pkg/models"
)
type NameExistsError struct {
Name string
Disambiguation string
}
func (e *NameExistsError) Error() string {
if e.Disambiguation != "" {
return fmt.Sprintf("performer with name '%s' and disambiguation '%s' already exists", e.Name, e.Disambiguation)
}
return fmt.Sprintf("performer with name '%s' already exists", e.Name)
}
// EnsureNameUnique returns an error if the performer name and disambiguation provided
// is used by another performer
func EnsureNameUnique(ctx context.Context, name string, disambig string, qb models.PerformerReaderWriter) error {
performerFilter := models.PerformerFilterType{
Name: &models.StringCriterionInput{
Value: name,
Modifier: models.CriterionModifierEquals,
},
}
if disambig != "" {
performerFilter.Disambiguation = &models.StringCriterionInput{
Value: disambig,
Modifier: models.CriterionModifierEquals,
}
}
pp := 1
findFilter := models.FindFilterType{
PerPage: &pp,
}
existing, _, err := qb.Query(ctx, &performerFilter, &findFilter)
if err != nil {
return err
}
if len(existing) > 0 {
return &NameExistsError{
Name: name,
Disambiguation: disambig,
}
}
return nil
}
// EnsureUpdateNameUnique performs the same check as EnsureNameUnique, but is used when modifying an existing performer.
func EnsureUpdateNameUnique(ctx context.Context, existing *models.Performer, name models.OptionalString, disambig models.OptionalString, qb models.PerformerReaderWriter) error {
newName := existing.Name
newDisambig := existing.Disambiguation
if name.Set {
newName = name.Value
}
if disambig.Set {
newDisambig = disambig.Value
}
if newName == existing.Name && newDisambig == existing.Disambiguation {
return nil
}
return EnsureNameUnique(ctx, newName, newDisambig, qb)
}

View File

@ -80,6 +80,7 @@ type ValidateModifyReader interface {
// 1. The studio exists locally
// 2. The studio is not its own ancestor
// 3. The studio's aliases are unique
// 4. The name is unique
func ValidateModify(ctx context.Context, s models.StudioPartial, qb ValidateModifyReader) error {
existing, err := qb.Find(ctx, s.ID)
if err != nil {
@ -108,6 +109,12 @@ func ValidateModify(ctx context.Context, s models.StudioPartial, qb ValidateModi
}
}
if s.Name.Set && s.Name.Value != existing.Name {
if err := EnsureStudioNameUnique(ctx, 0, s.Name.Value, qb); err != nil {
return err
}
}
return nil
}