mirror of
https://github.com/owncloud/ocis
synced 2026-04-25 17:25:21 +02:00
fix(collaboration): [OCISDEV-781] return 200 OK for WOPI Lock in read-only modes
OnlyOffice sends a WOPI Lock request on document open regardless of whether the user has write access. The Lock handler was calling SetLock with a read-only CS3 token, which returned a permission error propagated as HTTP 500 to OnlyOffice, causing an error dialog on load. Return 200 OK immediately for READ_ONLY and VIEW_ONLY view modes without acquiring a CS3 lock. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Julian Koberg <julian.koberg@kiteworks.com>
This commit is contained in:
11
changelog/unreleased/fix-wopi-lock-read-only-view-mode.md
Normal file
11
changelog/unreleased/fix-wopi-lock-read-only-view-mode.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Bugfix: Return 200 OK for WOPI Lock requests in read-only and view-only modes
|
||||
|
||||
OnlyOffice sends a WOPI Lock request when opening any document, even when
|
||||
the user only has read access. The WOPI Lock handler was attempting to acquire
|
||||
a CS3 write lock regardless of the view mode, causing a permission error for
|
||||
read-only tokens that OnlyOffice displayed as an error message on load.
|
||||
|
||||
The Lock handler now returns 200 OK immediately for READ_ONLY and VIEW_ONLY
|
||||
view modes without attempting to acquire a lock, consistent with the WOPI spec.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/12257
|
||||
@@ -212,6 +212,16 @@ func (f *FileConnector) Lock(ctx context.Context, lockID, oldLockID string) (*Co
|
||||
return NewResponse(400), nil
|
||||
}
|
||||
|
||||
// For read-only and view-only modes, the user has no write access.
|
||||
// OnlyOffice sends a Lock request even for view-only documents, but
|
||||
// attempting SetLock with a read-only token would fail at the CS3 layer.
|
||||
// Return 200 OK immediately without acquiring a lock.
|
||||
if wopiContext.ViewMode == appproviderv1beta1.ViewMode_VIEW_MODE_READ_ONLY ||
|
||||
wopiContext.ViewMode == appproviderv1beta1.ViewMode_VIEW_MODE_VIEW_ONLY {
|
||||
logger.Debug().Msg("Lock: view-only mode, skipping lock")
|
||||
return NewResponseWithVersion(nil), nil
|
||||
}
|
||||
|
||||
var setOrRefreshStatus *rpcv1beta1.Status
|
||||
if oldLockID == "" {
|
||||
// If the oldLockID is empty, this is a "LOCK" request
|
||||
|
||||
@@ -178,6 +178,28 @@ var _ = Describe("FileConnector", func() {
|
||||
Expect(response.Headers).To(BeNil())
|
||||
})
|
||||
|
||||
It("Read-only view mode returns 200 without locking", func() {
|
||||
gatewaySelector.EXPECT().Next().Unset()
|
||||
readOnlyCtx := wopiCtx
|
||||
readOnlyCtx.ViewMode = appproviderv1beta1.ViewMode_VIEW_MODE_READ_ONLY
|
||||
ctx := middleware.WopiContextToCtx(context.Background(), readOnlyCtx)
|
||||
|
||||
response, err := fc.Lock(ctx, "abcdef123", "")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(response.Status).To(Equal(200))
|
||||
})
|
||||
|
||||
It("View-only mode returns 200 without locking", func() {
|
||||
gatewaySelector.EXPECT().Next().Unset()
|
||||
viewOnlyCtx := wopiCtx
|
||||
viewOnlyCtx.ViewMode = appproviderv1beta1.ViewMode_VIEW_MODE_VIEW_ONLY
|
||||
ctx := middleware.WopiContextToCtx(context.Background(), viewOnlyCtx)
|
||||
|
||||
response, err := fc.Lock(ctx, "abcdef123", "")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(response.Status).To(Equal(200))
|
||||
})
|
||||
|
||||
It("Set lock failed", func() {
|
||||
ctx := middleware.WopiContextToCtx(context.Background(), wopiCtx)
|
||||
|
||||
@@ -2166,5 +2188,6 @@ var _ = Describe("FileConnector", func() {
|
||||
// so we can't compare the whole url
|
||||
Expect(templateSource).To(HavePrefix(expectedTemplateSource))
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user