Add project owner support (allow user management to a regular user), see #316

This commit is contained in:
Frédéric Guillot 2014-12-11 20:51:40 -05:00
parent 0cd31abbc4
commit 76019d7628
10 changed files with 145 additions and 8 deletions

View File

@ -252,6 +252,20 @@ abstract class Base
}
}
/**
* Check if the current user is owner of the given project
*
* @access protected
* @param integer $project_id Project id
*/
protected function checkProjectOwnerPermissions($project_id)
{
if (! $this->acl->isAdminUser() &&
! ($this->acl->isRegularUser() && $this->projectPermission->isOwner($project_id, $this->acl->getUserId()))) {
$this->forbidden();
}
}
/**
* Redirection when there is no project in the database
*
@ -299,6 +313,7 @@ abstract class Base
$params['project_content_for_layout'] = $content;
$params['title'] = $params['project']['name'] === $params['title'] ? $params['title'] : $params['project']['name'].' > '.$params['title'];
$params['board_selector'] = $this->projectPermission->getAllowedProjects($this->acl->getUserId());
$params['is_owner'] = $this->projectPermission->isOwner($params['project']['id'], $this->acl->getUserId());
return $this->template->layout('project/layout', $params);
}

View File

@ -244,11 +244,43 @@ class Project extends Base
public function allow()
{
$values = $this->request->getValues();
$this->checkProjectOwnerPermissions($values['project_id']);
list($valid,) = $this->projectPermission->validateUserModification($values);
if ($valid) {
if ($this->projectPermission->allowUser($values['project_id'], $values['user_id'])) {
if ($this->projectPermission->allowUser($values['project_id'], $values['user_id'], $values['is_owner'])) {
$this->session->flash(t('Project updated successfully.'));
}
else {
$this->session->flashError(t('Unable to update this project.'));
}
}
$this->response->redirect('?controller=project&action=users&project_id='.$values['project_id']);
}
/**
* Set ownership for a specific user (admin only)
*
* @access public
*/
public function setOwner()
{
$this->checkCSRFParam();
$values = array(
'project_id' => $this->request->getIntegerParam('project_id'),
'user_id' => $this->request->getIntegerParam('user_id'),
'is_owner' => $this->request->getIntegerParam('is_owner'),
);
$this->checkProjectOwnerPermissions($values['project_id']);
list($valid,) = $this->projectPermission->validateUserModification($values);
if ($valid) {
if ($this->projectPermission->setOwner($values['project_id'], $values['user_id'], $values['is_owner'])) {
$this->session->flash(t('Project updated successfully.'));
}
else {
@ -273,6 +305,7 @@ class Project extends Base
'user_id' => $this->request->getIntegerParam('user_id'),
);
$this->checkProjectOwnerPermissions($values['project_id']);
list($valid,) = $this->projectPermission->validateUserModification($values);
if ($valid) {

View File

@ -32,7 +32,7 @@ class Acl extends Base
*/
private $user_actions = array(
'app' => array('index', 'preview', 'status'),
'project' => array('index', 'show', 'exporttasks', 'exportdaily', 'share', 'edit', 'update', 'users', 'remove', 'duplicate', 'disable', 'enable', 'activity', 'search', 'tasks', 'create', 'save'),
'project' => array('index', 'show', 'exporttasks', 'exportdaily', 'share', 'edit', 'update', 'users', 'remove', 'duplicate', 'disable', 'enable', 'activity', 'search', 'tasks', 'create', 'save', 'revoke', 'setowner', 'allow'),
'board' => array('index', 'show', 'save', 'check', 'changeassignee', 'updateassignee', 'changecategory', 'updatecategory', 'movecolumn', 'edit', 'update', 'add', 'confirm', 'remove', 'subtasks', 'togglesubtask', 'attachments', 'comments', 'description'),
'user' => array('edit', 'forbidden', 'logout', 'show', 'external', 'unlinkgoogle', 'unlinkgithub', 'sessions', 'removesession', 'last', 'notifications', 'password'),
'comment' => array('create', 'save', 'confirm', 'remove', 'update', 'edit', 'forbidden'),

View File

@ -85,6 +85,27 @@ class ProjectPermission extends Base
return $this->user->prepareList($users);
}
/**
* Get a list of owners for a project
*
* @access public
* @param integer $project_id Project id
* @return array
*/
public function getOwners($project_id)
{
$users = $this->db
->table(self::TABLE)
->join(User::TABLE, 'id', 'user_id')
->eq('project_id', $project_id)
->eq('is_owner', 1)
->asc('username')
->columns(User::TABLE.'.id', User::TABLE.'.username', User::TABLE.'.name')
->findAll();
return $this->user->prepareList($users);
}
/**
* Get allowed and not allowed users for a project
*
@ -97,11 +118,13 @@ class ProjectPermission extends Base
$users = array(
'allowed' => array(),
'not_allowed' => array(),
'owners' => array(),
);
$all_users = $this->user->getList();
$users['allowed'] = $this->getMembers($project_id);
$users['owners'] = $this->getOwners($project_id);
foreach ($all_users as $user_id => $username) {
@ -128,6 +151,24 @@ class ProjectPermission extends Base
->save(array('project_id' => $project_id, 'user_id' => $user_id));
}
/**
* Make the specific user owner of the given project
*
* @access public
* @param integer $project_id Project id
* @param integer $user_id User id
* @param bool $is_owner Is user owner of the project
* @return bool
*/
public function setOwner($project_id, $user_id, $is_owner = 1)
{
return $this->db
->table(self::TABLE)
->eq('project_id', $project_id)
->eq('user_id', $user_id)
->update(array('is_owner' => $is_owner));
}
/**
* Revoke a specific user for a given project
*
@ -164,6 +205,24 @@ class ProjectPermission extends Base
->eq('project_id', $project_id)
->eq('user_id', $user_id)
->count();
}
/**
* Check if a specific user is owner of a given project
*
* @access public
* @param integer $project_id Project id
* @param integer $user_id User id
* @return bool
*/
public function isOwner($project_id, $user_id)
{
return (bool) $this->db
->table(self::TABLE)
->eq('project_id', $project_id)
->eq('user_id', $user_id)
->eq('is_owner', 1)
->count();
}
/**
@ -209,6 +268,10 @@ class ProjectPermission extends Base
return true;
}
if ($this->isOwner($project_id, $user_id)) {
return true;
}
return false;
}
@ -291,6 +354,7 @@ class ProjectPermission extends Base
new Validators\Integer('project_id', t('This value must be an integer')),
new Validators\Required('user_id', t('The user id is required')),
new Validators\Integer('user_id', t('This value must be an integer')),
new Validators\Integer('is_owner', t('This value must be an integer')),
));
return array(

View File

@ -5,7 +5,12 @@ namespace Schema;
use PDO;
use Core\Security;
const VERSION = 36;
const VERSION = 37;
function version_37($pdo)
{
$pdo->exec("ALTER TABLE project_has_users ADD COLUMN is_owner TINYINT(1) DEFAULT '0'");
}
function version_36($pdo)
{

View File

@ -5,7 +5,12 @@ namespace Schema;
use PDO;
use Core\Security;
const VERSION = 17;
const VERSION = 18;
function version_18($pdo)
{
$pdo->exec("ALTER TABLE project_has_users ADD COLUMN is_owner BOOLEAN DEFAULT '0'");
}
function version_17($pdo)
{

View File

@ -5,7 +5,12 @@ namespace Schema;
use Core\Security;
use PDO;
const VERSION = 35;
const VERSION = 36;
function version_36($pdo)
{
$pdo->exec('ALTER TABLE project_has_users ADD COLUMN is_owner INTEGER DEFAULT "0"');
}
function version_35($pdo)
{

View File

@ -7,7 +7,7 @@
</div>
<section class="sidebar-container" id="project-section">
<?= Helper\template('project/sidebar', array('project' => $project)) ?>
<?= Helper\template('project/sidebar', array('project' => $project, 'is_owner' => $is_owner)) ?>
<div class="sidebar-content">
<?= $project_content_for_layout ?>

View File

@ -18,11 +18,13 @@
<li>
<?= Helper\a(t('Category management'), 'category', 'index', array('project_id' => $project['id'])) ?>
</li>
<?php if (Helper\is_admin()): ?>
<?php endif ?>
<?php if ((Helper\is_admin() || $is_owner) && $project['is_private'] == 0): ?>
<li>
<?= Helper\a(t('User management'), 'project', 'users', array('project_id' => $project['id'])) ?>
</li>
<?php endif ?>
<?php if (Helper\is_admin() || $project['is_private']): ?>
<li>
<?= Helper\a(t('Automatic actions'), 'action', 'index', array('project_id' => $project['id'])) ?>
</li>

View File

@ -15,8 +15,16 @@
<?php foreach ($users['allowed'] as $user_id => $username): ?>
<li>
<strong><?= Helper\escape($username) ?></strong>
<?php $is_owner = array_key_exists($user_id, $users['owners']);
if ($is_owner): ?> [owner] <?php endif ?>
<?php if ($project['is_private'] == 0): ?>
(<?= Helper\a(t('revoke'), 'project', 'revoke', array('project_id' => $project['id'], 'user_id' => $user_id), true) ?>)
<?php if ($is_owner): ?>
(<a href=<?= Helper\u('project', 'setOwner', array('project_id' => $project['id'], 'user_id' => $user_id, 'is_owner' => 0), true) ?> ><?= t('make user') ?></a>
<?php else: ?>
(<a href=<?= Helper\u('project', 'setOwner', array('project_id' => $project['id'], 'user_id' => $user_id, 'is_owner' => 1), true) ?> ><?= t('make owner') ?></a>
<?php endif ?>
or
<?= Helper\a(t('revoke'), 'project', 'revoke', array('project_id' => $project['id'], 'user_id' => $user_id), true) ?>)
<?php endif ?>
</li>
<?php endforeach ?>