Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
enable the user to set a primary (notification) email address (backend)
- specific getters and setters on IUser and implementation
- new notify_email field in provisioning API

Signed-off-by: Arthur Schiwon <[email protected]>
  • Loading branch information
blizzz committed Sep 9, 2021
commit 4461b9e870d9d97e1cf83f2adfdeb09cd57c3e18
18 changes: 13 additions & 5 deletions apps/provisioning_api/lib/Controller/AUserData.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@
abstract class AUserData extends OCSController {
public const SCOPE_SUFFIX = 'Scope';

public const USER_FIELD_DISPLAYNAME = 'display';
public const USER_FIELD_LANGUAGE = 'language';
public const USER_FIELD_LOCALE = 'locale';
public const USER_FIELD_PASSWORD = 'password';
public const USER_FIELD_QUOTA = 'quota';
public const USER_FIELD_NOTIFICATION_EMAIL = 'notify_email';

/** @var IUserManager */
protected $userManager;
/** @var IConfig */
Expand Down Expand Up @@ -139,7 +146,7 @@ protected function getUserData(string $userId, bool $includeScopes = false): arr
$data['lastLogin'] = $targetUserObject->getLastLogin() * 1000;
$data['backend'] = $targetUserObject->getBackendClassName();
$data['subadmin'] = $this->getUserSubAdminGroupsData($targetUserObject->getUID());
$data['quota'] = $this->fillStorageInfo($targetUserObject->getUID());
$data[self::USER_FIELD_QUOTA] = $this->fillStorageInfo($targetUserObject->getUID());

try {
if ($includeScopes) {
Expand Down Expand Up @@ -187,8 +194,9 @@ protected function getUserData(string $userId, bool $includeScopes = false): arr
}

$data['groups'] = $gids;
$data['language'] = $this->l10nFactory->getUserLanguage($targetUserObject);
$data['locale'] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'locale');
$data[self::USER_FIELD_LANGUAGE] = $this->l10nFactory->getUserLanguage($targetUserObject);
$data[self::USER_FIELD_LOCALE] = $this->config->getUserValue($targetUserObject->getUID(), 'core', 'locale');
$data[self::USER_FIELD_NOTIFICATION_EMAIL] = $targetUserObject->getPrimaryEMailAddress();

$backend = $targetUserObject->getBackend();
$data['backendCapabilities'] = [
Expand Down Expand Up @@ -238,7 +246,7 @@ protected function fillStorageInfo(string $userId): array {
'used' => $storage['used'],
'total' => $storage['total'],
'relative' => $storage['relative'],
'quota' => $storage['quota'],
self::USER_FIELD_QUOTA => $storage['quota'],
];
} catch (NotFoundException $ex) {
// User fs is not setup yet
Expand All @@ -251,7 +259,7 @@ protected function fillStorageInfo(string $userId): array {
$quota = OC_Helper::computerFileSize($quota);
}
$data = [
'quota' => $quota !== false ? $quota : 'none',
self::USER_FIELD_QUOTA => $quota !== false ? $quota : 'none',
'used' => 0
];
}
Expand Down
66 changes: 44 additions & 22 deletions apps/provisioning_api/lib/Controller/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
*/
namespace OCA\Provisioning_API\Controller;

use InvalidArgumentException;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberFormat;
Expand Down Expand Up @@ -418,15 +419,15 @@ public function addUser(string $userid,
}

if ($displayName !== '') {
$this->editUser($userid, 'display', $displayName);
$this->editUser($userid, self::USER_FIELD_DISPLAYNAME, $displayName);
}

if ($quota !== '') {
$this->editUser($userid, 'quota', $quota);
$this->editUser($userid, self::USER_FIELD_QUOTA, $quota);
}

if ($language !== '') {
$this->editUser($userid, 'language', $language);
$this->editUser($userid, self::USER_FIELD_LANGUAGE, $language);
}

// Send new user mail only if a mail is set
Expand Down Expand Up @@ -466,7 +467,7 @@ public function addUser(string $userid,
]
);
throw $e;
} catch (\InvalidArgumentException $e) {
} catch (InvalidArgumentException $e) {
$this->logger->error('Failed addUser attempt with invalid argument exeption.',
[
'app' => 'ocs_api',
Expand Down Expand Up @@ -676,7 +677,7 @@ public function editUserMultiValue(
try {
$targetProperty->setScope($value);
$this->accountManager->updateAccount($userAccount);
} catch (\InvalidArgumentException $e) {
} catch (InvalidArgumentException $e) {
throw new OCSException('', 102);
}
} else {
Expand Down Expand Up @@ -717,7 +718,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon
if ($this->config->getSystemValue('allow_user_to_change_display_name', true) !== false) {
if ($targetUser->getBackend() instanceof ISetDisplayNameBackend
|| $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)) {
$permittedFields[] = 'display';
$permittedFields[] = self::USER_FIELD_DISPLAYNAME;
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
}
$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
Expand All @@ -728,15 +729,16 @@ public function editUser(string $userId, string $key, string $value): DataRespon

$permittedFields[] = IAccountManager::COLLECTION_EMAIL;

$permittedFields[] = 'password';
$permittedFields[] = self::USER_FIELD_PASSWORD;
$permittedFields[] = self::USER_FIELD_NOTIFICATION_EMAIL;
if ($this->config->getSystemValue('force_language', false) === false ||
$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
$permittedFields[] = 'language';
$permittedFields[] = self::USER_FIELD_LANGUAGE;
}

if ($this->config->getSystemValue('force_locale', false) === false ||
$this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
$permittedFields[] = 'locale';
$permittedFields[] = self::USER_FIELD_LOCALE;
}

$permittedFields[] = IAccountManager::PROPERTY_PHONE;
Expand All @@ -752,7 +754,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon

// If admin they can edit their own quota
if ($this->groupManager->isAdmin($currentLoggedInUser->getUID())) {
$permittedFields[] = 'quota';
$permittedFields[] = self::USER_FIELD_QUOTA;
}
} else {
// Check if admin / subadmin
Expand All @@ -762,19 +764,19 @@ public function editUser(string $userId, string $key, string $value): DataRespon
// They have permissions over the user
if ($targetUser->getBackend() instanceof ISetDisplayNameBackend
|| $targetUser->getBackend()->implementsActions(Backend::SET_DISPLAYNAME)) {
$permittedFields[] = 'display';
$permittedFields[] = self::USER_FIELD_DISPLAYNAME;
$permittedFields[] = IAccountManager::PROPERTY_DISPLAYNAME;
}
$permittedFields[] = IAccountManager::PROPERTY_EMAIL;
$permittedFields[] = IAccountManager::COLLECTION_EMAIL;
$permittedFields[] = 'password';
$permittedFields[] = 'language';
$permittedFields[] = 'locale';
$permittedFields[] = self::USER_FIELD_PASSWORD;
$permittedFields[] = self::USER_FIELD_LANGUAGE;
$permittedFields[] = self::USER_FIELD_LOCALE;
$permittedFields[] = IAccountManager::PROPERTY_PHONE;
$permittedFields[] = IAccountManager::PROPERTY_ADDRESS;
$permittedFields[] = IAccountManager::PROPERTY_WEBSITE;
$permittedFields[] = IAccountManager::PROPERTY_TWITTER;
$permittedFields[] = 'quota';
$permittedFields[] = self::USER_FIELD_QUOTA;
} else {
// No rights
throw new OCSException('', OCSController::RESPOND_NOT_FOUND);
Expand All @@ -786,11 +788,11 @@ public function editUser(string $userId, string $key, string $value): DataRespon
}
// Process the edit
switch ($key) {
case 'display':
case self::USER_FIELD_DISPLAYNAME:
case IAccountManager::PROPERTY_DISPLAYNAME:
$targetUser->setDisplayName($value);
break;
case 'quota':
case self::USER_FIELD_QUOTA:
$quota = $value;
if ($quota !== 'none' && $quota !== 'default') {
if (is_numeric($quota)) {
Expand Down Expand Up @@ -820,7 +822,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon
}
$targetUser->setQuota($quota);
break;
case 'password':
case self::USER_FIELD_PASSWORD:
try {
if (!$targetUser->canChangePassword()) {
throw new OCSException('Setting the password is not supported by the users backend', 103);
Expand All @@ -830,19 +832,39 @@ public function editUser(string $userId, string $key, string $value): DataRespon
throw new OCSException($e->getMessage(), 103);
}
break;
case 'language':
case self::USER_FIELD_LANGUAGE:
$languagesCodes = $this->l10nFactory->findAvailableLanguages();
if (!in_array($value, $languagesCodes, true) && $value !== 'en') {
throw new OCSException('Invalid language', 102);
}
$this->config->setUserValue($targetUser->getUID(), 'core', 'lang', $value);
break;
case 'locale':
case self::USER_FIELD_LOCALE:
if (!$this->l10nFactory->localeExists($value)) {
throw new OCSException('Invalid locale', 102);
}
$this->config->setUserValue($targetUser->getUID(), 'core', 'locale', $value);
break;
case self::USER_FIELD_NOTIFICATION_EMAIL:
$success = false;
if ($value === '' || filter_var($value, FILTER_VALIDATE_EMAIL)) {
try {
$targetUser->setPrimaryEMailAddress($value);
$success = true;
} catch (InvalidArgumentException $e) {
$this->logger->info(
'Cannot set primary email, because provided address is not verified',
[
'app' => 'provisioning_api',
'exception' => $e,
]
);
}
}
if (!$success) {
throw new OCSException('', 102);
}
break;
case IAccountManager::PROPERTY_EMAIL:
if (filter_var($value, FILTER_VALIDATE_EMAIL) || $value === '') {
$targetUser->setEMailAddress($value);
Expand Down Expand Up @@ -878,7 +900,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon
if ($userProperty->getName() === IAccountManager::PROPERTY_PHONE) {
$this->knownUserService->deleteByContactUserId($targetUser->getUID());
}
} catch (\InvalidArgumentException $e) {
} catch (InvalidArgumentException $e) {
throw new OCSException('Invalid ' . $e->getMessage(), 102);
}
}
Expand All @@ -901,7 +923,7 @@ public function editUser(string $userId, string $key, string $value): DataRespon
try {
$userProperty->setScope($value);
$this->accountManager->updateAccount($userAccount);
} catch (\InvalidArgumentException $e) {
} catch (InvalidArgumentException $e) {
throw new OCSException('Invalid ' . $e->getMessage(), 102);
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/private/Setup.php
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ public function install($options) {

// Set email for admin
if (!empty($options['adminemail'])) {
$config->setUserValue($user->getUID(), 'settings', 'email', $options['adminemail']);
$user->setSystemEMailAddress($options['adminemail']);
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/private/User/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,7 @@ private function getSeenUserIds($limit = null, $offset = null) {
* @since 9.1.0
*/
public function getByEmail($email) {
// looking for 'email' only (and not primary_mail) is intentional
$userIds = $this->config->getUsersForUserValueCaseInsensitive('settings', 'email', $email);

$users = array_map(function ($uid) {
Expand Down
77 changes: 66 additions & 11 deletions lib/private/User/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@
*/
namespace OC\User;

use InvalidArgumentException;
use OC\Accounts\AccountManager;
use OC\Avatar\AvatarManager;
use OC\Hooks\Emitter;
use OC_Helper;
use OCP\Accounts\IAccountManager;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Group\Events\BeforeUserRemovedEvent;
use OCP\Group\Events\UserRemovedEvent;
Expand All @@ -55,6 +57,8 @@
use Symfony\Component\EventDispatcher\GenericEvent;

class User implements IUser {
/** @var IAccountManager */
protected $accountManager;
/** @var string */
private $uid;

Expand Down Expand Up @@ -165,24 +169,61 @@ public function setDisplayName($displayName) {
}

/**
* set the email address of the user
*
* @param string|null $mailAddress
* @return void
* @since 9.0.0
* @inheritDoc
*/
public function setEMailAddress($mailAddress) {
$oldMailAddress = $this->getEMailAddress();
$this->setSystemEMailAddress($mailAddress);
}

/**
* @inheritDoc
*/
public function setSystemEMailAddress(string $mailAddress): void {
$oldMailAddress = $this->getSystemEMailAddress();

if ($mailAddress === '') {
$this->config->deleteUserValue($this->uid, 'settings', 'email');
} else {
$this->config->setUserValue($this->uid, 'settings', 'email', $mailAddress);
}

$primaryAddress = $this->getPrimaryEMailAddress();
if ($primaryAddress === $mailAddress) {
// on match no dedicated primary settings is necessary
$this->setPrimaryEMailAddress('');
}

if ($oldMailAddress !== $mailAddress) {
if ($mailAddress === '') {
$this->config->deleteUserValue($this->uid, 'settings', 'email');
} else {
$this->config->setUserValue($this->uid, 'settings', 'email', $mailAddress);
}
$this->triggerChange('eMailAddress', $mailAddress, $oldMailAddress);
}
}

/**
* @inheritDoc
*/
public function setPrimaryEMailAddress(string $mailAddress): void {
if ($mailAddress === '') {
$this->config->deleteUserValue($this->uid, 'settings', 'primary_email');
return;
}

$this->ensureAccountManager();
$account = $this->accountManager->getAccount($this);
$property = $account->getPropertyCollection(IAccountManager::COLLECTION_EMAIL)
->getPropertyByValue($mailAddress);

if ($property === null || $property->getLocallyVerified() !== IAccountManager::VERIFIED) {
throw new InvalidArgumentException('Only verified emails can be set as primary');
}
$this->config->setUserValue($this->uid, 'settings', 'primary_email', $mailAddress);
}

private function ensureAccountManager() {
if (!$this->accountManager instanceof IAccountManager) {
$this->accountManager = \OC::$server->get(IAccountManager::class);
}
}

/**
* returns the timestamp of the user's last login or 0 if the user did never
* login
Expand Down Expand Up @@ -390,9 +431,23 @@ public function setEnabled(bool $enabled = true) {
* @since 9.0.0
*/
public function getEMailAddress() {
return $this->getPrimaryEMailAddress() ?? $this->getSystemEMailAddress();
}

/**
* @inheritDoc
*/
public function getSystemEMailAddress(): ?string {
return $this->config->getUserValue($this->uid, 'settings', 'email', null);
}

/**
* @inheritDoc
*/
public function getPrimaryEMailAddress(): ?string {
return $this->config->getUserValue($this->uid, 'settings', 'primary_email', null);
}

/**
* get the users' quota
*
Expand Down
Loading