Skip to content
Open
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
4 changes: 4 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,9 @@
'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\\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 +120,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
4 changes: 4 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,9 @@ 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\\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 +135,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;
}
}
20 changes: 20 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,23 @@ protected function formatStorageForUI(): void {
}
}
}

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

public function __clone() {
$clone = new StorageConfig($this->getId());
$clone->setBackend(clone $this->getBackend());
$clone->setAuthMechanism(clone $this->getAuthMechanism());
$clone->setBackendOptions($this->getBackendOptions());
$clone->setMountPoint($this->getMountPoint());
$clone->setStatus($this->getStatus(), $this->getStatusMessage());
$clone->setPriority($this->getPriority());
$clone->setApplicableUsers($this->getApplicableUsers());
$clone->setApplicableGroups($this->getApplicableGroups());
$clone->setMountOptions($this->getMountOptions());
$clone->setType($this->getType());
return $clone;
}
}
26 changes: 26 additions & 0 deletions apps/files_external/lib/Service/DBConfigService.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,32 @@ public function getMountsForUser($userId, $groupIds) {
return $this->getMountsFromQuery($query);
}

public function getMountsForGroups($groupIds) {
$builder = $this->connection->getQueryBuilder();
$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
->from('external_mounts', 'm')
->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
->where($builder->expr()->andX( // mounts for group
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GROUP, IQueryBuilder::PARAM_INT)),
$builder->expr()->in('a.value', $builder->createNamedParameter($groupIds, IQueryBuilder::PARAM_STR_ARRAY)),
));

return $this->getMountsFromQuery($query);
}

public function getGlobalMounts() {
$builder = $this->connection->getQueryBuilder();
$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
->from('external_mounts', 'm')
->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'))
->where($builder->expr()->andX( // global mounts
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
$builder->expr()->isNull('a.value'),
), );

return $this->getMountsFromQuery($query);
}

public function modifyMountsOnUserDelete(string $uid): void {
$this->modifyMountsOnDelete($uid, self::APPLICABLE_TYPE_USER);
}
Expand Down
35 changes: 35 additions & 0 deletions apps/files_external/lib/Service/GlobalStoragesService.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@
namespace OCA\Files_External\Service;

use OC\Files\Filesystem;
use OCA\Files_External\Event\StorageCreatedEvent;
use OCA\Files_External\Event\StorageDeletedEvent;
use OCA\Files_External\Event\StorageUpdatedEvent;
use OCA\Files_External\Lib\StorageConfig;
use OCA\Files_External\MountConfig;
use OCP\IGroup;

/**
* Service class to manage global external storage
Expand Down Expand Up @@ -62,9 +66,13 @@ protected function triggerHooks(StorageConfig $storage, $signal) {
protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage) {
// if mount point changed, it's like a deletion + creation
if ($oldStorage->getMountPoint() !== $newStorage->getMountPoint()) {
$this->eventDispatcher->dispatchTyped(new StorageDeletedEvent($oldStorage));
$this->eventDispatcher->dispatchTyped(new StorageCreatedEvent($newStorage));
$this->triggerHooks($oldStorage, Filesystem::signal_delete_mount);
$this->triggerHooks($newStorage, Filesystem::signal_create_mount);
return;
} else {
$this->eventDispatcher->dispatchTyped(new StorageUpdatedEvent($oldStorage, $newStorage));
}

$userAdditions = array_diff($newStorage->getApplicableUsers(), $oldStorage->getApplicableUsers());
Expand Down Expand Up @@ -162,4 +170,31 @@ public function getStorageForAllUsers() {

return array_combine($keys, $configs);
}

/**
* Gets all storages for the group, not including any global storages
* @return StorageConfig[]
*/
public function getAllStoragesForGroup(IGroup $group): array {
$mounts = $this->dbConfig->getMountsForGroups([$group->getGID()]);
$configs = array_map($this->getStorageConfigFromDBMount(...), $mounts);
$configs = array_filter($configs, static fn (?StorageConfig $config): bool => $config instanceof StorageConfig);
$keys = array_map(static fn (StorageConfig $config) => $config->getId(), $configs);

$storages = array_combine($keys, $configs);
return array_filter($storages, $this->validateStorage(...));
}

/**
* @return StorageConfig[]
*/
public function getAllGlobalStorages(): array {
$mounts = $this->dbConfig->getGlobalMounts();

$configs = array_map($this->getStorageConfigFromDBMount(...), $mounts);
$configs = array_filter($configs, static fn (?StorageConfig $config): bool => $config instanceof StorageConfig);
$keys = array_map(static fn (StorageConfig $config) => $config->getId(), $configs);
$storages = array_combine($keys, $configs);
return array_filter($storages, $this->validateStorage(...));
}
}
Loading
Loading