Skip to content

Show unlock action for the file owner - #17838

Open
falkloewert wants to merge 2 commits into
nextcloud:masterfrom
falkloewert:fix/unlock-file-owner
Open

falkloewert wants to merge 2 commits into
nextcloud:masterfrom
falkloewert:fix/unlock-file-owner

Conversation

@falkloewert

Copy link
Copy Markdown

Fixes #17837

Summary

The "Unlock file" entry was only shown when the current user owns the lock (lockOwnerId == userId). The server also allows the file owner to unlock TYPE_USER locks — OCA\FilesLock\Service\LockService::canUnlock():

if ($request->getType() === ILock::TYPE_USER && $isFileOwner) {
    return;
}

Without this, a stale lock created by another client (e.g. the Text app, lock owner text) cannot be released from the app at all; with the default lock_timeout = -1 it never expires.

Change: FileLockingHelper.canUserUnlockFile() now also accepts file.ownerId == userId.

Known limitation: for group folders and external storage the server deliberately skips the file-owner check (MountProvider allowlist in canUnlock), so the client cannot mirror the rule exactly there; the action can then fail with the existing error snackbar.

🖼️ Screenshots

Not applicable — the only visible difference is an additional entry in the file overflow menu.

🏁 Checklist

  • ⛑️ Tests (unit and/or integration) are included or not needed — one added case; existing cases still pass (FileLockingHelperTest, 5 tests)
  • 🔙 Backport requests are created or not needed: not needed
  • 📅 Milestone is set
  • 🌸 PR title is meaningful (if it should be in the changelog: is it meaningful to users?): "Unlock a file locked by another client"

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI — assistant-generated patch, reviewed and tested by me.

The server allows the owner of a file to unlock TYPE_USER locks
(LockService::canUnlock), so a stale lock created by another client -
e.g. the Text app, whose locks have the owner "text" - can be released
by the user. The client only offered the action when the lock owner
matched the current user, leaving users without a way to clear such
locks until the lock timeout expires (which defaults to unlimited).

Signed-off-by: Falk Loewert <falk@co-sinus.de>
App locks created by the Text or OnlyOffice apps are of type TYPE_APP.
For those the server does not expose a lock owner and reports the lock
type as COLLABORATIVE, so the previous check (lock owner equals the
current user, MANUAL lock type) never matched and the unlock action
stayed hidden even for the owner of the file. LockService::canUnlock
accepts a TYPE_USER unlock request from the file owner for TYPE_USER and
TYPE_APP locks, so mirror that on the client and only keep TOKEN locks
restricted.

Additionally the lock info row was appended to the action list before
displayActions() ran. That method returns early when the list is not
empty, which left the bottom sheet without any action at all for locked
files. Render the actions first and append the lock info afterwards.

Signed-off-by: Falk Loewert <falk@co-sinus.de>
@falkloewert

Copy link
Copy Markdown
Author

Updated the patch after testing on a real device (Android 16, Pixel 9 Pro, files_lock 34.0.1, server 34).

Two things the first revision got wrong or missed:

  1. App locks are not MANUAL. Text and OnlyOffice lock with TYPE_APP (1), which the client maps to COLLABORATIVE, and for those locks the server returns no lock-owner at all. The old check (lockOwnerId == userId && lockType == MANUAL) could therefore never match. LockService::canUnlock accepts a TYPE_USER unlock request from the file owner for both TYPE_USER and TYPE_APP locks, so the client now mirrors that and only keeps TOKEN locks restricted.

  2. The action list was invisible for locked files. FileActionsBottomSheet.handleState() called displayLockInfo() before displayActions(), and displayActions() returns early when fileActionsList is not empty. With a lock present the sheet rendered only the "Locked by …" row and no actions at all — the unlock entry could not have been reached even with the permission check fixed. Reordered.

Verified end-to-end on device: open the actions sheet for a docx locked by OnlyOffice, tap "Unlock file", lock disappears from oc_files_lock.

🤖 Generated with Claude Code

@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown

Hello there,
Thank you so much for taking the time and effort to create a pull request to our Nextcloud project.

We hope that the review process is going smooth and is helpful for you. We want to ensure your pull request is reviewed to your satisfaction. If you have a moment, our community management team would very much appreciate your feedback on your experience with this PR review process.

Your feedback is valuable to us as we continuously strive to improve our community developer experience. Please take a moment to complete our short survey by clicking on the following link: https://cloud.nextcloud.com/apps/forms/s/i9Ago4EQRZ7TWxjfmeEpPkf6

Thank you for contributing to Nextcloud and we hope to hear from you soon!

(If you believe you should not receive this message, you can add yourself to the blocklist.)

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Lock owned by another client (e.g. Text app) cannot be unlocked from the app

1 participant