feat(fm): source-identity preconditions on move/copy/rename (#3565)
Move/copy/rename resolve sources by path; a delayed retried request can act on a different file that reused the path. The services now accept an optional expected-source hashid (expect_id / expect_ids, positional, empty entry skips) which is compared against the resolved file's database ID before mutation — mismatch fails with fs.ErrModified (409). The web app sends the selected files' IDs on every rename and move/copy. WebDAV and API callers omitting the field are unaffected.pull/3582/head
parent
5811af4503
commit
6928fd571a
@ -0,0 +1,28 @@
|
|||||||
|
package dbfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSourceIDMismatch(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
// No expectations -> never mismatches.
|
||||||
|
require.False(t, sourceIDMismatch(ctx, 0, 42))
|
||||||
|
require.False(t, sourceIDMismatch(ctx, 5, 42))
|
||||||
|
|
||||||
|
ctx = WithExpectedSourceIDs(ctx, []int{11, 0, 33})
|
||||||
|
|
||||||
|
// Matching positions pass.
|
||||||
|
require.False(t, sourceIDMismatch(ctx, 0, 11))
|
||||||
|
// Zero entries disable the check for that position.
|
||||||
|
require.False(t, sourceIDMismatch(ctx, 1, 999))
|
||||||
|
// Positions beyond the expectation list pass.
|
||||||
|
require.False(t, sourceIDMismatch(ctx, 3, 999))
|
||||||
|
// Mismatches are caught per position.
|
||||||
|
require.True(t, sourceIDMismatch(ctx, 0, 12))
|
||||||
|
require.True(t, sourceIDMismatch(ctx, 2, 34))
|
||||||
|
}
|
||||||
Loading…
Reference in new issue