]> source.dussan.org Git - nextcloud-server.git/commitdiff
Add typed events for password_policy 18019/head
authorChristoph Wurst <christoph@winzerhof-wurst.at>
Tue, 19 Nov 2019 18:18:00 +0000 (19:18 +0100)
committerChristoph Wurst <christoph@winzerhof-wurst.at>
Wed, 27 Nov 2019 08:56:12 +0000 (09:56 +0100)
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
lib/composer/composer/autoload_classmap.php
lib/composer/composer/autoload_static.php
lib/private/Share20/Manager.php
lib/private/User/Database.php
lib/public/Security/Events/GenerateSecurePasswordEvent.php [new file with mode: 0644]
lib/public/Security/Events/ValidatePasswordPolicyEvent.php [new file with mode: 0644]
tests/lib/Share20/ManagerTest.php
tests/lib/User/DatabaseTest.php

index 9a54c3bf3c605ec5ec5df4fd25e97ae241421516..99b35114969a7a9f8f83f02943f7e788c433ebbb 100644 (file)
@@ -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',
index e06489c4cc0bbbf026785548902cece63b456d35..bf7919d34a59bc6c90c10f92dad1621df8413e12 100644 (file)
@@ -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',
index d9809fd128a5005c9609be050d2265ad68a985e8..210dc7772c0df5e5492635b67edc889622e7c9ac 100644 (file)
@@ -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());
                }
index 23dbe8c2334ee8fe538ef2804a432e003cde9059..a4c35deb2b825e7fe5aeb7d453a5b9c8e7ef7573 100644 (file)
@@ -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);
diff --git a/lib/public/Security/Events/GenerateSecurePasswordEvent.php b/lib/public/Security/Events/GenerateSecurePasswordEvent.php
new file mode 100644 (file)
index 0000000..a55c8da
--- /dev/null
@@ -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;
+       }
+
+}
diff --git a/lib/public/Security/Events/ValidatePasswordPolicyEvent.php b/lib/public/Security/Events/ValidatePasswordPolicyEvent.php
new file mode 100644 (file)
index 0000000..1137852
--- /dev/null
@@ -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;
+       }
+
+}
index 26008c2a3deb1da47bf3ad1fe1627ab71c6b5268..3e34a64acf3b6a618ee0d9b13c96bf7d4cd0131b 100644 (file)
@@ -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']);
        }
index feba7a6926d0191f7dc37b13fb9e9048fab72713..8e52be50c750f07020e159a69723deb33c0e8a2a 100644 (file)
 */
 
 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";