mirror of
https://github.com/stashapp/stash.git
synced 2026-06-11 07:41:08 -05:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aeb68a5851 | ||
|
|
5cf28cf8af | ||
|
|
08b73581a6 |
@@ -61,16 +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 {
|
||||
if err := studio.ValidateCreate(ctx, newStudio, qb); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(input.Aliases) > 0 {
|
||||
if err := studio.EnsureAliasesUnique(ctx, 0, input.Aliases, qb); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = qb.Create(ctx, &newStudio)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -355,6 +355,10 @@ func (t *StashBoxBatchTagTask) processMatchedStudio(ctx context.Context, s *mode
|
||||
err = r.WithTxn(ctx, func(ctx context.Context) error {
|
||||
qb := r.Studio
|
||||
|
||||
if err := studio.ValidateCreate(ctx, *newStudio, qb); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := qb.Create(ctx, newStudio); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNameMissing = errors.New("studio name must not be blank")
|
||||
ErrStudioOwnAncestor = errors.New("studio cannot be an ancestor of itself")
|
||||
)
|
||||
|
||||
@@ -70,6 +71,32 @@ func EnsureAliasesUnique(ctx context.Context, id int, aliases []string, qb model
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateCreate(ctx context.Context, studio models.Studio, qb models.StudioQueryer) error {
|
||||
if err := validateName(ctx, 0, studio.Name, qb); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if studio.Aliases.Loaded() && len(studio.Aliases.List()) > 0 {
|
||||
if err := EnsureAliasesUnique(ctx, 0, studio.Aliases.List(), qb); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateName(ctx context.Context, studioID int, name string, qb models.StudioQueryer) error {
|
||||
if name == "" {
|
||||
return ErrNameMissing
|
||||
}
|
||||
|
||||
if err := EnsureStudioNameUnique(ctx, studioID, name, qb); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ValidateModifyReader interface {
|
||||
models.StudioGetter
|
||||
models.StudioQueryer
|
||||
@@ -110,7 +137,7 @@ 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 {
|
||||
if err := validateName(ctx, s.ID, s.Name.Value, qb); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
104
pkg/studio/validate_test.go
Normal file
104
pkg/studio/validate_test.go
Normal file
@@ -0,0 +1,104 @@
|
||||
package studio
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/models/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
func nameFilter(n string) *models.StudioFilterType {
|
||||
return &models.StudioFilterType{
|
||||
Name: &models.StringCriterionInput{
|
||||
Value: n,
|
||||
Modifier: models.CriterionModifierEquals,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateName(t *testing.T) {
|
||||
db := mocks.NewDatabase()
|
||||
|
||||
const (
|
||||
name1 = "name 1"
|
||||
newName = "new name"
|
||||
)
|
||||
|
||||
existing1 := models.Studio{
|
||||
ID: 1,
|
||||
Name: name1,
|
||||
}
|
||||
|
||||
pp := 1
|
||||
findFilter := &models.FindFilterType{
|
||||
PerPage: &pp,
|
||||
}
|
||||
|
||||
db.Studio.On("Query", testCtx, nameFilter(name1), findFilter).Return([]*models.Studio{&existing1}, 1, nil)
|
||||
db.Studio.On("Query", testCtx, mock.Anything, findFilter).Return(nil, 0, nil)
|
||||
|
||||
tests := []struct {
|
||||
tName string
|
||||
name string
|
||||
want error
|
||||
}{
|
||||
{"missing name", "", ErrNameMissing},
|
||||
{"new name", newName, nil},
|
||||
{"existing name", name1, &NameExistsError{name1}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.tName, func(t *testing.T) {
|
||||
got := validateName(testCtx, 0, tt.name, db.Studio)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateUpdateName(t *testing.T) {
|
||||
db := mocks.NewDatabase()
|
||||
|
||||
const (
|
||||
name1 = "name 1"
|
||||
name2 = "name 2"
|
||||
newName = "new name"
|
||||
)
|
||||
|
||||
existing1 := models.Studio{
|
||||
ID: 1,
|
||||
Name: name1,
|
||||
}
|
||||
existing2 := models.Studio{
|
||||
ID: 2,
|
||||
Name: name2,
|
||||
}
|
||||
|
||||
pp := 1
|
||||
findFilter := &models.FindFilterType{
|
||||
PerPage: &pp,
|
||||
}
|
||||
|
||||
db.Studio.On("Query", testCtx, nameFilter(name1), findFilter).Return([]*models.Studio{&existing1}, 1, nil)
|
||||
db.Studio.On("Query", testCtx, nameFilter(name2), findFilter).Return([]*models.Studio{&existing2}, 2, nil)
|
||||
db.Studio.On("Query", testCtx, mock.Anything, findFilter).Return(nil, 0, nil)
|
||||
|
||||
tests := []struct {
|
||||
tName string
|
||||
studio models.Studio
|
||||
name string
|
||||
want error
|
||||
}{
|
||||
{"missing name", existing1, "", ErrNameMissing},
|
||||
{"same name", existing2, name2, nil},
|
||||
{"new name", existing1, newName, nil},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.tName, func(t *testing.T) {
|
||||
got := validateName(testCtx, tt.studio.ID, tt.name, db.Studio)
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -491,7 +491,6 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
|
||||
if (!player) return;
|
||||
|
||||
function onplay(this: VideoJsPlayer) {
|
||||
this.persistVolume().enabled = true;
|
||||
if (scene.interactive && interactiveReady.current) {
|
||||
interactiveClient.play(this.currentTime());
|
||||
}
|
||||
@@ -767,13 +766,7 @@ export const ScenePlayer: React.FC<IScenePlayerProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
player.play()?.catch(() => {
|
||||
// Browser probably blocking non-muted autoplay, so mute and try again
|
||||
player.persistVolume().enabled = false;
|
||||
player.muted(true);
|
||||
|
||||
player.play();
|
||||
});
|
||||
player.play();
|
||||
auto.current = false;
|
||||
}, [getPlayer, scene, ready, interactiveClient, currentScript]);
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
* Added support for setting plugins path from the UI. ([#4382](https://github.com/stashapp/stash/pull/4382))
|
||||
|
||||
### 🐛 Bug fixes
|
||||
* **[0.24.3]** Fixed error when editing case of existing studio name. ([#4447](https://github.com/stashapp/stash/pull/4447))
|
||||
* **[0.24.3]** Fixed videos muting after auto-play fails. ([#4450](https://github.com/stashapp/stash/pull/4450))
|
||||
* **[0.24.2]** Fixed error when renaming marker files during scene merge operation ([#4446](https://github.com/stashapp/stash/pull/4446))
|
||||
* **[0.24.2]** Fixed error when creating/updating a Performer where an alias is the same as the Performer name. ([#4443](https://github.com/stashapp/stash/pull/4443))
|
||||
* **[0.24.2]** Errors during the tagger Scrape All operation now output to the scene card and no longer stop the operation. ([#4442](https://github.com/stashapp/stash/pull/4442))
|
||||
|
||||
Reference in New Issue
Block a user