Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>tags/v18.0.0beta1
@@ -385,6 +385,8 @@ return array( | |||
'OCP\\Search\\Provider' => $baseDir . '/lib/public/Search/Provider.php', | |||
'OCP\\Search\\Result' => $baseDir . '/lib/public/Search/Result.php', | |||
'OCP\\Security\\CSP\\AddContentSecurityPolicyEvent' => $baseDir . '/lib/public/Security/CSP/AddContentSecurityPolicyEvent.php', | |||
'OCP\\Security\\Events\\GenerateSecurePasswordEvent' => $baseDir . '/lib/public/Security/Events/GenerateSecurePasswordEvent.php', | |||
'OCP\\Security\\Events\\ValidatePasswordPolicyEvent' => $baseDir . '/lib/public/Security/Events/ValidatePasswordPolicyEvent.php', | |||
'OCP\\Security\\FeaturePolicy\\AddFeaturePolicyEvent' => $baseDir . '/lib/public/Security/FeaturePolicy/AddFeaturePolicyEvent.php', | |||
'OCP\\Security\\IContentSecurityPolicyManager' => $baseDir . '/lib/public/Security/IContentSecurityPolicyManager.php', | |||
'OCP\\Security\\ICredentialsManager' => $baseDir . '/lib/public/Security/ICredentialsManager.php', |
@@ -414,6 +414,8 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c | |||
'OCP\\Search\\Provider' => __DIR__ . '/../../..' . '/lib/public/Search/Provider.php', | |||
'OCP\\Search\\Result' => __DIR__ . '/../../..' . '/lib/public/Search/Result.php', | |||
'OCP\\Security\\CSP\\AddContentSecurityPolicyEvent' => __DIR__ . '/../../..' . '/lib/public/Security/CSP/AddContentSecurityPolicyEvent.php', | |||
'OCP\\Security\\Events\\GenerateSecurePasswordEvent' => __DIR__ . '/../../..' . '/lib/public/Security/Events/GenerateSecurePasswordEvent.php', | |||
'OCP\\Security\\Events\\ValidatePasswordPolicyEvent' => __DIR__ . '/../../..' . '/lib/public/Security/Events/ValidatePasswordPolicyEvent.php', | |||
'OCP\\Security\\FeaturePolicy\\AddFeaturePolicyEvent' => __DIR__ . '/../../..' . '/lib/public/Security/FeaturePolicy/AddFeaturePolicyEvent.php', | |||
'OCP\\Security\\IContentSecurityPolicyManager' => __DIR__ . '/../../..' . '/lib/public/Security/IContentSecurityPolicyManager.php', | |||
'OCP\\Security\\ICredentialsManager' => __DIR__ . '/../../..' . '/lib/public/Security/ICredentialsManager.php', |
@@ -55,6 +55,7 @@ use OCP\IUser; | |||
use OCP\IUserManager; | |||
use OCP\L10N\IFactory; | |||
use OCP\Mail\IMailer; | |||
use OCP\Security\Events\ValidatePasswordPolicyEvent; | |||
use OCP\Security\IHasher; | |||
use OCP\Security\ISecureRandom; | |||
use OCP\Share; | |||
@@ -191,8 +192,7 @@ class Manager implements IManager { | |||
// Let others verify the password | |||
try { | |||
$event = new GenericEvent($password); | |||
$this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event); | |||
$this->eventDispatcher->dispatch(new ValidatePasswordPolicyEvent($password)); | |||
} catch (HintException $e) { | |||
throw new \Exception($e->getHint()); | |||
} |
@@ -58,7 +58,9 @@ declare(strict_types=1); | |||
namespace OC\User; | |||
use OC\Cache\CappedMemoryCache; | |||
use OCP\EventDispatcher\IEventDispatcher; | |||
use OCP\IDBConnection; | |||
use OCP\Security\Events\ValidatePasswordPolicyEvent; | |||
use OCP\User\Backend\ABackend; | |||
use OCP\User\Backend\ICheckPasswordBackend; | |||
use OCP\User\Backend\ICountUsersBackend; | |||
@@ -68,7 +70,6 @@ use OCP\User\Backend\IGetHomeBackend; | |||
use OCP\User\Backend\IGetRealUIDBackend; | |||
use OCP\User\Backend\ISetDisplayNameBackend; | |||
use OCP\User\Backend\ISetPasswordBackend; | |||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||
use Symfony\Component\EventDispatcher\GenericEvent; | |||
/** | |||
@@ -86,7 +87,7 @@ class Database extends ABackend | |||
/** @var CappedMemoryCache */ | |||
private $cache; | |||
/** @var EventDispatcherInterface */ | |||
/** @var IEventDispatcher */ | |||
private $eventDispatcher; | |||
/** @var IDBConnection */ | |||
@@ -98,13 +99,13 @@ class Database extends ABackend | |||
/** | |||
* \OC\User\Database constructor. | |||
* | |||
* @param EventDispatcherInterface $eventDispatcher | |||
* @param IEventDispatcher $eventDispatcher | |||
* @param string $table | |||
*/ | |||
public function __construct($eventDispatcher = null, $table = 'users') { | |||
$this->cache = new CappedMemoryCache(); | |||
$this->table = $table; | |||
$this->eventDispatcher = $eventDispatcher ? $eventDispatcher : \OC::$server->getEventDispatcher(); | |||
$this->eventDispatcher = $eventDispatcher ? $eventDispatcher : \OC::$server->query(IEventDispatcher::class); | |||
} | |||
/** | |||
@@ -130,8 +131,7 @@ class Database extends ABackend | |||
$this->fixDI(); | |||
if (!$this->userExists($uid)) { | |||
$event = new GenericEvent($password); | |||
$this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event); | |||
$this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); | |||
$qb = $this->dbConn->getQueryBuilder(); | |||
$qb->insert($this->table) | |||
@@ -199,8 +199,7 @@ class Database extends ABackend | |||
$this->fixDI(); | |||
if ($this->userExists($uid)) { | |||
$event = new GenericEvent($password); | |||
$this->eventDispatcher->dispatch('OCP\PasswordPolicy::validate', $event); | |||
$this->eventDispatcher->dispatchTyped(new ValidatePasswordPolicyEvent($password)); | |||
$hasher = \OC::$server->getHasher(); | |||
$hashedPassword = $hasher->hash($password); |
@@ -0,0 +1,50 @@ | |||
<?php declare(strict_types=1); | |||
/** | |||
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* 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 | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
namespace OCP\Security\Events; | |||
use OCP\EventDispatcher\Event; | |||
/** | |||
* @since 18.0.0 | |||
*/ | |||
class GenerateSecurePasswordEvent extends Event { | |||
/** @var null|string */ | |||
private $password; | |||
/** | |||
* @since 18.0.0 | |||
*/ | |||
public function getPassword(): ?string { | |||
return $this->password; | |||
} | |||
/** | |||
* @since 18.0.0 | |||
*/ | |||
public function setPassword(string $password): void { | |||
$this->password = $password; | |||
} | |||
} |
@@ -0,0 +1,51 @@ | |||
<?php declare(strict_types=1); | |||
/** | |||
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at> | |||
* | |||
* @license GNU AGPL version 3 or any later version | |||
* | |||
* This program is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Affero General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* 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 | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
namespace OCP\Security\Events; | |||
use OCP\EventDispatcher\Event; | |||
/** | |||
* @since 18.0.0 | |||
*/ | |||
class ValidatePasswordPolicyEvent extends Event { | |||
/** @var string */ | |||
private $password; | |||
/** | |||
* @since 18.0.0 | |||
*/ | |||
public function __construct(string $password) { | |||
parent::__construct(); | |||
$this->password = $password; | |||
} | |||
/** | |||
* @since 18.0.0 | |||
*/ | |||
public function getPassword(): string { | |||
return $this->password; | |||
} | |||
} |
@@ -27,6 +27,7 @@ use OC\Share20\DefaultShareProvider; | |||
use OC\Share20\Exception; | |||
use OC\Share20\Manager; | |||
use OC\Share20\Share; | |||
use OCP\EventDispatcher\Event; | |||
use OCP\Files\File; | |||
use OCP\Files\Folder; | |||
use OCP\Files\IRootFolder; | |||
@@ -42,16 +43,18 @@ use OCP\ILogger; | |||
use OCP\IServerContainer; | |||
use OCP\IURLGenerator; | |||
use OCP\IUser; | |||
use OCP\IUserManager; | |||
use OCP\L10N\IFactory; | |||
use OCP\Mail\IMailer; | |||
use OCP\Security\Events\ValidatePasswordPolicyEvent; | |||
use OCP\Security\IHasher; | |||
use OCP\Security\ISecureRandom; | |||
use OCP\Share\Exceptions\ShareNotFound; | |||
use OCP\Share\IProviderFactory; | |||
use OCP\Share\IShare; | |||
use OCP\Share\IShareProvider; | |||
use PHPUnit\Framework\MockObject\MockBuilder; | |||
use PHPUnit\Framework\MockObject\MockObject; | |||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||
use Symfony\Component\EventDispatcher\GenericEvent; | |||
@@ -65,37 +68,37 @@ class ManagerTest extends \Test\TestCase { | |||
/** @var Manager */ | |||
protected $manager; | |||
/** @var ILogger|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var ILogger|MockObject */ | |||
protected $logger; | |||
/** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IConfig|MockObject */ | |||
protected $config; | |||
/** @var ISecureRandom|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var ISecureRandom|MockObject */ | |||
protected $secureRandom; | |||
/** @var IHasher|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IHasher|MockObject */ | |||
protected $hasher; | |||
/** @var IShareProvider|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IShareProvider|MockObject */ | |||
protected $defaultProvider; | |||
/** @var IMountManager|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IMountManager|MockObject */ | |||
protected $mountManager; | |||
/** @var IGroupManager|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IGroupManager|MockObject */ | |||
protected $groupManager; | |||
/** @var IL10N|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IL10N|MockObject */ | |||
protected $l; | |||
/** @var IFactory|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IFactory|MockObject */ | |||
protected $l10nFactory; | |||
/** @var DummyFactory */ | |||
protected $factory; | |||
/** @var IUserManager|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IUserManager|MockObject */ | |||
protected $userManager; | |||
/** @var IRootFolder | \PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IRootFolder | MockObject */ | |||
protected $rootFolder; | |||
/** @var EventDispatcherInterface | \PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var EventDispatcherInterface | MockObject */ | |||
protected $eventDispatcher; | |||
/** @var IMailer|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IMailer|MockObject */ | |||
protected $mailer; | |||
/** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IURLGenerator|MockObject */ | |||
protected $urlGenerator; | |||
/** @var \OC_Defaults|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var \OC_Defaults|MockObject */ | |||
protected $defaults; | |||
public function setUp() { | |||
@@ -146,7 +149,7 @@ class ManagerTest extends \Test\TestCase { | |||
} | |||
/** | |||
* @return \PHPUnit_Framework_MockObject_MockBuilder | |||
* @return MockBuilder | |||
*/ | |||
private function createManagerMock() { | |||
return $this->getMockBuilder('\OC\Share20\Manager') | |||
@@ -496,11 +499,12 @@ class ManagerTest extends \Test\TestCase { | |||
])); | |||
$this->eventDispatcher->expects($this->once())->method('dispatch') | |||
->willReturnCallback(function($eventName, GenericEvent $event) { | |||
$this->assertSame('OCP\PasswordPolicy::validate', $eventName); | |||
$this->assertSame('password', $event->getSubject()); | |||
->willReturnCallback(function(Event $event) { | |||
$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event); | |||
/** @var ValidatePasswordPolicyEvent $event */ | |||
$this->assertSame('password', $event->getPassword()); | |||
} | |||
); | |||
); | |||
$result = self::invokePrivate($this->manager, 'verifyPassword', ['password']); | |||
$this->assertNull($result); | |||
@@ -516,12 +520,13 @@ class ManagerTest extends \Test\TestCase { | |||
])); | |||
$this->eventDispatcher->expects($this->once())->method('dispatch') | |||
->willReturnCallback(function($eventName, GenericEvent $event) { | |||
$this->assertSame('OCP\PasswordPolicy::validate', $eventName); | |||
$this->assertSame('password', $event->getSubject()); | |||
->willReturnCallback(function(Event $event) { | |||
$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event); | |||
/** @var ValidatePasswordPolicyEvent $event */ | |||
$this->assertSame('password', $event->getPassword()); | |||
throw new HintException('message', 'password not accepted'); | |||
} | |||
); | |||
); | |||
self::invokePrivate($this->manager, 'verifyPassword', ['password']); | |||
} |
@@ -21,10 +21,14 @@ | |||
*/ | |||
namespace Test\User; | |||
use OC\HintException; | |||
use OC\User\User; | |||
use OCP\EventDispatcher\Event; | |||
use OCP\EventDispatcher\IEventDispatcher; | |||
use OCP\Security\Events\ValidatePasswordPolicyEvent; | |||
use PHPUnit\Framework\MockObject\MockObject; | |||
use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |||
use Symfony\Component\EventDispatcher\GenericEvent; | |||
/** | |||
* Class DatabaseTest | |||
@@ -34,7 +38,7 @@ use Symfony\Component\EventDispatcher\GenericEvent; | |||
class DatabaseTest extends Backend { | |||
/** @var array */ | |||
private $users; | |||
/** @var EventDispatcherInterface|\PHPUnit_Framework_MockObject_MockObject */ | |||
/** @var IEventDispatcher|MockObject */ | |||
private $eventDispatcher; | |||
public function getUser() { | |||
@@ -46,7 +50,7 @@ class DatabaseTest extends Backend { | |||
protected function setUp() { | |||
parent::setUp(); | |||
$this->eventDispatcher = $this->createMock(EventDispatcherInterface::class); | |||
$this->eventDispatcher = $this->createMock(IEventDispatcher::class); | |||
$this->backend=new \OC\User\Database($this->eventDispatcher); | |||
} | |||
@@ -65,11 +69,12 @@ class DatabaseTest extends Backend { | |||
$user = $this->getUser(); | |||
$this->backend->createUser($user, 'pass1'); | |||
$this->eventDispatcher->expects($this->once())->method('dispatch') | |||
$this->eventDispatcher->expects($this->once())->method('dispatchTyped') | |||
->willReturnCallback( | |||
function ($eventName, GenericEvent $event) { | |||
$this->assertSame('OCP\PasswordPolicy::validate', $eventName); | |||
$this->assertSame('newpass', $event->getSubject()); | |||
function (Event $event) { | |||
$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event); | |||
/** @var ValidatePasswordPolicyEvent $event */ | |||
$this->assertSame('newpass', $event->getPassword()); | |||
} | |||
); | |||
@@ -85,11 +90,12 @@ class DatabaseTest extends Backend { | |||
$user = $this->getUser(); | |||
$this->backend->createUser($user, 'pass1'); | |||
$this->eventDispatcher->expects($this->once())->method('dispatch') | |||
$this->eventDispatcher->expects($this->once())->method('dispatchTyped') | |||
->willReturnCallback( | |||
function ($eventName, GenericEvent $event) { | |||
$this->assertSame('OCP\PasswordPolicy::validate', $eventName); | |||
$this->assertSame('newpass', $event->getSubject()); | |||
function (Event $event) { | |||
$this->assertInstanceOf(ValidatePasswordPolicyEvent::class, $event); | |||
/** @var ValidatePasswordPolicyEvent $event */ | |||
$this->assertSame('newpass', $event->getPassword()); | |||
throw new HintException('password change failed', 'password change failed'); | |||
} | |||
); | |||
@@ -124,8 +130,8 @@ class DatabaseTest extends Backend { | |||
$user2 = $this->getUser(); | |||
$this->backend->createUser($user2, 'pass1'); | |||
$user1Obj = new User($user1, $this->backend, $this->eventDispatcher); | |||
$user2Obj = new User($user2, $this->backend, $this->eventDispatcher); | |||
$user1Obj = new User($user1, $this->backend, $this->createMock(EventDispatcherInterface::class)); | |||
$user2Obj = new User($user2, $this->backend, $this->createMock(EventDispatcherInterface::class)); | |||
$emailAddr1 = "$user1@nextcloud.com"; | |||
$emailAddr2 = "$user2@nextcloud.com"; | |||