Skip to content

Commit

Permalink
Prevent duplicate email address when syncing users
Browse files Browse the repository at this point in the history
When trying to insert/update a user with a duplicate email address,
change that one to empty to avoid failure or loss of access.
  • Loading branch information
Vincent Petry committed Apr 19, 2017
1 parent 29ab0b0 commit b9441a0
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 4 deletions.
3 changes: 3 additions & 0 deletions lib/private/User/Manager.php
Expand Up @@ -368,6 +368,9 @@ public function callForSeenUsers (\Closure $callback) {
*/
public function getByEmail($email) {
$account = $this->accountMapper->getByEmail($email);
if ($account === null) {
return null;
}
return [$this->getUserObject($account)];
}

Expand Down
36 changes: 32 additions & 4 deletions lib/private/User/SyncService.php
Expand Up @@ -27,6 +27,7 @@
use OCP\IConfig;
use OCP\ILogger;
use OCP\UserInterface;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;

/**
* Class SyncService
Expand Down Expand Up @@ -97,19 +98,46 @@ public function run(\Closure $callback) {

// update existing and insert new users
foreach ($users as $uid) {
$isNew = false;
try {
$a = $this->mapper->getByUid($uid);
if ($a->getBackend() !== $this->backendClass) {
$this->logger->debug("User <$uid> already provided by another backend({$a->getBackend()} != {$this->backendClass})");
continue;
}
$a = $this->setupAccount($a, $uid);
$this->mapper->update($a);
} catch(DoesNotExistException $ex) {
} catch (DoesNotExistException $ex) {
$isNew = true;
$a = $this->createNewAccount($uid);
$this->setupAccount($a, $uid);
$this->mapper->insert($a);
}

do {
$retry = false;
try {
if ($isNew) {
$this->mapper->insert($a);
} else {
$this->mapper->update($a);
}
} catch (UniqueConstraintViolationException $ex) {
// could be due to a duplicate email
$email = $a->getEmail();
if ($email === null || $email === '') {
// it's a different issue, rethrow
throw $ex;
}
// find out if there is another account with the same email address
$existingAccount = $this->mapper->getByEmail($email);
if (!$existingAccount) {
// it's a different issue, rethrow
throw $ex;
}

// it's a duplicate email, so clear the field and try again
$a->setEmail(null);
$retry = true;
}
} while ($retry);
// clean the user's preferences
$this->cleanPreferences($uid);

Expand Down

0 comments on commit b9441a0

Please sign in to comment.