Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions apps/files_external/composer/composer/autoload_classmap.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
'OCA\\Files_External\\Controller\\StoragesController' => $baseDir . '/../lib/Controller/StoragesController.php',
'OCA\\Files_External\\Controller\\UserGlobalStoragesController' => $baseDir . '/../lib/Controller/UserGlobalStoragesController.php',
'OCA\\Files_External\\Controller\\UserStoragesController' => $baseDir . '/../lib/Controller/UserStoragesController.php',
'OCA\\Files_External\\Event\\StorageCreatedEvent' => $baseDir . '/../lib/Event/StorageCreatedEvent.php',
'OCA\\Files_External\\Event\\StorageDeletedEvent' => $baseDir . '/../lib/Event/StorageDeletedEvent.php',
'OCA\\Files_External\\Event\\StorageUpdatedEvent' => $baseDir . '/../lib/Event/StorageUpdatedEvent.php',
'OCA\\Files_External\\Lib\\ApplicableHelper' => $baseDir . '/../lib/Lib/ApplicableHelper.php',
'OCA\\Files_External\\Lib\\Auth\\AmazonS3\\AccessKey' => $baseDir . '/../lib/Lib/Auth/AmazonS3/AccessKey.php',
'OCA\\Files_External\\Lib\\Auth\\AuthMechanism' => $baseDir . '/../lib/Lib/Auth/AuthMechanism.php',
'OCA\\Files_External\\Lib\\Auth\\Builtin' => $baseDir . '/../lib/Lib/Auth/Builtin.php',
Expand Down Expand Up @@ -117,6 +121,7 @@
'OCA\\Files_External\\Service\\GlobalStoragesService' => $baseDir . '/../lib/Service/GlobalStoragesService.php',
'OCA\\Files_External\\Service\\ImportLegacyStoragesService' => $baseDir . '/../lib/Service/ImportLegacyStoragesService.php',
'OCA\\Files_External\\Service\\LegacyStoragesService' => $baseDir . '/../lib/Service/LegacyStoragesService.php',
'OCA\\Files_External\\Service\\MountCacheService' => $baseDir . '/../lib/Service/MountCacheService.php',
'OCA\\Files_External\\Service\\StoragesService' => $baseDir . '/../lib/Service/StoragesService.php',
'OCA\\Files_External\\Service\\UserGlobalStoragesService' => $baseDir . '/../lib/Service/UserGlobalStoragesService.php',
'OCA\\Files_External\\Service\\UserStoragesService' => $baseDir . '/../lib/Service/UserStoragesService.php',
Expand Down
5 changes: 5 additions & 0 deletions apps/files_external/composer/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class ComposerStaticInitFiles_External
'OCA\\Files_External\\Controller\\StoragesController' => __DIR__ . '/..' . '/../lib/Controller/StoragesController.php',
'OCA\\Files_External\\Controller\\UserGlobalStoragesController' => __DIR__ . '/..' . '/../lib/Controller/UserGlobalStoragesController.php',
'OCA\\Files_External\\Controller\\UserStoragesController' => __DIR__ . '/..' . '/../lib/Controller/UserStoragesController.php',
'OCA\\Files_External\\Event\\StorageCreatedEvent' => __DIR__ . '/..' . '/../lib/Event/StorageCreatedEvent.php',
'OCA\\Files_External\\Event\\StorageDeletedEvent' => __DIR__ . '/..' . '/../lib/Event/StorageDeletedEvent.php',
'OCA\\Files_External\\Event\\StorageUpdatedEvent' => __DIR__ . '/..' . '/../lib/Event/StorageUpdatedEvent.php',
'OCA\\Files_External\\Lib\\ApplicableHelper' => __DIR__ . '/..' . '/../lib/Lib/ApplicableHelper.php',
'OCA\\Files_External\\Lib\\Auth\\AmazonS3\\AccessKey' => __DIR__ . '/..' . '/../lib/Lib/Auth/AmazonS3/AccessKey.php',
'OCA\\Files_External\\Lib\\Auth\\AuthMechanism' => __DIR__ . '/..' . '/../lib/Lib/Auth/AuthMechanism.php',
'OCA\\Files_External\\Lib\\Auth\\Builtin' => __DIR__ . '/..' . '/../lib/Lib/Auth/Builtin.php',
Expand Down Expand Up @@ -132,6 +136,7 @@ class ComposerStaticInitFiles_External
'OCA\\Files_External\\Service\\GlobalStoragesService' => __DIR__ . '/..' . '/../lib/Service/GlobalStoragesService.php',
'OCA\\Files_External\\Service\\ImportLegacyStoragesService' => __DIR__ . '/..' . '/../lib/Service/ImportLegacyStoragesService.php',
'OCA\\Files_External\\Service\\LegacyStoragesService' => __DIR__ . '/..' . '/../lib/Service/LegacyStoragesService.php',
'OCA\\Files_External\\Service\\MountCacheService' => __DIR__ . '/..' . '/../lib/Service/MountCacheService.php',
'OCA\\Files_External\\Service\\StoragesService' => __DIR__ . '/..' . '/../lib/Service/StoragesService.php',
'OCA\\Files_External\\Service\\UserGlobalStoragesService' => __DIR__ . '/..' . '/../lib/Service/UserGlobalStoragesService.php',
'OCA\\Files_External\\Service\\UserStoragesService' => __DIR__ . '/..' . '/../lib/Service/UserStoragesService.php',
Expand Down
23 changes: 18 additions & 5 deletions apps/files_external/lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
use OCA\Files_External\Config\ConfigAdapter;
use OCA\Files_External\Config\UserPlaceholderHandler;
use OCA\Files_External\ConfigLexicon;
use OCA\Files_External\Event\StorageCreatedEvent;
use OCA\Files_External\Event\StorageDeletedEvent;
use OCA\Files_External\Event\StorageUpdatedEvent;
use OCA\Files_External\Lib\Auth\AmazonS3\AccessKey;
use OCA\Files_External\Lib\Auth\Builtin;
use OCA\Files_External\Lib\Auth\NullMechanism;
Expand Down Expand Up @@ -42,19 +45,22 @@
use OCA\Files_External\Lib\Config\IBackendProvider;
use OCA\Files_External\Listener\GroupDeletedListener;
use OCA\Files_External\Listener\LoadAdditionalListener;
use OCA\Files_External\Listener\StorePasswordListener;
use OCA\Files_External\Listener\UserDeletedListener;
use OCA\Files_External\Service\BackendService;
use OCA\Files_External\Service\MountCacheService;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\AppFramework\QueryException;
use OCP\Files\Config\IMountProviderCollection;
use OCP\Group\Events\BeforeGroupDeletedEvent;
use OCP\Group\Events\GroupDeletedEvent;
use OCP\User\Events\PasswordUpdatedEvent;
use OCP\Group\Events\UserAddedEvent;
use OCP\Group\Events\UserRemovedEvent;
use OCP\User\Events\PostLoginEvent;
use OCP\User\Events\UserCreatedEvent;
use OCP\User\Events\UserDeletedEvent;
use OCP\User\Events\UserLoggedInEvent;

/**
* @package OCA\Files_External\AppInfo
Expand All @@ -75,8 +81,15 @@ public function register(IRegistrationContext $context): void {
$context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class);
$context->registerEventListener(GroupDeletedEvent::class, GroupDeletedListener::class);
$context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class);
$context->registerEventListener(UserLoggedInEvent::class, StorePasswordListener::class);
$context->registerEventListener(PasswordUpdatedEvent::class, StorePasswordListener::class);
$context->registerEventListener(StorageCreatedEvent::class, MountCacheService::class);
$context->registerEventListener(StorageDeletedEvent::class, MountCacheService::class);
$context->registerEventListener(StorageUpdatedEvent::class, MountCacheService::class);
$context->registerEventListener(BeforeGroupDeletedEvent::class, MountCacheService::class);
$context->registerEventListener(UserCreatedEvent::class, MountCacheService::class);
$context->registerEventListener(UserAddedEvent::class, MountCacheService::class);
$context->registerEventListener(UserRemovedEvent::class, MountCacheService::class);
$context->registerEventListener(PostLoginEvent::class, MountCacheService::class);

$context->registerConfigLexicon(ConfigLexicon::class);
}

Expand Down
17 changes: 11 additions & 6 deletions apps/files_external/lib/Config/ConfigAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use OCA\Files_External\Service\UserGlobalStoragesService;
use OCA\Files_External\Service\UserStoragesService;
use OCP\AppFramework\QueryException;
use OCP\Files\Config\IAuthoritativeMountProvider;
use OCP\Files\Config\IMountProvider;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\ObjectStore\IObjectStore;
Expand All @@ -32,7 +33,7 @@
/**
* Make the old files_external config work with the new public mount config api
*/
class ConfigAdapter implements IMountProvider {
class ConfigAdapter implements IMountProvider, IAuthoritativeMountProvider {
public function __construct(
private UserStoragesService $userStoragesService,
private UserGlobalStoragesService $userGlobalStoragesService,
Expand Down Expand Up @@ -73,6 +74,11 @@ private function prepareStorageConfig(StorageConfig &$storage, IUser $user): voi
$storage->getBackend()->manipulateStorageConfig($storage, $user);
}

public function constructStorageForUser(IUser $user, StorageConfig $storage) {
$this->prepareStorageConfig($storage, $user);
return $this->constructStorage($storage);
}

/**
* Construct the storage implementation
*
Expand Down Expand Up @@ -105,8 +111,7 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) {

$storages = array_map(function (StorageConfig $storageConfig) use ($user) {
try {
$this->prepareStorageConfig($storageConfig, $user);
return $this->constructStorage($storageConfig);
return $this->constructStorageForUser($user, $storageConfig);
} catch (\Exception $e) {
// propagate exception into filesystem
return new FailedStorage(['exception' => $e]);
Expand All @@ -123,7 +128,7 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) {
$availability = $storage->getAvailability();
if (!$availability['available'] && !Availability::shouldRecheck($availability)) {
$storage = new FailedStorage([
'exception' => new StorageNotAvailableException('Storage with mount id ' . $storageConfig->getId() . ' is not available')
'exception' => new StorageNotAvailableException('Storage with mount id ' . $storageConfig->getId() . ' is not available'),
]);
}
} catch (\Exception $e) {
Expand All @@ -148,7 +153,7 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) {
null,
$loader,
$storageConfig->getMountOptions(),
$storageConfig->getId()
$storageConfig->getId(),
);
} else {
return new SystemMountPoint(
Expand All @@ -158,7 +163,7 @@ public function getMountsForUser(IUser $user, IStorageFactory $loader) {
null,
$loader,
$storageConfig->getMountOptions(),
$storageConfig->getId()
$storageConfig->getId(),
);
}
}, $storageConfigs, $availableStorages);
Expand Down
6 changes: 4 additions & 2 deletions apps/files_external/lib/Config/UserContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ protected function getUserId(): ?string {
}
try {
$shareToken = $this->request->getParam('token');
$share = $this->shareManager->getShareByToken($shareToken);
return $share->getShareOwner();
if ($shareToken !== null) {
$share = $this->shareManager->getShareByToken($shareToken);
return $share->getShareOwner();
}
} catch (ShareNotFound $e) {
}

Expand Down
24 changes: 24 additions & 0 deletions apps/files_external/lib/Event/StorageCreatedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Robin Appelman <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Files_External\Event;

use OCA\Files_External\Lib\StorageConfig;
use OCP\EventDispatcher\Event;

class StorageCreatedEvent extends Event {
public function __construct(
private readonly StorageConfig $newConfig,
) {
parent::__construct();
}

public function getNewConfig(): StorageConfig {
return $this->newConfig;
}
}
24 changes: 24 additions & 0 deletions apps/files_external/lib/Event/StorageDeletedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Robin Appelman <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Files_External\Event;

use OCA\Files_External\Lib\StorageConfig;
use OCP\EventDispatcher\Event;

class StorageDeletedEvent extends Event {
public function __construct(
private readonly StorageConfig $oldConfig,
) {
parent::__construct();
}

public function getOldConfig(): StorageConfig {
return $this->oldConfig;
}
}
29 changes: 29 additions & 0 deletions apps/files_external/lib/Event/StorageUpdatedEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2025 Robin Appelman <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Files_External\Event;

use OCA\Files_External\Lib\StorageConfig;
use OCP\EventDispatcher\Event;

class StorageUpdatedEvent extends Event {
public function __construct(
private readonly StorageConfig $oldConfig,
private readonly StorageConfig $newConfig,
) {
parent::__construct();
}

public function getOldConfig(): StorageConfig {
return $this->oldConfig;
}

public function getNewConfig(): StorageConfig {
return $this->newConfig;
}
}
114 changes: 114 additions & 0 deletions apps/files_external/lib/Lib/ApplicableHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<?php

declare(strict_types=1);
/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Files_External\Lib;

use OC\User\LazyUser;
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserManager;

class ApplicableHelper {
public function __construct(
private readonly IUserManager $userManager,
private readonly IGroupManager $groupManager,
) {
}

/**
* Get all users that have access to a storage
*
* @return \Iterator<string, IUser>
*/
public function getUsersForStorage(StorageConfig $storage): \Iterator {
$yielded = [];
if (count($storage->getApplicableUsers()) + count($storage->getApplicableGroups()) === 0) {
yield from $this->userManager->getSeenUsers();
}
foreach ($storage->getApplicableUsers() as $userId) {
$yielded[$userId] = true;
yield $userId => new LazyUser($userId, $this->userManager);
}
foreach ($storage->getApplicableGroups() as $groupId) {
$group = $this->groupManager->get($groupId);
if ($group !== null) {
foreach ($group->getUsers() as $user) {
if (!isset($yielded[$user->getUID()])) {
$yielded[$user->getUID()] = true;
yield $user->getUID() => $user;
}
}
}
}
}

public function isApplicableForUser(StorageConfig $storage, IUser $user): bool {
if (count($storage->getApplicableUsers()) + count($storage->getApplicableGroups()) === 0) {
return true;
}
if (in_array($user->getUID(), $storage->getApplicableUsers())) {
return true;
}
$groupIds = $this->groupManager->getUserGroupIds($user);
foreach ($groupIds as $groupId) {
if (in_array($groupId, $storage->getApplicableGroups())) {
return true;
}
}
return false;
}

/**
* Return all users that are applicable for storage $a, but not for $b
*
* @return \Iterator<IUser>
*/
public function diffApplicable(StorageConfig $a, StorageConfig $b): \Iterator {
$aIsAll = count($a->getApplicableUsers()) + count($a->getApplicableGroups()) === 0;
$bIsAll = count($b->getApplicableUsers()) + count($b->getApplicableGroups()) === 0;
if ($bIsAll) {
return;
}

if ($aIsAll) {
foreach ($this->getUsersForStorage($a) as $user) {
if (!$this->isApplicableForUser($b, $user)) {
yield $user;
}
}
} else {
$yielded = [];
foreach ($a->getApplicableGroups() as $groupId) {
if (!in_array($groupId, $b->getApplicableGroups())) {
$group = $this->groupManager->get($groupId);
if ($group) {
foreach ($group->getUsers() as $user) {
if (!$this->isApplicableForUser($b, $user)) {
if (!isset($yielded[$user->getUID()])) {
$yielded[$user->getUID()] = true;
yield $user;
}
}
}
}
}
}
foreach ($a->getApplicableUsers() as $userId) {
if (!in_array($userId, $b->getApplicableUsers())) {
$user = $this->userManager->get($userId);
if ($user && !$this->isApplicableForUser($b, $user)) {
if (!isset($yielded[$user->getUID()])) {
$yielded[$user->getUID()] = true;
yield $user;
}
}
}
}
}
}
}
10 changes: 10 additions & 0 deletions apps/files_external/lib/Lib/StorageConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use OCA\Files_External\Lib\Auth\IUserProvided;
use OCA\Files_External\Lib\Backend\Backend;
use OCA\Files_External\ResponseDefinitions;
use OCP\IUser;

/**
* External storage configuration
Expand Down Expand Up @@ -435,4 +436,13 @@ protected function formatStorageForUI(): void {
}
}
}

public function getMountPointForUser(IUser $user): string {
return '/' . $user->getUID() . '/files/' . trim($this->mountPoint, '/') . '/';
}

public function __clone() {
$this->backend = clone $this->backend;
$this->authMechanism = clone $this->authMechanism;
}
}
Loading
Loading