mirror of
https://github.com/stashapp/stash.git
synced 2025-12-17 04:14:39 +03:00
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:
@@ -108,6 +108,10 @@ func (r *mutationResolver) PerformerCreate(ctx context.Context, input models.Per
|
|||||||
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
||||||
qb := r.repository.Performer
|
qb := r.repository.Performer
|
||||||
|
|
||||||
|
if err := performer.EnsureNameUnique(ctx, newPerformer.Name, newPerformer.Disambiguation, qb); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
err = qb.Create(ctx, &newPerformer)
|
err = qb.Create(ctx, &newPerformer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
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 {
|
if err := performer.ValidateDeathDate(existing, input.Birthdate, input.DeathDate); err != nil {
|
||||||
return err
|
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)
|
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)
|
err = performer.ValidateDeathDate(existing, input.Birthdate, input.DeathDate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err := r.withTxn(ctx, func(ctx context.Context) error {
|
||||||
qb := r.repository.Studio
|
qb := r.repository.Studio
|
||||||
|
|
||||||
|
if err := studio.EnsureStudioNameUnique(ctx, 0, newStudio.Name, qb); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if len(input.Aliases) > 0 {
|
if len(input.Aliases) > 0 {
|
||||||
if err := studio.EnsureAliasesUnique(ctx, 0, input.Aliases, qb); err != nil {
|
if err := studio.EnsureAliasesUnique(ctx, 0, input.Aliases, qb); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
76
pkg/performer/update.go
Normal file
76
pkg/performer/update.go
Normal 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)
|
||||||
|
}
|
||||||
@@ -80,6 +80,7 @@ type ValidateModifyReader interface {
|
|||||||
// 1. The studio exists locally
|
// 1. The studio exists locally
|
||||||
// 2. The studio is not its own ancestor
|
// 2. The studio is not its own ancestor
|
||||||
// 3. The studio's aliases are unique
|
// 3. The studio's aliases are unique
|
||||||
|
// 4. The name is unique
|
||||||
func ValidateModify(ctx context.Context, s models.StudioPartial, qb ValidateModifyReader) error {
|
func ValidateModify(ctx context.Context, s models.StudioPartial, qb ValidateModifyReader) error {
|
||||||
existing, err := qb.Find(ctx, s.ID)
|
existing, err := qb.Find(ctx, s.ID)
|
||||||
if err != nil {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user