mirror of
https://github.com/stashapp/stash.git
synced 2025-12-16 20:07:05 +03:00
Improve plugin hook cyclic detection (#4625)
* Move and rename HookTriggerEnum into separate package * Move visited plugin hook handler code * Allow up to ten plugin hook loops
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/stashapp/stash/pkg/logger"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/plugin"
|
||||
"github.com/stashapp/stash/pkg/plugin/hook"
|
||||
)
|
||||
|
||||
type ScanCreatorUpdater interface {
|
||||
@@ -83,7 +84,7 @@ func (h *ScanHandler) Handle(ctx context.Context, f models.File, oldFile models.
|
||||
return fmt.Errorf("creating new gallery: %w", err)
|
||||
}
|
||||
|
||||
h.PluginCache.RegisterPostHooks(ctx, newGallery.ID, plugin.GalleryCreatePost, nil, nil)
|
||||
h.PluginCache.RegisterPostHooks(ctx, newGallery.ID, hook.GalleryCreatePost, nil, nil)
|
||||
|
||||
// associate all the images in the zip file with the gallery
|
||||
for _, i := range images {
|
||||
@@ -138,7 +139,7 @@ func (h *ScanHandler) associateExisting(ctx context.Context, existing []*models.
|
||||
}
|
||||
|
||||
if !found || updateExisting {
|
||||
h.PluginCache.RegisterPostHooks(ctx, i.ID, plugin.GalleryUpdatePost, nil, nil)
|
||||
h.PluginCache.RegisterPostHooks(ctx, i.ID, hook.GalleryUpdatePost, nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/models/paths"
|
||||
"github.com/stashapp/stash/pkg/plugin"
|
||||
"github.com/stashapp/stash/pkg/plugin/hook"
|
||||
"github.com/stashapp/stash/pkg/sliceutil"
|
||||
"github.com/stashapp/stash/pkg/txn"
|
||||
)
|
||||
@@ -137,7 +138,7 @@ func (h *ScanHandler) Handle(ctx context.Context, f models.File, oldFile models.
|
||||
}
|
||||
}
|
||||
|
||||
h.PluginCache.RegisterPostHooks(ctx, newImage.ID, plugin.ImageCreatePost, nil, nil)
|
||||
h.PluginCache.RegisterPostHooks(ctx, newImage.ID, hook.ImageCreatePost, nil, nil)
|
||||
|
||||
existing = []*models.Image{&newImage}
|
||||
}
|
||||
@@ -228,7 +229,7 @@ func (h *ScanHandler) associateExisting(ctx context.Context, existing []*models.
|
||||
}
|
||||
|
||||
if changed || updateExisting {
|
||||
h.PluginCache.RegisterPostHooks(ctx, i.ID, plugin.ImageUpdatePost, nil, nil)
|
||||
h.PluginCache.RegisterPostHooks(ctx, i.ID, hook.ImageUpdatePost, nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +258,7 @@ func (h *ScanHandler) getOrCreateFolderBasedGallery(ctx context.Context, f model
|
||||
return nil, fmt.Errorf("creating folder based gallery: %w", err)
|
||||
}
|
||||
|
||||
h.PluginCache.RegisterPostHooks(ctx, newGallery.ID, plugin.GalleryCreatePost, nil, nil)
|
||||
h.PluginCache.RegisterPostHooks(ctx, newGallery.ID, hook.GalleryCreatePost, nil, nil)
|
||||
|
||||
// it's possible that there are other images in the folder that
|
||||
// need to be added to the new gallery. Find and add them now.
|
||||
@@ -311,7 +312,7 @@ func (h *ScanHandler) getOrCreateZipBasedGallery(ctx context.Context, zipFile mo
|
||||
return nil, fmt.Errorf("creating zip-based gallery: %w", err)
|
||||
}
|
||||
|
||||
h.PluginCache.RegisterPostHooks(ctx, newGallery.ID, plugin.GalleryCreatePost, nil, nil)
|
||||
h.PluginCache.RegisterPostHooks(ctx, newGallery.ID, hook.GalleryCreatePost, nil, nil)
|
||||
|
||||
return &newGallery, nil
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/stashapp/stash/pkg/plugin/hook"
|
||||
"github.com/stashapp/stash/pkg/utils"
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
@@ -195,7 +196,7 @@ func (c Config) getPluginHooks(includePlugin bool) []*PluginHook {
|
||||
return ret
|
||||
}
|
||||
|
||||
func convertHooks(hooks []HookTriggerEnum) []string {
|
||||
func convertHooks(hooks []hook.TriggerEnum) []string {
|
||||
var ret []string
|
||||
for _, h := range hooks {
|
||||
ret = append(ret, h.String())
|
||||
@@ -275,7 +276,7 @@ func (c Config) getTask(name string) *OperationConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Config) getHooks(hookType HookTriggerEnum) []*HookConfig {
|
||||
func (c Config) getHooks(hookType hook.TriggerEnum) []*HookConfig {
|
||||
var ret []*HookConfig
|
||||
for _, h := range c.Hooks {
|
||||
for _, t := range h.TriggeredBy {
|
||||
@@ -399,7 +400,7 @@ type HookConfig struct {
|
||||
OperationConfig `yaml:",inline"`
|
||||
|
||||
// A list of stash operations that will be used to trigger this hook operation.
|
||||
TriggeredBy []HookTriggerEnum `yaml:"triggeredBy"`
|
||||
TriggeredBy []hook.TriggerEnum `yaml:"triggeredBy"`
|
||||
}
|
||||
|
||||
func loadPluginFromYAML(reader io.Reader) (*Config, error) {
|
||||
|
||||
131
pkg/plugin/hook/hooks.go
Normal file
131
pkg/plugin/hook/hooks.go
Normal file
@@ -0,0 +1,131 @@
|
||||
package hook
|
||||
|
||||
type TriggerEnum string
|
||||
|
||||
// Scan-related hooks are current disabled until post-hook execution is
|
||||
// integrated.
|
||||
|
||||
const (
|
||||
SceneMarkerCreatePost TriggerEnum = "SceneMarker.Create.Post"
|
||||
SceneMarkerUpdatePost TriggerEnum = "SceneMarker.Update.Post"
|
||||
SceneMarkerDestroyPost TriggerEnum = "SceneMarker.Destroy.Post"
|
||||
|
||||
SceneCreatePost TriggerEnum = "Scene.Create.Post"
|
||||
SceneUpdatePost TriggerEnum = "Scene.Update.Post"
|
||||
SceneDestroyPost TriggerEnum = "Scene.Destroy.Post"
|
||||
|
||||
ImageCreatePost TriggerEnum = "Image.Create.Post"
|
||||
ImageUpdatePost TriggerEnum = "Image.Update.Post"
|
||||
ImageDestroyPost TriggerEnum = "Image.Destroy.Post"
|
||||
|
||||
GalleryCreatePost TriggerEnum = "Gallery.Create.Post"
|
||||
GalleryUpdatePost TriggerEnum = "Gallery.Update.Post"
|
||||
GalleryDestroyPost TriggerEnum = "Gallery.Destroy.Post"
|
||||
|
||||
GalleryChapterCreatePost TriggerEnum = "GalleryChapter.Create.Post"
|
||||
GalleryChapterUpdatePost TriggerEnum = "GalleryChapter.Update.Post"
|
||||
GalleryChapterDestroyPost TriggerEnum = "GalleryChapter.Destroy.Post"
|
||||
|
||||
MovieCreatePost TriggerEnum = "Movie.Create.Post"
|
||||
MovieUpdatePost TriggerEnum = "Movie.Update.Post"
|
||||
MovieDestroyPost TriggerEnum = "Movie.Destroy.Post"
|
||||
|
||||
PerformerCreatePost TriggerEnum = "Performer.Create.Post"
|
||||
PerformerUpdatePost TriggerEnum = "Performer.Update.Post"
|
||||
PerformerDestroyPost TriggerEnum = "Performer.Destroy.Post"
|
||||
|
||||
StudioCreatePost TriggerEnum = "Studio.Create.Post"
|
||||
StudioUpdatePost TriggerEnum = "Studio.Update.Post"
|
||||
StudioDestroyPost TriggerEnum = "Studio.Destroy.Post"
|
||||
|
||||
TagCreatePost TriggerEnum = "Tag.Create.Post"
|
||||
TagUpdatePost TriggerEnum = "Tag.Update.Post"
|
||||
TagMergePost TriggerEnum = "Tag.Merge.Post"
|
||||
TagDestroyPost TriggerEnum = "Tag.Destroy.Post"
|
||||
)
|
||||
|
||||
var AllHookTriggerEnum = []TriggerEnum{
|
||||
SceneMarkerCreatePost,
|
||||
SceneMarkerUpdatePost,
|
||||
SceneMarkerDestroyPost,
|
||||
|
||||
SceneCreatePost,
|
||||
SceneUpdatePost,
|
||||
SceneDestroyPost,
|
||||
|
||||
ImageCreatePost,
|
||||
ImageUpdatePost,
|
||||
ImageDestroyPost,
|
||||
|
||||
GalleryCreatePost,
|
||||
GalleryUpdatePost,
|
||||
GalleryDestroyPost,
|
||||
|
||||
GalleryChapterCreatePost,
|
||||
GalleryChapterUpdatePost,
|
||||
GalleryChapterDestroyPost,
|
||||
|
||||
MovieCreatePost,
|
||||
MovieUpdatePost,
|
||||
MovieDestroyPost,
|
||||
|
||||
PerformerCreatePost,
|
||||
PerformerUpdatePost,
|
||||
PerformerDestroyPost,
|
||||
|
||||
StudioCreatePost,
|
||||
StudioUpdatePost,
|
||||
StudioDestroyPost,
|
||||
|
||||
TagCreatePost,
|
||||
TagUpdatePost,
|
||||
TagMergePost,
|
||||
TagDestroyPost,
|
||||
}
|
||||
|
||||
func (e TriggerEnum) IsValid() bool {
|
||||
|
||||
switch e {
|
||||
case SceneMarkerCreatePost,
|
||||
SceneMarkerUpdatePost,
|
||||
SceneMarkerDestroyPost,
|
||||
|
||||
SceneCreatePost,
|
||||
SceneUpdatePost,
|
||||
SceneDestroyPost,
|
||||
|
||||
ImageCreatePost,
|
||||
ImageUpdatePost,
|
||||
ImageDestroyPost,
|
||||
|
||||
GalleryCreatePost,
|
||||
GalleryUpdatePost,
|
||||
GalleryDestroyPost,
|
||||
|
||||
GalleryChapterCreatePost,
|
||||
GalleryChapterUpdatePost,
|
||||
GalleryChapterDestroyPost,
|
||||
|
||||
MovieCreatePost,
|
||||
MovieUpdatePost,
|
||||
MovieDestroyPost,
|
||||
|
||||
PerformerCreatePost,
|
||||
PerformerUpdatePost,
|
||||
PerformerDestroyPost,
|
||||
|
||||
StudioCreatePost,
|
||||
StudioUpdatePost,
|
||||
StudioDestroyPost,
|
||||
|
||||
TagCreatePost,
|
||||
TagUpdatePost,
|
||||
TagDestroyPost:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e TriggerEnum) String() string {
|
||||
return string(e)
|
||||
}
|
||||
@@ -12,136 +12,6 @@ type PluginHook struct {
|
||||
Plugin *Plugin `json:"plugin"`
|
||||
}
|
||||
|
||||
type HookTriggerEnum string
|
||||
|
||||
// Scan-related hooks are current disabled until post-hook execution is
|
||||
// integrated.
|
||||
|
||||
const (
|
||||
SceneMarkerCreatePost HookTriggerEnum = "SceneMarker.Create.Post"
|
||||
SceneMarkerUpdatePost HookTriggerEnum = "SceneMarker.Update.Post"
|
||||
SceneMarkerDestroyPost HookTriggerEnum = "SceneMarker.Destroy.Post"
|
||||
|
||||
SceneCreatePost HookTriggerEnum = "Scene.Create.Post"
|
||||
SceneUpdatePost HookTriggerEnum = "Scene.Update.Post"
|
||||
SceneDestroyPost HookTriggerEnum = "Scene.Destroy.Post"
|
||||
|
||||
ImageCreatePost HookTriggerEnum = "Image.Create.Post"
|
||||
ImageUpdatePost HookTriggerEnum = "Image.Update.Post"
|
||||
ImageDestroyPost HookTriggerEnum = "Image.Destroy.Post"
|
||||
|
||||
GalleryCreatePost HookTriggerEnum = "Gallery.Create.Post"
|
||||
GalleryUpdatePost HookTriggerEnum = "Gallery.Update.Post"
|
||||
GalleryDestroyPost HookTriggerEnum = "Gallery.Destroy.Post"
|
||||
|
||||
GalleryChapterCreatePost HookTriggerEnum = "GalleryChapter.Create.Post"
|
||||
GalleryChapterUpdatePost HookTriggerEnum = "GalleryChapter.Update.Post"
|
||||
GalleryChapterDestroyPost HookTriggerEnum = "GalleryChapter.Destroy.Post"
|
||||
|
||||
MovieCreatePost HookTriggerEnum = "Movie.Create.Post"
|
||||
MovieUpdatePost HookTriggerEnum = "Movie.Update.Post"
|
||||
MovieDestroyPost HookTriggerEnum = "Movie.Destroy.Post"
|
||||
|
||||
PerformerCreatePost HookTriggerEnum = "Performer.Create.Post"
|
||||
PerformerUpdatePost HookTriggerEnum = "Performer.Update.Post"
|
||||
PerformerDestroyPost HookTriggerEnum = "Performer.Destroy.Post"
|
||||
|
||||
StudioCreatePost HookTriggerEnum = "Studio.Create.Post"
|
||||
StudioUpdatePost HookTriggerEnum = "Studio.Update.Post"
|
||||
StudioDestroyPost HookTriggerEnum = "Studio.Destroy.Post"
|
||||
|
||||
TagCreatePost HookTriggerEnum = "Tag.Create.Post"
|
||||
TagUpdatePost HookTriggerEnum = "Tag.Update.Post"
|
||||
TagMergePost HookTriggerEnum = "Tag.Merge.Post"
|
||||
TagDestroyPost HookTriggerEnum = "Tag.Destroy.Post"
|
||||
)
|
||||
|
||||
var AllHookTriggerEnum = []HookTriggerEnum{
|
||||
SceneMarkerCreatePost,
|
||||
SceneMarkerUpdatePost,
|
||||
SceneMarkerDestroyPost,
|
||||
|
||||
SceneCreatePost,
|
||||
SceneUpdatePost,
|
||||
SceneDestroyPost,
|
||||
|
||||
ImageCreatePost,
|
||||
ImageUpdatePost,
|
||||
ImageDestroyPost,
|
||||
|
||||
GalleryCreatePost,
|
||||
GalleryUpdatePost,
|
||||
GalleryDestroyPost,
|
||||
|
||||
GalleryChapterCreatePost,
|
||||
GalleryChapterUpdatePost,
|
||||
GalleryChapterDestroyPost,
|
||||
|
||||
MovieCreatePost,
|
||||
MovieUpdatePost,
|
||||
MovieDestroyPost,
|
||||
|
||||
PerformerCreatePost,
|
||||
PerformerUpdatePost,
|
||||
PerformerDestroyPost,
|
||||
|
||||
StudioCreatePost,
|
||||
StudioUpdatePost,
|
||||
StudioDestroyPost,
|
||||
|
||||
TagCreatePost,
|
||||
TagUpdatePost,
|
||||
TagMergePost,
|
||||
TagDestroyPost,
|
||||
}
|
||||
|
||||
func (e HookTriggerEnum) IsValid() bool {
|
||||
|
||||
switch e {
|
||||
case SceneMarkerCreatePost,
|
||||
SceneMarkerUpdatePost,
|
||||
SceneMarkerDestroyPost,
|
||||
|
||||
SceneCreatePost,
|
||||
SceneUpdatePost,
|
||||
SceneDestroyPost,
|
||||
|
||||
ImageCreatePost,
|
||||
ImageUpdatePost,
|
||||
ImageDestroyPost,
|
||||
|
||||
GalleryCreatePost,
|
||||
GalleryUpdatePost,
|
||||
GalleryDestroyPost,
|
||||
|
||||
GalleryChapterCreatePost,
|
||||
GalleryChapterUpdatePost,
|
||||
GalleryChapterDestroyPost,
|
||||
|
||||
MovieCreatePost,
|
||||
MovieUpdatePost,
|
||||
MovieDestroyPost,
|
||||
|
||||
PerformerCreatePost,
|
||||
PerformerUpdatePost,
|
||||
PerformerDestroyPost,
|
||||
|
||||
StudioCreatePost,
|
||||
StudioUpdatePost,
|
||||
StudioDestroyPost,
|
||||
|
||||
TagCreatePost,
|
||||
TagUpdatePost,
|
||||
TagDestroyPost:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e HookTriggerEnum) String() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
func addHookContext(argsMap common.ArgsMap, hookContext common.HookContext) {
|
||||
argsMap[common.HookContextKey] = hookContext
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"github.com/stashapp/stash/pkg/logger"
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/plugin/common"
|
||||
"github.com/stashapp/stash/pkg/plugin/hook"
|
||||
"github.com/stashapp/stash/pkg/session"
|
||||
"github.com/stashapp/stash/pkg/sliceutil"
|
||||
"github.com/stashapp/stash/pkg/txn"
|
||||
@@ -356,7 +357,7 @@ func waitForTask(ctx context.Context, task Task) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c Cache) ExecutePostHooks(ctx context.Context, id int, hookType HookTriggerEnum, input interface{}, inputFields []string) {
|
||||
func (c Cache) ExecutePostHooks(ctx context.Context, id int, hookType hook.TriggerEnum, input interface{}, inputFields []string) {
|
||||
if err := c.executePostHooks(ctx, hookType, common.HookContext{
|
||||
ID: id,
|
||||
Type: hookType.String(),
|
||||
@@ -367,7 +368,7 @@ func (c Cache) ExecutePostHooks(ctx context.Context, id int, hookType HookTrigge
|
||||
}
|
||||
}
|
||||
|
||||
func (c Cache) RegisterPostHooks(ctx context.Context, id int, hookType HookTriggerEnum, input interface{}, inputFields []string) {
|
||||
func (c Cache) RegisterPostHooks(ctx context.Context, id int, hookType hook.TriggerEnum, input interface{}, inputFields []string) {
|
||||
txn.AddPostCommitHook(ctx, func(ctx context.Context) {
|
||||
c.ExecutePostHooks(ctx, id, hookType, input, inputFields)
|
||||
})
|
||||
@@ -379,23 +380,28 @@ func (c Cache) ExecuteSceneUpdatePostHooks(ctx context.Context, input models.Sce
|
||||
logger.Errorf("error converting id in SceneUpdatePostHooks: %v", err)
|
||||
return
|
||||
}
|
||||
c.ExecutePostHooks(ctx, id, SceneUpdatePost, input, inputFields)
|
||||
c.ExecutePostHooks(ctx, id, hook.SceneUpdatePost, input, inputFields)
|
||||
}
|
||||
|
||||
func (c Cache) executePostHooks(ctx context.Context, hookType HookTriggerEnum, hookContext common.HookContext) error {
|
||||
visitedPlugins := session.GetVisitedPlugins(ctx)
|
||||
// maxCyclicLoopDepth is the maximum number of identical plugin hook calls that
|
||||
// can be made before a cyclic loop is detected. It is set to an arbitrary value
|
||||
// that should not be hit under normal circumstances.
|
||||
const maxCyclicLoopDepth = 10
|
||||
|
||||
func (c Cache) executePostHooks(ctx context.Context, hookType hook.TriggerEnum, hookContext common.HookContext) error {
|
||||
visitedPluginHookCounts := getVisitedPluginHookCounts(ctx)
|
||||
|
||||
for _, p := range c.enabledPlugins() {
|
||||
hooks := p.getHooks(hookType)
|
||||
// don't revisit a plugin we've already visited
|
||||
// only log if there's hooks that we're skipping
|
||||
if len(hooks) > 0 && sliceutil.Contains(visitedPlugins, p.id) {
|
||||
logger.Debugf("plugin ID '%s' already triggered, not re-triggering", p.id)
|
||||
if len(hooks) > 0 && visitedPluginHookCounts.For(p.id, hookType) >= maxCyclicLoopDepth {
|
||||
logger.Debugf("cyclic loop detected: plugin ID '%s' hook %s, not re-triggering", p.id, hookType)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, h := range hooks {
|
||||
newCtx := session.AddVisitedPlugin(ctx, p.id)
|
||||
newCtx := session.AddVisitedPluginHook(ctx, p.id, hookType)
|
||||
serverConnection := c.makeServerConnection(newCtx)
|
||||
|
||||
pluginInput := buildPluginInput(&p, &h.OperationConfig, serverConnection, nil)
|
||||
@@ -434,6 +440,46 @@ func (c Cache) executePostHooks(ctx context.Context, hookType HookTriggerEnum, h
|
||||
return nil
|
||||
}
|
||||
|
||||
type visitedPluginHookCount struct {
|
||||
session.VisitedPluginHook
|
||||
Count int
|
||||
}
|
||||
|
||||
type visitedPluginHookCounts []visitedPluginHookCount
|
||||
|
||||
func (v visitedPluginHookCounts) For(pluginID string, hookType hook.TriggerEnum) int {
|
||||
for _, c := range v {
|
||||
if c.VisitedPluginHook.PluginID == pluginID && c.VisitedPluginHook.HookType == hookType {
|
||||
return c.Count
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func getVisitedPluginHookCounts(ctx context.Context) visitedPluginHookCounts {
|
||||
visitedPluginHooks := session.GetVisitedPluginHooks(ctx)
|
||||
|
||||
visitedPluginHookCounts := make([]visitedPluginHookCount, 0)
|
||||
for _, p := range visitedPluginHooks {
|
||||
found := false
|
||||
for i, v := range visitedPluginHookCounts {
|
||||
if v.VisitedPluginHook == p {
|
||||
visitedPluginHookCounts[i].Count++
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
visitedPluginHookCounts = append(visitedPluginHookCounts, visitedPluginHookCount{
|
||||
VisitedPluginHook: p,
|
||||
Count: 1,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return visitedPluginHookCounts
|
||||
}
|
||||
|
||||
func (c Cache) getPlugin(pluginID string) *Config {
|
||||
for _, s := range c.plugins {
|
||||
if s.id == pluginID {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/plugin"
|
||||
"github.com/stashapp/stash/pkg/plugin/hook"
|
||||
)
|
||||
|
||||
func (s *Service) Create(ctx context.Context, input *models.Scene, fileIDs []models.FileID, coverImage []byte) (*models.Scene, error) {
|
||||
@@ -54,7 +54,7 @@ func (s *Service) Create(ctx context.Context, input *models.Scene, fileIDs []mod
|
||||
}
|
||||
}
|
||||
|
||||
s.PluginCache.RegisterPostHooks(ctx, ret.ID, plugin.SceneCreatePost, nil, nil)
|
||||
s.PluginCache.RegisterPostHooks(ctx, ret.ID, hook.SceneCreatePost, nil, nil)
|
||||
|
||||
// re-find the scene so that it correctly returns file-related fields
|
||||
return ret, nil
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/stashapp/stash/pkg/models"
|
||||
"github.com/stashapp/stash/pkg/models/paths"
|
||||
"github.com/stashapp/stash/pkg/plugin"
|
||||
"github.com/stashapp/stash/pkg/plugin/hook"
|
||||
"github.com/stashapp/stash/pkg/txn"
|
||||
)
|
||||
|
||||
@@ -107,7 +108,7 @@ func (h *ScanHandler) Handle(ctx context.Context, f models.File, oldFile models.
|
||||
return fmt.Errorf("creating new scene: %w", err)
|
||||
}
|
||||
|
||||
h.PluginCache.RegisterPostHooks(ctx, newScene.ID, plugin.SceneCreatePost, nil, nil)
|
||||
h.PluginCache.RegisterPostHooks(ctx, newScene.ID, hook.SceneCreatePost, nil, nil)
|
||||
|
||||
existing = []*models.Scene{&newScene}
|
||||
}
|
||||
@@ -164,7 +165,7 @@ func (h *ScanHandler) associateExisting(ctx context.Context, existing []*models.
|
||||
}
|
||||
|
||||
if !found || updateExisting {
|
||||
h.PluginCache.RegisterPostHooks(ctx, s.ID, plugin.SceneUpdatePost, nil, nil)
|
||||
h.PluginCache.RegisterPostHooks(ctx, s.ID, hook.SceneUpdatePost, nil, nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
82
pkg/session/plugin.go
Normal file
82
pkg/session/plugin.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/gob"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/securecookie"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/stashapp/stash/pkg/logger"
|
||||
"github.com/stashapp/stash/pkg/plugin/hook"
|
||||
)
|
||||
|
||||
type VisitedPluginHook struct {
|
||||
PluginID string
|
||||
HookType hook.TriggerEnum
|
||||
}
|
||||
|
||||
func init() {
|
||||
gob.Register([]VisitedPluginHook{})
|
||||
}
|
||||
|
||||
func (s *Store) VisitedPluginHandler() func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// get the visited plugins from the cookie and set in the context
|
||||
session, err := s.sessionStore.Get(r, cookieName)
|
||||
|
||||
// ignore errors
|
||||
if err == nil {
|
||||
val := session.Values[visitedPluginHooksKey]
|
||||
|
||||
visitedPlugins, _ := val.([]VisitedPluginHook)
|
||||
|
||||
ctx := setVisitedPluginHooks(r.Context(), visitedPlugins)
|
||||
r = r.WithContext(ctx)
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func GetVisitedPluginHooks(ctx context.Context) []VisitedPluginHook {
|
||||
ctxVal := ctx.Value(contextVisitedPlugins)
|
||||
if ctxVal != nil {
|
||||
return ctxVal.([]VisitedPluginHook)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func AddVisitedPluginHook(ctx context.Context, pluginID string, hookType hook.TriggerEnum) context.Context {
|
||||
curVal := GetVisitedPluginHooks(ctx)
|
||||
curVal = append(curVal, VisitedPluginHook{PluginID: pluginID, HookType: hookType})
|
||||
return setVisitedPluginHooks(ctx, curVal)
|
||||
}
|
||||
|
||||
func setVisitedPluginHooks(ctx context.Context, visitedPlugins []VisitedPluginHook) context.Context {
|
||||
return context.WithValue(ctx, contextVisitedPlugins, visitedPlugins)
|
||||
}
|
||||
|
||||
func (s *Store) MakePluginCookie(ctx context.Context) *http.Cookie {
|
||||
currentUser := GetCurrentUserID(ctx)
|
||||
visitedPlugins := GetVisitedPluginHooks(ctx)
|
||||
|
||||
session := sessions.NewSession(s.sessionStore, cookieName)
|
||||
if currentUser != nil {
|
||||
session.Values[userIDKey] = *currentUser
|
||||
}
|
||||
|
||||
session.Values[visitedPluginHooksKey] = visitedPlugins
|
||||
|
||||
encoded, err := securecookie.EncodeMulti(session.Name(), session.Values,
|
||||
s.sessionStore.Codecs...)
|
||||
if err != nil {
|
||||
logger.Errorf("error creating session cookie: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
return sessions.NewCookie(session.Name(), encoded, session.Options)
|
||||
}
|
||||
@@ -5,10 +5,8 @@ import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/securecookie"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/stashapp/stash/pkg/logger"
|
||||
"github.com/stashapp/stash/pkg/sliceutil"
|
||||
)
|
||||
|
||||
type key int
|
||||
@@ -19,8 +17,8 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
userIDKey = "userID"
|
||||
visitedPluginsKey = "visitedPlugins"
|
||||
userIDKey = "userID"
|
||||
visitedPluginHooksKey = "visitedPluginsHooks"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -147,67 +145,6 @@ func GetCurrentUserID(ctx context.Context) *string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) VisitedPluginHandler() func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// get the visited plugins from the cookie and set in the context
|
||||
session, err := s.sessionStore.Get(r, cookieName)
|
||||
|
||||
// ignore errors
|
||||
if err == nil {
|
||||
val := session.Values[visitedPluginsKey]
|
||||
|
||||
visitedPlugins, _ := val.([]string)
|
||||
|
||||
ctx := setVisitedPlugins(r.Context(), visitedPlugins)
|
||||
r = r.WithContext(ctx)
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func GetVisitedPlugins(ctx context.Context) []string {
|
||||
ctxVal := ctx.Value(contextVisitedPlugins)
|
||||
if ctxVal != nil {
|
||||
return ctxVal.([]string)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func AddVisitedPlugin(ctx context.Context, pluginID string) context.Context {
|
||||
curVal := GetVisitedPlugins(ctx)
|
||||
curVal = sliceutil.AppendUnique(curVal, pluginID)
|
||||
return setVisitedPlugins(ctx, curVal)
|
||||
}
|
||||
|
||||
func setVisitedPlugins(ctx context.Context, visitedPlugins []string) context.Context {
|
||||
return context.WithValue(ctx, contextVisitedPlugins, visitedPlugins)
|
||||
}
|
||||
|
||||
func (s *Store) MakePluginCookie(ctx context.Context) *http.Cookie {
|
||||
currentUser := GetCurrentUserID(ctx)
|
||||
visitedPlugins := GetVisitedPlugins(ctx)
|
||||
|
||||
session := sessions.NewSession(s.sessionStore, cookieName)
|
||||
if currentUser != nil {
|
||||
session.Values[userIDKey] = *currentUser
|
||||
}
|
||||
|
||||
session.Values[visitedPluginsKey] = visitedPlugins
|
||||
|
||||
encoded, err := securecookie.EncodeMulti(session.Name(), session.Values,
|
||||
s.sessionStore.Codecs...)
|
||||
if err != nil {
|
||||
logger.Errorf("error creating session cookie: %s", err.Error())
|
||||
return nil
|
||||
}
|
||||
|
||||
return sessions.NewCookie(session.Name(), encoded, session.Options)
|
||||
}
|
||||
|
||||
func (s *Store) Authenticate(w http.ResponseWriter, r *http.Request) (userID string, err error) {
|
||||
c := s.config
|
||||
|
||||
|
||||
Reference in New Issue
Block a user