Added basic privilege system
This commit is contained in:
parent
2ecb79a2fa
commit
de31770c87
12 changed files with 77 additions and 16 deletions
|
@ -7,6 +7,13 @@ name = booru-dev
|
|||
secret = change
|
||||
minPasswordLength = 5
|
||||
|
||||
[security.privileges]
|
||||
anonymous = register, viewUser
|
||||
regularUser = listUsers, viewUser
|
||||
powerUser = listUsers, viewUser
|
||||
moderator = listUsers, viewUser
|
||||
administrator = listUsers, viewUser
|
||||
|
||||
[users]
|
||||
minUserNameLength = 1
|
||||
maxUserNameLength = 32
|
||||
|
|
|
@ -44,10 +44,8 @@ App.Auth = function(jQuery, util, api, appState, promise) {
|
|||
|
||||
function logout() {
|
||||
return promise.make(function(resolve, reject) {
|
||||
appState.set('loggedIn', false);
|
||||
appState.set('loginToken', null);
|
||||
jQuery.removeCookie('auth');
|
||||
resolve();
|
||||
return loginAnonymous().then(resolve).fail(reject);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -75,6 +73,7 @@ App.Auth = function(jQuery, util, api, appState, promise) {
|
|||
};
|
||||
|
||||
function updateAppState(response) {
|
||||
appState.set('privileges', response.json.privileges || []);
|
||||
appState.set('loginToken', response.json.token && response.json.token.name);
|
||||
appState.set('loggedInUser', response.json.user);
|
||||
appState.set('loggedIn', response.json.user && !!response.json.user.id);
|
||||
|
|
|
@ -9,6 +9,7 @@ App.Presenters.PagedCollectionPresenter = function(util, promise, api) {
|
|||
var baseUri;
|
||||
var backendUri;
|
||||
var renderCallback;
|
||||
var failCallback;
|
||||
|
||||
var template;
|
||||
var pageSize;
|
||||
|
@ -19,11 +20,10 @@ App.Presenters.PagedCollectionPresenter = function(util, promise, api) {
|
|||
baseUri = args.baseUri;
|
||||
backendUri = args.backendUri;
|
||||
renderCallback = args.renderCallback;
|
||||
failCallback = args.failCallback;
|
||||
|
||||
promise.wait(util.promiseTemplate('pager')).then(function(html) {
|
||||
template = _.template(html);
|
||||
//renderCallback({entities: [], totalRecords: 0});
|
||||
|
||||
changePage(pageNumber);
|
||||
});
|
||||
}
|
||||
|
@ -44,7 +44,11 @@ App.Presenters.PagedCollectionPresenter = function(util, promise, api) {
|
|||
entities: response.json.data,
|
||||
totalRecords: response.json.totalRecords});
|
||||
}).fail(function(response) {
|
||||
if (typeof(failCallback) !== 'undefined') {
|
||||
failCallback(response);
|
||||
} else {
|
||||
console.log(Error(response.json && response.json.error || response));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ App.Presenters.TopNavigationPresenter = function(
|
|||
$el.html(template({
|
||||
loggedIn: appState.get('loggedIn'),
|
||||
user: appState.get('loggedInUser'),
|
||||
privileges: appState.get('privileges'),
|
||||
}));
|
||||
$el.find('li.' + selectedElement).addClass('active');
|
||||
};
|
||||
|
|
|
@ -7,7 +7,8 @@ App.Presenters.UserListPresenter = function(
|
|||
promise,
|
||||
router,
|
||||
pagedCollectionPresenter,
|
||||
topNavigationPresenter) {
|
||||
topNavigationPresenter,
|
||||
messagePresenter) {
|
||||
|
||||
var $el = jQuery('#content');
|
||||
var template;
|
||||
|
@ -28,6 +29,10 @@ App.Presenters.UserListPresenter = function(
|
|||
renderCallback: function updateCollection(data) {
|
||||
userList = data.entities;
|
||||
render();
|
||||
},
|
||||
failCallback: function(response) {
|
||||
$el.empty();
|
||||
messagePresenter.showError($el, response.json && response.json.error || response);
|
||||
}});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
var App = App || {};
|
||||
|
||||
App.Router = function(jQuery, util) {
|
||||
App.Router = function(jQuery, util, appState) {
|
||||
|
||||
var root = '#/';
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<ul>
|
||||
<!-- todo: check privileges -->
|
||||
<% if (_.contains(privileges, 'listUsers')) { %>
|
||||
<li class="users">
|
||||
<a href="#/users">Users</a>
|
||||
</li>
|
||||
<% } %>
|
||||
<% if (!loggedIn) { %>
|
||||
<li class="login">
|
||||
<a href="#/login">Login</a>
|
||||
|
|
|
@ -45,6 +45,7 @@ final class AuthController extends AbstractController
|
|||
[
|
||||
'token' => new \Szurubooru\ViewProxies\Token($this->authService->getLoginToken()),
|
||||
'user' => new \Szurubooru\ViewProxies\User($this->authService->getLoggedInUser()),
|
||||
'privileges' => $this->authService->getCurrentPrivileges(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,15 +3,18 @@ namespace Szurubooru\Controllers;
|
|||
|
||||
final class UserController extends AbstractController
|
||||
{
|
||||
private $inputReader;
|
||||
private $authService;
|
||||
private $userService;
|
||||
private $inputReader;
|
||||
|
||||
public function __construct(
|
||||
\Szurubooru\Services\AuthService $authService,
|
||||
\Szurubooru\Services\UserService $userService,
|
||||
\Szurubooru\Helpers\InputReader $inputReader)
|
||||
{
|
||||
$this->inputReader = $inputReader;
|
||||
$this->authService = $authService;
|
||||
$this->userService = $userService;
|
||||
$this->inputReader = $inputReader;
|
||||
}
|
||||
|
||||
public function registerRoutes(\Szurubooru\Router $router)
|
||||
|
@ -25,7 +28,8 @@ final class UserController extends AbstractController
|
|||
|
||||
public function getFiltered()
|
||||
{
|
||||
//todo: privilege checking
|
||||
$this->authService->assertPrivilege(\Szurubooru\Privilege::PRIVILEGE_LIST_USERS);
|
||||
|
||||
//todo: move this to form data constructor
|
||||
$searchFormData = new \Szurubooru\FormData\SearchFormData;
|
||||
$searchFormData->query = $this->inputReader->query;
|
||||
|
@ -41,7 +45,8 @@ final class UserController extends AbstractController
|
|||
|
||||
public function getByName($name)
|
||||
{
|
||||
//todo: privilege checking
|
||||
$this->authService->assertPrivilege(\Szurubooru\Privilege::PRIVILEGE_VIEW_USER);
|
||||
|
||||
$user = $this->userService->getByName($name);
|
||||
if (!$user)
|
||||
throw new \DomainException('User with name "' . $name . '" was not found.');
|
||||
|
@ -50,7 +55,8 @@ final class UserController extends AbstractController
|
|||
|
||||
public function register()
|
||||
{
|
||||
//todo: privilege checking
|
||||
$this->authService->assertPrivilege(\Szurubooru\Privilege::PRIVILEGE_REGISTER);
|
||||
|
||||
$input = new \Szurubooru\FormData\RegistrationFormData;
|
||||
//todo: move this to form data constructor
|
||||
$input->name = $this->inputReader->userName;
|
||||
|
|
9
src/Privilege.php
Normal file
9
src/Privilege.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
namespace Szurubooru;
|
||||
|
||||
class Privilege
|
||||
{
|
||||
const PRIVILEGE_LIST_USERS = 'listUsers';
|
||||
const PRIVILEGE_VIEW_USER = 'viewUser';
|
||||
const PRIVILEGE_REGISTER = 'register';
|
||||
}
|
|
@ -7,6 +7,7 @@ class AuthService
|
|||
private $loginToken = null;
|
||||
|
||||
private $validator;
|
||||
private $config;
|
||||
private $passwordService;
|
||||
private $timeService;
|
||||
private $userDao;
|
||||
|
@ -14,6 +15,7 @@ class AuthService
|
|||
|
||||
public function __construct(
|
||||
\Szurubooru\Validator $validator,
|
||||
\Szurubooru\Config $config,
|
||||
\Szurubooru\Services\PasswordService $passwordService,
|
||||
\Szurubooru\Services\TimeService $timeService,
|
||||
\Szurubooru\Dao\TokenDao $tokenDao,
|
||||
|
@ -22,6 +24,7 @@ class AuthService
|
|||
$this->loggedInUser = $this->getAnonymousUser();
|
||||
|
||||
$this->validator = $validator;
|
||||
$this->config = $config;
|
||||
$this->passwordService = $passwordService;
|
||||
$this->timeService = $timeService;
|
||||
$this->tokenDao = $tokenDao;
|
||||
|
@ -103,6 +106,27 @@ class AuthService
|
|||
$this->loginToken = null;
|
||||
}
|
||||
|
||||
public function getCurrentPrivileges()
|
||||
{
|
||||
switch ($this->getLoggedInUser()->accessRank)
|
||||
{
|
||||
case \Szurubooru\Entities\User::ACCESS_RANK_ANONYMOUS: $keyName = 'anonymous'; break;
|
||||
case \Szurubooru\Entities\User::ACCESS_RANK_REGULAR_USER: $keyName = 'regularUser'; break;
|
||||
case \Szurubooru\Entities\User::ACCESS_RANK_POWER_USER: $keyName = 'powerUser'; break;
|
||||
case \Szurubooru\Entities\User::ACCESS_RANK_MODERATOR: $keyName = 'moderator'; break;
|
||||
case \Szurubooru\Entities\User::ACCESS_RANK_ADMINISTRATOR: $keyName = 'administrator'; break;
|
||||
default:
|
||||
throw new \DomainException('Invalid access rank!');
|
||||
}
|
||||
return array_filter(preg_split('/[;,\s]+/', $this->config->security->privileges[$keyName]));
|
||||
}
|
||||
|
||||
public function assertPrivilege($privilege)
|
||||
{
|
||||
if (!in_array($privilege, $this->getCurrentPrivileges()))
|
||||
throw new \DomainException('Unprivileged operation');
|
||||
}
|
||||
|
||||
private function createAndSaveLoginToken(\Szurubooru\Entities\User $user)
|
||||
{
|
||||
$loginToken = new \Szurubooru\Entities\Token();
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Szurubooru\Tests\Services;
|
|||
class AuthServiceTest extends \Szurubooru\Tests\AbstractTestCase
|
||||
{
|
||||
private $validatorMock;
|
||||
private $configMock;
|
||||
private $passwordServiceMock;
|
||||
private $timeServiceMock;
|
||||
private $tokenDaoMock;
|
||||
|
@ -12,6 +13,7 @@ class AuthServiceTest extends \Szurubooru\Tests\AbstractTestCase
|
|||
public function setUp()
|
||||
{
|
||||
$this->validatorMock = $this->mock(\Szurubooru\Validator::class);
|
||||
$this->configMock = $this->mock(\Szurubooru\Config::class);
|
||||
$this->passwordServiceMock = $this->mock(\Szurubooru\Services\PasswordService::class);
|
||||
$this->timeServiceMock = $this->mock(\Szurubooru\Services\TimeService::class);
|
||||
$this->tokenDaoMock = $this->mock(\Szurubooru\Dao\TokenDao::class);
|
||||
|
@ -94,6 +96,7 @@ class AuthServiceTest extends \Szurubooru\Tests\AbstractTestCase
|
|||
{
|
||||
return new \Szurubooru\Services\AuthService(
|
||||
$this->validatorMock,
|
||||
$this->configMock,
|
||||
$this->passwordServiceMock,
|
||||
$this->timeServiceMock,
|
||||
$this->tokenDaoMock,
|
||||
|
|
Loading…
Reference in a new issue