node build fixed
This commit is contained in:
412
seanime-2.9.10/internal/plugin/system_test.go
Normal file
412
seanime-2.9.10/internal/plugin/system_test.go
Normal file
@@ -0,0 +1,412 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"seanime/internal/extension"
|
||||
"testing"
|
||||
|
||||
"github.com/samber/mo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// Mock AppContextImpl for testing
|
||||
type mockAppContext struct {
|
||||
AppContextImpl
|
||||
mockPaths map[string][]string
|
||||
}
|
||||
|
||||
// Create a new mock context with initialized fields
|
||||
func newMockAppContext(paths map[string][]string) *mockAppContext {
|
||||
ctx := &mockAppContext{
|
||||
mockPaths: paths,
|
||||
}
|
||||
// Initialize the animeLibraryPaths field with mock data
|
||||
if libraryPaths, ok := paths["SEANIME_ANIME_LIBRARY"]; ok {
|
||||
ctx.animeLibraryPaths = mo.Some(libraryPaths)
|
||||
} else {
|
||||
ctx.animeLibraryPaths = mo.Some([]string{})
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func TestIsAllowedPath(t *testing.T) {
|
||||
// Create mock context with predefined paths
|
||||
mockCtx := newMockAppContext(map[string][]string{
|
||||
"SEANIME_ANIME_LIBRARY": {"/anime/lib1", "/anime/lib2"},
|
||||
"HOME": {"/home/user"},
|
||||
"TEMP": {"/tmp"},
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
ext *extension.Extension
|
||||
path string
|
||||
mode int
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "nil extension",
|
||||
ext: nil,
|
||||
path: "/some/path",
|
||||
mode: AllowPathRead,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "no patterns",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
path: "/some/path",
|
||||
mode: AllowPathRead,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "simple path match",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
ReadPaths: []string{"/test/*.txt"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
path: "/test/file.txt",
|
||||
mode: AllowPathRead,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "multiple library paths - first match",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
ReadPaths: []string{"$SEANIME_ANIME_LIBRARY/**"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
path: "/anime/lib1/file.txt",
|
||||
mode: AllowPathRead,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "multiple library paths - second match",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
ReadPaths: []string{"$SEANIME_ANIME_LIBRARY/**"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
path: "/anime/lib2/file.txt",
|
||||
mode: AllowPathRead,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "write mode with read pattern",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
path: "/test/file.txt",
|
||||
mode: AllowPathWrite,
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "multiple patterns - match one",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
ReadPaths: []string{"$SEANIME_ANIME_LIBRARY/**"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
path: "/anime/lib1/file.txt",
|
||||
mode: AllowPathRead,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "no matching pattern",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
ReadPaths: []string{"$SEANIME_ANIME_LIBRARY/**"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
path: "/anime/lib1/file.txt",
|
||||
mode: AllowPathRead,
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := mockCtx.isAllowedPath(tt.ext, tt.path, tt.mode)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsAllowedCommand(t *testing.T) {
|
||||
// Create mock context
|
||||
mockCtx := newMockAppContext(map[string][]string{
|
||||
"HOME": {"/home/user"},
|
||||
"SEANIME_ANIME_LIBRARY": {}, // Empty but initialized
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
ext *extension.Extension
|
||||
cmd string
|
||||
args []string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "nil extension",
|
||||
ext: nil,
|
||||
cmd: "ls",
|
||||
args: []string{"-l"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "simple command no args",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
CommandScopes: []extension.CommandScope{
|
||||
{
|
||||
Command: "ls",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmd: "ls",
|
||||
args: []string{},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "command with fixed args - match",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
CommandScopes: []extension.CommandScope{
|
||||
{
|
||||
Command: "git",
|
||||
Args: []extension.CommandArg{
|
||||
{Value: "pull"},
|
||||
{Value: "origin"},
|
||||
{Value: "main"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmd: "git",
|
||||
args: []string{"pull", "origin", "main"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "command with fixed args - no match",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
CommandScopes: []extension.CommandScope{
|
||||
{
|
||||
Command: "git",
|
||||
Args: []extension.CommandArg{
|
||||
{Value: "pull"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmd: "git",
|
||||
args: []string{"push"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "command with $ARGS validator",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
CommandScopes: []extension.CommandScope{
|
||||
{
|
||||
Command: "echo",
|
||||
Args: []extension.CommandArg{
|
||||
{Validator: "$ARGS"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmd: "echo",
|
||||
args: []string{"hello", "world"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "command with regex validator - match",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
CommandScopes: []extension.CommandScope{
|
||||
{
|
||||
Command: "open",
|
||||
Args: []extension.CommandArg{
|
||||
{Validator: "^https?://.*$"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmd: "open",
|
||||
args: []string{"https://example.com"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "command with regex validator - no match",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
CommandScopes: []extension.CommandScope{
|
||||
{
|
||||
Command: "open",
|
||||
Args: []extension.CommandArg{
|
||||
{Validator: "^https?://.*$"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmd: "open",
|
||||
args: []string{"file://example.com"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "command with $PATH validator",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
CommandScopes: []extension.CommandScope{
|
||||
{
|
||||
Command: "open",
|
||||
Args: []extension.CommandArg{
|
||||
{Validator: "$PATH"},
|
||||
},
|
||||
},
|
||||
},
|
||||
WritePaths: []string{"$SEANIME_ANIME_LIBRARY/**"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmd: "open",
|
||||
args: []string{"/anime/lib1/test.txt"},
|
||||
expected: false, // Directory does not exist on the machine
|
||||
},
|
||||
{
|
||||
name: "too many args",
|
||||
ext: &extension.Extension{
|
||||
Plugin: &extension.PluginManifest{
|
||||
Permissions: extension.PluginPermissions{
|
||||
Scopes: []extension.PluginPermissionScope{
|
||||
extension.PluginPermissionSystem,
|
||||
},
|
||||
Allow: extension.PluginAllowlist{
|
||||
CommandScopes: []extension.CommandScope{
|
||||
{
|
||||
Command: "ls",
|
||||
Args: []extension.CommandArg{
|
||||
{Value: "-l"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
cmd: "ls",
|
||||
args: []string{"-l", "-a"},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
result := mockCtx.isAllowedCommand(tt.ext, tt.cmd, tt.args...)
|
||||
assert.Equal(t, tt.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user