Merge pull request #17494 from nextcloud/fix/16340/ignore-invalid-json

Return a default user record if json is broken
This commit is contained in:
blizzz 2019-12-13 15:43:36 +01:00 committed by GitHub
commit f7674c592c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 14 deletions

View File

@ -1,4 +1,5 @@
<?php <?php
/** /**
* @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright Copyright (c) 2016, ownCloud, Inc.
* @copyright Copyright (c) 2016, Björn Schießle * @copyright Copyright (c) 2016, Björn Schießle
@ -33,9 +34,12 @@ use OCP\Accounts\IAccount;
use OCP\Accounts\IAccountManager; use OCP\Accounts\IAccountManager;
use OCP\BackgroundJob\IJobList; use OCP\BackgroundJob\IJobList;
use OCP\IDBConnection; use OCP\IDBConnection;
use OCP\ILogger;
use OCP\IUser; use OCP\IUser;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent; use Symfony\Component\EventDispatcher\GenericEvent;
use function json_decode;
use function json_last_error;
/** /**
* Class AccountManager * Class AccountManager
@ -59,6 +63,9 @@ class AccountManager implements IAccountManager {
/** @var IJobList */ /** @var IJobList */
private $jobList; private $jobList;
/** @var ILogger */
private $logger;
/** /**
* AccountManager constructor. * AccountManager constructor.
* *
@ -68,10 +75,12 @@ class AccountManager implements IAccountManager {
*/ */
public function __construct(IDBConnection $connection, public function __construct(IDBConnection $connection,
EventDispatcherInterface $eventDispatcher, EventDispatcherInterface $eventDispatcher,
IJobList $jobList) { IJobList $jobList,
ILogger $logger) {
$this->connection = $connection; $this->connection = $connection;
$this->eventDispatcher = $eventDispatcher; $this->eventDispatcher = $eventDispatcher;
$this->jobList = $jobList; $this->jobList = $jobList;
$this->logger = $logger;
} }
/** /**
@ -137,6 +146,11 @@ class AccountManager implements IAccountManager {
} }
$userDataArray = json_decode($result[0]['data'], true); $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); $userDataArray = $this->addMissingDefaultValues($userDataArray);

View File

@ -87,12 +87,8 @@ class Hooks {
* @return AccountManager * @return AccountManager
*/ */
protected function getAccountManager() { protected function getAccountManager() {
if (is_null($this->accountManager)) { if ($this->accountManager === null) {
$this->accountManager = new AccountManager( $this->accountManager = \OC::$server->query(AccountManager::class);
\OC::$server->getDatabaseConnection(),
\OC::$server->getEventDispatcher(),
\OC::$server->getJobList()
);
} }
return $this->accountManager; return $this->accountManager;
} }

View File

@ -26,7 +26,9 @@ use OC\Accounts\Account;
use OC\Accounts\AccountManager; use OC\Accounts\AccountManager;
use OCP\Accounts\IAccountManager; use OCP\Accounts\IAccountManager;
use OCP\BackgroundJob\IJobList; use OCP\BackgroundJob\IJobList;
use OCP\ILogger;
use OCP\IUser; use OCP\IUser;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent; use Symfony\Component\EventDispatcher\GenericEvent;
use Test\TestCase; use Test\TestCase;
@ -42,21 +44,24 @@ class AccountsManagerTest extends TestCase {
/** @var \OCP\IDBConnection */ /** @var \OCP\IDBConnection */
private $connection; private $connection;
/** @var EventDispatcherInterface | \PHPUnit_Framework_MockObject_MockObject */ /** @var EventDispatcherInterface|MockObject */
private $eventDispatcher; private $eventDispatcher;
/** @var IJobList | \PHPUnit_Framework_MockObject_MockObject */ /** @var IJobList|MockObject */
private $jobList; private $jobList;
/** @var string accounts table name */ /** @var string accounts table name */
private $table = 'accounts'; private $table = 'accounts';
/** @var ILogger|MockObject */
private $logger;
protected function setUp(): void { protected function setUp(): void {
parent::setUp(); parent::setUp();
$this->eventDispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface') $this->eventDispatcher = $this->createMock(EventDispatcherInterface::class);
->disableOriginalConstructor()->getMock();
$this->connection = \OC::$server->getDatabaseConnection(); $this->connection = \OC::$server->getDatabaseConnection();
$this->jobList = $this->getMockBuilder(IJobList::class)->getMock(); $this->jobList = $this->createMock(IJobList::class);
$this->logger = $this->createMock(ILogger::class);
} }
protected function tearDown(): void { protected function tearDown(): void {
@ -69,11 +74,11 @@ class AccountsManagerTest extends TestCase {
* get a instance of the accountManager * get a instance of the accountManager
* *
* @param array $mockedMethods list of methods which should be mocked * @param array $mockedMethods list of methods which should be mocked
* @return \PHPUnit_Framework_MockObject_MockObject | AccountManager * @return MockObject | AccountManager
*/ */
public function getInstance($mockedMethods = null) { public function getInstance($mockedMethods = null) {
return $this->getMockBuilder(AccountManager::class) return $this->getMockBuilder(AccountManager::class)
->setConstructorArgs([$this->connection, $this->eventDispatcher, $this->jobList]) ->setConstructorArgs([$this->connection, $this->eventDispatcher, $this->jobList, $this->logger])
->setMethods($mockedMethods) ->setMethods($mockedMethods)
->getMock(); ->getMock();