mirror of
https://github.com/nextcloud/server.git
synced 2026-02-03 20:41:22 -05:00
Merge pull request #57497 from nextcloud/carl/external-storage-ipartialmountpoint
feat(external-storage): Implement IPartialMountPoint
This commit is contained in:
commit
f2373f1102
9 changed files with 483 additions and 175 deletions
|
|
@ -18,6 +18,7 @@ use OCA\Files_External\Service\UserGlobalStoragesService;
|
|||
use OCA\Files_External\Service\UserStoragesService;
|
||||
use OCP\Files\Config\IAuthoritativeMountProvider;
|
||||
use OCP\Files\Config\IMountProvider;
|
||||
use OCP\Files\Config\IPartialMountProvider;
|
||||
use OCP\Files\Mount\IMountPoint;
|
||||
use OCP\Files\ObjectStore\IObjectStore;
|
||||
use OCP\Files\Storage\IConstructableStorage;
|
||||
|
|
@ -26,6 +27,7 @@ use OCP\Files\Storage\IStorageFactory;
|
|||
use OCP\Files\StorageNotAvailableException;
|
||||
use OCP\IUser;
|
||||
use OCP\Server;
|
||||
use Override;
|
||||
use Psr\Clock\ClockInterface;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
|
@ -33,7 +35,7 @@ use Psr\Log\LoggerInterface;
|
|||
/**
|
||||
* Make the old files_external config work with the new public mount config api
|
||||
*/
|
||||
class ConfigAdapter implements IMountProvider, IAuthoritativeMountProvider {
|
||||
class ConfigAdapter implements IMountProvider, IAuthoritativeMountProvider, IPartialMountProvider {
|
||||
public function __construct(
|
||||
private UserStoragesService $userStoragesService,
|
||||
private UserGlobalStoragesService $userGlobalStoragesService,
|
||||
|
|
@ -81,8 +83,6 @@ class ConfigAdapter implements IMountProvider, IAuthoritativeMountProvider {
|
|||
|
||||
/**
|
||||
* Construct the storage implementation
|
||||
*
|
||||
* @param StorageConfig $storageConfig
|
||||
*/
|
||||
private function constructStorage(StorageConfig $storageConfig): IStorage {
|
||||
$class = $storageConfig->getBackend()->getStorageClass();
|
||||
|
|
@ -99,17 +99,12 @@ class ConfigAdapter implements IMountProvider, IAuthoritativeMountProvider {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all mountpoints applicable for the user
|
||||
*
|
||||
* @return IMountPoint[]
|
||||
* @param list<StorageConfig> $storageConfigs
|
||||
* @return array
|
||||
* @throws ContainerExceptionInterface
|
||||
*/
|
||||
public function getMountsForUser(IUser $user, IStorageFactory $loader) {
|
||||
$this->userStoragesService->setUser($user);
|
||||
$this->userGlobalStoragesService->setUser($user);
|
||||
|
||||
$storageConfigs = $this->userGlobalStoragesService->getAllStoragesForUser();
|
||||
|
||||
$storages = array_map(function (StorageConfig $storageConfig) use ($user) {
|
||||
private function getAvailableStorages(array $storageConfigs, IUser $user): array {
|
||||
$storages = array_map(function (StorageConfig $storageConfig) use ($user): IStorage {
|
||||
try {
|
||||
return $this->constructStorageForUser($user, $storageConfig);
|
||||
} catch (\Exception $e) {
|
||||
|
|
@ -123,7 +118,7 @@ class ConfigAdapter implements IMountProvider, IAuthoritativeMountProvider {
|
|||
return $storage->getId();
|
||||
}, $storages));
|
||||
|
||||
$availableStorages = array_map(function (IStorage $storage, StorageConfig $storageConfig): IStorage {
|
||||
return array_map(function (IStorage $storage, StorageConfig $storageConfig): IStorage {
|
||||
try {
|
||||
$availability = $storage->getAvailability();
|
||||
if (!$availability['available'] && !Availability::shouldRecheck($availability)) {
|
||||
|
|
@ -137,35 +132,23 @@ class ConfigAdapter implements IMountProvider, IAuthoritativeMountProvider {
|
|||
}
|
||||
return $storage;
|
||||
}, $storages, $storageConfigs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all mountpoints applicable for the user
|
||||
*
|
||||
* @return IMountPoint[]
|
||||
*/
|
||||
public function getMountsForUser(IUser $user, IStorageFactory $loader): array {
|
||||
$this->userStoragesService->setUser($user);
|
||||
$this->userGlobalStoragesService->setUser($user);
|
||||
|
||||
$storageConfigs = $this->userGlobalStoragesService->getAllStoragesForUser();
|
||||
$availableStorages = $this->getAvailableStorages($storageConfigs, $user);
|
||||
|
||||
$mounts = array_map(function (StorageConfig $storageConfig, IStorage $storage) use ($user, $loader) {
|
||||
$storage->setOwner($user->getUID());
|
||||
if ($storageConfig->getType() === StorageConfig::MOUNT_TYPE_PERSONAL) {
|
||||
return new PersonalMount(
|
||||
$this->userStoragesService,
|
||||
$storageConfig,
|
||||
$storageConfig->getId(),
|
||||
new KnownMtime([
|
||||
'storage' => $storage,
|
||||
'clock' => $this->clock,
|
||||
]),
|
||||
'/' . $user->getUID() . '/files' . $storageConfig->getMountPoint(),
|
||||
null,
|
||||
$loader,
|
||||
$storageConfig->getMountOptions(),
|
||||
$storageConfig->getId(),
|
||||
);
|
||||
} else {
|
||||
return new SystemMountPoint(
|
||||
$storageConfig,
|
||||
$storage,
|
||||
'/' . $user->getUID() . '/files' . $storageConfig->getMountPoint(),
|
||||
null,
|
||||
$loader,
|
||||
$storageConfig->getMountOptions(),
|
||||
$storageConfig->getId(),
|
||||
);
|
||||
}
|
||||
$mountpoint = '/' . $user->getUID() . '/files' . $storageConfig->getMountPoint();
|
||||
return $this->storageConfigToMount($user, $mountpoint, $loader, $storage, $storageConfig);
|
||||
}, $storageConfigs, $availableStorages);
|
||||
|
||||
$this->userStoragesService->resetUser();
|
||||
|
|
@ -173,4 +156,65 @@ class ConfigAdapter implements IMountProvider, IAuthoritativeMountProvider {
|
|||
|
||||
return $mounts;
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function getMountsForPath(string $setupPathHint, bool $forChildren, array $mountProviderArgs, IStorageFactory $loader): array {
|
||||
$user = $mountProviderArgs[0]->mountInfo->getUser();
|
||||
|
||||
if (!$forChildren) {
|
||||
// override path with mount point when fetching without children
|
||||
$setupPathHint = $mountProviderArgs[0]->mountInfo->getMountPoint();
|
||||
}
|
||||
|
||||
$this->userStoragesService->setUser($user);
|
||||
$this->userGlobalStoragesService->setUser($user);
|
||||
|
||||
$storageConfigs = $this->userGlobalStoragesService->getAllStoragesForUserWithPath($setupPathHint, $forChildren);
|
||||
$availableStorages = $this->getAvailableStorages($storageConfigs, $user);
|
||||
|
||||
$mounts = [];
|
||||
|
||||
$i = 0;
|
||||
foreach ($storageConfigs as $storageConfig) {
|
||||
$storage = $availableStorages[$i];
|
||||
$i++;
|
||||
$mountPoint = '/' . $user->getUID() . '/files' . $storageConfig->getMountPoint();
|
||||
$mounts[$mountPoint] = $this->storageConfigToMount($user, $mountPoint, $loader, $storage, $storageConfig);
|
||||
}
|
||||
|
||||
$this->userStoragesService->resetUser();
|
||||
$this->userGlobalStoragesService->resetUser();
|
||||
|
||||
return $mounts;
|
||||
}
|
||||
|
||||
private function storageConfigToMount(IUser $user, string $mountPoint, IStorageFactory $loader, IStorage $storage, StorageConfig $storageConfig): IMountPoint {
|
||||
$storage->setOwner($user->getUID());
|
||||
if ($storageConfig->getType() === StorageConfig::MOUNT_TYPE_PERSONAL) {
|
||||
return new PersonalMount(
|
||||
$this->userStoragesService,
|
||||
$storageConfig,
|
||||
$storageConfig->getId(),
|
||||
new KnownMtime([
|
||||
'storage' => $storage,
|
||||
'clock' => $this->clock,
|
||||
]),
|
||||
$mountPoint,
|
||||
null,
|
||||
$loader,
|
||||
$storageConfig->getMountOptions(),
|
||||
$storageConfig->getId()
|
||||
);
|
||||
} else {
|
||||
return new SystemMountPoint(
|
||||
$storageConfig,
|
||||
$storage,
|
||||
$mountPoint,
|
||||
null,
|
||||
$loader,
|
||||
$storageConfig->getMountOptions(),
|
||||
$storageConfig->getId()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,10 +76,8 @@ class StorageConfig implements \JsonSerializable {
|
|||
|
||||
/**
|
||||
* Priority
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $priority;
|
||||
private int $priority = 100;
|
||||
|
||||
/**
|
||||
* List of users who have access to this storage
|
||||
|
|
@ -242,7 +240,7 @@ class StorageConfig implements \JsonSerializable {
|
|||
*
|
||||
* @return int priority
|
||||
*/
|
||||
public function getPriority() {
|
||||
public function getPriority(): int {
|
||||
return $this->priority;
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +249,7 @@ class StorageConfig implements \JsonSerializable {
|
|||
*
|
||||
* @param int $priority priority
|
||||
*/
|
||||
public function setPriority($priority) {
|
||||
public function setPriority(int $priority): void {
|
||||
$this->priority = $priority;
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +258,7 @@ class StorageConfig implements \JsonSerializable {
|
|||
*
|
||||
* @return list<string> applicable users
|
||||
*/
|
||||
public function getApplicableUsers() {
|
||||
public function getApplicableUsers(): array {
|
||||
return $this->applicableUsers;
|
||||
}
|
||||
|
||||
|
|
@ -399,9 +397,7 @@ class StorageConfig implements \JsonSerializable {
|
|||
$result['backend'] = $this->backend->getIdentifier();
|
||||
$result['authMechanism'] = $this->authMechanism->getIdentifier();
|
||||
$result['backendOptions'] = $this->backendOptions;
|
||||
if (!is_null($this->priority)) {
|
||||
$result['priority'] = $this->priority;
|
||||
}
|
||||
$result['priority'] = $this->priority;
|
||||
if (!empty($this->applicableUsers)) {
|
||||
$result['applicableUsers'] = $this->applicableUsers;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
namespace OCA\Files_External\Service;
|
||||
|
||||
use OCP\DB\Exception;
|
||||
use OCP\DB\QueryBuilder\IParameter;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Security\ICrypto;
|
||||
|
|
@ -17,7 +18,17 @@ use OCP\Security\ICrypto;
|
|||
* Stores the mount config in the database
|
||||
*
|
||||
* @psalm-type ApplicableConfig = array{type: int, value: string}
|
||||
* @psalm-type StorageConfigData = array{type: int, priority: int, applicable: list<ApplicableConfig>, config: array, options: array, ...<string, mixed>}
|
||||
* @psalm-type ExternalMountInfo = array{
|
||||
* mount_id: int,
|
||||
* mount_point: string,
|
||||
* storage_backend: string,
|
||||
* auth_backend: string,
|
||||
* priority: int,
|
||||
* type: self::MOUNT_TYPE_ADMIN|self::MOUNT_TYPE_PERSONAL,
|
||||
* applicable: list<ApplicableConfig>,
|
||||
* config: array,
|
||||
* options: array,
|
||||
* }
|
||||
*/
|
||||
class DBConfigService {
|
||||
public const MOUNT_TYPE_ADMIN = 1;
|
||||
|
|
@ -35,6 +46,9 @@ class DBConfigService {
|
|||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?ExternalMountInfo
|
||||
*/
|
||||
public function getMountById(int $mountId): ?array {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
|
||||
|
|
@ -51,57 +65,88 @@ class DBConfigService {
|
|||
/**
|
||||
* Get all configured mounts
|
||||
*
|
||||
* @return array
|
||||
* @return list<ExternalMountInfo>
|
||||
*/
|
||||
public function getAllMounts() {
|
||||
public function getAllMounts(): array {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
|
||||
->from('external_mounts');
|
||||
return $this->getMountsFromQuery($query);
|
||||
}
|
||||
|
||||
public function getMountsForUser($userId, $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()->orX(
|
||||
$builder->expr()->andX( // global mounts
|
||||
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
|
||||
$builder->expr()->isNull('a.value'),
|
||||
),
|
||||
$builder->expr()->andX( // mounts for user
|
||||
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)),
|
||||
$builder->expr()->eq('a.value', $builder->createNamedParameter($userId)),
|
||||
),
|
||||
$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)),
|
||||
),
|
||||
));
|
||||
public function getMountsForUser(string $userId, array $groupIds): array {
|
||||
$builder = $this->getSelectQueryBuilder();
|
||||
$builder = $builder->where($builder->expr()->orX(
|
||||
$builder->expr()->andX( // global mounts
|
||||
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
|
||||
$builder->expr()->isNull('a.value'),
|
||||
),
|
||||
$builder->expr()->andX( // mounts for user
|
||||
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)),
|
||||
$builder->expr()->eq('a.value', $builder->createNamedParameter($userId)),
|
||||
),
|
||||
$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 $this->getMountsFromQuery($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $groupIds
|
||||
* @return list<StorageConfigData>
|
||||
* @return list<ExternalMountInfo>
|
||||
*/
|
||||
public function getMountsForGroups(array $groupIds): array {
|
||||
$builder = $this->getSelectQueryBuilder();
|
||||
$builder = $builder->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($builder);
|
||||
}
|
||||
|
||||
private function getSelectQueryBuilder(): IQueryBuilder {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $builder->select(['m.mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'm.type'])
|
||||
return $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
|
||||
->innerJoin('m', 'external_applicable', 'a', $builder->expr()->eq('m.mount_id', 'a.mount_id'));
|
||||
}
|
||||
|
||||
/*
|
||||
* @return list<ExternalMountInfo>
|
||||
*/
|
||||
public function getMountsForUserAndPath(string $userId, array $groupIds, string $path, bool $forChildren): array {
|
||||
$path = str_replace('/' . $userId . '/files', '', $path);
|
||||
$builder = $this->getSelectQueryBuilder();
|
||||
$builder->where($builder->expr()->orX(
|
||||
$builder->expr()->andX( // global mounts
|
||||
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_GLOBAL, IQueryBuilder::PARAM_INT)),
|
||||
$builder->expr()->isNull('a.value'),
|
||||
$forChildren ? $builder->expr()->like('m.mount_point', $builder->createNamedParameter($this->connection->escapeLikeParameter($path) . '_%', IQueryBuilder::PARAM_STR))
|
||||
: $builder->expr()->eq('m.mount_point', $builder->createNamedParameter($path, IQueryBuilder::PARAM_STR)),
|
||||
),
|
||||
$builder->expr()->andX( // mounts for user
|
||||
$builder->expr()->eq('a.type', $builder->createNamedParameter(self::APPLICABLE_TYPE_USER, IQueryBuilder::PARAM_INT)),
|
||||
$builder->expr()->eq('a.value', $builder->createNamedParameter($userId)),
|
||||
$forChildren ? $builder->expr()->like('m.mount_point', $builder->createNamedParameter($this->connection->escapeLikeParameter($path) . '_%', IQueryBuilder::PARAM_STR))
|
||||
: $builder->expr()->eq('m.mount_point', $builder->createNamedParameter($path, IQueryBuilder::PARAM_STR)),
|
||||
),
|
||||
$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)),
|
||||
));
|
||||
$forChildren ? $builder->expr()->like('m.mount_point', $builder->createNamedParameter($this->connection->escapeLikeParameter($path) . '_%', IQueryBuilder::PARAM_STR))
|
||||
: $builder->expr()->eq('m.mount_point', $builder->createNamedParameter($path, IQueryBuilder::PARAM_STR)),
|
||||
),
|
||||
));
|
||||
|
||||
return $this->getMountsFromQuery($query);
|
||||
return $this->getMountsFromQuery($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<StorageConfigData>
|
||||
* @return list<ExternalMountInfo>
|
||||
*/
|
||||
public function getGlobalMounts(): array {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
|
@ -151,9 +196,9 @@ class DBConfigService {
|
|||
/**
|
||||
* Get admin defined mounts
|
||||
*
|
||||
* @return array
|
||||
* @return list<ExternalMountInfo>
|
||||
*/
|
||||
public function getAdminMounts() {
|
||||
public function getAdminMounts(): array {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $builder->select(['mount_id', 'mount_point', 'storage_backend', 'auth_backend', 'priority', 'type'])
|
||||
->from('external_mounts')
|
||||
|
|
@ -161,19 +206,17 @@ class DBConfigService {
|
|||
return $this->getMountsFromQuery($query);
|
||||
}
|
||||
|
||||
protected function getForQuery(IQueryBuilder $builder, $type, $value) {
|
||||
$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()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
|
||||
protected function getForQuery(IQueryBuilder $builder, int $type, ?string $value): IQueryBuilder {
|
||||
$builder = $this->getSelectQueryBuilder();
|
||||
$builder = $builder->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
if (is_null($value)) {
|
||||
$query = $query->andWhere($builder->expr()->isNull('a.value'));
|
||||
$builder = $builder->andWhere($builder->expr()->isNull('a.value'));
|
||||
} else {
|
||||
$query = $query->andWhere($builder->expr()->eq('a.value', $builder->createNamedParameter($value)));
|
||||
$builder = $builder->andWhere($builder->expr()->eq('a.value', $builder->createNamedParameter($value)));
|
||||
}
|
||||
|
||||
return $query;
|
||||
return $builder;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -181,9 +224,9 @@ class DBConfigService {
|
|||
*
|
||||
* @param int $type any of the self::APPLICABLE_TYPE_ constants
|
||||
* @param string|null $value user_id, group_id or null for global mounts
|
||||
* @return array
|
||||
* @return list<ExternalMountInfo>
|
||||
*/
|
||||
public function getMountsFor($type, $value) {
|
||||
public function getMountsFor(int $type, ?string $value): array {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $this->getForQuery($builder, $type, $value);
|
||||
|
||||
|
|
@ -195,9 +238,9 @@ class DBConfigService {
|
|||
*
|
||||
* @param int $type any of the self::APPLICABLE_TYPE_ constants
|
||||
* @param string|null $value user_id, group_id or null for global mounts
|
||||
* @return array
|
||||
* @return list<ExternalMountInfo>
|
||||
*/
|
||||
public function getAdminMountsFor($type, $value) {
|
||||
public function getAdminMountsFor(int $type, ?string $value): array {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $this->getForQuery($builder, $type, $value);
|
||||
$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
|
||||
|
|
@ -210,22 +253,20 @@ class DBConfigService {
|
|||
*
|
||||
* @param int $type any of the self::APPLICABLE_TYPE_ constants
|
||||
* @param string[] $values user_ids or group_ids
|
||||
* @return array
|
||||
* @return list<ExternalMountInfo>
|
||||
*/
|
||||
public function getAdminMountsForMultiple($type, array $values) {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$params = array_map(function ($value) use ($builder) {
|
||||
public function getAdminMountsForMultiple(int $type, array $values): array {
|
||||
$builder = $this->getSelectQueryBuilder();
|
||||
$params = array_map(function (string $value) use ($builder): IParameter {
|
||||
return $builder->createNamedParameter($value, IQueryBuilder::PARAM_STR);
|
||||
}, $values);
|
||||
|
||||
$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'))
|
||||
$builder = $builder
|
||||
->where($builder->expr()->eq('a.type', $builder->createNamedParameter($type, IQueryBuilder::PARAM_INT)))
|
||||
->andWhere($builder->expr()->in('a.value', $params));
|
||||
$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
|
||||
$builder->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_ADMIN, IQueryBuilder::PARAM_INT)));
|
||||
|
||||
return $this->getMountsFromQuery($query);
|
||||
return $this->getMountsFromQuery($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -233,9 +274,9 @@ class DBConfigService {
|
|||
*
|
||||
* @param int $type any of the self::APPLICABLE_TYPE_ constants
|
||||
* @param string|null $value user_id, group_id or null for global mounts
|
||||
* @return array
|
||||
* @return list<ExternalMountInfo>
|
||||
*/
|
||||
public function getUserMountsFor($type, $value) {
|
||||
public function getUserMountsFor(int $type, ?string $value): array {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $this->getForQuery($builder, $type, $value);
|
||||
$query->andWhere($builder->expr()->eq('m.type', $builder->expr()->literal(self::MOUNT_TYPE_PERSONAL, IQueryBuilder::PARAM_INT)));
|
||||
|
|
@ -246,14 +287,10 @@ class DBConfigService {
|
|||
/**
|
||||
* Add a mount to the database
|
||||
*
|
||||
* @param string $mountPoint
|
||||
* @param string $storageBackend
|
||||
* @param string $authBackend
|
||||
* @param int $priority
|
||||
* @param int $type self::MOUNT_TYPE_ADMIN or self::MOUNT_TYPE_PERSONAL
|
||||
* @param self::MOUNT_TYPE_ADMIN|self::MOUNT_TYPE_PERSONAL $type
|
||||
* @return int the id of the new mount
|
||||
*/
|
||||
public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
|
||||
public function addMount(string $mountPoint, string $storageBackend, string $authBackend, ?int $priority, int $type): int {
|
||||
if (!$priority) {
|
||||
$priority = 100;
|
||||
}
|
||||
|
|
@ -272,10 +309,8 @@ class DBConfigService {
|
|||
|
||||
/**
|
||||
* Remove a mount from the database
|
||||
*
|
||||
* @param int $mountId
|
||||
*/
|
||||
public function removeMount($mountId) {
|
||||
public function removeMount(int $mountId): void {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $builder->delete('external_mounts')
|
||||
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)));
|
||||
|
|
@ -297,11 +332,7 @@ class DBConfigService {
|
|||
$query->executeStatement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $mountId
|
||||
* @param string $newMountPoint
|
||||
*/
|
||||
public function setMountPoint($mountId, $newMountPoint) {
|
||||
public function setMountPoint(int $mountId, string $newMountPoint): void {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$query = $builder->update('external_mounts')
|
||||
|
|
@ -311,11 +342,7 @@ class DBConfigService {
|
|||
$query->executeStatement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $mountId
|
||||
* @param string $newAuthBackend
|
||||
*/
|
||||
public function setAuthBackend($mountId, $newAuthBackend) {
|
||||
public function setAuthBackend(int $mountId, string $newAuthBackend): void {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
|
||||
$query = $builder->update('external_mounts')
|
||||
|
|
@ -325,12 +352,7 @@ class DBConfigService {
|
|||
$query->executeStatement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $mountId
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*/
|
||||
public function setConfig($mountId, $key, $value) {
|
||||
public function setConfig(int $mountId, string $key, string $value): void {
|
||||
if ($key === 'password') {
|
||||
$value = $this->encryptValue($value);
|
||||
}
|
||||
|
|
@ -355,12 +377,7 @@ class DBConfigService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $mountId
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
*/
|
||||
public function setOption($mountId, $key, $value) {
|
||||
public function setOption(int $mountId, string $key, string $value): void {
|
||||
try {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$builder->insert('external_options')
|
||||
|
|
@ -381,7 +398,7 @@ class DBConfigService {
|
|||
}
|
||||
}
|
||||
|
||||
public function addApplicable($mountId, $type, $value) {
|
||||
public function addApplicable(int $mountId, int $type, ?string $value): void {
|
||||
try {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$builder->insert('external_applicable')
|
||||
|
|
@ -397,7 +414,7 @@ class DBConfigService {
|
|||
}
|
||||
}
|
||||
|
||||
public function removeApplicable($mountId, $type, $value) {
|
||||
public function removeApplicable(int $mountId, int $type, ?string $value): void {
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$query = $builder->delete('external_applicable')
|
||||
->where($builder->expr()->eq('mount_id', $builder->createNamedParameter($mountId, IQueryBuilder::PARAM_INT)))
|
||||
|
|
@ -413,11 +430,13 @@ class DBConfigService {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return list<StorageConfigData>
|
||||
* @return list<ExternalMountInfo>
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getMountsFromQuery(IQueryBuilder $query): array {
|
||||
$result = $query->executeQuery();
|
||||
$mounts = $result->fetchAllAssociative();
|
||||
/** @var \Generator<array{mount_id: int, mount_point: string, storage_backend: string, auth_backend: string, priority: mixed, type: int}> $mounts */
|
||||
$mounts = $result->iterateAssociative();
|
||||
$uniqueMounts = [];
|
||||
foreach ($mounts as $mount) {
|
||||
$id = $mount['mount_id'];
|
||||
|
|
@ -427,7 +446,7 @@ class DBConfigService {
|
|||
}
|
||||
$uniqueMounts = array_values($uniqueMounts);
|
||||
|
||||
$mountIds = array_map(function ($mount) {
|
||||
$mountIds = array_map(function (array $mount): int {
|
||||
return $mount['mount_id'];
|
||||
}, $uniqueMounts);
|
||||
$mountIds = array_values(array_unique($mountIds));
|
||||
|
|
@ -436,8 +455,10 @@ class DBConfigService {
|
|||
$config = $this->getConfigForMounts($mountIds);
|
||||
$options = $this->getOptionsForMounts($mountIds);
|
||||
|
||||
return array_map(function ($mount, $applicable, $config, $options) {
|
||||
$mount['type'] = (int)$mount['type'];
|
||||
return array_map(function (array $mount, array $applicable, array $config, array $options): array {
|
||||
$mountType = (int)$mount['type'];
|
||||
assert($mountType === self::MOUNT_TYPE_ADMIN || $mountType === self::MOUNT_TYPE_PERSONAL);
|
||||
$mount['type'] = $mountType;
|
||||
$mount['priority'] = (int)$mount['priority'];
|
||||
$mount['applicable'] = $applicable;
|
||||
$mount['config'] = $config;
|
||||
|
|
@ -449,7 +470,6 @@ class DBConfigService {
|
|||
/**
|
||||
* Get mount options from a table grouped by mount id
|
||||
*
|
||||
* @param string $table
|
||||
* @param string[] $fields
|
||||
* @param int[] $mountIds
|
||||
* @return array<int, list<array>> [$mountId => [['field1' => $value1, ...], ...], ...]
|
||||
|
|
@ -460,9 +480,7 @@ class DBConfigService {
|
|||
}
|
||||
$builder = $this->connection->getQueryBuilder();
|
||||
$fields[] = 'mount_id';
|
||||
$placeHolders = array_map(function ($id) use ($builder) {
|
||||
return $builder->createPositionalParameter($id, IQueryBuilder::PARAM_INT);
|
||||
}, $mountIds);
|
||||
$placeHolders = array_map(fn ($id) => $builder->createPositionalParameter($id, IQueryBuilder::PARAM_INT), $mountIds);
|
||||
$query = $builder->select($fields)
|
||||
->from($table)
|
||||
->where($builder->expr()->in('mount_id', $placeHolders));
|
||||
|
|
@ -486,26 +504,28 @@ class DBConfigService {
|
|||
|
||||
/**
|
||||
* @param int[] $mountIds
|
||||
* @return array<int, list<ApplicableConfig>> [$id => [['type' => $type, 'value' => $value], ...], ...]
|
||||
* @return array<int, list<array{type: mixed, value: string}>> [$id => [['type' => $type, 'value' => $value], ...], ...]
|
||||
*/
|
||||
public function getApplicableForMounts(array $mountIds): array {
|
||||
return $this->selectForMounts('external_applicable', ['type', 'value'], $mountIds);
|
||||
/** @var array<int, list<array{type: mixed, value: string}>> $result */
|
||||
$result = $this->selectForMounts('external_applicable', ['type', 'value'], $mountIds);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $mountIds
|
||||
* @return array [$id => ['key1' => $value1, ...], ...]
|
||||
* @return array<int, array> [$id => ['key1' => $value1, ...], ...]
|
||||
*/
|
||||
public function getConfigForMounts($mountIds) {
|
||||
public function getConfigForMounts(array $mountIds): array {
|
||||
$mountConfigs = $this->selectForMounts('external_config', ['key', 'value'], $mountIds);
|
||||
return array_map([$this, 'createKeyValueMap'], $mountConfigs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $mountIds
|
||||
* @return array [$id => ['key1' => $value1, ...], ...]
|
||||
* @return array<int, array> [$id => ['key1' => $value1, ...], ...]
|
||||
*/
|
||||
public function getOptionsForMounts($mountIds) {
|
||||
public function getOptionsForMounts(array $mountIds): array {
|
||||
$mountOptions = $this->selectForMounts('external_options', ['key', 'value'], $mountIds);
|
||||
$optionsMap = array_map([$this, 'createKeyValueMap'], $mountOptions);
|
||||
return array_map(function (array $options) {
|
||||
|
|
@ -516,10 +536,10 @@ class DBConfigService {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array $keyValuePairs [['key'=>$key, 'value=>$value], ...]
|
||||
* @param list<array{key: string, value: string}> $keyValuePairs [['key'=>$key, 'value=>$value], ...]
|
||||
* @return array ['key1' => $value1, ...]
|
||||
*/
|
||||
private function createKeyValueMap(array $keyValuePairs) {
|
||||
private function createKeyValueMap(array $keyValuePairs): array {
|
||||
$decryptedPairts = array_map(function ($pair) {
|
||||
if ($pair['key'] === 'password') {
|
||||
$pair['value'] = $this->decryptValue($pair['value']);
|
||||
|
|
@ -536,14 +556,14 @@ class DBConfigService {
|
|||
return array_combine($keys, $values);
|
||||
}
|
||||
|
||||
private function encryptValue($value) {
|
||||
private function encryptValue(string $value): string {
|
||||
return $this->crypto->encrypt($value);
|
||||
}
|
||||
|
||||
private function decryptValue($value) {
|
||||
private function decryptValue(string $value): string {
|
||||
try {
|
||||
return $this->crypto->decrypt($value);
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Exception) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,10 +120,9 @@ abstract class StoragesService {
|
|||
*
|
||||
* @param int $id storage id
|
||||
*
|
||||
* @return StorageConfig
|
||||
* @throws NotFoundException if the storage with the given id was not found
|
||||
*/
|
||||
public function getStorage(int $id) {
|
||||
public function getStorage(int $id): StorageConfig {
|
||||
$mount = $this->dbConfig->getMountById($id);
|
||||
|
||||
if (!is_array($mount)) {
|
||||
|
|
|
|||
|
|
@ -58,18 +58,18 @@ class UserGlobalStoragesService extends GlobalStoragesService {
|
|||
return array_merge($userMounts, $groupMounts, $globalMounts);
|
||||
}
|
||||
|
||||
public function addStorage(StorageConfig $newStorage) {
|
||||
public function addStorage(StorageConfig $newStorage): never {
|
||||
throw new \DomainException('UserGlobalStoragesService writing disallowed');
|
||||
}
|
||||
|
||||
public function updateStorage(StorageConfig $updatedStorage) {
|
||||
public function updateStorage(StorageConfig $updatedStorage): never {
|
||||
throw new \DomainException('UserGlobalStoragesService writing disallowed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $id
|
||||
*/
|
||||
public function removeStorage($id) {
|
||||
public function removeStorage($id): never {
|
||||
throw new \DomainException('UserGlobalStoragesService writing disallowed');
|
||||
}
|
||||
|
||||
|
|
@ -164,16 +164,33 @@ class UserGlobalStoragesService extends GlobalStoragesService {
|
|||
}
|
||||
$groupIds = $this->groupManager->getUserGroupIds($user);
|
||||
$mounts = $this->dbConfig->getMountsForUser($user->getUID(), $groupIds);
|
||||
$configs = array_map([$this, 'getStorageConfigFromDBMount'], $mounts);
|
||||
$configs = array_filter($configs, function ($config) {
|
||||
return $config instanceof StorageConfig;
|
||||
});
|
||||
$configs = array_map($this->getStorageConfigFromDBMount(...), $mounts);
|
||||
$configs = array_filter($configs, static fn ($config) => $config instanceof StorageConfig);
|
||||
|
||||
$keys = array_map(function (StorageConfig $config) {
|
||||
return $config->getId();
|
||||
}, $configs);
|
||||
$keys = array_map(static fn (StorageConfig $config) => $config->getId(), $configs);
|
||||
|
||||
$storages = array_combine($keys, $configs);
|
||||
return array_filter($storages, [$this, 'validateStorage']);
|
||||
return array_filter($storages, $this->validateStorage(...));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return StorageConfig[]
|
||||
*/
|
||||
public function getAllStoragesForUserWithPath(string $path, bool $forChildren): array {
|
||||
$user = $this->getUser();
|
||||
|
||||
if (is_null($user)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$groupIds = $this->groupManager->getUserGroupIds($user);
|
||||
$mounts = $this->dbConfig->getMountsForUserAndPath($user->getUID(), $groupIds, $path, $forChildren);
|
||||
$configs = array_map($this->getStorageConfigFromDBMount(...), $mounts);
|
||||
$configs = array_filter($configs, static fn ($config) => $config instanceof StorageConfig);
|
||||
$keys = array_map(static fn (StorageConfig $config) => $config->getId(), $configs);
|
||||
|
||||
$storages = array_combine($keys, $configs);
|
||||
return array_filter($storages, $this->validateStorage(...));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,11 +116,11 @@ class UserStoragesService extends StoragesService {
|
|||
*
|
||||
* @return int BackendService::VISIBILITY_* constants
|
||||
*/
|
||||
public function getVisibilityType() {
|
||||
public function getVisibilityType(): int {
|
||||
return BackendService::VISIBILITY_PERSONAL;
|
||||
}
|
||||
|
||||
protected function isApplicable(StorageConfig $config) {
|
||||
protected function isApplicable(StorageConfig $config): bool {
|
||||
return ($config->getApplicableUsers() === [$this->getUser()->getUID()]) && $config->getType() === StorageConfig::MOUNT_TYPE_PERSONAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
226
apps/files_external/tests/Config/ConfigAdapterTest.php
Normal file
226
apps/files_external/tests/Config/ConfigAdapterTest.php
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH
|
||||
* SPDX-FileContributor: Carl Schwan
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\Files_External\Tests\Config;
|
||||
|
||||
use OC\Files\Storage\StorageFactory;
|
||||
use OCA\Files_External\Config\ConfigAdapter;
|
||||
use OCA\Files_External\Lib\Auth\AuthMechanism;
|
||||
use OCA\Files_External\Lib\Auth\NullMechanism;
|
||||
use OCA\Files_External\Lib\Backend\Backend;
|
||||
use OCA\Files_External\Lib\Backend\SMB;
|
||||
use OCA\Files_External\Lib\StorageConfig;
|
||||
use OCA\Files_External\Service\BackendService;
|
||||
use OCA\Files_External\Service\UserGlobalStoragesService;
|
||||
use OCA\Files_External\Service\UserStoragesService;
|
||||
use OCP\Files\Cache\ICacheEntry;
|
||||
use OCP\Files\Config\ICachedMountFileInfo;
|
||||
use OCP\Files\Config\MountProviderArgs;
|
||||
use OCP\IUser;
|
||||
use OCP\Server;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use PHPUnit\Framework\Attributes\Group;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Clock\ClockInterface;
|
||||
use Test\TestCase;
|
||||
|
||||
#[Group(name: 'DB')]
|
||||
class ConfigAdapterTest extends TestCase {
|
||||
private ConfigAdapter $adapter;
|
||||
private BackendService&MockObject $backendService;
|
||||
private IUser&MockObject $user;
|
||||
private UserStoragesService $userStoragesService;
|
||||
private UserGlobalStoragesService $userGlobalStoragesService;
|
||||
private array $storageIds = [];
|
||||
|
||||
protected function makeStorageConfig(array $data): StorageConfig {
|
||||
$storage = new StorageConfig();
|
||||
if (isset($data['id'])) {
|
||||
$storage->setId($data['id']);
|
||||
}
|
||||
$storage->setMountPoint($data['mountPoint']);
|
||||
$data['backend'] = $this->backendService->getBackend($data['backendIdentifier']);
|
||||
if (!isset($data['backend'])) {
|
||||
throw new \Exception('oops, no backend');
|
||||
}
|
||||
$data['authMechanism'] = $this->backendService->getAuthMechanism($data['authMechanismIdentifier']);
|
||||
if (!isset($data['authMechanism'])) {
|
||||
throw new \Exception('oops, no auth mechanism');
|
||||
}
|
||||
$storage->setId(StorageConfig::MOUNT_TYPE_PERSONAL);
|
||||
$storage->setApplicableUsers([$this->user->getUID()]);
|
||||
$storage->setBackend($data['backend']);
|
||||
$storage->setAuthMechanism($data['authMechanism']);
|
||||
$storage->setBackendOptions($data['backendOptions']);
|
||||
$storage->setPriority($data['priority']);
|
||||
if (isset($data['mountOptions'])) {
|
||||
$storage->setMountOptions($data['mountOptions']);
|
||||
}
|
||||
return $storage;
|
||||
}
|
||||
|
||||
protected function getBackendMock($class = SMB::class, $storageClass = \OCA\Files_External\Lib\Storage\SMB::class) {
|
||||
$backend = $this->createMock(Backend::class);
|
||||
$backend->method('getStorageClass')
|
||||
->willReturn($storageClass);
|
||||
$backend->method('getIdentifier')
|
||||
->willReturn('identifier:' . $class);
|
||||
return $backend;
|
||||
}
|
||||
|
||||
protected function getAuthMechMock($scheme = 'null', $class = NullMechanism::class) {
|
||||
$authMech = $this->createMock(AuthMechanism::class);
|
||||
$authMech->method('getScheme')
|
||||
->willReturn($scheme);
|
||||
$authMech->method('getIdentifier')
|
||||
->willReturn('identifier:' . $class);
|
||||
|
||||
return $authMech;
|
||||
}
|
||||
|
||||
public function setUp(): void {
|
||||
// prepare BackendService mock
|
||||
$this->backendService = $this->createMock(BackendService::class);
|
||||
|
||||
$authMechanisms = [
|
||||
'identifier:\Auth\Mechanism' => $this->getAuthMechMock('null', '\Auth\Mechanism'),
|
||||
'identifier:\Other\Auth\Mechanism' => $this->getAuthMechMock('null', '\Other\Auth\Mechanism'),
|
||||
'identifier:\OCA\Files_External\Lib\Auth\NullMechanism' => $this->getAuthMechMock(),
|
||||
];
|
||||
$this->backendService->method('getAuthMechanism')
|
||||
->willReturnCallback(function ($class) use ($authMechanisms) {
|
||||
if (isset($authMechanisms[$class])) {
|
||||
return $authMechanisms[$class];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
$this->backendService->method('getAuthMechanismsByScheme')
|
||||
->willReturnCallback(function ($schemes) use ($authMechanisms) {
|
||||
return array_filter($authMechanisms, function ($authMech) use ($schemes) {
|
||||
return in_array($authMech->getScheme(), $schemes, true);
|
||||
});
|
||||
});
|
||||
|
||||
$backends = [
|
||||
'identifier:\OCA\Files_External\Lib\Backend\DAV' => $this->getBackendMock('\OCA\Files_External\Lib\Backend\DAV', '\OC\Files\Storage\DAV'),
|
||||
'identifier:\OCA\Files_External\Lib\Backend\SMB' => $this->getBackendMock('\OCA\Files_External\Lib\Backend\SMB', '\OCA\Files_External\Lib\Storage\SMB'),
|
||||
];
|
||||
$this->backendService->method('getBackend')
|
||||
->willReturnCallback(function ($backendClass) use ($backends) {
|
||||
if (isset($backends[$backendClass])) {
|
||||
return $backends[$backendClass];
|
||||
}
|
||||
return null;
|
||||
});
|
||||
$this->backendService->method('getAuthMechanisms')
|
||||
->willReturn($authMechanisms);
|
||||
$this->backendService->method('getBackends')
|
||||
->willReturn($backends);
|
||||
|
||||
$this->userStoragesService = Server::get(UserStoragesService::class);
|
||||
$this->userGlobalStoragesService = Server::get(UserGlobalStoragesService::class);
|
||||
$this->adapter = new ConfigAdapter($this->userStoragesService, $this->userGlobalStoragesService, $this->createMock(ClockInterface::class));
|
||||
|
||||
$this->user = $this->createMock(IUser::class);
|
||||
$this->user->method('getUID')->willReturn('user1');
|
||||
|
||||
$this->userStoragesService->setUser($this->user);
|
||||
|
||||
$storageConfig = $this->makeStorageConfig([
|
||||
'mountPoint' => '/mountpoint',
|
||||
'backendIdentifier' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
||||
'authMechanismIdentifier' => 'identifier:\Auth\Mechanism',
|
||||
'backendOptions' => [
|
||||
'option1' => 'value1',
|
||||
'option2' => 'value2',
|
||||
'password' => 'testPassword',
|
||||
],
|
||||
'priority' => 15,
|
||||
'mountOptions' => [
|
||||
'preview' => false,
|
||||
]
|
||||
]);
|
||||
$this->storageIds[] = $this->userStoragesService->addStorage($storageConfig)->getId();
|
||||
|
||||
$storageConfig = $this->makeStorageConfig([
|
||||
'mountPoint' => '/subfolder/mountpoint',
|
||||
'backendIdentifier' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
||||
'authMechanismIdentifier' => 'identifier:\Auth\Mechanism',
|
||||
'backendOptions' => [
|
||||
'option1' => 'value1',
|
||||
'option2' => 'value2',
|
||||
'password' => 'testPassword',
|
||||
],
|
||||
'priority' => 15,
|
||||
'mountOptions' => [
|
||||
'preview' => false,
|
||||
]
|
||||
]);
|
||||
$this->storageIds[] = $this->userStoragesService->addStorage($storageConfig)->getId();
|
||||
|
||||
$storageConfig = $this->makeStorageConfig([
|
||||
'mountPoint' => '/subfolder/subfolder/mountpoint',
|
||||
'backendIdentifier' => 'identifier:\OCA\Files_External\Lib\Backend\SMB',
|
||||
'authMechanismIdentifier' => 'identifier:\Auth\Mechanism',
|
||||
'backendOptions' => [
|
||||
'option1' => 'value1',
|
||||
'option2' => 'value2',
|
||||
'password' => 'testPassword',
|
||||
],
|
||||
'priority' => 15,
|
||||
'mountOptions' => [
|
||||
'preview' => false,
|
||||
]
|
||||
]);
|
||||
$this->storageIds[] = $this->userStoragesService->addStorage($storageConfig)->getId();
|
||||
}
|
||||
|
||||
public function tearDown(): void {
|
||||
$this->user = $this->createMock(IUser::class);
|
||||
$this->user->method('getUID')->willReturn('user1');
|
||||
$this->userStoragesService->setUser($this->user);
|
||||
foreach ($this->storageIds as $storageId) {
|
||||
$this->userStoragesService->removeStorage($storageId);
|
||||
}
|
||||
}
|
||||
|
||||
public static function pathsProvider(): \Generator {
|
||||
yield ['/user1/files/subfolder', 2];
|
||||
yield ['/user1/files/subfolder/subfolder', 1];
|
||||
yield ['/user1/files/nothing', 0];
|
||||
yield ['/user1/files/mountpoint', 0]; // we only want the children
|
||||
}
|
||||
|
||||
#[DataProvider(methodName: 'pathsProvider')]
|
||||
public function testPartialMountpointWithChildren(string $path, int $count): void {
|
||||
$mountFileInfo = $this->createMock(ICachedMountFileInfo::class);
|
||||
$mountFileInfo->method('getUser')->willReturn($this->user);
|
||||
$cacheEntry = $this->createMock(ICacheEntry::class);
|
||||
|
||||
$result = $this->adapter->getMountsForPath($path, true, [
|
||||
new MountProviderArgs($mountFileInfo, $cacheEntry),
|
||||
], $this->createMock(StorageFactory::class));
|
||||
|
||||
$this->assertCount($count, $result);
|
||||
}
|
||||
|
||||
public function testPartialMountpointExact(): void {
|
||||
$mountFileInfo = $this->createMock(ICachedMountFileInfo::class);
|
||||
$mountFileInfo->method('getUser')->willReturn($this->user);
|
||||
$mountFileInfo->method('getMountPoint')->willReturn('/user1/files/subfolder/subfolder');
|
||||
$cacheEntry = $this->createMock(ICacheEntry::class);
|
||||
|
||||
$result = $this->adapter->getMountsForPath('/user1/files/subfolder/subfolder', true, [
|
||||
new MountProviderArgs($mountFileInfo, $cacheEntry),
|
||||
], $this->createMock(StorageFactory::class));
|
||||
|
||||
$this->assertCount(1, $result);
|
||||
}
|
||||
}
|
||||
|
|
@ -40,13 +40,13 @@ use PHPUnit\Framework\MockObject\MockObject;
|
|||
class CleaningDBConfig extends DBConfigService {
|
||||
private array $mountIds = [];
|
||||
|
||||
public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type) {
|
||||
public function addMount($mountPoint, $storageBackend, $authBackend, $priority, $type): int {
|
||||
$id = parent::addMount($mountPoint, $storageBackend, $authBackend, $priority, $type); // TODO: Change the autogenerated stub
|
||||
$this->mountIds[] = $id;
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function clean() {
|
||||
public function clean(): void {
|
||||
foreach ($this->mountIds as $id) {
|
||||
$this->removeMount($id);
|
||||
}
|
||||
|
|
@ -205,6 +205,7 @@ abstract class StoragesServiceTestCase extends \Test\TestCase {
|
|||
if (isset($data['mountOptions'])) {
|
||||
$storage->setMountOptions($data['mountOptions']);
|
||||
}
|
||||
$storage->setPriority(100);
|
||||
return $storage;
|
||||
}
|
||||
|
||||
|
|
@ -258,6 +259,7 @@ abstract class StoragesServiceTestCase extends \Test\TestCase {
|
|||
$storage->setBackend($backend);
|
||||
$storage->setAuthMechanism($authMechanism);
|
||||
$storage->setBackendOptions($backendOptions);
|
||||
$storage->setPriority(0);
|
||||
|
||||
$newStorage = $this->service->addStorage($storage);
|
||||
$id = $newStorage->getId();
|
||||
|
|
@ -399,6 +401,7 @@ abstract class StoragesServiceTestCase extends \Test\TestCase {
|
|||
$storage->setBackend($backend);
|
||||
$storage->setAuthMechanism($authMechanism);
|
||||
$storage->setBackendOptions(['password' => 'testPassword']);
|
||||
$storage->setPriority(0);
|
||||
|
||||
$newStorage = $this->service->addStorage($storage);
|
||||
|
||||
|
|
@ -424,6 +427,7 @@ abstract class StoragesServiceTestCase extends \Test\TestCase {
|
|||
$storage->setBackend($backend);
|
||||
$storage->setAuthMechanism($authMechanism);
|
||||
$storage->setBackendOptions(['password' => 'testPassword']);
|
||||
$storage->setPriority(0);
|
||||
|
||||
$newStorage = $this->service->addStorage($storage);
|
||||
|
||||
|
|
@ -480,6 +484,7 @@ abstract class StoragesServiceTestCase extends \Test\TestCase {
|
|||
$storage->setBackend($backend);
|
||||
$storage->setAuthMechanism($authMechanism);
|
||||
$storage->setBackendOptions(['password' => 'testPassword']);
|
||||
$storage->setPriority(0);
|
||||
|
||||
$savedStorage = $this->service->addStorage($storage);
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ class UserGlobalStoragesServiceTest extends GlobalStoragesServiceTest {
|
|||
$storage->setBackendOptions(['password' => 'testPassword']);
|
||||
$storage->setApplicableUsers($applicableUsers);
|
||||
$storage->setApplicableGroups($applicableGroups);
|
||||
$storage->setPriority(0);
|
||||
|
||||
$newStorage = $this->globalStoragesService->addStorage($storage);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue