/** * Triggers signal_create_mount or signal_delete_mount to * accomodate for additions/deletions in applicableUsers * and applicableGroups fields. * * @param StorageConfig $oldStorage old storage config * @param StorageConfig $newStorage new storage config */ protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage) { // if mount point changed, it's like a deletion + creation if ($oldStorage->getMountPoint() !== $newStorage->getMountPoint()) { $this->triggerHooks($oldStorage, Filesystem::signal_delete_mount); $this->triggerHooks($newStorage, Filesystem::signal_create_mount); return; } $userAdditions = array_diff($newStorage->getApplicableUsers(), $oldStorage->getApplicableUsers()); $userDeletions = array_diff($oldStorage->getApplicableUsers(), $newStorage->getApplicableUsers()); $groupAdditions = array_diff($newStorage->getApplicableGroups(), $oldStorage->getApplicableGroups()); $groupDeletions = array_diff($oldStorage->getApplicableGroups(), $newStorage->getApplicableGroups()); // FIXME: Use as expression in empty once PHP 5.4 support is dropped // if no applicable were set, raise a signal for "all" $oldApplicableUsers = $oldStorage->getApplicableUsers(); $oldApplicableGroups = $oldStorage->getApplicableGroups(); if (empty($oldApplicableUsers) && empty($oldApplicableGroups)) { $this->triggerApplicableHooks(Filesystem::signal_delete_mount, $oldStorage->getMountPoint(), \OC_Mount_Config::MOUNT_TYPE_USER, ['all']); } // trigger delete for removed users $this->triggerApplicableHooks(Filesystem::signal_delete_mount, $oldStorage->getMountPoint(), \OC_Mount_Config::MOUNT_TYPE_USER, $userDeletions); // trigger delete for removed groups $this->triggerApplicableHooks(Filesystem::signal_delete_mount, $oldStorage->getMountPoint(), \OC_Mount_Config::MOUNT_TYPE_GROUP, $groupDeletions); // and now add the new users $this->triggerApplicableHooks(Filesystem::signal_create_mount, $newStorage->getMountPoint(), \OC_Mount_Config::MOUNT_TYPE_USER, $userAdditions); // and now add the new groups $this->triggerApplicableHooks(Filesystem::signal_create_mount, $newStorage->getMountPoint(), \OC_Mount_Config::MOUNT_TYPE_GROUP, $groupAdditions); // FIXME: Use as expression in empty once PHP 5.4 support is dropped // if no applicable, raise a signal for "all" $newApplicableUsers = $newStorage->getApplicableUsers(); $newApplicableGroups = $newStorage->getApplicableGroups(); if (empty($newApplicableUsers) && empty($newApplicableGroups)) { $this->triggerApplicableHooks(Filesystem::signal_create_mount, $newStorage->getMountPoint(), \OC_Mount_Config::MOUNT_TYPE_USER, ['all']); } }
/** * Triggers signal_create_mount or signal_delete_mount to * accomodate for additions/deletions in applicableUsers * and applicableGroups fields. * * @param StorageConfig $oldStorage old storage data * @param StorageConfig $newStorage new storage data */ protected function triggerChangeHooks(StorageConfig $oldStorage, StorageConfig $newStorage) { // if mount point changed, it's like a deletion + creation if ($oldStorage->getMountPoint() !== $newStorage->getMountPoint()) { $this->triggerHooks($oldStorage, Filesystem::signal_delete_mount); $this->triggerHooks($newStorage, Filesystem::signal_create_mount); } }
/** * @param StorageConfig $mount * @param string $key * @param OutputInterface $output */ protected function getOption(StorageConfig $mount, $key, OutputInterface $output) { if ($key === 'mountpoint' || $key === 'mount_point') { $value = $mount->getMountPoint(); } else { $value = $mount->getBackendOption($key); } if (!is_string($value)) { // show bools and objects correctly $value = json_encode($value); } $output->writeln($value); }
/** * Validate storage config * * @param StorageConfig $storage storage config * * @return DataResponse|null returns response in case of validation error */ protected function validate(StorageConfig $storage) { $mountPoint = $storage->getMountPoint(); if ($mountPoint === '' || $mountPoint === '/') { return new DataResponse(array('message' => (string) $this->l10n->t('Invalid mount point')), Http::STATUS_UNPROCESSABLE_ENTITY); } // TODO: validate that other attrs are set $backends = \OC_Mount_Config::getBackends(); if (!isset($backends[$storage->getBackendClass()])) { // invalid backend return new DataResponse(array('message' => (string) $this->l10n->t('Invalid storage backend "%s"', array($storage->getBackendClass()))), Http::STATUS_UNPROCESSABLE_ENTITY); } return null; }
/** * Convert a StorageConfig to the legacy mountPoints array format * There's a lot of extra information in here, to satisfy all of the legacy functions * * @param StorageConfig $storage * @param bool $isPersonal * @return array */ private static function prepareMountPointEntry(StorageConfig $storage, $isPersonal) { $mountEntry = []; $mountEntry['mountpoint'] = substr($storage->getMountPoint(), 1); // remove leading slash $mountEntry['class'] = $storage->getBackend()->getIdentifier(); $mountEntry['backend'] = $storage->getBackend()->getText(); $mountEntry['authMechanism'] = $storage->getAuthMechanism()->getIdentifier(); $mountEntry['personal'] = $isPersonal; $mountEntry['options'] = self::decryptPasswords($storage->getBackendOptions()); $mountEntry['mountOptions'] = $storage->getMountOptions(); $mountEntry['priority'] = $storage->getPriority(); $mountEntry['applicable'] = ['groups' => $storage->getApplicableGroups(), 'users' => $storage->getApplicableUsers()]; // if mountpoint is applicable to all users the old API expects ['all'] if (empty($mountEntry['applicable']['groups']) && empty($mountEntry['applicable']['users'])) { $mountEntry['applicable']['users'] = ['all']; } $mountEntry['id'] = $storage->getId(); return $mountEntry; }
/** * Add new storage to the configuration * * @param StorageConfig $newStorage storage attributes * * @return StorageConfig storage config, with added id */ public function addStorage(StorageConfig $newStorage) { $allStorages = $this->readConfig(); $configId = $this->dbConfig->addMount($newStorage->getMountPoint(), $newStorage->getBackend()->getIdentifier(), $newStorage->getAuthMechanism()->getIdentifier(), $newStorage->getPriority(), $this->getType()); $newStorage->setId($configId); foreach ($newStorage->getApplicableUsers() as $user) { $this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_USER, $user); } foreach ($newStorage->getApplicableGroups() as $group) { $this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_GROUP, $group); } foreach ($newStorage->getBackendOptions() as $key => $value) { $this->dbConfig->setConfig($configId, $key, $value); } foreach ($newStorage->getMountOptions() as $key => $value) { $this->dbConfig->setOption($configId, $key, $value); } if (count($newStorage->getApplicableUsers()) === 0 && count($newStorage->getApplicableGroups()) === 0) { $this->dbConfig->addApplicable($configId, DBConfigService::APPLICABLE_TYPE_GLOBAL, null); } // add new storage $allStorages[$configId] = $newStorage; $this->triggerHooks($newStorage, Filesystem::signal_create_mount); $newStorage->setStatus(StorageNotAvailableException::STATUS_SUCCESS); return $newStorage; }
/** * Update storage to the configuration * * @param StorageConfig $updatedStorage storage attributes * * @return StorageConfig storage config * @throws NotFoundException if the given storage does not exist in the config */ public function updateStorage(StorageConfig $updatedStorage) { $id = $updatedStorage->getId(); $existingMount = $this->dbConfig->getMountById($id); if (!is_array($existingMount)) { throw new NotFoundException('Storage with id "' . $id . '" not found while updating storage'); } $oldStorage = $this->getStorageConfigFromDBMount($existingMount); $removedUsers = array_diff($oldStorage->getApplicableUsers(), $updatedStorage->getApplicableUsers()); $removedGroups = array_diff($oldStorage->getApplicableGroups(), $updatedStorage->getApplicableGroups()); $addedUsers = array_diff($updatedStorage->getApplicableUsers(), $oldStorage->getApplicableUsers()); $addedGroups = array_diff($updatedStorage->getApplicableGroups(), $oldStorage->getApplicableGroups()); $oldUserCount = count($oldStorage->getApplicableUsers()); $oldGroupCount = count($oldStorage->getApplicableGroups()); $newUserCount = count($updatedStorage->getApplicableUsers()); $newGroupCount = count($updatedStorage->getApplicableGroups()); $wasGlobal = $oldUserCount + $oldGroupCount === 0; $isGlobal = $newUserCount + $newGroupCount === 0; foreach ($removedUsers as $user) { $this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, $user); } foreach ($removedGroups as $group) { $this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_GROUP, $group); } foreach ($addedUsers as $user) { $this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_USER, $user); } foreach ($addedGroups as $group) { $this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GROUP, $group); } if ($wasGlobal && !$isGlobal) { $this->dbConfig->removeApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null); } else { if (!$wasGlobal && $isGlobal) { $this->dbConfig->addApplicable($id, DBConfigService::APPLICABLE_TYPE_GLOBAL, null); } } $changedConfig = array_diff_assoc($updatedStorage->getBackendOptions(), $oldStorage->getBackendOptions()); $changedOptions = array_diff_assoc($updatedStorage->getMountOptions(), $oldStorage->getMountOptions()); foreach ($changedConfig as $key => $value) { $this->dbConfig->setConfig($id, $key, $value); } foreach ($changedOptions as $key => $value) { $this->dbConfig->setOption($id, $key, $value); } if ($updatedStorage->getMountPoint() !== $oldStorage->getMountPoint()) { $this->dbConfig->setMountPoint($id, $updatedStorage->getMountPoint()); } if ($updatedStorage->getAuthMechanism()->getIdentifier() !== $oldStorage->getAuthMechanism()->getIdentifier()) { $this->dbConfig->setAuthBackend($id, $updatedStorage->getAuthMechanism()->getIdentifier()); } $this->triggerChangeHooks($oldStorage, $updatedStorage); if ($wasGlobal && !$isGlobal || count($removedGroups) > 0) { // to expensive to properly handle these on the fly $this->userMountCache->remoteStorageMounts($this->getStorageId($updatedStorage)); } else { $storageId = $this->getStorageId($updatedStorage); foreach ($removedUsers as $userId) { $this->userMountCache->removeUserStorageMount($storageId, $userId); } } return $this->getStorage($id); }
/** * Validate storage config * * @param StorageConfig $storage storage config * * @return DataResponse|null returns response in case of validation error */ protected function validate(StorageConfig $storage) { $mountPoint = $storage->getMountPoint(); if ($mountPoint === '' || $mountPoint === '/') { return new DataResponse(array('message' => (string) $this->l10n->t('Invalid mount point')), Http::STATUS_UNPROCESSABLE_ENTITY); } if ($storage->getBackendOption('objectstore')) { // objectstore must not be sent from client side return new DataResponse(array('message' => (string) $this->l10n->t('Objectstore forbidden')), Http::STATUS_UNPROCESSABLE_ENTITY); } /** @var Backend */ $backend = $storage->getBackend(); /** @var AuthMechanism */ $authMechanism = $storage->getAuthMechanism(); if ($backend->checkDependencies()) { // invalid backend return new DataResponse(array('message' => (string) $this->l10n->t('Invalid storage backend "%s"', [$backend->getIdentifier()])), Http::STATUS_UNPROCESSABLE_ENTITY); } if (!$backend->isVisibleFor($this->service->getVisibilityType())) { // not permitted to use backend return new DataResponse(array('message' => (string) $this->l10n->t('Not permitted to use backend "%s"', [$backend->getIdentifier()])), Http::STATUS_UNPROCESSABLE_ENTITY); } if (!$authMechanism->isVisibleFor($this->service->getVisibilityType())) { // not permitted to use auth mechanism return new DataResponse(array('message' => (string) $this->l10n->t('Not permitted to use authentication mechanism "%s"', [$authMechanism->getIdentifier()])), Http::STATUS_UNPROCESSABLE_ENTITY); } if (!$backend->validateStorage($storage)) { // unsatisfied parameters return new DataResponse(array('message' => (string) $this->l10n->t('Unsatisfied backend parameters')), Http::STATUS_UNPROCESSABLE_ENTITY); } if (!$authMechanism->validateStorage($storage)) { // unsatisfied parameters return new DataResponse(['message' => (string) $this->l10n->t('Unsatisfied authentication mechanism parameters')], Http::STATUS_UNPROCESSABLE_ENTITY); } return null; }
/** * Convert a StorageConfig to the legacy mountPoints array format * There's a lot of extra information in here, to satisfy all of the legacy functions * * @param StorageConfig $storage * @param bool $isPersonal * @return array */ private static function prepareMountPointEntry(StorageConfig $storage, $isPersonal) { $mountEntry = []; $mountEntry['mountpoint'] = substr($storage->getMountPoint(), 1); // remove leading slash $mountEntry['class'] = $storage->getBackend()->getIdentifier(); $mountEntry['backend'] = $storage->getBackend()->getText(); $mountEntry['authMechanism'] = $storage->getAuthMechanism()->getIdentifier(); $mountEntry['personal'] = $isPersonal; $mountEntry['options'] = self::decryptPasswords($storage->getBackendOptions()); $mountEntry['mountOptions'] = $storage->getMountOptions(); $mountEntry['priority'] = $storage->getPriority(); $mountEntry['applicable'] = ['groups' => $storage->getApplicableGroups(), 'users' => $storage->getApplicableUsers()]; $mountEntry['id'] = $storage->getId(); // $mountEntry['storage_id'] = null; // we don't store this! return $mountEntry; }
/** * Validate storage config * * @param StorageConfig $storage storage config * * @return DataResponse|null returns response in case of validation error */ protected function validate(StorageConfig $storage) { $mountPoint = $storage->getMountPoint(); if ($mountPoint === '' || $mountPoint === '/') { return new DataResponse(array('message' => (string) $this->l10n->t('Invalid mount point')), Http::STATUS_UNPROCESSABLE_ENTITY); } /** @var Backend */ $backend = $storage->getBackend(); /** @var AuthMechanism */ $authMechanism = $storage->getAuthMechanism(); if (!$backend || $backend->checkDependencies()) { // invalid backend return new DataResponse(array('message' => (string) $this->l10n->t('Invalid storage backend "%s"', [$storage->getBackend()->getIdentifier()])), Http::STATUS_UNPROCESSABLE_ENTITY); } if (!$backend->validateStorage($storage)) { // unsatisfied parameters return new DataResponse(array('message' => (string) $this->l10n->t('Unsatisfied backend parameters')), Http::STATUS_UNPROCESSABLE_ENTITY); } if (!$authMechanism->validateStorage($storage)) { // unsatisfied parameters return new DataResponse(['message' => (string) $this->l10n->t('Unsatisfied authentication mechanism parameters')], Http::STATUS_UNPROCESSABLE_ENTITY); } return null; }