mirror of https://github.com/stashapp/stash.git
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:
parent
2fd7141f0f
commit
789de2d5f6
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue