mirror of
https://github.com/nextcloud/server.git
synced 2025-02-12 03:59:16 +00:00
![Ferdinand Thiessen](/assets/img/avatar_default.png)
Currently there is a problem if an exception is thrown in `User::delete`, because at that point the user is already removed from the backend, but not all data is deleted. There is no way to recover from this state, as the user is gone no information is available anymore. This means the data is still available on the server but can not removed by any API anymore. The solution here is to first set a flag and backup the user home, this can be used to recover failed user deletions in a way the delete can be re-tried. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1026 lines
27 KiB
PHP
1026 lines
27 KiB
PHP
<?php
|
|
|
|
/**
|
|
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
|
|
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
|
|
namespace Test\User;
|
|
|
|
use OC\AllConfig;
|
|
use OC\Files\Mount\ObjectHomeMountProvider;
|
|
use OC\Hooks\PublicEmitter;
|
|
use OC\User\User;
|
|
use OCP\Comments\ICommentsManager;
|
|
use OCP\EventDispatcher\IEventDispatcher;
|
|
use OCP\Files\Storage\IStorageFactory;
|
|
use OCP\IConfig;
|
|
use OCP\IURLGenerator;
|
|
use OCP\IUser;
|
|
use OCP\Notification\IManager as INotificationManager;
|
|
use OCP\Notification\INotification;
|
|
use OCP\Server;
|
|
use OCP\UserInterface;
|
|
use PHPUnit\Framework\MockObject\MockObject;
|
|
use Test\TestCase;
|
|
|
|
/**
|
|
* Class UserTest
|
|
*
|
|
* @group DB
|
|
*
|
|
* @package Test\User
|
|
*/
|
|
class UserTest extends TestCase {
|
|
/** @var IEventDispatcher|MockObject */
|
|
protected $dispatcher;
|
|
|
|
protected function setUp(): void {
|
|
parent::setUp();
|
|
$this->dispatcher = Server::get(IEventDispatcher::class);
|
|
}
|
|
|
|
public function testDisplayName(): void {
|
|
/**
|
|
* @var \OC\User\Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\OC\User\Backend::class);
|
|
$backend->expects($this->once())
|
|
->method('getDisplayName')
|
|
->with($this->equalTo('foo'))
|
|
->willReturn('Foo');
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->with($this->equalTo(\OC\User\Backend::GET_DISPLAYNAME))
|
|
->willReturn(true);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertEquals('Foo', $user->getDisplayName());
|
|
}
|
|
|
|
/**
|
|
* if the display name contain whitespaces only, we expect the uid as result
|
|
*/
|
|
public function testDisplayNameEmpty(): void {
|
|
/**
|
|
* @var \OC\User\Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\OC\User\Backend::class);
|
|
$backend->expects($this->once())
|
|
->method('getDisplayName')
|
|
->with($this->equalTo('foo'))
|
|
->willReturn(' ');
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->with($this->equalTo(\OC\User\Backend::GET_DISPLAYNAME))
|
|
->willReturn(true);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertEquals('foo', $user->getDisplayName());
|
|
}
|
|
|
|
public function testDisplayNameNotSupported(): void {
|
|
/**
|
|
* @var \OC\User\Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\OC\User\Backend::class);
|
|
$backend->expects($this->never())
|
|
->method('getDisplayName');
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->with($this->equalTo(\OC\User\Backend::GET_DISPLAYNAME))
|
|
->willReturn(false);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertEquals('foo', $user->getDisplayName());
|
|
}
|
|
|
|
public function testSetPassword(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
$backend->expects($this->once())
|
|
->method('setPassword')
|
|
->with($this->equalTo('foo'), $this->equalTo('bar'));
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::SET_PASSWORD) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertTrue($user->setPassword('bar', ''));
|
|
}
|
|
|
|
public function testSetPasswordNotSupported(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
$backend->expects($this->never())
|
|
->method('setPassword');
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturn(false);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertFalse($user->setPassword('bar', ''));
|
|
}
|
|
|
|
public function testChangeAvatarSupportedYes(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(AvatarUserDummy::class);
|
|
$backend->expects($this->once())
|
|
->method('canChangeAvatar')
|
|
->with($this->equalTo('foo'))
|
|
->willReturn(true);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::PROVIDE_AVATAR) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertTrue($user->canChangeAvatar());
|
|
}
|
|
|
|
public function testChangeAvatarSupportedNo(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(AvatarUserDummy::class);
|
|
$backend->expects($this->once())
|
|
->method('canChangeAvatar')
|
|
->with($this->equalTo('foo'))
|
|
->willReturn(false);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::PROVIDE_AVATAR) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertFalse($user->canChangeAvatar());
|
|
}
|
|
|
|
public function testChangeAvatarNotSupported(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(AvatarUserDummy::class);
|
|
$backend->expects($this->never())
|
|
->method('canChangeAvatar');
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturn(false);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertTrue($user->canChangeAvatar());
|
|
}
|
|
|
|
public function testDelete(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
$backend->expects($this->once())
|
|
->method('deleteUser')
|
|
->with($this->equalTo('foo'));
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertTrue($user->delete());
|
|
}
|
|
|
|
public function testDeleteWithDifferentHome(): void {
|
|
/** @var ObjectHomeMountProvider $homeProvider */
|
|
$homeProvider = \OC::$server->get(ObjectHomeMountProvider::class);
|
|
$user = $this->createMock(IUser::class);
|
|
$user->method('getUID')
|
|
->willReturn('foo');
|
|
if ($homeProvider->getHomeMountForUser($user, $this->createMock(IStorageFactory::class)) !== null) {
|
|
$this->markTestSkipped('Skipping test for non local home storage');
|
|
}
|
|
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$backend->expects($this->once())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::GET_HOME) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
// important: getHome MUST be called before deleteUser because
|
|
// once the user is deleted, getHome implementations might not
|
|
// return anything
|
|
$backend->expects($this->once())
|
|
->method('getHome')
|
|
->with($this->equalTo('foo'))
|
|
->willReturn('/home/foo');
|
|
|
|
$backend->expects($this->once())
|
|
->method('deleteUser')
|
|
->with($this->equalTo('foo'));
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertTrue($user->delete());
|
|
}
|
|
|
|
public function testGetHome(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
$backend->expects($this->once())
|
|
->method('getHome')
|
|
->with($this->equalTo('foo'))
|
|
->willReturn('/home/foo');
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::GET_HOME) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertEquals('/home/foo', $user->getHome());
|
|
}
|
|
|
|
public function testGetBackendClassName(): void {
|
|
$user = new User('foo', new \Test\Util\User\Dummy(), $this->dispatcher);
|
|
$this->assertEquals('Dummy', $user->getBackendClassName());
|
|
$user = new User('foo', new \OC\User\Database(), $this->dispatcher);
|
|
$this->assertEquals('Database', $user->getBackendClassName());
|
|
}
|
|
|
|
public function testGetHomeNotSupported(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
$backend->expects($this->never())
|
|
->method('getHome');
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturn(false);
|
|
|
|
$allConfig = $this->getMockBuilder(IConfig::class)
|
|
->disableOriginalConstructor()
|
|
->getMock();
|
|
$allConfig->expects($this->any())
|
|
->method('getUserValue')
|
|
->willReturn(true);
|
|
$allConfig->expects($this->any())
|
|
->method('getSystemValueString')
|
|
->with($this->equalTo('datadirectory'))
|
|
->willReturn('arbitrary/path');
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, null, $allConfig);
|
|
$this->assertEquals('arbitrary/path/foo', $user->getHome());
|
|
}
|
|
|
|
public function testCanChangePassword(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::SET_PASSWORD) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertTrue($user->canChangePassword());
|
|
}
|
|
|
|
public function testCanChangePasswordNotSupported(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturn(false);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertFalse($user->canChangePassword());
|
|
}
|
|
|
|
public function testCanChangeDisplayName(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::SET_DISPLAYNAME) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->method('getSystemValueBool')
|
|
->with('allow_user_to_change_display_name')
|
|
->willReturn(true);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, null, $config);
|
|
$this->assertTrue($user->canChangeDisplayName());
|
|
}
|
|
|
|
public function testCanChangeDisplayNameNotSupported(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturn(false);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertFalse($user->canChangeDisplayName());
|
|
}
|
|
|
|
public function testSetDisplayNameSupported(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\OC\User\Database::class);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::SET_DISPLAYNAME) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$backend->expects($this->once())
|
|
->method('setDisplayName')
|
|
->with('foo', 'Foo')
|
|
->willReturn(true);
|
|
|
|
$user = new User('foo', $backend, $this->createMock(IEventDispatcher::class));
|
|
$this->assertTrue($user->setDisplayName('Foo'));
|
|
$this->assertEquals('Foo', $user->getDisplayName());
|
|
}
|
|
|
|
/**
|
|
* don't allow display names containing whitespaces only
|
|
*/
|
|
public function testSetDisplayNameEmpty(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\OC\User\Database::class);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::SET_DISPLAYNAME) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertFalse($user->setDisplayName(' '));
|
|
$this->assertEquals('foo', $user->getDisplayName());
|
|
}
|
|
|
|
public function testSetDisplayNameNotSupported(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\OC\User\Database::class);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturn(false);
|
|
|
|
$backend->expects($this->never())
|
|
->method('setDisplayName');
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher);
|
|
$this->assertFalse($user->setDisplayName('Foo'));
|
|
$this->assertEquals('foo', $user->getDisplayName());
|
|
}
|
|
|
|
public function testSetPasswordHooks(): void {
|
|
$hooksCalled = 0;
|
|
$test = $this;
|
|
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
$backend->expects($this->once())
|
|
->method('setPassword');
|
|
|
|
/**
|
|
* @param User $user
|
|
* @param string $password
|
|
*/
|
|
$hook = function ($user, $password) use ($test, &$hooksCalled) {
|
|
$hooksCalled++;
|
|
$test->assertEquals('foo', $user->getUID());
|
|
$test->assertEquals('bar', $password);
|
|
};
|
|
|
|
$emitter = new PublicEmitter();
|
|
$emitter->listen('\OC\User', 'preSetPassword', $hook);
|
|
$emitter->listen('\OC\User', 'postSetPassword', $hook);
|
|
|
|
$backend->expects($this->any())
|
|
->method('implementsActions')
|
|
->willReturnCallback(function ($actions) {
|
|
if ($actions === \OC\User\Backend::SET_PASSWORD) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
});
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, $emitter);
|
|
|
|
$user->setPassword('bar', '');
|
|
$this->assertEquals(2, $hooksCalled);
|
|
}
|
|
|
|
public function dataDeleteHooks() {
|
|
return [
|
|
[true, 2],
|
|
[false, 1],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider dataDeleteHooks
|
|
* @param bool $result
|
|
* @param int $expectedHooks
|
|
*/
|
|
public function testDeleteHooks($result, $expectedHooks): void {
|
|
$hooksCalled = 0;
|
|
$test = $this;
|
|
|
|
/**
|
|
* @var UserInterface&MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
$backend->expects($this->once())
|
|
->method('deleteUser')
|
|
->willReturn($result);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->method('getSystemValue')
|
|
->willReturnArgument(1);
|
|
$config->method('getSystemValueString')
|
|
->willReturnArgument(1);
|
|
$config->method('getSystemValueBool')
|
|
->willReturnArgument(1);
|
|
$config->method('getSystemValueInt')
|
|
->willReturnArgument(1);
|
|
|
|
$emitter = new PublicEmitter();
|
|
$user = new User('foo', $backend, $this->dispatcher, $emitter, $config);
|
|
|
|
/**
|
|
* @param User $user
|
|
*/
|
|
$hook = function ($user) use ($test, &$hooksCalled) {
|
|
$hooksCalled++;
|
|
$test->assertEquals('foo', $user->getUID());
|
|
};
|
|
|
|
$emitter->listen('\OC\User', 'preDelete', $hook);
|
|
$emitter->listen('\OC\User', 'postDelete', $hook);
|
|
|
|
$commentsManager = $this->createMock(ICommentsManager::class);
|
|
$notificationManager = $this->createMock(INotificationManager::class);
|
|
|
|
if ($result) {
|
|
$config->expects($this->atLeastOnce())
|
|
->method('deleteAllUserValues')
|
|
->with('foo');
|
|
|
|
$commentsManager->expects($this->once())
|
|
->method('deleteReferencesOfActor')
|
|
->with('users', 'foo');
|
|
$commentsManager->expects($this->once())
|
|
->method('deleteReadMarksFromUser')
|
|
->with($user);
|
|
|
|
$notification = $this->createMock(INotification::class);
|
|
$notification->expects($this->once())
|
|
->method('setUser')
|
|
->with('foo');
|
|
|
|
$notificationManager->expects($this->once())
|
|
->method('createNotification')
|
|
->willReturn($notification);
|
|
$notificationManager->expects($this->once())
|
|
->method('markProcessed')
|
|
->with($notification);
|
|
} else {
|
|
$config->expects($this->never())
|
|
->method('deleteAllUserValues');
|
|
|
|
$commentsManager->expects($this->never())
|
|
->method('deleteReferencesOfActor');
|
|
$commentsManager->expects($this->never())
|
|
->method('deleteReadMarksFromUser');
|
|
|
|
$notificationManager->expects($this->never())
|
|
->method('createNotification');
|
|
$notificationManager->expects($this->never())
|
|
->method('markProcessed');
|
|
}
|
|
|
|
$this->overwriteService(\OCP\Notification\IManager::class, $notificationManager);
|
|
$this->overwriteService(\OCP\Comments\ICommentsManager::class, $commentsManager);
|
|
|
|
$this->assertSame($result, $user->delete());
|
|
|
|
$this->restoreService(AllConfig::class);
|
|
$this->restoreService(\OCP\Comments\ICommentsManager::class);
|
|
$this->restoreService(\OCP\Notification\IManager::class);
|
|
|
|
$this->assertEquals($expectedHooks, $hooksCalled);
|
|
}
|
|
|
|
public function testDeleteRecoverState() {
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
$backend->expects($this->once())
|
|
->method('deleteUser')
|
|
->willReturn(true);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->method('getSystemValue')
|
|
->willReturnArgument(1);
|
|
$config->method('getSystemValueString')
|
|
->willReturnArgument(1);
|
|
$config->method('getSystemValueBool')
|
|
->willReturnArgument(1);
|
|
$config->method('getSystemValueInt')
|
|
->willReturnArgument(1);
|
|
|
|
$userConfig = [];
|
|
$config->expects(self::atLeast(2))
|
|
->method('setUserValue')
|
|
->willReturnCallback(function () {
|
|
$userConfig[] = func_get_args();
|
|
});
|
|
|
|
$commentsManager = $this->createMock(ICommentsManager::class);
|
|
$commentsManager->expects($this->once())
|
|
->method('deleteReferencesOfActor')
|
|
->willThrowException(new \Error('Test exception'));
|
|
|
|
$this->overwriteService(\OCP\Comments\ICommentsManager::class, $commentsManager);
|
|
$this->expectException(\Error::class);
|
|
|
|
$user = $this->getMockBuilder(User::class)
|
|
->onlyMethods(['getHome'])
|
|
->setConstructorArgs(['foo', $backend, $this->dispatcher, null, $config])
|
|
->getMock();
|
|
|
|
$user->expects(self::atLeastOnce())
|
|
->method('getHome')
|
|
->willReturn('/home/path');
|
|
|
|
$user->delete();
|
|
|
|
$this->assertEqualsCanonicalizing(
|
|
[
|
|
['foo', 'core', 'deleted', 'true', null],
|
|
['foo', 'core', 'deleted.backup-home', '/home/path', null],
|
|
],
|
|
$userConfig,
|
|
);
|
|
|
|
$this->restoreService(\OCP\Comments\ICommentsManager::class);
|
|
}
|
|
|
|
public function dataGetCloudId(): array {
|
|
return [
|
|
['https://localhost:8888/nextcloud', 'foo@localhost:8888/nextcloud'],
|
|
['http://localhost:8888/nextcloud', 'foo@http://localhost:8888/nextcloud'],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider dataGetCloudId
|
|
*/
|
|
public function testGetCloudId(string $absoluteUrl, string $cloudId): void {
|
|
/** @var Backend|MockObject $backend */
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
$urlGenerator = $this->createMock(IURLGenerator::class);
|
|
$urlGenerator->method('getAbsoluteURL')
|
|
->withAnyParameters()
|
|
->willReturn($absoluteUrl);
|
|
$user = new User('foo', $backend, $this->dispatcher, null, null, $urlGenerator);
|
|
$this->assertEquals($cloudId, $user->getCloudId());
|
|
}
|
|
|
|
public function testSetEMailAddressEmpty(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$test = $this;
|
|
$hooksCalled = 0;
|
|
|
|
/**
|
|
* @param IUser $user
|
|
* @param string $feature
|
|
* @param string $value
|
|
*/
|
|
$hook = function (IUser $user, $feature, $value) use ($test, &$hooksCalled) {
|
|
$hooksCalled++;
|
|
$test->assertEquals('eMailAddress', $feature);
|
|
$test->assertEquals('', $value);
|
|
};
|
|
|
|
$emitter = new PublicEmitter();
|
|
$emitter->listen('\OC\User', 'changeUser', $hook);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->expects($this->once())
|
|
->method('deleteUserValue')
|
|
->with(
|
|
'foo',
|
|
'settings',
|
|
'email'
|
|
);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, $emitter, $config);
|
|
$user->setEMailAddress('');
|
|
}
|
|
|
|
public function testSetEMailAddress(): void {
|
|
/**
|
|
* @var UserInterface | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$test = $this;
|
|
$hooksCalled = 0;
|
|
|
|
/**
|
|
* @param IUser $user
|
|
* @param string $feature
|
|
* @param string $value
|
|
*/
|
|
$hook = function (IUser $user, $feature, $value) use ($test, &$hooksCalled) {
|
|
$hooksCalled++;
|
|
$test->assertEquals('eMailAddress', $feature);
|
|
$test->assertEquals('foo@bar.com', $value);
|
|
};
|
|
|
|
$emitter = new PublicEmitter();
|
|
$emitter->listen('\OC\User', 'changeUser', $hook);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->expects($this->once())
|
|
->method('setUserValue')
|
|
->with(
|
|
'foo',
|
|
'settings',
|
|
'email',
|
|
'foo@bar.com'
|
|
);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, $emitter, $config);
|
|
$user->setEMailAddress('foo@bar.com');
|
|
}
|
|
|
|
public function testSetEMailAddressNoChange(): void {
|
|
/**
|
|
* @var UserInterface | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
/** @var PublicEmitter|MockObject $emitter */
|
|
$emitter = $this->createMock(PublicEmitter::class);
|
|
$emitter->expects($this->never())
|
|
->method('emit');
|
|
|
|
$dispatcher = $this->createMock(IEventDispatcher::class);
|
|
$dispatcher->expects($this->never())
|
|
->method('dispatch');
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->expects($this->any())
|
|
->method('getUserValue')
|
|
->willReturn('foo@bar.com');
|
|
$config->expects($this->any())
|
|
->method('setUserValue');
|
|
|
|
$user = new User('foo', $backend, $dispatcher, $emitter, $config);
|
|
$user->setEMailAddress('foo@bar.com');
|
|
}
|
|
|
|
public function testSetQuota(): void {
|
|
/**
|
|
* @var UserInterface | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$test = $this;
|
|
$hooksCalled = 0;
|
|
|
|
/**
|
|
* @param IUser $user
|
|
* @param string $feature
|
|
* @param string $value
|
|
*/
|
|
$hook = function (IUser $user, $feature, $value) use ($test, &$hooksCalled) {
|
|
$hooksCalled++;
|
|
$test->assertEquals('quota', $feature);
|
|
$test->assertEquals('23 TB', $value);
|
|
};
|
|
|
|
$emitter = new PublicEmitter();
|
|
$emitter->listen('\OC\User', 'changeUser', $hook);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->expects($this->once())
|
|
->method('setUserValue')
|
|
->with(
|
|
'foo',
|
|
'files',
|
|
'quota',
|
|
'23 TB'
|
|
);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, $emitter, $config);
|
|
$user->setQuota('23 TB');
|
|
}
|
|
|
|
public function testGetDefaultUnlimitedQuota(): void {
|
|
/**
|
|
* @var UserInterface | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
/** @var PublicEmitter|MockObject $emitter */
|
|
$emitter = $this->createMock(PublicEmitter::class);
|
|
$emitter->expects($this->never())
|
|
->method('emit');
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$user = new User('foo', $backend, $this->dispatcher, $emitter, $config);
|
|
|
|
$userValueMap = [
|
|
['foo', 'files', 'quota', 'default', 'default'],
|
|
];
|
|
$appValueMap = [
|
|
['files', 'default_quota', 'none', 'none'],
|
|
// allow unlimited quota
|
|
['files', 'allow_unlimited_quota', '1', '1'],
|
|
];
|
|
$config->method('getUserValue')
|
|
->will($this->returnValueMap($userValueMap));
|
|
$config->method('getAppValue')
|
|
->will($this->returnValueMap($appValueMap));
|
|
|
|
$quota = $user->getQuota();
|
|
$this->assertEquals('none', $quota);
|
|
}
|
|
|
|
public function testGetDefaultUnlimitedQuotaForbidden(): void {
|
|
/**
|
|
* @var UserInterface | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
/** @var PublicEmitter|MockObject $emitter */
|
|
$emitter = $this->createMock(PublicEmitter::class);
|
|
$emitter->expects($this->never())
|
|
->method('emit');
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$user = new User('foo', $backend, $this->dispatcher, $emitter, $config);
|
|
|
|
$userValueMap = [
|
|
['foo', 'files', 'quota', 'default', 'default'],
|
|
];
|
|
$appValueMap = [
|
|
['files', 'default_quota', 'none', 'none'],
|
|
// do not allow unlimited quota
|
|
['files', 'allow_unlimited_quota', '1', '0'],
|
|
['files', 'quota_preset', '1 GB, 5 GB, 10 GB', '1 GB, 5 GB, 10 GB'],
|
|
// expect seeing 1 GB used as fallback value
|
|
['files', 'default_quota', '1 GB', '1 GB'],
|
|
];
|
|
$config->method('getUserValue')
|
|
->will($this->returnValueMap($userValueMap));
|
|
$config->method('getAppValue')
|
|
->will($this->returnValueMap($appValueMap));
|
|
|
|
$quota = $user->getQuota();
|
|
$this->assertEquals('1 GB', $quota);
|
|
}
|
|
|
|
public function testSetQuotaAddressNoChange(): void {
|
|
/**
|
|
* @var UserInterface | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
/** @var PublicEmitter|MockObject $emitter */
|
|
$emitter = $this->createMock(PublicEmitter::class);
|
|
$emitter->expects($this->never())
|
|
->method('emit');
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->expects($this->any())
|
|
->method('getUserValue')
|
|
->willReturn('23 TB');
|
|
$config->expects($this->never())
|
|
->method('setUserValue');
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, $emitter, $config);
|
|
$user->setQuota('23 TB');
|
|
}
|
|
|
|
public function testGetLastLogin(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->method('getUserValue')
|
|
->willReturnCallback(function ($uid, $app, $key, $default) {
|
|
if ($uid === 'foo' && $app === 'login' && $key === 'lastLogin') {
|
|
return 42;
|
|
} else {
|
|
return $default;
|
|
}
|
|
});
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, null, $config);
|
|
$this->assertSame(42, $user->getLastLogin());
|
|
}
|
|
|
|
public function testSetEnabled(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->expects($this->once())
|
|
->method('setUserValue')
|
|
->with(
|
|
$this->equalTo('foo'),
|
|
$this->equalTo('core'),
|
|
$this->equalTo('enabled'),
|
|
'true'
|
|
);
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, null, $config);
|
|
$user->setEnabled(true);
|
|
}
|
|
|
|
public function testSetDisabled(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->expects($this->once())
|
|
->method('setUserValue')
|
|
->with(
|
|
$this->equalTo('foo'),
|
|
$this->equalTo('core'),
|
|
$this->equalTo('enabled'),
|
|
'false'
|
|
);
|
|
|
|
$user = $this->getMockBuilder(User::class)
|
|
->setConstructorArgs([
|
|
'foo',
|
|
$backend,
|
|
$this->dispatcher,
|
|
null,
|
|
$config,
|
|
])
|
|
->setMethods(['isEnabled', 'triggerChange'])
|
|
->getMock();
|
|
|
|
$user->expects($this->once())
|
|
->method('isEnabled')
|
|
->willReturn(true);
|
|
$user->expects($this->once())
|
|
->method('triggerChange')
|
|
->with(
|
|
'enabled',
|
|
false
|
|
);
|
|
|
|
$user->setEnabled(false);
|
|
}
|
|
|
|
public function testSetDisabledAlreadyDisabled(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->expects($this->never())
|
|
->method('setUserValue');
|
|
|
|
$user = $this->getMockBuilder(User::class)
|
|
->setConstructorArgs([
|
|
'foo',
|
|
$backend,
|
|
$this->dispatcher,
|
|
null,
|
|
$config,
|
|
])
|
|
->setMethods(['isEnabled', 'triggerChange'])
|
|
->getMock();
|
|
|
|
$user->expects($this->once())
|
|
->method('isEnabled')
|
|
->willReturn(false);
|
|
$user->expects($this->never())
|
|
->method('triggerChange');
|
|
|
|
$user->setEnabled(false);
|
|
}
|
|
|
|
public function testGetEMailAddress(): void {
|
|
/**
|
|
* @var Backend | MockObject $backend
|
|
*/
|
|
$backend = $this->createMock(\Test\Util\User\Dummy::class);
|
|
|
|
$config = $this->createMock(IConfig::class);
|
|
$config->method('getUserValue')
|
|
->willReturnCallback(function ($uid, $app, $key, $default) {
|
|
if ($uid === 'foo' && $app === 'settings' && $key === 'email') {
|
|
return 'foo@bar.com';
|
|
} else {
|
|
return $default;
|
|
}
|
|
});
|
|
|
|
$user = new User('foo', $backend, $this->dispatcher, null, $config);
|
|
$this->assertSame('foo@bar.com', $user->getEMailAddress());
|
|
}
|
|
}
|