Add generic authorization class
This commit is contained in:
@@ -1,49 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Kanboard\Auth;
|
|
||||||
|
|
||||||
use Kanboard\Core\Base;
|
|
||||||
use Kanboard\Model\User;
|
|
||||||
use Kanboard\Event\AuthEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Database authentication
|
|
||||||
*
|
|
||||||
* @package auth
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Database extends Base
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Backend name
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
const AUTH_NAME = 'Database';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticate a user
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $username Username
|
|
||||||
* @param string $password Password
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public function authenticate($username, $password)
|
|
||||||
{
|
|
||||||
$user = $this->db
|
|
||||||
->table(User::TABLE)
|
|
||||||
->eq('username', $username)
|
|
||||||
->eq('disable_login_form', 0)
|
|
||||||
->eq('is_ldap_user', 0)
|
|
||||||
->findOne();
|
|
||||||
|
|
||||||
if (is_array($user) && password_verify($password, $user['password'])) {
|
|
||||||
$this->userSession->initialize($user);
|
|
||||||
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
92
app/Core/Security/AccessMap.php
Normal file
92
app/Core/Security/AccessMap.php
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access Map Definition
|
||||||
|
*
|
||||||
|
* @package security
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class AccessMap
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Default role
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $defaultRole = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access map
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $map = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the default role when nothing match
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $role
|
||||||
|
* @return Acl
|
||||||
|
*/
|
||||||
|
public function setDefaultRole($role)
|
||||||
|
{
|
||||||
|
$this->defaultRole = $role;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new access rules
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $controller
|
||||||
|
* @param string $method
|
||||||
|
* @param array $roles
|
||||||
|
* @return Acl
|
||||||
|
*/
|
||||||
|
public function add($controller, $method, array $roles)
|
||||||
|
{
|
||||||
|
$controller = strtolower($controller);
|
||||||
|
$method = strtolower($method);
|
||||||
|
|
||||||
|
if (! isset($this->map[$controller])) {
|
||||||
|
$this->map[$controller] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! isset($this->map[$controller][$method])) {
|
||||||
|
$this->map[$controller][$method] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->map[$controller][$method] = $roles;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get roles that match the given controller/method
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $controller
|
||||||
|
* @param string $method
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getRoles($controller, $method)
|
||||||
|
{
|
||||||
|
$controller = strtolower($controller);
|
||||||
|
$method = strtolower($method);
|
||||||
|
|
||||||
|
if (isset($this->map[$controller][$method])) {
|
||||||
|
return $this->map[$controller][$method];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($this->map[$controller]['*'])) {
|
||||||
|
return $this->map[$controller]['*'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array($this->defaultRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
app/Core/Security/Authorization.php
Normal file
46
app/Core/Security/Authorization.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authorization Handler
|
||||||
|
*
|
||||||
|
* @package security
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Authorization
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Access Map
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var AccessMap
|
||||||
|
*/
|
||||||
|
private $acl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param AccessMap $acl
|
||||||
|
*/
|
||||||
|
public function __construct(AccessMap $acl)
|
||||||
|
{
|
||||||
|
$this->acl = $acl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given role is allowed to access to the specified resource
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $controller
|
||||||
|
* @param string $method
|
||||||
|
* @param string $role
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isAllowed($controller, $method, $role)
|
||||||
|
{
|
||||||
|
$roles = $this->acl->getRoles($controller, $method);
|
||||||
|
return in_array($role, $roles);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
app/Core/Security/Role.php
Normal file
21
app/Core/Security/Role.php
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Role Definitions
|
||||||
|
*
|
||||||
|
* @package security
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Role
|
||||||
|
{
|
||||||
|
const APP_ADMIN = 'app-admin';
|
||||||
|
const APP_MANAGER = 'app-manager';
|
||||||
|
const APP_USER = 'app-user';
|
||||||
|
const APP_PUBLIC = 'app-public';
|
||||||
|
|
||||||
|
const PROJECT_MANAGER = 'project-manager';
|
||||||
|
const PROJECT_MEMBER = 'project-member';
|
||||||
|
const PROJECT_VIEWER = 'project-viewer';
|
||||||
|
}
|
||||||
22
tests/units/Core/Security/AccessMapTest.php
Normal file
22
tests/units/Core/Security/AccessMapTest.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../../Base.php';
|
||||||
|
|
||||||
|
use Kanboard\Core\Security\AccessMap;
|
||||||
|
|
||||||
|
class AccessMapTest extends Base
|
||||||
|
{
|
||||||
|
public function testGetRoles()
|
||||||
|
{
|
||||||
|
$acl = new AccessMap;
|
||||||
|
$acl->setDefaultRole('role3');
|
||||||
|
$acl->add('MyController', 'myAction1', array('role1', 'role2'));
|
||||||
|
$acl->add('MyController', 'myAction2', array('role1'));
|
||||||
|
$acl->add('MyAdminController', '*', array('role2'));
|
||||||
|
|
||||||
|
$this->assertEquals(array('role1', 'role2'), $acl->getRoles('mycontroller', 'MyAction1'));
|
||||||
|
$this->assertEquals(array('role1'), $acl->getRoles('mycontroller', 'MyAction2'));
|
||||||
|
$this->assertEquals(array('role2'), $acl->getRoles('Myadmincontroller', 'MyAction'));
|
||||||
|
$this->assertEquals(array('role3'), $acl->getRoles('AnotherController', 'ActionNotFound'));
|
||||||
|
}
|
||||||
|
}
|
||||||
28
tests/units/Core/Security/AuthorizationTest.php
Normal file
28
tests/units/Core/Security/AuthorizationTest.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__.'/../../Base.php';
|
||||||
|
|
||||||
|
use Kanboard\Core\Security\Role;
|
||||||
|
use Kanboard\Core\Security\AccessMap;
|
||||||
|
use Kanboard\Core\Security\Authorization;
|
||||||
|
|
||||||
|
class AuthorizationTest extends Base
|
||||||
|
{
|
||||||
|
public function testIsAllowed()
|
||||||
|
{
|
||||||
|
$acl = new AccessMap;
|
||||||
|
$acl->setDefaultRole(Role::APP_USER);
|
||||||
|
$acl->add('MyController', 'myAction1', array(Role::APP_ADMIN, Role::APP_MANAGER));
|
||||||
|
$acl->add('MyController', 'myAction2', array(Role::APP_ADMIN));
|
||||||
|
$acl->add('MyAdminController', '*', array(Role::APP_MANAGER));
|
||||||
|
|
||||||
|
$authorization = new Authorization($acl);
|
||||||
|
$this->assertTrue($authorization->isAllowed('myController', 'myAction1', Role::APP_ADMIN));
|
||||||
|
$this->assertTrue($authorization->isAllowed('myController', 'myAction1', Role::APP_MANAGER));
|
||||||
|
$this->assertFalse($authorization->isAllowed('myController', 'myAction1', Role::APP_USER));
|
||||||
|
$this->assertTrue($authorization->isAllowed('anotherController', 'anotherAction', Role::APP_USER));
|
||||||
|
$this->assertTrue($authorization->isAllowed('MyAdminController', 'myAction', Role::APP_MANAGER));
|
||||||
|
$this->assertFalse($authorization->isAllowed('MyAdminController', 'myAction', Role::APP_ADMIN));
|
||||||
|
$this->assertFalse($authorization->isAllowed('MyAdminController', 'myAction', 'something else'));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user