]> git.andy128k.dev Git - ipf.git/commitdiff
introduce AuthService
authorAndrey Kutejko <andy128k@gmail.com>
Sun, 7 Apr 2019 10:04:06 +0000 (12:04 +0200)
committerAndrey Kutejko <andy128k@gmail.com>
Sun, 7 Apr 2019 10:04:06 +0000 (12:04 +0200)
ipf/admin/controllers/user.php
ipf/admin/forms/login.php
ipf/auth/admin.php
ipf/auth/app.php
ipf/auth/auth_service.php [new file with mode: 0644]
ipf/auth/commands/createsuperuser.php
ipf/auth/models.php
ipf/crypto.php
t/CryptoTest.php [deleted file]

index c46efc3e59212b10af07a7b7ae416b232834586b..81eff8dc2f17ec338e2268bfe4debb3194a04db2 100644 (file)
@@ -21,15 +21,16 @@ class IPF_Admin_User_Controller extends IPF_Admin_Base_Controller
             $success_url = $this->container['router']->reverse(array('IPF_Admin_Dashboard_Controller', 'index'));
 
         $auth_app = $this->authApp();
+        $auth_serice = $this->container['auth_service'];
 
         if ($this->request->method == 'POST') {
-            $form = new IPF_Admin_Forms_Login($this->request->POST, array('auth_app' => $auth_app));
+            $form = new IPF_Admin_Forms_Login($this->request->POST, array('auth_app' => $auth_app, 'auth_service' => $auth_serice));
             if ($form->isValid()) {
                 $auth_app->login($this->request, $form->user);
                 return new IPF_HTTP_Response_Redirect($success_url);
             }
         } else {
-            $form = new IPF_Admin_Forms_Login(array('next'=>$success_url), array('auth_app' => $auth_app));
+            $form = new IPF_Admin_Forms_Login(array('next'=>$success_url), array('auth_app' => $auth_app, 'auth_service' => $auth_serice));
         }
 
         $context = array(
index 55289f327e94b40bd4ef6dfc95057027283ddc80..3977318ebd02418dea1ed611a91c936051e5af16 100644 (file)
@@ -7,10 +7,13 @@ class IPF_Admin_Forms_Login extends IPF_Form
 
     /** @var IPF_Auth_App */
     private $auth_app;
+    /** @var \IPF\Auth\AuthService */
+    private $auth_service;
 
     protected function initFields($extra=array())
     {
         $this->auth_app = $extra['auth_app'];
+        $this->auth_service = $extra['auth_service'];
 
         $this->fields['username'] = new IPF_Form_Field_Varchar(array('required'=>true));
         $this->fields['password'] = new IPF_Form_Field_Varchar(array('required'=>true,'widget'=>'IPF_Form_Widget_PasswordInput'));
@@ -22,11 +25,12 @@ class IPF_Admin_Forms_Login extends IPF_Form
         $data = parent::clean();
 
         $user = $this->auth_app->findUserByUsername($data['username']);
-        if (!$user || !$user->checkPassword($data['password']))
+        if ($this->auth_service->checkPassword($user, $data['password'])) {
+            $this->user = $user;
+            return $data;
+        } else {
             throw new IPF_Exception_Form(__('The login or the password is not valid. The login and the password are case sensitive.'));
-
-        $this->user = $user;
-        return $data;
+        }
     }
 
     public function render()
index 76db597de48caf40ffcc42b0b1f6779051a58929..c068cba8131d5d0e8864415d3ac2e6a742ae16f1 100644 (file)
@@ -3,6 +3,7 @@
 namespace IPF\Auth\Admin;
 
 use Doctrine\DBAL\Connection;
+use IPF\Auth\AuthService;
 use IPF\Auth\Permission as Permission;
 use IPF\Auth\Role as Role;
 use IPF_Admin_App;
@@ -116,11 +117,14 @@ abstract class Component extends \IPF_Admin_Component
 {
     /** @var Container */
     protected $container;
+    /** @var AuthService */
+    protected $auth_service;
 
-    function __construct(Container $container, IPF_Auth_App $auth_app)
+    function __construct(Container $container, IPF_Auth_App $auth_app, AuthService $auth_service)
     {
         $this->auth_app = $auth_app;
         $this->container = $container;
+        $this->auth_service = $auth_service;
     }
 
     /**
@@ -262,8 +266,9 @@ class AdminUser extends Component
             $user = $this->authApp()->createUser();
 
         $form->toObject($user);
-        if ($form->cleaned_data['password1'])
-            $user->setPassword($form->cleaned_data['password1']);
+        if ($form->cleaned_data['password1']) {
+            $this->auth_service->setPassword($user, $form->cleaned_data['password1']);
+        }
         $user->save($connection);
 
         if ($this->authApp()->arePermissionsEnabled()) {
@@ -415,12 +420,14 @@ class AuthAdminSection implements \IPF_Admin_ISection
     {
         /** @var IPF_Auth_App $app */
 
+        $auth_service = $container['auth_service'];
+
         $components = array(
-            new AdminUser($container, $app),
+            new AdminUser($container, $app, $auth_service),
         );
 
         if ($app->arePermissionsEnabled()) {
-            $components[] = new AdminRole($container, $app);
+            $components[] = new AdminRole($container, $app, $auth_service);
         }
 
         return $components;
index a87b508fa999c8e9be08946e075a495eafff8e11..df14637be21538b4529798ec2bad0bdc85f6d4c2 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 use Doctrine\DBAL\Connection;
+use IPF\Auth\AuthServiceDefault;
 use IPF\Auth\User;
 use Pimple\Container;
 
@@ -19,6 +20,10 @@ class IPF_Auth_App extends IPF_Application
      */
     public function configure(Container $container)
     {
+        $container['auth_service'] = function ($c) {
+            return new AuthServiceDefault();
+        };
+
         $this->container = $container;
         $this->userModel = $container['settings']->get('auth_user_model', User::class);
     }
@@ -83,7 +88,7 @@ class IPF_Auth_App extends IPF_Application
     public function commands()
     {
         return array(
-            new \IPF\Auth\Commands\CreateSuperUser($this),
+            new \IPF\Auth\Commands\CreateSuperUser($this, $this->container['auth_service']),
         );
     }
 
diff --git a/ipf/auth/auth_service.php b/ipf/auth/auth_service.php
new file mode 100644 (file)
index 0000000..7633ed4
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+namespace IPF\Auth;
+
+use IPF_Utils;
+
+interface AuthService
+{
+    function setPassword($user, $raw_password);
+
+    function checkPassword($user, $raw_password);
+}
+
+class AuthServiceDefault implements AuthService
+{
+    function setPassword($user, $raw_password)
+    {
+        if ($raw_password) {
+            $salt = IPF_Utils::randomString(5);
+            $user->password = 'sha1:' . $salt . ':' . sha1($salt . $raw_password);
+        } else {
+            $user->password = '';
+        }
+    }
+
+    function checkPassword($user, $raw_password)
+    {
+        if ($raw_password &&
+            $user &&
+            $user->is_active &&
+            $user->password &&
+            strpos($user->password, ':') !== false
+        ) {
+            list($algo, $salt, $hash) = explode(':', $user->password);
+            return $hash === $algo($salt . $raw_password);
+        } else {
+            return false;
+        }
+    }
+}
index 43a179daaa16d9ff649674abc95f009a33cec67d..2722a71259adc4098eb7fdca766e79f6f19e9d12 100644 (file)
@@ -2,6 +2,8 @@
 
 namespace IPF\Auth\Commands;
 
+use IPF\Auth\AuthService;
+
 class CreateSuperUser
 {
     public $command = 'createsuperuser';
@@ -9,10 +11,13 @@ class CreateSuperUser
 
     /** @var \IPF_Auth_App */
     private $auth_app;
+    /** @var AuthService */
+    private $auth_service;
 
-    public function __construct(\IPF_Auth_App $auth_app)
+    public function __construct(\IPF_Auth_App $auth_app, AuthService $auth_service)
     {
         $this->auth_app = $auth_app;
+        $this->auth_service = $auth_service;
     }
 
     public function run($args=null)
@@ -29,7 +34,7 @@ class CreateSuperUser
         $su->is_staff     = true;
         $su->is_active    = true;
         $su->is_superuser = true;
-        $su->setPassword($password);
+        $this->auth_service->setPassword($su, $password);
         $su->save();
         print "Done\n";
     }
index 4af576722ca6de03f8b621c2384a37442d898b28..1da877e4f9c91084c40eb06792fd0f78bc345289 100644 (file)
@@ -73,19 +73,6 @@ class User extends DBObject
         return $s;
     }
 
-    function setPassword($raw_password)
-    {
-        if ($raw_password)
-            $this->password = \IPF_Crypto::hashPassword($raw_password);
-        else
-            $this->password = '';
-    }
-
-    function checkPassword($raw_password)
-    {
-        return $this->is_active && \IPF_Crypto::checkPassword($raw_password, $this->password);
-    }
-
     function isAnonymous()
     {
         return false;
index 9722b49591e38fccd97238428bce645e5fe22703..f4624b7dae9798063197ee7c612d620d7b34d833 100644 (file)
@@ -22,20 +22,6 @@ class IPF_Crypto
         return hash_hmac('sha1', $string, self::get_key());
     }
 
-    public static function hashPassword($rawPassword)
-    {
-        $salt = IPF_Utils::randomString(5);
-        return 'sha1:'.$salt.':'.sha1($salt . $rawPassword);
-    }
-
-    public static function checkPassword($rawPassword, $hashedPassword)
-    {
-        if (!$rawPassword || !$hashedPassword || strpos($hashedPassword, ':') === false)
-            return false;
-        list($algo, $salt, $hash) = explode(':', $hashedPassword);
-        return $hash === $algo($salt . $rawPassword);
-    }
-
     private static function get_key()
     {
         $secret = self::secretKey();
@@ -57,4 +43,3 @@ class IPF_Crypto
             throw new Exception('Security error: "secret_key" is not set in the configuration file.');
     }
 }
-
diff --git a/t/CryptoTest.php b/t/CryptoTest.php
deleted file mode 100644 (file)
index d865881..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php
-
-class Crypto_Test extends PHPUnit_Framework_TestCase
-{
-    public function testRecording()
-    {
-        $this->assertFalse(IPF_Crypto::checkPassword('secret', 'badhash'));
-    }
-}