Folder create/rename/delete/move, photo move, heap convert, and file rename now reject paths outside the caller's BasePath (403). Sources resolved via PhotoPrism UIDs are re-checked in movePhotoFiles. The USER_BASEPATHS reconciler also sets upload_path so client-app uploads land inside the user's subtree. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
51 lines
1.6 KiB
Go
51 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"net/http/httptest"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func scopeCtx(basePath string) *gin.Context {
|
|
gin.SetMode(gin.TestMode)
|
|
c, _ := gin.CreateTestContext(httptest.NewRecorder())
|
|
c.Set("basePath", basePath)
|
|
return c
|
|
}
|
|
|
|
func TestRequireUserScope(t *testing.T) {
|
|
cfg := &Config{OriginalsRoot: filepath.FromSlash("/originals")}
|
|
abs := func(rel string) string { return filepath.Join(cfg.OriginalsRoot, filepath.FromSlash(rel)) }
|
|
|
|
cases := []struct {
|
|
name string
|
|
basePath string
|
|
path string
|
|
strict bool
|
|
want bool
|
|
}{
|
|
{"admin sees root", "", cfg.OriginalsRoot, false, true},
|
|
{"admin anywhere", "", abs("bob/x"), false, true},
|
|
{"admin strict rejects root", "", cfg.OriginalsRoot, true, false},
|
|
{"scoped inside own tree", "alice", abs("alice/2024"), false, true},
|
|
{"scoped own root non-strict", "alice", abs("alice"), false, true},
|
|
{"scoped own root strict", "alice", abs("alice"), true, false},
|
|
{"scoped other user", "alice", abs("bob/2024"), false, false},
|
|
{"scoped sibling prefix", "alice", abs("alice2/2024"), false, false},
|
|
{"scoped originals root", "alice", cfg.OriginalsRoot, false, false},
|
|
{"nested base path", "family/alice", abs("family/alice/x"), false, true},
|
|
{"nested base path parent", "family/alice", abs("family"), false, false},
|
|
}
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
c := scopeCtx(tc.basePath)
|
|
if got := requireUserScope(c, cfg, tc.path, tc.strict); got != tc.want {
|
|
t.Errorf("requireUserScope(base=%q, path=%q, strict=%v) = %v, want %v",
|
|
tc.basePath, tc.path, tc.strict, got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|