Revalidate existing share links against the owner's current status and group permissions. Reject redirected direct links when the owner's current group disables direct links. Refresh restored share navigator state before serving cached paths. Prevent client-side redirect caching and add regression coverage for restricted owners. Co-authored-by: Codex <codex@openai.com>pull/3524/head
parent
cec2b55e1e
commit
e18785a9ca
@ -0,0 +1,44 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
entuser "github.com/cloudreve/Cloudreve/v4/ent/user"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
||||
"github.com/cloudreve/Cloudreve/v4/pkg/boolset"
|
||||
)
|
||||
|
||||
func TestIsValidShareChecksCurrentOwnerAccess(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
status entuser.Status
|
||||
canShare bool
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "active owner with share permission", status: entuser.StatusActive, canShare: true},
|
||||
{name: "active owner without share permission", status: entuser.StatusActive, wantErr: true},
|
||||
{name: "manually banned owner", status: entuser.StatusManualBanned, canShare: true, wantErr: true},
|
||||
{name: "system banned owner", status: entuser.StatusSysBanned, canShare: true, wantErr: true},
|
||||
{name: "inactive owner", status: entuser.StatusInactive, canShare: true, wantErr: true},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
permissions := &boolset.BooleanSet{}
|
||||
boolset.Set(types.GroupPermissionShare, tt.canShare, permissions)
|
||||
group := &ent.Group{Permissions: permissions}
|
||||
owner := &ent.User{ID: 1, Status: tt.status}
|
||||
owner.SetGroup(group)
|
||||
file := &ent.File{OwnerID: owner.ID, FileChildren: 1}
|
||||
share := &ent.Share{}
|
||||
share.SetUser(owner)
|
||||
share.SetFile(file)
|
||||
|
||||
err := IsValidShare(share)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Fatalf("IsValidShare() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
package dbfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/cloudreve/Cloudreve/v4/ent"
|
||||
entuser "github.com/cloudreve/Cloudreve/v4/ent/user"
|
||||
"github.com/cloudreve/Cloudreve/v4/inventory/types"
|
||||
)
|
||||
|
||||
func TestGetFileFromDirectLinkRejectsRestrictedOwner(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
status entuser.Status
|
||||
batchSize int
|
||||
}{
|
||||
{name: "active owner without direct link permission", status: entuser.StatusActive},
|
||||
{name: "manually banned owner", status: entuser.StatusManualBanned, batchSize: 1},
|
||||
{name: "system banned owner", status: entuser.StatusSysBanned, batchSize: 1},
|
||||
{name: "inactive owner", status: entuser.StatusInactive, batchSize: 1},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
owner := &ent.User{Status: tt.status}
|
||||
owner.SetGroup(&ent.Group{Settings: &types.GroupSetting{SourceBatchSize: tt.batchSize}})
|
||||
file := &ent.File{}
|
||||
file.SetOwner(owner)
|
||||
link := &ent.DirectLink{}
|
||||
link.SetFile(file)
|
||||
|
||||
if _, err := (&DBFS{}).GetFileFromDirectLink(context.Background(), link); err == nil {
|
||||
t.Fatal("GetFileFromDirectLink() error = nil, want restricted owner to be rejected")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue