mirror of
https://github.com/nextcloud/server.git
synced 2026-06-09 08:44:07 -04:00
feat: listen to user/group events and update external storage mounts
Signed-off-by: Robin Appelman <robin@icewind.nl>
This commit is contained in:
parent
5565cdb390
commit
d64f7eb939
5 changed files with 128 additions and 9 deletions
|
|
@ -45,7 +45,6 @@ use OCA\Files_External\Lib\Config\IAuthMechanismProvider;
|
|||
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;
|
||||
|
|
@ -55,10 +54,12 @@ 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\UserCreatedEvent;
|
||||
use OCP\User\Events\UserDeletedEvent;
|
||||
use OCP\User\Events\UserLoggedInEvent;
|
||||
|
||||
/**
|
||||
* @package OCA\Files_External\AppInfo
|
||||
|
|
@ -79,11 +80,14 @@ class Application extends App implements IBackendProvider, IAuthMechanismProvide
|
|||
$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->registerConfigLexicon(ConfigLexicon::class);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ use OCP\Security\ICrypto;
|
|||
|
||||
/**
|
||||
* Stores the mount config in the database
|
||||
*
|
||||
* @psalm-type StorageConfigData = array{type: int, priority: int, applicable: list<array{type: mixed, value: mixed}>, config: array, options: array}
|
||||
*/
|
||||
class DBConfigService {
|
||||
public const MOUNT_TYPE_ADMIN = 1;
|
||||
|
|
@ -80,6 +82,39 @@ class DBConfigService {
|
|||
return $this->getMountsFromQuery($query);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $groupIds
|
||||
* @return list<StorageConfigData>
|
||||
*/
|
||||
public function getMountsForGroups(array $groupIds): array {
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<StorageConfigData>
|
||||
*/
|
||||
public function getGlobalMounts(): array {
|
||||
$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);
|
||||
}
|
||||
|
|
@ -376,7 +411,10 @@ class DBConfigService {
|
|||
$query->executeStatement();
|
||||
}
|
||||
|
||||
private function getMountsFromQuery(IQueryBuilder $query) {
|
||||
/**
|
||||
* @return list<StorageConfigData>
|
||||
*/
|
||||
private function getMountsFromQuery(IQueryBuilder $query): array {
|
||||
$result = $query->executeQuery();
|
||||
$mounts = $result->fetchAllAssociative();
|
||||
$uniqueMounts = [];
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ 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
|
||||
|
|
@ -169,4 +170,31 @@ class GlobalStoragesService extends StoragesService {
|
|||
|
||||
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(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,16 +20,19 @@ use OCP\EventDispatcher\Event as T;
|
|||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Files\Cache\ICacheEntry;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\Files\IMimeTypeLoader;
|
||||
use OCP\Group\Events\BeforeGroupDeletedEvent;
|
||||
use OCP\Group\Events\UserAddedEvent;
|
||||
use OCP\Group\Events\UserRemovedEvent;
|
||||
use OCP\IGroup;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUser;
|
||||
use OCP\IUserManager;
|
||||
use OCP\User\Events\UserCreatedEvent;
|
||||
|
||||
/**
|
||||
* Listens to config events and update the mounts for the applicable users
|
||||
*
|
||||
* @template-implements IEventListener<StorageCreatedEvent|StorageDeletedEvent|StorageUpdatedEvent|Event>
|
||||
* @template-implements IEventListener<StorageCreatedEvent|StorageDeletedEvent|StorageUpdatedEvent|BeforeGroupDeletedEvent|UserCreatedEvent|UserAddedEvent|UserRemovedEvent|Event>
|
||||
*/
|
||||
class MountCacheService implements IEventListener {
|
||||
public function __construct(
|
||||
|
|
@ -37,6 +40,7 @@ class MountCacheService implements IEventListener {
|
|||
private readonly ConfigAdapter $configAdapter,
|
||||
private readonly IUserManager $userManager,
|
||||
private readonly IGroupManager $groupManager,
|
||||
private readonly GlobalStoragesService $storagesService,
|
||||
) {
|
||||
}
|
||||
|
||||
|
|
@ -50,6 +54,18 @@ class MountCacheService implements IEventListener {
|
|||
if ($event instanceof StorageUpdatedEvent) {
|
||||
$this->handleUpdatedStorage($event->getOldConfig(), $event->getNewConfig());
|
||||
}
|
||||
if ($event instanceof UserAddedEvent) {
|
||||
$this->handleUserAdded($event->getGroup(), $event->getUser());
|
||||
}
|
||||
if ($event instanceof UserRemovedEvent) {
|
||||
$this->handleUserRemoved($event->getGroup(), $event->getUser());
|
||||
}
|
||||
if ($event instanceof BeforeGroupDeletedEvent) {
|
||||
$this->handleGroupDeleted($event->getGroup());
|
||||
}
|
||||
if ($event instanceof UserCreatedEvent) {
|
||||
$this->handleUserCreated($event->getUser());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -153,4 +169,38 @@ class MountCacheService implements IEventListener {
|
|||
$storage->getId(),
|
||||
);
|
||||
}
|
||||
|
||||
private function handleUserRemoved(IGroup $group, IUser $user): void {
|
||||
$storages = $this->storagesService->getAllStoragesForGroup($group);
|
||||
foreach ($storages as $storage) {
|
||||
if (!in_array($user->getUID(), $storage->getApplicableUsers())) {
|
||||
$this->userMountCache->removeMount($storage->getMountPointForUser($user));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function handleUserAdded(IGroup $group, IUser $user): void {
|
||||
$storages = $this->storagesService->getAllStoragesForGroup($group);
|
||||
foreach ($storages as $storage) {
|
||||
$this->registerForUser($user, $storage);
|
||||
}
|
||||
}
|
||||
|
||||
private function handleGroupDeleted(IGroup $group): void {
|
||||
$storages = $this->storagesService->getAllStoragesForGroup($group);
|
||||
foreach ($storages as $storage) {
|
||||
foreach ($group->searchUsers('') as $user) {
|
||||
if (!in_array($user->getUID(), $storage->getApplicableUsers())) {
|
||||
$this->userMountCache->removeMount($storage->getMountPointForUser($user));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function handleUserCreated(IUser $user): void {
|
||||
$storages = $this->storagesService->getAllGlobalStorages();
|
||||
foreach ($storages as $storage) {
|
||||
$this->registerForUser($user, $storage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ namespace OCA\Files_External\Service;
|
|||
|
||||
use OCA\Files_External\Lib\StorageConfig;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Files\Config\IUserMountCache;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUser;
|
||||
|
|
|
|||
Loading…
Reference in a new issue