Skip to content

Commit

Permalink
feat: Implement handling for lock managers who can unlock files
Browse files Browse the repository at this point in the history
Signed-off-by: Julius Härtl <jus@bitgrid.net>
  • Loading branch information
juliusknorr committed Jan 3, 2024
1 parent 1b3d345 commit 531815e
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 30 deletions.
1 change: 1 addition & 0 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class Application extends App implements IBootstrap {
public const DAV_PROPERTY_LOCK_TIME = '{http://nextcloud.org/ns}lock-time';
public const DAV_PROPERTY_LOCK_TIMEOUT = '{http://nextcloud.org/ns}lock-timeout';
public const DAV_PROPERTY_LOCK_TOKEN = '{http://nextcloud.org/ns}lock-token';
public const DAV_PROPERTY_LOCK_MANAGER = '{http://nextcloud.org/ns}lock-manager';


/** @var IUserSession */
Expand Down
4 changes: 4 additions & 0 deletions lib/DAV/LockPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ public function customProperties(PropFind $propFind, INode $node) {

return $lock->getToken();
});

$propFind->handle(Application::DAV_PROPERTY_LOCK_MANAGER, function () use ($node) {
return $this->lockService->isLockManager($this->userSession->getUser(), $node->getNode());
});
}

public function httpLock(RequestInterface $request, ResponseInterface $response) {
Expand Down
63 changes: 33 additions & 30 deletions lib/Service/LockService.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,18 @@
use OCA\FilesLock\Model\FileLock;
use OCA\FilesLock\Tools\Traits\TLogger;
use OCA\FilesLock\Tools\Traits\TStringTools;
use OCA\GroupFolders\Mount\GroupMountPoint;
use OCP\App\IAppManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\InvalidPathException;
use OCP\Files\Lock\ILock;
use OCP\Files\Lock\LockContext;
use OCP\Files\Lock\OwnerLockedException;
use OCP\Files\Node;
use OCP\Files\NotFoundException;
use OCP\IGroupManager;
use OCP\IL10N;
use OCP\IUser;
use OCP\IUserManager;

/**
Expand All @@ -56,47 +60,26 @@
class LockService {
public const PREFIX = 'files_lock';


use TStringTools;
use TLogger;


private ?string $userId;
private IUserManager $userManager;
private IL10N $l10n;
private LocksRequest $locksRequest;
private FileService $fileService;
private ConfigService $configService;
private IAppManager $appManager;
private IEventDispatcher $eventDispatcher;


private array $locks = [];
private bool $lockRetrieved = false;
private array $lockCache = [];
private ?array $directEditors = null;
private bool $allowUserOverride = false;


public function __construct(
$userId,
IL10N $l10n,
IUserManager $userManager,
LocksRequest $locksRequest,
FileService $fileService,
ConfigService $configService,
IAppManager $appManager,
IEventDispatcher $eventDispatcher
private ?string $userId,
private IL10N $l10n,
private IUserManager $userManager,
private IGroupManager $groupManager,
private LocksRequest $locksRequest,
private FileService $fileService,
private ConfigService $configService,
private IAppManager $appManager,
private IEventDispatcher $eventDispatcher
) {
$this->userId = $userId;
$this->l10n = $l10n;
$this->userManager = $userManager;
$this->locksRequest = $locksRequest;
$this->fileService = $fileService;
$this->configService = $configService;
$this->appManager = $appManager;
$this->eventDispatcher = $eventDispatcher;

$this->setup('app', 'files_lock');
}

Expand Down Expand Up @@ -402,4 +385,24 @@ private function propagateEtag(LockContext $lockContext): void {
]);
$node->getStorage()->getUpdater()->propagate($node->getInternalPath(), $node->getMTime());
}

public function isLockManager(IUser $user, ?Node $node): bool {
if ($this->groupManager->isAdmin($user->getUID())) {
return true;
}

$lockManagerGroups = explode('|', $this->configService->getAppValue('lock_managers') ?? '');
$userGroups = $this->groupManager->getUserGroupIds($user);
$matchGroups = !empty(array_intersect($lockManagerGroups, $userGroups));

if ($matchGroups) {
return true;
}

if ($node && $node->getOwner()?->getUID() === $user?->getUID() && !$node->getMountPoint() instanceof GroupMountPoint) {

Check failure on line 402 in lib/Service/LockService.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

TypeDoesNotContainNull

lib/Service/LockService.php:402:49: TypeDoesNotContainNull: OCP\IUser does not contain null (see https://psalm.dev/090)

Check failure on line 402 in lib/Service/LockService.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

RedundantCondition

lib/Service/LockService.php:402:49: RedundantCondition: Type OCP\IUser for $user is never null (see https://psalm.dev/122)

Check failure on line 402 in lib/Service/LockService.php

View workflow job for this annotation

GitHub Actions / static-psalm-analysis

UndefinedClass

lib/Service/LockService.php:402:104: UndefinedClass: Class, interface or enum named OCA\GroupFolders\Mount\GroupMountPoint does not exist (see https://psalm.dev/019)
return true;
}

return false;
}
}
7 changes: 7 additions & 0 deletions src/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const getLockStateFromAttributes = (node: Node): LockState => {
lockOwnerType: parseInt(node.attributes['lock-owner-type']),
lockOwnerEditor: node.attributes['lock-owner-editor'],
lockTime: parseInt(node.attributes['lock-time']),
lockManager: !!node.attributes['lock-manager'],
}
}

Expand All @@ -53,6 +54,12 @@ export const canUnlock = (node: Node): boolean => {
return false
}

const aclManager = !!node.attributes['acl-can-manage']

if (state.lockManager || aclManager) {
return true
}

if (state.lockOwnerType === LockType.User && state.lockOwner === getCurrentUser()?.uid) {
return true
}
Expand Down
1 change: 1 addition & 0 deletions src/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ registerDavProperty('nc:lock-owner-displayname', { nc: 'http://nextcloud.org/ns'
registerDavProperty('nc:lock-owner-type', { nc: 'http://nextcloud.org/ns' })
registerDavProperty('nc:lock-owner-editor', { nc: 'http://nextcloud.org/ns' })
registerDavProperty('nc:lock-time', { nc: 'http://nextcloud.org/ns' })
registerDavProperty('nc:lock-manager', { nc: 'http://nextcloud.org/ns' })
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ export type LockState = {
lockOwnerDisplayName: string,
lockOwnerType: LockType,
lockOwnerEditor: string,
lockManager: boolean,
lockTime: number,
}

0 comments on commit 531815e

Please sign in to comment.