From 5d14fd4396b54134ce04809a10f46b084107003b Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 23 Mar 2021 16:59:05 +0100 Subject: Make extra user profile fields always editable The fields for phone number, address, website and twitter are now editable regardless whether federated sharing and the lookup server are enabled or not. Signed-off-by: Vincent Petry --- .../lib/Controller/UsersController.php | 31 ++++++---------------- 1 file changed, 8 insertions(+), 23 deletions(-) (limited to 'apps/provisioning_api/lib/Controller/UsersController.php') diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index d2f9b9e91c2..3a1dcd4f43a 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -50,7 +50,6 @@ use OC\Accounts\AccountManager; use OC\Authentication\Token\RemoteWipe; use OC\HintException; use OC\KnownUser\KnownUserService; -use OCA\Provisioning_API\FederatedShareProviderFactory; use OCA\Settings\Mailer\NewUserMailHelper; use OCP\Accounts\IAccountManager; use OCP\App\IAppManager; @@ -85,8 +84,6 @@ class UsersController extends AUserData { protected $l10nFactory; /** @var NewUserMailHelper */ private $newUserMailHelper; - /** @var FederatedShareProviderFactory */ - private $federatedShareProviderFactory; /** @var ISecureRandom */ private $secureRandom; /** @var RemoteWipe */ @@ -108,7 +105,6 @@ class UsersController extends AUserData { LoggerInterface $logger, IFactory $l10nFactory, NewUserMailHelper $newUserMailHelper, - FederatedShareProviderFactory $federatedShareProviderFactory, ISecureRandom $secureRandom, RemoteWipe $remoteWipe, KnownUserService $knownUserService, @@ -127,7 +123,6 @@ class UsersController extends AUserData { $this->logger = $logger; $this->l10nFactory = $l10nFactory; $this->newUserMailHelper = $newUserMailHelper; - $this->federatedShareProviderFactory = $federatedShareProviderFactory; $this->secureRandom = $secureRandom; $this->remoteWipe = $remoteWipe; $this->knownUserService = $knownUserService; @@ -532,15 +527,10 @@ class UsersController extends AUserData { $permittedFields[] = IAccountManager::PROPERTY_EMAIL; } - if ($this->appManager->isEnabledForUser('federatedfilesharing')) { - $shareProvider = $this->federatedShareProviderFactory->get(); - if ($shareProvider->isLookupServerUploadEnabled()) { - $permittedFields[] = IAccountManager::PROPERTY_PHONE; - $permittedFields[] = IAccountManager::PROPERTY_ADDRESS; - $permittedFields[] = IAccountManager::PROPERTY_WEBSITE; - $permittedFields[] = IAccountManager::PROPERTY_TWITTER; - } - } + $permittedFields[] = IAccountManager::PROPERTY_PHONE; + $permittedFields[] = IAccountManager::PROPERTY_ADDRESS; + $permittedFields[] = IAccountManager::PROPERTY_WEBSITE; + $permittedFields[] = IAccountManager::PROPERTY_TWITTER; return new DataResponse($permittedFields); } @@ -586,15 +576,10 @@ class UsersController extends AUserData { $permittedFields[] = 'locale'; } - if ($this->appManager->isEnabledForUser('federatedfilesharing')) { - $shareProvider = $this->federatedShareProviderFactory->get(); - if ($shareProvider->isLookupServerUploadEnabled()) { - $permittedFields[] = IAccountManager::PROPERTY_PHONE; - $permittedFields[] = IAccountManager::PROPERTY_ADDRESS; - $permittedFields[] = IAccountManager::PROPERTY_WEBSITE; - $permittedFields[] = IAccountManager::PROPERTY_TWITTER; - } - } + $permittedFields[] = IAccountManager::PROPERTY_PHONE; + $permittedFields[] = IAccountManager::PROPERTY_ADDRESS; + $permittedFields[] = IAccountManager::PROPERTY_WEBSITE; + $permittedFields[] = IAccountManager::PROPERTY_TWITTER; // If admin they can edit their own quota if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) { -- cgit v1.2.3 From 266a6fb5f8a0ec0e89e2a96f7e2ebb4a5bbf44f5 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Wed, 24 Mar 2021 12:32:06 +0100 Subject: OCS allow reading and writing account property scopes Extends the provisioning API to allow a user to get and set their own account property scopes. Signed-off-by: Vincent Petry --- apps/provisioning_api/lib/Controller/AUserData.php | 29 ++++++++++++++---- .../lib/Controller/UsersController.php | 34 ++++++++++++++++++++-- lib/private/Accounts/AccountManager.php | 33 ++++++++++++++++++++- lib/private/Accounts/AccountProperty.php | 2 +- 4 files changed, 88 insertions(+), 10 deletions(-) (limited to 'apps/provisioning_api/lib/Controller/UsersController.php') diff --git a/apps/provisioning_api/lib/Controller/AUserData.php b/apps/provisioning_api/lib/Controller/AUserData.php index 5e6af27cf72..a1391e023b7 100644 --- a/apps/provisioning_api/lib/Controller/AUserData.php +++ b/apps/provisioning_api/lib/Controller/AUserData.php @@ -51,6 +51,7 @@ use OCP\User\Backend\ISetDisplayNameBackend; use OCP\User\Backend\ISetPasswordBackend; abstract class AUserData extends OCSController { + public const SCOPE_SUFFIX = 'Scope'; /** @var IUserManager */ protected $userManager; @@ -87,12 +88,13 @@ abstract class AUserData extends OCSController { * creates a array with all user data * * @param string $userId + * @param bool $includeScopes * @return array * @throws NotFoundException * @throws OCSException * @throws OCSNotFoundException */ - protected function getUserData(string $userId): array { + protected function getUserData(string $userId, bool $includeScopes = false): array { $currentLoggedInUser = $this->userSession->getUser(); $data = []; @@ -115,7 +117,7 @@ abstract class AUserData extends OCSController { } // Get groups data - $userAccount = $this->accountManager->getUser($targetUserObject); + $userAccount = $this->accountManager->getAccount($targetUserObject); $groups = $this->groupManager->getUserGroups($targetUserObject); $gids = []; foreach ($groups as $group) { @@ -138,11 +140,26 @@ abstract class AUserData extends OCSController { $data['subadmin'] = $this->getUserSubAdminGroupsData($targetUserObject->getUID()); $data['quota'] = $this->fillStorageInfo($targetUserObject->getUID()); $data[IAccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress(); + if ($includeScopes) { + $data[IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX] = $userAccount->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(); + } $data[IAccountManager::PROPERTY_DISPLAYNAME] = $targetUserObject->getDisplayName(); - $data[IAccountManager::PROPERTY_PHONE] = $userAccount[IAccountManager::PROPERTY_PHONE]['value']; - $data[IAccountManager::PROPERTY_ADDRESS] = $userAccount[IAccountManager::PROPERTY_ADDRESS]['value']; - $data[IAccountManager::PROPERTY_WEBSITE] = $userAccount[IAccountManager::PROPERTY_WEBSITE]['value']; - $data[IAccountManager::PROPERTY_TWITTER] = $userAccount[IAccountManager::PROPERTY_TWITTER]['value']; + if ($includeScopes) { + $data[IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX] = $userAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME)->getScope(); + } + + foreach ([ + IAccountManager::PROPERTY_PHONE, + IAccountManager::PROPERTY_ADDRESS, + IAccountManager::PROPERTY_WEBSITE, + IAccountManager::PROPERTY_TWITTER, + ] as $propertyName) { + $property = $userAccount->getProperty($propertyName); + $data[$propertyName] = $property->getValue(); + if ($includeScopes) { + $data[$propertyName . self::SCOPE_SUFFIX] = $property->getScope(); + } + } $data['groups'] = $gids; $data['language'] = $this->l10nFactory->getUserLanguage($targetUserObject); $data['locale'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'locale'); diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index 3a1dcd4f43a..968cf22e647 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -483,7 +483,13 @@ class UsersController extends AUserData { * @throws OCSException */ public function getUser(string $userId): DataResponse { - $data = $this->getUserData($userId); + $includeScopes = false; + $currentUser = $this->userSession->getUser(); + if ($currentUser && $currentUser->getUID() === $userId) { + $includeScopes = true; + } + + $data = $this->getUserData($userId, $includeScopes); // getUserData returns empty array if not enough permissions if (empty($data)) { throw new OCSException('', OCSController::RESPOND_UNAUTHORISED); @@ -503,7 +509,7 @@ class UsersController extends AUserData { public function getCurrentUser(): DataResponse { $user = $this->userSession->getUser(); if ($user) { - $data = $this->getUserData($user->getUID()); + $data = $this->getUserData($user->getUID(), true); // rename "displayname" to "display-name" only for this call to keep // the API stable. $data['display-name'] = $data['displayname']; @@ -565,6 +571,9 @@ class UsersController extends AUserData { $permittedFields[] = IAccountManager::PROPERTY_EMAIL; } + $permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX; + $permittedFields[] = IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX; + $permittedFields[] = 'password'; if ($this->config->getSystemValue('force_language', false) === false || $this->groupManager->isAdmin($currentLoggedInUser->getUID())) { @@ -580,6 +589,10 @@ class UsersController extends AUserData { $permittedFields[] = IAccountManager::PROPERTY_ADDRESS; $permittedFields[] = IAccountManager::PROPERTY_WEBSITE; $permittedFields[] = IAccountManager::PROPERTY_TWITTER; + $permittedFields[] = IAccountManager::PROPERTY_PHONE . self::SCOPE_SUFFIX; + $permittedFields[] = IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX; + $permittedFields[] = IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX; + $permittedFields[] = IAccountManager::PROPERTY_TWITTER . self::SCOPE_SUFFIX; // If admin they can edit their own quota if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) { @@ -684,6 +697,23 @@ class UsersController extends AUserData { } } break; + case IAccountManager::PROPERTY_DISPLAYNAME . self::SCOPE_SUFFIX: + case IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX: + case IAccountManager::PROPERTY_PHONE . self::SCOPE_SUFFIX: + case IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX: + case IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX: + case IAccountManager::PROPERTY_TWITTER . self::SCOPE_SUFFIX: + $propertyName = substr($key, 0, strlen($key) - strlen(self::SCOPE_SUFFIX)); + $userAccount = $this->accountManager->getUser($targetUser); + if ($userAccount[$propertyName]['scope'] !== $value) { + $userAccount[$propertyName]['scope'] = $value; + try { + $this->accountManager->updateUser($targetUser, $userAccount, true); + } catch (\InvalidArgumentException $e) { + throw new OCSException('Invalid ' . $e->getMessage(), 102); + } + } + break; default: throw new OCSException('', 103); } diff --git a/lib/private/Accounts/AccountManager.php b/lib/private/Accounts/AccountManager.php index ff3b04d8395..74ba53737ca 100644 --- a/lib/private/Accounts/AccountManager.php +++ b/lib/private/Accounts/AccountManager.php @@ -144,6 +144,37 @@ class AccountManager implements IAccountManager { } } + $allowedScopes = [ + self::SCOPE_PRIVATE, + self::SCOPE_LOCAL, + self::SCOPE_FEDERATED, + self::SCOPE_PUBLISHED, + self::VISIBILITY_PRIVATE, + self::VISIBILITY_CONTACTS_ONLY, + self::VISIBILITY_PUBLIC, + ]; + + // validate and convert scope values + foreach ($data as $propertyName => $propertyData) { + if (isset($propertyData['scope'])) { + if ($throwOnData && !in_array($propertyData['scope'], $allowedScopes, true)) { + throw new \InvalidArgumentException('scope'); + } + + if ( + $propertyData['scope'] === self::SCOPE_PRIVATE + && ($propertyName === self::PROPERTY_DISPLAYNAME || $propertyName === self::PROPERTY_EMAIL) + ) { + // v2-private is not available for these fields + throw new \InvalidArgumentException('scope'); + } + + // migrate scope values to the new format + // invalid scopes are mapped to a default value + $data[$propertyName]['scope'] = AccountProperty::mapScopeToV2($propertyData['scope']); + } + } + if (empty($userData)) { $this->insertNewUser($user, $data); } elseif ($userData !== $data) { @@ -405,7 +436,7 @@ class AccountManager implements IAccountManager { } $query->setParameter('name', $propertyName) - ->setParameter('value', $property['value']); + ->setParameter('value', $property['value'] ?? ''); $query->execute(); } } diff --git a/lib/private/Accounts/AccountProperty.php b/lib/private/Accounts/AccountProperty.php index 4c75ad85414..850f39df9e3 100644 --- a/lib/private/Accounts/AccountProperty.php +++ b/lib/private/Accounts/AccountProperty.php @@ -128,7 +128,7 @@ class AccountProperty implements IAccountProperty { return $this->scope; } - private function mapScopeToV2($scope) { + public static function mapScopeToV2($scope) { if (strpos($scope, 'v2-') === 0) { return $scope; } -- cgit v1.2.3 From 2a312fe4e3a9c07bdc4b4e10bed66af48e07463a Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Wed, 24 Mar 2021 15:32:51 +0100 Subject: Expose avatarScope through provisioning API Signed-off-by: Vincent Petry --- apps/provisioning_api/lib/Controller/AUserData.php | 6 ++++++ apps/provisioning_api/lib/Controller/UsersController.php | 3 +++ 2 files changed, 9 insertions(+) (limited to 'apps/provisioning_api/lib/Controller/UsersController.php') diff --git a/apps/provisioning_api/lib/Controller/AUserData.php b/apps/provisioning_api/lib/Controller/AUserData.php index a1391e023b7..c26c4f9e2d0 100644 --- a/apps/provisioning_api/lib/Controller/AUserData.php +++ b/apps/provisioning_api/lib/Controller/AUserData.php @@ -139,6 +139,11 @@ abstract class AUserData extends OCSController { $data['backend'] = $targetUserObject->getBackendClassName(); $data['subadmin'] = $this->getUserSubAdminGroupsData($targetUserObject->getUID()); $data['quota'] = $this->fillStorageInfo($targetUserObject->getUID()); + + if ($includeScopes) { + $data[IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX] = $userAccount->getProperty(IAccountManager::PROPERTY_AVATAR)->getScope(); + } + $data[IAccountManager::PROPERTY_EMAIL] = $targetUserObject->getEMailAddress(); if ($includeScopes) { $data[IAccountManager::PROPERTY_EMAIL . self::SCOPE_SUFFIX] = $userAccount->getProperty(IAccountManager::PROPERTY_EMAIL)->getScope(); @@ -160,6 +165,7 @@ abstract class AUserData extends OCSController { $data[$propertyName . self::SCOPE_SUFFIX] = $property->getScope(); } } + $data['groups'] = $gids; $data['language'] = $this->l10nFactory->getUserLanguage($targetUserObject); $data['locale'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'locale'); diff --git a/apps/provisioning_api/lib/Controller/UsersController.php b/apps/provisioning_api/lib/Controller/UsersController.php index 968cf22e647..0019472c884 100644 --- a/apps/provisioning_api/lib/Controller/UsersController.php +++ b/apps/provisioning_api/lib/Controller/UsersController.php @@ -594,6 +594,8 @@ class UsersController extends AUserData { $permittedFields[] = IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX; $permittedFields[] = IAccountManager::PROPERTY_TWITTER . self::SCOPE_SUFFIX; + $permittedFields[] = IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX; + // If admin they can edit their own quota if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) { $permittedFields[] = 'quota'; @@ -703,6 +705,7 @@ class UsersController extends AUserData { case IAccountManager::PROPERTY_ADDRESS . self::SCOPE_SUFFIX: case IAccountManager::PROPERTY_WEBSITE . self::SCOPE_SUFFIX: case IAccountManager::PROPERTY_TWITTER . self::SCOPE_SUFFIX: + case IAccountManager::PROPERTY_AVATAR . self::SCOPE_SUFFIX: $propertyName = substr($key, 0, strlen($key) - strlen(self::SCOPE_SUFFIX)); $userAccount = $this->accountManager->getUser($targetUser); if ($userAccount[$propertyName]['scope'] !== $value) { -- cgit v1.2.3