mirror of
https://github.com/nextcloud/server.git
synced 2026-02-25 10:51:41 -05:00
To continue this formatting madness, here's a tiny patch that adds unified formatting for control structures like if and loops as well as classes, their methods and anonymous functions. This basically forces the constructs to start on the same line. This is not exactly what PSR2 wants, but I think we can have a few exceptions with "our" style. The starting of braces on the same line is pracrically standard for our code. This also removes and empty lines from method/function bodies at the beginning and end. Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
356 lines
11 KiB
PHP
356 lines
11 KiB
PHP
<?php
|
|
/**
|
|
* @copyright Copyright (c) 2016, ownCloud, Inc.
|
|
* @copyright Copyright (c) 2016, Björn Schießle
|
|
*
|
|
* @author Bjoern Schiessle <bjoern@schiessle.org>
|
|
* @author Björn Schießle <bjoern@schiessle.org>
|
|
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
|
|
* @author Daniel Kesselberg <mail@danielkesselberg.de>
|
|
* @author Joas Schilling <coding@schilljs.com>
|
|
* @author Julius Härtl <jus@bitgrid.net>
|
|
* @author Morris Jobke <hey@morrisjobke.de>
|
|
* @author Roeland Jago Douma <roeland@famdouma.nl>
|
|
*
|
|
* @license AGPL-3.0
|
|
*
|
|
* This code is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3,
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License, version 3,
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
*/
|
|
|
|
namespace OC\Accounts;
|
|
|
|
use OCA\Settings\BackgroundJobs\VerifyUserData;
|
|
use OCP\Accounts\IAccount;
|
|
use OCP\Accounts\IAccountManager;
|
|
use OCP\BackgroundJob\IJobList;
|
|
use OCP\IDBConnection;
|
|
use OCP\ILogger;
|
|
use OCP\IUser;
|
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
|
use Symfony\Component\EventDispatcher\GenericEvent;
|
|
use function json_decode;
|
|
use function json_last_error;
|
|
|
|
/**
|
|
* Class AccountManager
|
|
*
|
|
* Manage system accounts table
|
|
*
|
|
* @group DB
|
|
* @package OC\Accounts
|
|
*/
|
|
class AccountManager implements IAccountManager {
|
|
|
|
/** @var IDBConnection database connection */
|
|
private $connection;
|
|
|
|
/** @var string table name */
|
|
private $table = 'accounts';
|
|
|
|
/** @var EventDispatcherInterface */
|
|
private $eventDispatcher;
|
|
|
|
/** @var IJobList */
|
|
private $jobList;
|
|
|
|
/** @var ILogger */
|
|
private $logger;
|
|
|
|
/**
|
|
* AccountManager constructor.
|
|
*
|
|
* @param IDBConnection $connection
|
|
* @param EventDispatcherInterface $eventDispatcher
|
|
* @param IJobList $jobList
|
|
*/
|
|
public function __construct(IDBConnection $connection,
|
|
EventDispatcherInterface $eventDispatcher,
|
|
IJobList $jobList,
|
|
ILogger $logger) {
|
|
$this->connection = $connection;
|
|
$this->eventDispatcher = $eventDispatcher;
|
|
$this->jobList = $jobList;
|
|
$this->logger = $logger;
|
|
}
|
|
|
|
/**
|
|
* update user record
|
|
*
|
|
* @param IUser $user
|
|
* @param $data
|
|
*/
|
|
public function updateUser(IUser $user, $data) {
|
|
$userData = $this->getUser($user);
|
|
$updated = true;
|
|
if (empty($userData)) {
|
|
$this->insertNewUser($user, $data);
|
|
} elseif ($userData !== $data) {
|
|
$data = $this->checkEmailVerification($userData, $data, $user);
|
|
$data = $this->updateVerifyStatus($userData, $data);
|
|
$this->updateExistingUser($user, $data);
|
|
} else {
|
|
// nothing needs to be done if new and old data set are the same
|
|
$updated = false;
|
|
}
|
|
|
|
if ($updated) {
|
|
$this->eventDispatcher->dispatch(
|
|
'OC\AccountManager::userUpdated',
|
|
new GenericEvent($user, $data)
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* delete user from accounts table
|
|
*
|
|
* @param IUser $user
|
|
*/
|
|
public function deleteUser(IUser $user) {
|
|
$uid = $user->getUID();
|
|
$query = $this->connection->getQueryBuilder();
|
|
$query->delete($this->table)
|
|
->where($query->expr()->eq('uid', $query->createNamedParameter($uid)))
|
|
->execute();
|
|
}
|
|
|
|
/**
|
|
* get stored data from a given user
|
|
*
|
|
* @param IUser $user
|
|
* @return array
|
|
*/
|
|
public function getUser(IUser $user) {
|
|
$uid = $user->getUID();
|
|
$query = $this->connection->getQueryBuilder();
|
|
$query->select('data')->from($this->table)
|
|
->where($query->expr()->eq('uid', $query->createParameter('uid')))
|
|
->setParameter('uid', $uid);
|
|
$query->execute();
|
|
$result = $query->execute()->fetchAll();
|
|
|
|
if (empty($result)) {
|
|
$userData = $this->buildDefaultUserRecord($user);
|
|
$this->insertNewUser($user, $userData);
|
|
return $userData;
|
|
}
|
|
|
|
$userDataArray = json_decode($result[0]['data'], true);
|
|
$jsonError = json_last_error();
|
|
if ($userDataArray === null || $jsonError !== JSON_ERROR_NONE) {
|
|
$this->logger->critical("User data of $uid contained invalid JSON (error $jsonError), hence falling back to a default user record");
|
|
return $this->buildDefaultUserRecord($user);
|
|
}
|
|
|
|
$userDataArray = $this->addMissingDefaultValues($userDataArray);
|
|
|
|
return $userDataArray;
|
|
}
|
|
|
|
/**
|
|
* check if we need to ask the server for email verification, if yes we create a cronjob
|
|
*
|
|
* @param $oldData
|
|
* @param $newData
|
|
* @param IUser $user
|
|
* @return array
|
|
*/
|
|
protected function checkEmailVerification($oldData, $newData, IUser $user) {
|
|
if ($oldData[self::PROPERTY_EMAIL]['value'] !== $newData[self::PROPERTY_EMAIL]['value']) {
|
|
$this->jobList->add(VerifyUserData::class,
|
|
[
|
|
'verificationCode' => '',
|
|
'data' => $newData[self::PROPERTY_EMAIL]['value'],
|
|
'type' => self::PROPERTY_EMAIL,
|
|
'uid' => $user->getUID(),
|
|
'try' => 0,
|
|
'lastRun' => time()
|
|
]
|
|
);
|
|
$newData[AccountManager::PROPERTY_EMAIL]['verified'] = AccountManager::VERIFICATION_IN_PROGRESS;
|
|
}
|
|
|
|
return $newData;
|
|
}
|
|
|
|
/**
|
|
* make sure that all expected data are set
|
|
*
|
|
* @param array $userData
|
|
* @return array
|
|
*/
|
|
protected function addMissingDefaultValues(array $userData) {
|
|
foreach ($userData as $key => $value) {
|
|
if (!isset($userData[$key]['verified'])) {
|
|
$userData[$key]['verified'] = self::NOT_VERIFIED;
|
|
}
|
|
}
|
|
|
|
return $userData;
|
|
}
|
|
|
|
/**
|
|
* reset verification status if personal data changed
|
|
*
|
|
* @param array $oldData
|
|
* @param array $newData
|
|
* @return array
|
|
*/
|
|
protected function updateVerifyStatus($oldData, $newData) {
|
|
|
|
// which account was already verified successfully?
|
|
$twitterVerified = isset($oldData[self::PROPERTY_TWITTER]['verified']) && $oldData[self::PROPERTY_TWITTER]['verified'] === self::VERIFIED;
|
|
$websiteVerified = isset($oldData[self::PROPERTY_WEBSITE]['verified']) && $oldData[self::PROPERTY_WEBSITE]['verified'] === self::VERIFIED;
|
|
$emailVerified = isset($oldData[self::PROPERTY_EMAIL]['verified']) && $oldData[self::PROPERTY_EMAIL]['verified'] === self::VERIFIED;
|
|
|
|
// keep old verification status if we don't have a new one
|
|
if (!isset($newData[self::PROPERTY_TWITTER]['verified'])) {
|
|
// keep old verification status if value didn't changed and an old value exists
|
|
$keepOldStatus = $newData[self::PROPERTY_TWITTER]['value'] === $oldData[self::PROPERTY_TWITTER]['value'] && isset($oldData[self::PROPERTY_TWITTER]['verified']);
|
|
$newData[self::PROPERTY_TWITTER]['verified'] = $keepOldStatus ? $oldData[self::PROPERTY_TWITTER]['verified'] : self::NOT_VERIFIED;
|
|
}
|
|
|
|
if (!isset($newData[self::PROPERTY_WEBSITE]['verified'])) {
|
|
// keep old verification status if value didn't changed and an old value exists
|
|
$keepOldStatus = $newData[self::PROPERTY_WEBSITE]['value'] === $oldData[self::PROPERTY_WEBSITE]['value'] && isset($oldData[self::PROPERTY_WEBSITE]['verified']);
|
|
$newData[self::PROPERTY_WEBSITE]['verified'] = $keepOldStatus ? $oldData[self::PROPERTY_WEBSITE]['verified'] : self::NOT_VERIFIED;
|
|
}
|
|
|
|
if (!isset($newData[self::PROPERTY_EMAIL]['verified'])) {
|
|
// keep old verification status if value didn't changed and an old value exists
|
|
$keepOldStatus = $newData[self::PROPERTY_EMAIL]['value'] === $oldData[self::PROPERTY_EMAIL]['value'] && isset($oldData[self::PROPERTY_EMAIL]['verified']);
|
|
$newData[self::PROPERTY_EMAIL]['verified'] = $keepOldStatus ? $oldData[self::PROPERTY_EMAIL]['verified'] : self::VERIFICATION_IN_PROGRESS;
|
|
}
|
|
|
|
// reset verification status if a value from a previously verified data was changed
|
|
if ($twitterVerified &&
|
|
$oldData[self::PROPERTY_TWITTER]['value'] !== $newData[self::PROPERTY_TWITTER]['value']
|
|
) {
|
|
$newData[self::PROPERTY_TWITTER]['verified'] = self::NOT_VERIFIED;
|
|
}
|
|
|
|
if ($websiteVerified &&
|
|
$oldData[self::PROPERTY_WEBSITE]['value'] !== $newData[self::PROPERTY_WEBSITE]['value']
|
|
) {
|
|
$newData[self::PROPERTY_WEBSITE]['verified'] = self::NOT_VERIFIED;
|
|
}
|
|
|
|
if ($emailVerified &&
|
|
$oldData[self::PROPERTY_EMAIL]['value'] !== $newData[self::PROPERTY_EMAIL]['value']
|
|
) {
|
|
$newData[self::PROPERTY_EMAIL]['verified'] = self::NOT_VERIFIED;
|
|
}
|
|
|
|
return $newData;
|
|
}
|
|
|
|
/**
|
|
* add new user to accounts table
|
|
*
|
|
* @param IUser $user
|
|
* @param array $data
|
|
*/
|
|
protected function insertNewUser(IUser $user, $data) {
|
|
$uid = $user->getUID();
|
|
$jsonEncodedData = json_encode($data);
|
|
$query = $this->connection->getQueryBuilder();
|
|
$query->insert($this->table)
|
|
->values(
|
|
[
|
|
'uid' => $query->createNamedParameter($uid),
|
|
'data' => $query->createNamedParameter($jsonEncodedData),
|
|
]
|
|
)
|
|
->execute();
|
|
}
|
|
|
|
/**
|
|
* update existing user in accounts table
|
|
*
|
|
* @param IUser $user
|
|
* @param array $data
|
|
*/
|
|
protected function updateExistingUser(IUser $user, $data) {
|
|
$uid = $user->getUID();
|
|
$jsonEncodedData = json_encode($data);
|
|
$query = $this->connection->getQueryBuilder();
|
|
$query->update($this->table)
|
|
->set('data', $query->createNamedParameter($jsonEncodedData))
|
|
->where($query->expr()->eq('uid', $query->createNamedParameter($uid)))
|
|
->execute();
|
|
}
|
|
|
|
/**
|
|
* build default user record in case not data set exists yet
|
|
*
|
|
* @param IUser $user
|
|
* @return array
|
|
*/
|
|
protected function buildDefaultUserRecord(IUser $user) {
|
|
return [
|
|
self::PROPERTY_DISPLAYNAME =>
|
|
[
|
|
'value' => $user->getDisplayName(),
|
|
'scope' => self::VISIBILITY_CONTACTS_ONLY,
|
|
'verified' => self::NOT_VERIFIED,
|
|
],
|
|
self::PROPERTY_ADDRESS =>
|
|
[
|
|
'value' => '',
|
|
'scope' => self::VISIBILITY_PRIVATE,
|
|
'verified' => self::NOT_VERIFIED,
|
|
],
|
|
self::PROPERTY_WEBSITE =>
|
|
[
|
|
'value' => '',
|
|
'scope' => self::VISIBILITY_PRIVATE,
|
|
'verified' => self::NOT_VERIFIED,
|
|
],
|
|
self::PROPERTY_EMAIL =>
|
|
[
|
|
'value' => $user->getEMailAddress(),
|
|
'scope' => self::VISIBILITY_CONTACTS_ONLY,
|
|
'verified' => self::NOT_VERIFIED,
|
|
],
|
|
self::PROPERTY_AVATAR =>
|
|
[
|
|
'scope' => self::VISIBILITY_CONTACTS_ONLY
|
|
],
|
|
self::PROPERTY_PHONE =>
|
|
[
|
|
'value' => '',
|
|
'scope' => self::VISIBILITY_PRIVATE,
|
|
'verified' => self::NOT_VERIFIED,
|
|
],
|
|
self::PROPERTY_TWITTER =>
|
|
[
|
|
'value' => '',
|
|
'scope' => self::VISIBILITY_PRIVATE,
|
|
'verified' => self::NOT_VERIFIED,
|
|
],
|
|
];
|
|
}
|
|
|
|
private function parseAccountData(IUser $user, $data): Account {
|
|
$account = new Account($user);
|
|
foreach ($data as $property => $accountData) {
|
|
$account->setProperty($property, $accountData['value'] ?? '', $accountData['scope'] ?? self::VISIBILITY_PRIVATE, $accountData['verified'] ?? self::NOT_VERIFIED);
|
|
}
|
|
return $account;
|
|
}
|
|
|
|
public function getAccount(IUser $user): IAccount {
|
|
return $this->parseAccountData($user, $this->getUser($user));
|
|
}
|
|
}
|