Refactoring: added controlled middleware and changed response class
This commit is contained in:
parent
108e867605
commit
67b8361649
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Action extends Base
|
class Action extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* List of automatic actions for a given project
|
* List of automatic actions for a given project
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class ActionCreation extends Base
|
class ActionCreation extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show the form (step 1)
|
* Show the form (step 1)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class ActionProject extends Base
|
class ActionProject extends BaseController
|
||||||
{
|
{
|
||||||
public function project()
|
public function project()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Activity extends Base
|
class Activity extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Activity page for a project
|
* Activity page for a project
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use Kanboard\Model\Task as TaskModel;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Analytic extends Base
|
class Analytic extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show average Lead and Cycle time
|
* Show average Lead and Cycle time
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AppController
|
||||||
|
*
|
||||||
|
* @package Kanboard\Controller
|
||||||
|
*/
|
||||||
|
class AppController extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Forbidden page
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param bool $withoutLayout
|
||||||
|
*/
|
||||||
|
public function accessForbidden($withoutLayout = false)
|
||||||
|
{
|
||||||
|
if ($this->request->isAjax()) {
|
||||||
|
$this->response->json(array('message' => 'Access Forbidden'), 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->html($this->helper->layout->app('app/forbidden', array(
|
||||||
|
'title' => t('Access Forbidden'),
|
||||||
|
'no_layout' => $withoutLayout,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page not found
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param boolean $withoutLayout
|
||||||
|
*/
|
||||||
|
public function notFound($withoutLayout = false)
|
||||||
|
{
|
||||||
|
$this->response->html($this->helper->layout->app('app/notfound', array(
|
||||||
|
'title' => t('Page not found'),
|
||||||
|
'no_layout' => $withoutLayout,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Auth extends Base
|
class Auth extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display the form login
|
* Display the form login
|
||||||
|
|
@ -20,16 +20,16 @@ class Auth extends Base
|
||||||
public function login(array $values = array(), array $errors = array())
|
public function login(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
if ($this->userSession->isLogged()) {
|
if ($this->userSession->isLogged()) {
|
||||||
$this->response->redirect($this->helper->url->to('app', 'index'));
|
$this->response->redirect($this->helper->url->to('DashboardController', 'show'));
|
||||||
|
} else {
|
||||||
|
$this->response->html($this->helper->layout->app('auth/index', array(
|
||||||
|
'captcha' => ! empty($values['username']) && $this->userLocking->hasCaptcha($values['username']),
|
||||||
|
'errors' => $errors,
|
||||||
|
'values' => $values,
|
||||||
|
'no_layout' => true,
|
||||||
|
'title' => t('Login')
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->app('auth/index', array(
|
|
||||||
'captcha' => ! empty($values['username']) && $this->userLocking->hasCaptcha($values['username']),
|
|
||||||
'errors' => $errors,
|
|
||||||
'values' => $values,
|
|
||||||
'no_layout' => true,
|
|
||||||
'title' => t('Login')
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -45,9 +45,9 @@ class Auth extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
$this->redirectAfterLogin();
|
$this->redirectAfterLogin();
|
||||||
|
} else {
|
||||||
|
$this->login($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->login($values, $errors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -76,8 +76,8 @@ class Auth extends Base
|
||||||
$redirect = $this->sessionStorage->redirectAfterLogin;
|
$redirect = $this->sessionStorage->redirectAfterLogin;
|
||||||
unset($this->sessionStorage->redirectAfterLogin);
|
unset($this->sessionStorage->redirectAfterLogin);
|
||||||
$this->response->redirect($redirect);
|
$this->response->redirect($redirect);
|
||||||
|
} else {
|
||||||
|
$this->response->redirect($this->helper->url->to('DashboardController', 'show'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('app', 'index'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use Kanboard\Core\Thumbnail;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class AvatarFile extends Base
|
class AvatarFile extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display avatar page
|
* Display avatar page
|
||||||
|
|
@ -61,8 +61,8 @@ class AvatarFile extends Base
|
||||||
$filename = $this->avatarFile->getFilename($user_id);
|
$filename = $this->avatarFile->getFilename($user_id);
|
||||||
$etag = md5($filename.$size);
|
$etag = md5($filename.$size);
|
||||||
|
|
||||||
$this->response->cache(365 * 86400, $etag);
|
$this->response->withCache(365 * 86400, $etag);
|
||||||
$this->response->contentType('image/jpeg');
|
$this->response->withContentType('image/jpeg');
|
||||||
|
|
||||||
if ($this->request->getHeader('If-None-Match') !== '"'.$etag.'"') {
|
if ($this->request->getHeader('If-None-Match') !== '"'.$etag.'"') {
|
||||||
$this->render($filename, $size);
|
$this->render($filename, $size);
|
||||||
|
|
|
||||||
|
|
@ -1,290 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
|
||||||
|
|
||||||
use Kanboard\Core\Security\Role;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base controller
|
|
||||||
*
|
|
||||||
* @package controller
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
abstract class Base extends \Kanboard\Core\Base
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Method executed before each action
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function beforeAction()
|
|
||||||
{
|
|
||||||
$this->sessionManager->open();
|
|
||||||
$this->dispatcher->dispatch('app.bootstrap');
|
|
||||||
$this->sendHeaders();
|
|
||||||
$this->authenticationManager->checkCurrentSession();
|
|
||||||
|
|
||||||
if (! $this->applicationAuthorization->isAllowed($this->router->getController(), $this->router->getAction(), Role::APP_PUBLIC)) {
|
|
||||||
$this->handleAuthentication();
|
|
||||||
$this->handlePostAuthentication();
|
|
||||||
$this->checkApplicationAuthorization();
|
|
||||||
$this->checkProjectAuthorization();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send HTTP headers
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private function sendHeaders()
|
|
||||||
{
|
|
||||||
// HTTP secure headers
|
|
||||||
$this->response->csp($this->container['cspRules']);
|
|
||||||
$this->response->nosniff();
|
|
||||||
$this->response->xss();
|
|
||||||
|
|
||||||
// Allow the public board iframe inclusion
|
|
||||||
if (ENABLE_XFRAME && $this->router->getAction() !== 'readonly') {
|
|
||||||
$this->response->xframe();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ENABLE_HSTS) {
|
|
||||||
$this->response->hsts();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check authentication
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private function handleAuthentication()
|
|
||||||
{
|
|
||||||
if (! $this->userSession->isLogged() && ! $this->authenticationManager->preAuthentication()) {
|
|
||||||
if ($this->request->isAjax()) {
|
|
||||||
$this->response->text('Not Authorized', 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->sessionStorage->redirectAfterLogin = $this->request->getUri();
|
|
||||||
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle Post-Authentication (2FA)
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private function handlePostAuthentication()
|
|
||||||
{
|
|
||||||
$controller = strtolower($this->router->getController());
|
|
||||||
$action = strtolower($this->router->getAction());
|
|
||||||
$ignore = ($controller === 'twofactor' && in_array($action, array('code', 'check'))) || ($controller === 'auth' && $action === 'logout');
|
|
||||||
|
|
||||||
if ($ignore === false && $this->userSession->hasPostAuthentication() && ! $this->userSession->isPostAuthenticationValidated()) {
|
|
||||||
if ($this->request->isAjax()) {
|
|
||||||
$this->response->text('Not Authorized', 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('twofactor', 'code'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check application authorization
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private function checkApplicationAuthorization()
|
|
||||||
{
|
|
||||||
if (! $this->helper->user->hasAccess($this->router->getController(), $this->router->getAction())) {
|
|
||||||
$this->forbidden();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check project authorization
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private function checkProjectAuthorization()
|
|
||||||
{
|
|
||||||
$project_id = $this->request->getIntegerParam('project_id');
|
|
||||||
$task_id = $this->request->getIntegerParam('task_id');
|
|
||||||
|
|
||||||
// Allow urls without "project_id"
|
|
||||||
if ($task_id > 0 && $project_id === 0) {
|
|
||||||
$project_id = $this->taskFinder->getProjectId($task_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($project_id > 0 && ! $this->helper->user->hasProjectAccess($this->router->getController(), $this->router->getAction(), $project_id)) {
|
|
||||||
$this->forbidden();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Application not found page (404 error)
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @param boolean $no_layout Display the layout or not
|
|
||||||
*/
|
|
||||||
protected function notfound($no_layout = false)
|
|
||||||
{
|
|
||||||
$this->response->html($this->helper->layout->app('app/notfound', array(
|
|
||||||
'title' => t('Page not found'),
|
|
||||||
'no_layout' => $no_layout,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Application forbidden page
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @param boolean $no_layout Display the layout or not
|
|
||||||
*/
|
|
||||||
protected function forbidden($no_layout = false)
|
|
||||||
{
|
|
||||||
if ($this->request->isAjax()) {
|
|
||||||
$this->response->text('Access Forbidden', 403);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->app('app/forbidden', array(
|
|
||||||
'title' => t('Access Forbidden'),
|
|
||||||
'no_layout' => $no_layout,
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the CSRF token from the URL is correct
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
protected function checkCSRFParam()
|
|
||||||
{
|
|
||||||
if (! $this->token->validateCSRFToken($this->request->getStringParam('csrf_token'))) {
|
|
||||||
$this->forbidden();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check webhook token
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
protected function checkWebhookToken()
|
|
||||||
{
|
|
||||||
if ($this->config->get('webhook_token') !== $this->request->getStringParam('token')) {
|
|
||||||
$this->response->text('Not Authorized', 401);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common method to get a task for task views
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getTask()
|
|
||||||
{
|
|
||||||
$project_id = $this->request->getIntegerParam('project_id');
|
|
||||||
$task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
|
|
||||||
|
|
||||||
if (empty($task)) {
|
|
||||||
$this->notfound();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($project_id !== 0 && $project_id != $task['project_id']) {
|
|
||||||
$this->forbidden();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $task;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get Task or Project file
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
*/
|
|
||||||
protected function getFile()
|
|
||||||
{
|
|
||||||
$task_id = $this->request->getIntegerParam('task_id');
|
|
||||||
$file_id = $this->request->getIntegerParam('file_id');
|
|
||||||
$model = 'projectFile';
|
|
||||||
|
|
||||||
if ($task_id > 0) {
|
|
||||||
$model = 'taskFile';
|
|
||||||
$project_id = $this->taskFinder->getProjectId($task_id);
|
|
||||||
|
|
||||||
if ($project_id !== $this->request->getIntegerParam('project_id')) {
|
|
||||||
$this->forbidden();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = $this->$model->getById($file_id);
|
|
||||||
|
|
||||||
if (empty($file)) {
|
|
||||||
$this->notfound();
|
|
||||||
}
|
|
||||||
|
|
||||||
$file['model'] = $model;
|
|
||||||
return $file;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common method to get a project
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @param integer $project_id Default project id
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getProject($project_id = 0)
|
|
||||||
{
|
|
||||||
$project_id = $this->request->getIntegerParam('project_id', $project_id);
|
|
||||||
$project = $this->project->getByIdWithOwner($project_id);
|
|
||||||
|
|
||||||
if (empty($project)) {
|
|
||||||
$this->notfound();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $project;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Common method to get the user
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getUser()
|
|
||||||
{
|
|
||||||
$user = $this->user->getById($this->request->getIntegerParam('user_id', $this->userSession->getId()));
|
|
||||||
|
|
||||||
if (empty($user)) {
|
|
||||||
$this->notfound();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $this->userSession->isAdmin() && $this->userSession->getId() != $user['id']) {
|
|
||||||
$this->forbidden();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the current subtask
|
|
||||||
*
|
|
||||||
* @access protected
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function getSubtask()
|
|
||||||
{
|
|
||||||
$subtask = $this->subtask->getById($this->request->getIntegerParam('subtask_id'));
|
|
||||||
|
|
||||||
if (empty($subtask)) {
|
|
||||||
$this->notfound();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $subtask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
use Kanboard\Core\Controller\PageNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base Controller
|
||||||
|
*
|
||||||
|
* @package Kanboard\Controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
abstract class BaseController extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Check if the CSRF token from the URL is correct
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
protected function checkCSRFParam()
|
||||||
|
{
|
||||||
|
if (! $this->token->validateCSRFToken($this->request->getStringParam('csrf_token'))) {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check webhook token
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
*/
|
||||||
|
protected function checkWebhookToken()
|
||||||
|
{
|
||||||
|
if ($this->config->get('webhook_token') !== $this->request->getStringParam('token')) {
|
||||||
|
$this->response->text('Not Authorized', 401);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common method to get a task for task views
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
* @throws AccessForbiddenException
|
||||||
|
*/
|
||||||
|
protected function getTask()
|
||||||
|
{
|
||||||
|
$project_id = $this->request->getIntegerParam('project_id');
|
||||||
|
$task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
|
||||||
|
|
||||||
|
if (empty($task)) {
|
||||||
|
throw new PageNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($project_id !== 0 && $project_id != $task['project_id']) {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $task;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Task or Project file
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
* @throws AccessForbiddenException
|
||||||
|
*/
|
||||||
|
protected function getFile()
|
||||||
|
{
|
||||||
|
$task_id = $this->request->getIntegerParam('task_id');
|
||||||
|
$file_id = $this->request->getIntegerParam('file_id');
|
||||||
|
$model = 'projectFile';
|
||||||
|
|
||||||
|
if ($task_id > 0) {
|
||||||
|
$model = 'taskFile';
|
||||||
|
$project_id = $this->taskFinder->getProjectId($task_id);
|
||||||
|
|
||||||
|
if ($project_id !== $this->request->getIntegerParam('project_id')) {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = $this->$model->getById($file_id);
|
||||||
|
|
||||||
|
if (empty($file)) {
|
||||||
|
throw new PageNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$file['model'] = $model;
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common method to get a project
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @param integer $project_id Default project id
|
||||||
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
*/
|
||||||
|
protected function getProject($project_id = 0)
|
||||||
|
{
|
||||||
|
$project_id = $this->request->getIntegerParam('project_id', $project_id);
|
||||||
|
$project = $this->project->getByIdWithOwner($project_id);
|
||||||
|
|
||||||
|
if (empty($project)) {
|
||||||
|
throw new PageNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $project;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common method to get the user
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
* @throws AccessForbiddenException
|
||||||
|
*/
|
||||||
|
protected function getUser()
|
||||||
|
{
|
||||||
|
$user = $this->user->getById($this->request->getIntegerParam('user_id', $this->userSession->getId()));
|
||||||
|
|
||||||
|
if (empty($user)) {
|
||||||
|
throw new PageNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $this->userSession->isAdmin() && $this->userSession->getId() != $user['id']) {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current subtask
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
*/
|
||||||
|
protected function getSubtask()
|
||||||
|
{
|
||||||
|
$subtask = $this->subtask->getById($this->request->getIntegerParam('subtask_id'));
|
||||||
|
|
||||||
|
if (empty($subtask)) {
|
||||||
|
throw new PageNotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $subtask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
use Kanboard\Formatter\BoardFormatter;
|
use Kanboard\Formatter\BoardFormatter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -10,7 +11,7 @@ use Kanboard\Formatter\BoardFormatter;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Board extends Base
|
class Board extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display the public version of a board
|
* Display the public version of a board
|
||||||
|
|
@ -25,7 +26,7 @@ class Board extends Base
|
||||||
|
|
||||||
// Token verification
|
// Token verification
|
||||||
if (empty($project)) {
|
if (empty($project)) {
|
||||||
$this->forbidden(true);
|
throw AccessForbiddenException::getInstance()->withoutLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display the board with a specific layout
|
// Display the board with a specific layout
|
||||||
|
|
@ -74,7 +75,7 @@ class Board extends Base
|
||||||
$project_id = $this->request->getIntegerParam('project_id');
|
$project_id = $this->request->getIntegerParam('project_id');
|
||||||
|
|
||||||
if (! $project_id || ! $this->request->isAjax()) {
|
if (! $project_id || ! $this->request->isAjax()) {
|
||||||
return $this->response->status(403);
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$values = $this->request->getJson();
|
$values = $this->request->getJson();
|
||||||
|
|
@ -88,10 +89,10 @@ class Board extends Base
|
||||||
);
|
);
|
||||||
|
|
||||||
if (! $result) {
|
if (! $result) {
|
||||||
return $this->response->status(400);
|
$this->response->status(400);
|
||||||
|
} else {
|
||||||
|
$this->response->html($this->renderBoard($project_id), 201);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->renderBoard($project_id), 201);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -105,14 +106,12 @@ class Board extends Base
|
||||||
$timestamp = $this->request->getIntegerParam('timestamp');
|
$timestamp = $this->request->getIntegerParam('timestamp');
|
||||||
|
|
||||||
if (! $project_id || ! $this->request->isAjax()) {
|
if (! $project_id || ! $this->request->isAjax()) {
|
||||||
return $this->response->status(403);
|
$this->response->status(403);
|
||||||
|
} elseif (! $this->project->isModifiedSince($project_id, $timestamp)) {
|
||||||
|
$this->response->status(304);
|
||||||
|
} else {
|
||||||
|
$this->response->html($this->renderBoard($project_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $this->project->isModifiedSince($project_id, $timestamp)) {
|
|
||||||
return $this->response->status(304);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->response->html($this->renderBoard($project_id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -125,7 +124,7 @@ class Board extends Base
|
||||||
$project_id = $this->request->getIntegerParam('project_id');
|
$project_id = $this->request->getIntegerParam('project_id');
|
||||||
|
|
||||||
if (! $project_id || ! $this->request->isAjax()) {
|
if (! $project_id || ! $this->request->isAjax()) {
|
||||||
return $this->response->status(403);
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$values = $this->request->getJson();
|
$values = $this->request->getJson();
|
||||||
|
|
@ -177,6 +176,7 @@ class Board extends Base
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @param integer $project_id
|
* @param integer $project_id
|
||||||
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function renderBoard($project_id)
|
private function renderBoard($project_id)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class BoardPopover extends Base
|
class BoardPopover extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Confirmation before to close all column tasks
|
* Confirmation before to close all column tasks
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class BoardTooltip extends Base
|
class BoardTooltip extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get links on mouseover
|
* Get links on mouseover
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use Kanboard\Model\Task as TaskModel;
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
* @author Timo Litzbarski
|
* @author Timo Litzbarski
|
||||||
*/
|
*/
|
||||||
class Calendar extends Base
|
class Calendar extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show calendar view for projects
|
* Show calendar view for projects
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use Gregwar\Captcha\CaptchaBuilder;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Captcha extends Base
|
class Captcha extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display captcha image
|
* Display captcha image
|
||||||
|
|
@ -19,7 +19,7 @@ class Captcha extends Base
|
||||||
*/
|
*/
|
||||||
public function image()
|
public function image()
|
||||||
{
|
{
|
||||||
$this->response->contentType('image/jpeg');
|
$this->response->withContentType('image/jpeg');
|
||||||
|
|
||||||
$builder = new CaptchaBuilder;
|
$builder = new CaptchaBuilder;
|
||||||
$builder->build();
|
$builder->build();
|
||||||
|
|
|
||||||
|
|
@ -2,28 +2,29 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\PageNotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Category management
|
* Category management
|
||||||
*
|
*
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Category extends Base
|
class Category extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get the category (common method between actions)
|
* Get the category (common method between actions)
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @param integer $project_id
|
|
||||||
* @return array
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
private function getCategory($project_id)
|
private function getCategory()
|
||||||
{
|
{
|
||||||
$category = $this->category->getById($this->request->getIntegerParam('category_id'));
|
$category = $this->category->getById($this->request->getIntegerParam('category_id'));
|
||||||
|
|
||||||
if (empty($category)) {
|
if (empty($category)) {
|
||||||
$this->flash->failure(t('Category not found.'));
|
throw new PageNotFoundException();
|
||||||
$this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project_id)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $category;
|
return $category;
|
||||||
|
|
@ -33,6 +34,9 @@ class Category extends Base
|
||||||
* List of categories for a given project
|
* List of categories for a given project
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function index(array $values = array(), array $errors = array())
|
public function index(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -62,24 +66,27 @@ class Category extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->category->create($values)) {
|
if ($this->category->create($values)) {
|
||||||
$this->flash->success(t('Your category have been created successfully.'));
|
$this->flash->success(t('Your category have been created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to create your category.'));
|
$this->flash->failure(t('Unable to create your category.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->index($values, $errors);
|
return $this->index($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit a category (display the form)
|
* Edit a category (display the form)
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
$category = $this->getCategory($project['id']);
|
$category = $this->getCategory();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('category/edit', array(
|
$this->response->html($this->helper->layout->project('category/edit', array(
|
||||||
'values' => empty($values) ? $category : $values,
|
'values' => empty($values) ? $category : $values,
|
||||||
|
|
@ -104,13 +111,13 @@ class Category extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->category->update($values)) {
|
if ($this->category->update($values)) {
|
||||||
$this->flash->success(t('Your category have been updated successfully.'));
|
$this->flash->success(t('Your category have been updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to update your category.'));
|
$this->flash->failure(t('Unable to update your category.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -121,7 +128,7 @@ class Category extends Base
|
||||||
public function confirm()
|
public function confirm()
|
||||||
{
|
{
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
$category = $this->getCategory($project['id']);
|
$category = $this->getCategory();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('category/remove', array(
|
$this->response->html($this->helper->layout->project('category/remove', array(
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
|
|
@ -139,7 +146,7 @@ class Category extends Base
|
||||||
{
|
{
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
$category = $this->getCategory($project['id']);
|
$category = $this->getCategory();
|
||||||
|
|
||||||
if ($this->category->remove($category['id'])) {
|
if ($this->category->remove($category['id'])) {
|
||||||
$this->flash->success(t('Category removed successfully.'));
|
$this->flash->success(t('Category removed successfully.'));
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Column controller
|
* Column controller
|
||||||
*
|
*
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Column extends Base
|
class Column extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display columns list
|
* Display columns list
|
||||||
|
|
@ -31,6 +33,9 @@ class Column extends Base
|
||||||
* Show form to create a new column
|
* Show form to create a new column
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -69,7 +74,7 @@ class Column extends Base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
return $this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -108,13 +113,13 @@ class Column extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->column->update($values['id'], $values['title'], $values['task_limit'], $values['description'])) {
|
if ($this->column->update($values['id'], $values['title'], $values['task_limit'], $values['description'])) {
|
||||||
$this->flash->success(t('Board updated successfully.'));
|
$this->flash->success(t('Board updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to update this board.'));
|
$this->flash->failure(t('Unable to update this board.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -129,10 +134,10 @@ class Column extends Base
|
||||||
|
|
||||||
if (! empty($values) && isset($values['column_id']) && isset($values['position'])) {
|
if (! empty($values) && isset($values['column_id']) && isset($values['position'])) {
|
||||||
$result = $this->column->changePosition($project['id'], $values['column_id'], $values['position']);
|
$result = $this->column->changePosition($project['id'], $values['column_id'], $values['position']);
|
||||||
return $this->response->json(array('result' => $result));
|
$this->response->json(array('result' => $result));
|
||||||
|
} else {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->forbidden();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,35 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
use Kanboard\Core\Controller\PageNotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comment controller
|
* Comment controller
|
||||||
*
|
*
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Comment extends Base
|
class Comment extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get the current comment
|
* Get the current comment
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @return array
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
* @throws AccessForbiddenException
|
||||||
*/
|
*/
|
||||||
private function getComment()
|
private function getComment()
|
||||||
{
|
{
|
||||||
$comment = $this->comment->getById($this->request->getIntegerParam('comment_id'));
|
$comment = $this->comment->getById($this->request->getIntegerParam('comment_id'));
|
||||||
|
|
||||||
if (empty($comment)) {
|
if (empty($comment)) {
|
||||||
return $this->notfound();
|
throw new PageNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $this->userSession->isAdmin() && $comment['user_id'] != $this->userSession->getId()) {
|
if (! $this->userSession->isAdmin() && $comment['user_id'] != $this->userSession->getId()) {
|
||||||
return $this->forbidden();
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $comment;
|
return $comment;
|
||||||
|
|
@ -35,6 +40,10 @@ class Comment extends Base
|
||||||
* Add comment form
|
* Add comment form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws AccessForbiddenException
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -76,13 +85,17 @@ class Comment extends Base
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'), true);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
return $this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit a comment
|
* Edit a comment
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws AccessForbiddenException
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -121,7 +134,7 @@ class Comment extends Base
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), false);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -8,50 +8,8 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Config extends Base
|
class Config extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Common method between pages
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @param string $redirect Action to redirect after saving the form
|
|
||||||
*/
|
|
||||||
private function common($redirect)
|
|
||||||
{
|
|
||||||
if ($this->request->isPost()) {
|
|
||||||
$values = $this->request->getValues();
|
|
||||||
|
|
||||||
switch ($redirect) {
|
|
||||||
case 'application':
|
|
||||||
$values += array('password_reset' => 0);
|
|
||||||
break;
|
|
||||||
case 'project':
|
|
||||||
$values += array(
|
|
||||||
'subtask_restriction' => 0,
|
|
||||||
'subtask_time_tracking' => 0,
|
|
||||||
'cfd_include_closed_tasks' => 0,
|
|
||||||
'disable_private_project' => 0,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'integrations':
|
|
||||||
$values += array('integration_gravatar' => 0);
|
|
||||||
break;
|
|
||||||
case 'calendar':
|
|
||||||
$values += array('calendar_user_subtasks_time_tracking' => 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->config->save($values)) {
|
|
||||||
$this->language->loadCurrentLanguage();
|
|
||||||
$this->flash->success(t('Settings saved successfully.'));
|
|
||||||
} else {
|
|
||||||
$this->flash->failure(t('Unable to save your settings.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('config', $redirect));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the about page
|
* Display the about page
|
||||||
*
|
*
|
||||||
|
|
@ -67,6 +25,45 @@ class Config extends Base
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save settings
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function save()
|
||||||
|
{
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
$redirect = $this->request->getStringParam('redirect', 'application');
|
||||||
|
|
||||||
|
switch ($redirect) {
|
||||||
|
case 'application':
|
||||||
|
$values += array('password_reset' => 0);
|
||||||
|
break;
|
||||||
|
case 'project':
|
||||||
|
$values += array(
|
||||||
|
'subtask_restriction' => 0,
|
||||||
|
'subtask_time_tracking' => 0,
|
||||||
|
'cfd_include_closed_tasks' => 0,
|
||||||
|
'disable_private_project' => 0,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'integrations':
|
||||||
|
$values += array('integration_gravatar' => 0);
|
||||||
|
break;
|
||||||
|
case 'calendar':
|
||||||
|
$values += array('calendar_user_subtasks_time_tracking' => 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->config->save($values)) {
|
||||||
|
$this->language->loadCurrentLanguage();
|
||||||
|
$this->flash->success(t('Settings saved successfully.'));
|
||||||
|
} else {
|
||||||
|
$this->flash->failure(t('Unable to save your settings.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('config', $redirect));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the plugin page
|
* Display the plugin page
|
||||||
*
|
*
|
||||||
|
|
@ -87,8 +84,6 @@ class Config extends Base
|
||||||
*/
|
*/
|
||||||
public function application()
|
public function application()
|
||||||
{
|
{
|
||||||
$this->common('application');
|
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->config('config/application', array(
|
$this->response->html($this->helper->layout->config('config/application', array(
|
||||||
'languages' => $this->language->getLanguages(),
|
'languages' => $this->language->getLanguages(),
|
||||||
'timezones' => $this->timezone->getTimezones(),
|
'timezones' => $this->timezone->getTimezones(),
|
||||||
|
|
@ -106,8 +101,6 @@ class Config extends Base
|
||||||
*/
|
*/
|
||||||
public function project()
|
public function project()
|
||||||
{
|
{
|
||||||
$this->common('project');
|
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->config('config/project', array(
|
$this->response->html($this->helper->layout->config('config/project', array(
|
||||||
'colors' => $this->color->getList(),
|
'colors' => $this->color->getList(),
|
||||||
'default_columns' => implode(', ', $this->board->getDefaultColumns()),
|
'default_columns' => implode(', ', $this->board->getDefaultColumns()),
|
||||||
|
|
@ -122,8 +115,6 @@ class Config extends Base
|
||||||
*/
|
*/
|
||||||
public function board()
|
public function board()
|
||||||
{
|
{
|
||||||
$this->common('board');
|
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->config('config/board', array(
|
$this->response->html($this->helper->layout->config('config/board', array(
|
||||||
'title' => t('Settings').' > '.t('Board settings'),
|
'title' => t('Settings').' > '.t('Board settings'),
|
||||||
)));
|
)));
|
||||||
|
|
@ -136,8 +127,6 @@ class Config extends Base
|
||||||
*/
|
*/
|
||||||
public function calendar()
|
public function calendar()
|
||||||
{
|
{
|
||||||
$this->common('calendar');
|
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->config('config/calendar', array(
|
$this->response->html($this->helper->layout->config('config/calendar', array(
|
||||||
'title' => t('Settings').' > '.t('Calendar settings'),
|
'title' => t('Settings').' > '.t('Calendar settings'),
|
||||||
)));
|
)));
|
||||||
|
|
@ -150,8 +139,6 @@ class Config extends Base
|
||||||
*/
|
*/
|
||||||
public function integrations()
|
public function integrations()
|
||||||
{
|
{
|
||||||
$this->common('integrations');
|
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->config('config/integrations', array(
|
$this->response->html($this->helper->layout->config('config/integrations', array(
|
||||||
'title' => t('Settings').' > '.t('Integrations'),
|
'title' => t('Settings').' > '.t('Integrations'),
|
||||||
)));
|
)));
|
||||||
|
|
@ -164,8 +151,6 @@ class Config extends Base
|
||||||
*/
|
*/
|
||||||
public function webhook()
|
public function webhook()
|
||||||
{
|
{
|
||||||
$this->common('webhook');
|
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->config('config/webhook', array(
|
$this->response->html($this->helper->layout->config('config/webhook', array(
|
||||||
'title' => t('Settings').' > '.t('Webhook settings'),
|
'title' => t('Settings').' > '.t('Webhook settings'),
|
||||||
)));
|
)));
|
||||||
|
|
@ -191,7 +176,7 @@ class Config extends Base
|
||||||
public function downloadDb()
|
public function downloadDb()
|
||||||
{
|
{
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
$this->response->forceDownload('db.sqlite.gz');
|
$this->response->withDownload('db.sqlite.gz');
|
||||||
$this->response->binary($this->config->downloadDatabase());
|
$this->response->binary($this->config->downloadDatabase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,14 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Currency extends Base
|
class Currency extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display all currency rates and form
|
* Display all currency rates and form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function index(array $values = array(), array $errors = array())
|
public function index(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -40,13 +42,13 @@ class Currency extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->currency->create($values['currency'], $values['rate'])) {
|
if ($this->currency->create($values['currency'], $values['rate'])) {
|
||||||
$this->flash->success(t('The currency rate have been added successfully.'));
|
$this->flash->success(t('The currency rate have been added successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('currency', 'index'));
|
return $this->response->redirect($this->helper->url->to('currency', 'index'));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to add this currency rate.'));
|
$this->flash->failure(t('Unable to add this currency rate.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->index($values, $errors);
|
return $this->index($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -10,7 +11,7 @@ use Kanboard\Core\Security\Role;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Timo Litzbarski
|
* @author Timo Litzbarski
|
||||||
*/
|
*/
|
||||||
class Customfilter extends Base
|
class Customfilter extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display list of filters
|
* Display list of filters
|
||||||
|
|
@ -47,13 +48,13 @@ class Customfilter extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->customFilter->create($values)) {
|
if ($this->customFilter->create($values)) {
|
||||||
$this->flash->success(t('Your custom filter have been created successfully.'));
|
$this->flash->success(t('Your custom filter have been created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to create your custom filter.'));
|
$this->flash->failure(t('Unable to create your custom filter.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->index($values, $errors);
|
return $this->index($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -143,13 +144,13 @@ class Customfilter extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->customFilter->update($values)) {
|
if ($this->customFilter->update($values)) {
|
||||||
$this->flash->success(t('Your custom filter have been updated successfully.'));
|
$this->flash->success(t('Your custom filter have been updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to update custom filter.'));
|
$this->flash->failure(t('Unable to update custom filter.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkPermission(array $project, array $filter)
|
private function checkPermission(array $project, array $filter)
|
||||||
|
|
@ -157,7 +158,7 @@ class Customfilter extends Base
|
||||||
$user_id = $this->userSession->getId();
|
$user_id = $this->userSession->getId();
|
||||||
|
|
||||||
if ($filter['user_id'] != $user_id && ($this->projectUserRole->getUserRole($project['id'], $user_id) === Role::PROJECT_MANAGER || ! $this->userSession->isAdmin())) {
|
if ($filter['user_id'] != $user_id && ($this->projectUserRole->getUserRole($project['id'], $user_id) === Role::PROJECT_MANAGER || ! $this->userSession->isAdmin())) {
|
||||||
$this->forbidden();
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@ use Kanboard\Model\Project as ProjectModel;
|
||||||
use Kanboard\Model\Subtask as SubtaskModel;
|
use Kanboard\Model\Subtask as SubtaskModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Application controller
|
* Dashboard Controller
|
||||||
*
|
*
|
||||||
* @package controller
|
* @package Kanboard\Controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class App extends Base
|
class DashboardController extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get project pagination
|
* Get project pagination
|
||||||
|
|
@ -25,7 +25,7 @@ class App extends Base
|
||||||
private function getProjectPaginator($user_id, $action, $max)
|
private function getProjectPaginator($user_id, $action, $max)
|
||||||
{
|
{
|
||||||
return $this->paginator
|
return $this->paginator
|
||||||
->setUrl('app', $action, array('pagination' => 'projects', 'user_id' => $user_id))
|
->setUrl('DashboardController', $action, array('pagination' => 'projects', 'user_id' => $user_id))
|
||||||
->setMax($max)
|
->setMax($max)
|
||||||
->setOrder(ProjectModel::TABLE.'.name')
|
->setOrder(ProjectModel::TABLE.'.name')
|
||||||
->setQuery($this->project->getQueryColumnStats($this->projectPermission->getActiveProjectIds($user_id)))
|
->setQuery($this->project->getQueryColumnStats($this->projectPermission->getActiveProjectIds($user_id)))
|
||||||
|
|
@ -44,7 +44,7 @@ class App extends Base
|
||||||
private function getTaskPaginator($user_id, $action, $max)
|
private function getTaskPaginator($user_id, $action, $max)
|
||||||
{
|
{
|
||||||
return $this->paginator
|
return $this->paginator
|
||||||
->setUrl('app', $action, array('pagination' => 'tasks', 'user_id' => $user_id))
|
->setUrl('DashboardController', $action, array('pagination' => 'tasks', 'user_id' => $user_id))
|
||||||
->setMax($max)
|
->setMax($max)
|
||||||
->setOrder('tasks.id')
|
->setOrder('tasks.id')
|
||||||
->setQuery($this->taskFinder->getUserQuery($user_id))
|
->setQuery($this->taskFinder->getUserQuery($user_id))
|
||||||
|
|
@ -63,33 +63,23 @@ class App extends Base
|
||||||
private function getSubtaskPaginator($user_id, $action, $max)
|
private function getSubtaskPaginator($user_id, $action, $max)
|
||||||
{
|
{
|
||||||
return $this->paginator
|
return $this->paginator
|
||||||
->setUrl('app', $action, array('pagination' => 'subtasks', 'user_id' => $user_id))
|
->setUrl('DashboardController', $action, array('pagination' => 'subtasks', 'user_id' => $user_id))
|
||||||
->setMax($max)
|
->setMax($max)
|
||||||
->setOrder('tasks.id')
|
->setOrder('tasks.id')
|
||||||
->setQuery($this->subtask->getUserQuery($user_id, array(SubTaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS)))
|
->setQuery($this->subtask->getUserQuery($user_id, array(SubTaskModel::STATUS_TODO, SubtaskModel::STATUS_INPROGRESS)))
|
||||||
->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
|
->calculateOnlyIf($this->request->getStringParam('pagination') === 'subtasks');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the user is connected
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function status()
|
|
||||||
{
|
|
||||||
$this->response->text('OK');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dashboard overview
|
* Dashboard overview
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
*/
|
*/
|
||||||
public function index()
|
public function show()
|
||||||
{
|
{
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->dashboard('app/overview', array(
|
$this->response->html($this->helper->layout->dashboard('dashboard/show', array(
|
||||||
'title' => t('Dashboard'),
|
'title' => t('Dashboard'),
|
||||||
'project_paginator' => $this->getProjectPaginator($user['id'], 'index', 10),
|
'project_paginator' => $this->getProjectPaginator($user['id'], 'index', 10),
|
||||||
'task_paginator' => $this->getTaskPaginator($user['id'], 'index', 10),
|
'task_paginator' => $this->getTaskPaginator($user['id'], 'index', 10),
|
||||||
|
|
@ -107,7 +97,7 @@ class App extends Base
|
||||||
{
|
{
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->dashboard('app/tasks', array(
|
$this->response->html($this->helper->layout->dashboard('dashboard/tasks', array(
|
||||||
'title' => t('My tasks'),
|
'title' => t('My tasks'),
|
||||||
'paginator' => $this->getTaskPaginator($user['id'], 'tasks', 50),
|
'paginator' => $this->getTaskPaginator($user['id'], 'tasks', 50),
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
|
@ -123,7 +113,7 @@ class App extends Base
|
||||||
{
|
{
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->dashboard('app/subtasks', array(
|
$this->response->html($this->helper->layout->dashboard('dashboard/subtasks', array(
|
||||||
'title' => t('My subtasks'),
|
'title' => t('My subtasks'),
|
||||||
'paginator' => $this->getSubtaskPaginator($user['id'], 'subtasks', 50),
|
'paginator' => $this->getSubtaskPaginator($user['id'], 'subtasks', 50),
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
|
@ -139,7 +129,7 @@ class App extends Base
|
||||||
{
|
{
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->dashboard('app/projects', array(
|
$this->response->html($this->helper->layout->dashboard('dashboard/projects', array(
|
||||||
'title' => t('My projects'),
|
'title' => t('My projects'),
|
||||||
'paginator' => $this->getProjectPaginator($user['id'], 'projects', 25),
|
'paginator' => $this->getProjectPaginator($user['id'], 'projects', 25),
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
|
@ -155,7 +145,7 @@ class App extends Base
|
||||||
{
|
{
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->dashboard('app/activity', array(
|
$this->response->html($this->helper->layout->dashboard('dashboard/activity', array(
|
||||||
'title' => t('My activity stream'),
|
'title' => t('My activity stream'),
|
||||||
'events' => $this->helper->projectActivity->getProjectsEvents($this->projectPermission->getActiveProjectIds($user['id']), 100),
|
'events' => $this->helper->projectActivity->getProjectsEvents($this->projectPermission->getActiveProjectIds($user['id']), 100),
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
|
@ -169,7 +159,7 @@ class App extends Base
|
||||||
*/
|
*/
|
||||||
public function calendar()
|
public function calendar()
|
||||||
{
|
{
|
||||||
$this->response->html($this->helper->layout->dashboard('app/calendar', array(
|
$this->response->html($this->helper->layout->dashboard('dashboard/calendar', array(
|
||||||
'title' => t('My calendar'),
|
'title' => t('My calendar'),
|
||||||
'user' => $this->getUser(),
|
'user' => $this->getUser(),
|
||||||
)));
|
)));
|
||||||
|
|
@ -184,7 +174,7 @@ class App extends Base
|
||||||
{
|
{
|
||||||
$user = $this->getUser();
|
$user = $this->getUser();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->dashboard('app/notifications', array(
|
$this->response->html($this->helper->layout->dashboard('dashboard/notifications', array(
|
||||||
'title' => t('My notifications'),
|
'title' => t('My notifications'),
|
||||||
'notifications' => $this->userUnreadNotification->getAll($user['id']),
|
'notifications' => $this->userUnreadNotification->getAll($user['id']),
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
|
@ -10,7 +10,7 @@ use Parsedown;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Doc extends Base
|
class Doc extends BaseController
|
||||||
{
|
{
|
||||||
public function show()
|
public function show()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,18 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Export extends Base
|
class Export extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Common export method
|
* Common export method
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
|
* @param string $model
|
||||||
|
* @param string $method
|
||||||
|
* @param string $filename
|
||||||
|
* @param string $action
|
||||||
|
* @param string $page_title
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
private function common($model, $method, $filename, $action, $page_title)
|
private function common($model, $method, $filename, $action, $page_title)
|
||||||
{
|
{
|
||||||
|
|
@ -23,7 +29,7 @@ class Export extends Base
|
||||||
|
|
||||||
if ($from && $to) {
|
if ($from && $to) {
|
||||||
$data = $this->$model->$method($project['id'], $from, $to);
|
$data = $this->$model->$method($project['id'], $from, $to);
|
||||||
$this->response->forceDownload($filename.'.csv');
|
$this->response->withDownload($filename.'.csv');
|
||||||
$this->response->csv($data);
|
$this->response->csv($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Atom/RSS Feed controller
|
* Atom/RSS Feed controller
|
||||||
*
|
*
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Feed extends Base
|
class Feed extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* RSS feed for a user
|
* RSS feed for a user
|
||||||
|
|
@ -22,7 +24,7 @@ class Feed extends Base
|
||||||
|
|
||||||
// Token verification
|
// Token verification
|
||||||
if (empty($user)) {
|
if (empty($user)) {
|
||||||
$this->forbidden(true);
|
throw AccessForbiddenException::getInstance()->withoutLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->xml($this->template->render('feed/user', array(
|
$this->response->xml($this->template->render('feed/user', array(
|
||||||
|
|
@ -41,9 +43,8 @@ class Feed extends Base
|
||||||
$token = $this->request->getStringParam('token');
|
$token = $this->request->getStringParam('token');
|
||||||
$project = $this->project->getByToken($token);
|
$project = $this->project->getByToken($token);
|
||||||
|
|
||||||
// Token verification
|
|
||||||
if (empty($project)) {
|
if (empty($project)) {
|
||||||
$this->forbidden(true);
|
throw AccessForbiddenException::getInstance()->withoutLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->xml($this->template->render('feed/project', array(
|
$this->response->xml($this->template->render('feed/project', array(
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use Kanboard\Core\ObjectStorage\ObjectStorageException;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class FileViewer extends Base
|
class FileViewer extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get file content from object storage
|
* Get file content from object storage
|
||||||
|
|
@ -24,11 +24,9 @@ class FileViewer extends Base
|
||||||
$content = '';
|
$content = '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if ($file['is_image'] == 0) {
|
if ($file['is_image'] == 0) {
|
||||||
$content = $this->objectStorage->get($file['path']);
|
$content = $this->objectStorage->get($file['path']);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (ObjectStorageException $e) {
|
} catch (ObjectStorageException $e) {
|
||||||
$this->logger->error($e->getMessage());
|
$this->logger->error($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
@ -68,17 +66,18 @@ class FileViewer extends Base
|
||||||
{
|
{
|
||||||
$file = $this->getFile();
|
$file = $this->getFile();
|
||||||
$etag = md5($file['path']);
|
$etag = md5($file['path']);
|
||||||
$this->response->contentType($this->helper->file->getImageMimeType($file['name']));
|
$this->response->withContentType($this->helper->file->getImageMimeType($file['name']));
|
||||||
$this->response->cache(5 * 86400, $etag);
|
$this->response->withCache(5 * 86400, $etag);
|
||||||
|
|
||||||
if ($this->request->getHeader('If-None-Match') === '"'.$etag.'"') {
|
if ($this->request->getHeader('If-None-Match') === '"'.$etag.'"') {
|
||||||
return $this->response->status(304);
|
$this->response->status(304);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->objectStorage->output($file['path']);
|
$this->objectStorage->output($file['path']);
|
||||||
} catch (ObjectStorageException $e) {
|
} catch (ObjectStorageException $e) {
|
||||||
$this->logger->error($e->getMessage());
|
$this->logger->error($e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -94,23 +93,24 @@ class FileViewer extends Base
|
||||||
$filename = $this->$model->getThumbnailPath($file['path']);
|
$filename = $this->$model->getThumbnailPath($file['path']);
|
||||||
$etag = md5($filename);
|
$etag = md5($filename);
|
||||||
|
|
||||||
$this->response->cache(5 * 86400, $etag);
|
$this->response->withCache(5 * 86400, $etag);
|
||||||
$this->response->contentType('image/jpeg');
|
$this->response->withContentType('image/jpeg');
|
||||||
|
|
||||||
if ($this->request->getHeader('If-None-Match') === '"'.$etag.'"') {
|
if ($this->request->getHeader('If-None-Match') === '"'.$etag.'"') {
|
||||||
return $this->response->status(304);
|
$this->response->status(304);
|
||||||
}
|
} else {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$this->objectStorage->output($filename);
|
$this->objectStorage->output($filename);
|
||||||
} catch (ObjectStorageException $e) {
|
} catch (ObjectStorageException $e) {
|
||||||
$this->logger->error($e->getMessage());
|
$this->logger->error($e->getMessage());
|
||||||
|
|
||||||
// Try to generate thumbnail on the fly for images uploaded before Kanboard < 1.0.19
|
// Try to generate thumbnail on the fly for images uploaded before Kanboard < 1.0.19
|
||||||
$data = $this->objectStorage->get($file['path']);
|
$data = $this->objectStorage->get($file['path']);
|
||||||
$this->$model->generateThumbnailFromData($file['path'], $data);
|
$this->$model->generateThumbnailFromData($file['path'], $data);
|
||||||
$this->objectStorage->output($this->$model->getThumbnailPath($file['path']));
|
$this->objectStorage->output($this->$model->getThumbnailPath($file['path']));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,7 +123,7 @@ class FileViewer extends Base
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$file = $this->getFile();
|
$file = $this->getFile();
|
||||||
$this->response->forceDownload($file['name']);
|
$this->response->withDownload($file['name']);
|
||||||
$this->objectStorage->output($file['path']);
|
$this->objectStorage->output($file['path']);
|
||||||
} catch (ObjectStorageException $e) {
|
} catch (ObjectStorageException $e) {
|
||||||
$this->logger->error($e->getMessage());
|
$this->logger->error($e->getMessage());
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ use Kanboard\Model\Project as ProjectModel;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Gantt extends Base
|
class Gantt extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show Gantt chart for all projects
|
* Show Gantt chart for all projects
|
||||||
|
|
@ -53,9 +53,9 @@ class Gantt extends Base
|
||||||
|
|
||||||
if (! $result) {
|
if (! $result) {
|
||||||
$this->response->json(array('message' => 'Unable to save project'), 400);
|
$this->response->json(array('message' => 'Unable to save project'), 400);
|
||||||
|
} else {
|
||||||
|
$this->response->json(array('message' => 'OK'), 201);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->json(array('message' => 'OK'), 201);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -99,15 +99,18 @@ class Gantt extends Base
|
||||||
|
|
||||||
if (! $result) {
|
if (! $result) {
|
||||||
$this->response->json(array('message' => 'Unable to save task'), 400);
|
$this->response->json(array('message' => 'Unable to save task'), 400);
|
||||||
|
} else {
|
||||||
|
$this->response->json(array('message' => 'OK'), 201);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->json(array('message' => 'OK'), 201);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplified form to create a new task
|
* Simplified form to create a new task
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function task(array $values = array(), array $errors = array())
|
public function task(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -151,12 +154,12 @@ class Gantt extends Base
|
||||||
|
|
||||||
if ($task_id !== false) {
|
if ($task_id !== false) {
|
||||||
$this->flash->success(t('Task created successfully.'));
|
$this->flash->success(t('Task created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('gantt', 'project', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('gantt', 'project', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to create your task.'));
|
$this->flash->failure(t('Unable to create your task.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->task($values, $errors);
|
return $this->task($values, $errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Group extends Base
|
class Group extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* List all groups
|
* List all groups
|
||||||
|
|
@ -58,6 +58,8 @@ class Group extends Base
|
||||||
* Display a form to create a new group
|
* Display a form to create a new group
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -81,19 +83,21 @@ class Group extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->group->create($values['name']) !== false) {
|
if ($this->group->create($values['name']) !== false) {
|
||||||
$this->flash->success(t('Group created successfully.'));
|
$this->flash->success(t('Group created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('group', 'index'));
|
return $this->response->redirect($this->helper->url->to('group', 'index'));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to create your group.'));
|
$this->flash->failure(t('Unable to create your group.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
return $this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a form to update a group
|
* Display a form to update a group
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -121,24 +125,26 @@ class Group extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->group->update($values) !== false) {
|
if ($this->group->update($values) !== false) {
|
||||||
$this->flash->success(t('Group updated successfully.'));
|
$this->flash->success(t('Group updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('group', 'index'));
|
return $this->response->redirect($this->helper->url->to('group', 'index'));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to update your group.'));
|
$this->flash->failure(t('Unable to update your group.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form to associate a user to a group
|
* Form to associate a user to a group
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function associate(array $values = array(), array $errors = array())
|
public function associate(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
$group_id = $this->request->getIntegerParam('group_id');
|
$group_id = $this->request->getIntegerParam('group_id');
|
||||||
$group = $this->group->getbyId($group_id);
|
$group = $this->group->getById($group_id);
|
||||||
|
|
||||||
if (empty($values)) {
|
if (empty($values)) {
|
||||||
$values['group_id'] = $group_id;
|
$values['group_id'] = $group_id;
|
||||||
|
|
@ -165,13 +171,13 @@ class Group extends Base
|
||||||
if (isset($values['group_id']) && isset($values['user_id'])) {
|
if (isset($values['group_id']) && isset($values['user_id'])) {
|
||||||
if ($this->groupMember->addUser($values['group_id'], $values['user_id'])) {
|
if ($this->groupMember->addUser($values['group_id'], $values['user_id'])) {
|
||||||
$this->flash->success(t('Group member added successfully.'));
|
$this->flash->success(t('Group member added successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('group', 'users', array('group_id' => $values['group_id'])));
|
return $this->response->redirect($this->helper->url->to('group', 'users', array('group_id' => $values['group_id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to add group member.'));
|
$this->flash->failure(t('Unable to add group member.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->associate($values);
|
return $this->associate($values);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use Kanboard\Formatter\GroupAutoCompleteFormatter;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class GroupHelper extends Base
|
class GroupHelper extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Group auto-completion (Ajax)
|
* Group auto-completion (Ajax)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
use Kanboard\Core\Filter\QueryBuilder;
|
use Kanboard\Core\Filter\QueryBuilder;
|
||||||
use Kanboard\Filter\TaskAssigneeFilter;
|
use Kanboard\Filter\TaskAssigneeFilter;
|
||||||
use Kanboard\Filter\TaskProjectFilter;
|
use Kanboard\Filter\TaskProjectFilter;
|
||||||
|
|
@ -16,7 +17,7 @@ use Eluceo\iCal\Component\Calendar as iCalendar;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Ical extends Base
|
class Ical extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get user iCalendar
|
* Get user iCalendar
|
||||||
|
|
@ -30,7 +31,7 @@ class Ical extends Base
|
||||||
|
|
||||||
// Token verification
|
// Token verification
|
||||||
if (empty($user)) {
|
if (empty($user)) {
|
||||||
$this->forbidden(true);
|
throw AccessForbiddenException::getInstance()->withoutLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common filter
|
// Common filter
|
||||||
|
|
@ -61,7 +62,7 @@ class Ical extends Base
|
||||||
|
|
||||||
// Token verification
|
// Token verification
|
||||||
if (empty($project)) {
|
if (empty($project)) {
|
||||||
$this->forbidden(true);
|
throw AccessForbiddenException::getInstance()->withoutLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common filter
|
// Common filter
|
||||||
|
|
@ -84,6 +85,8 @@ class Ical extends Base
|
||||||
* Common method to render iCal events
|
* Common method to render iCal events
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
|
* @param QueryBuilder $queryBuilder
|
||||||
|
* @param iCalendar $calendar
|
||||||
*/
|
*/
|
||||||
private function renderCalendar(QueryBuilder $queryBuilder, iCalendar $calendar)
|
private function renderCalendar(QueryBuilder $queryBuilder, iCalendar $calendar)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\PageNotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Link controller
|
* Link controller
|
||||||
*
|
*
|
||||||
|
|
@ -9,20 +11,21 @@ namespace Kanboard\Controller;
|
||||||
* @author Olivier Maridat
|
* @author Olivier Maridat
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Link extends Base
|
class Link extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get the current link
|
* Get the current link
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @return array
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
private function getLink()
|
private function getLink()
|
||||||
{
|
{
|
||||||
$link = $this->link->getById($this->request->getIntegerParam('link_id'));
|
$link = $this->link->getById($this->request->getIntegerParam('link_id'));
|
||||||
|
|
||||||
if (empty($link)) {
|
if (empty($link)) {
|
||||||
$this->notfound();
|
throw new PageNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $link;
|
return $link;
|
||||||
|
|
@ -32,6 +35,8 @@ class Link extends Base
|
||||||
* List of links
|
* List of links
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function index(array $values = array(), array $errors = array())
|
public function index(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -56,19 +61,22 @@ class Link extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->link->create($values['label'], $values['opposite_label']) !== false) {
|
if ($this->link->create($values['label'], $values['opposite_label']) !== false) {
|
||||||
$this->flash->success(t('Link added successfully.'));
|
$this->flash->success(t('Link added successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('link', 'index'));
|
return $this->response->redirect($this->helper->url->to('link', 'index'));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to create your link.'));
|
$this->flash->failure(t('Unable to create your link.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->index($values, $errors);
|
return $this->index($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit form
|
* Edit form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -97,13 +105,13 @@ class Link extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->link->update($values)) {
|
if ($this->link->update($values)) {
|
||||||
$this->flash->success(t('Link updated successfully.'));
|
$this->flash->success(t('Link updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('link', 'index'));
|
return $this->response->redirect($this->helper->url->to('link', 'index'));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to update your link.'));
|
$this->flash->failure(t('Unable to update your link.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ use Kanboard\Model\Task as TaskModel;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Listing extends Base
|
class Listing extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show list view for projects
|
* Show list view for projects
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use Kanboard\Core\Security\OAuthAuthenticationProviderInterface;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Oauth extends Base
|
class Oauth extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Redirect to the provider if no code received
|
* Redirect to the provider if no code received
|
||||||
|
|
@ -106,7 +106,7 @@ class Oauth extends Base
|
||||||
protected function authenticate($providerName)
|
protected function authenticate($providerName)
|
||||||
{
|
{
|
||||||
if ($this->authenticationManager->oauthAuthentication($providerName)) {
|
if ($this->authenticationManager->oauthAuthentication($providerName)) {
|
||||||
$this->response->redirect($this->helper->url->to('app', 'index'));
|
$this->response->redirect($this->helper->url->to('DashboardController', 'show'));
|
||||||
} else {
|
} else {
|
||||||
$this->authenticationFailure(t('External authentication failed'));
|
$this->authenticationFailure(t('External authentication failed'));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Password Reset Controller
|
* Password Reset Controller
|
||||||
*
|
*
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class PasswordReset extends Base
|
class PasswordReset extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show the form to reset the password
|
* Show the form to reset the password
|
||||||
|
|
@ -37,9 +39,9 @@ class PasswordReset extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
$this->sendEmail($values['username']);
|
$this->sendEmail($values['username']);
|
||||||
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
||||||
|
} else {
|
||||||
|
$this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -59,9 +61,9 @@ class PasswordReset extends Base
|
||||||
'values' => $values,
|
'values' => $values,
|
||||||
'no_layout' => true,
|
'no_layout' => true,
|
||||||
)));
|
)));
|
||||||
|
} else {
|
||||||
|
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -83,10 +85,10 @@ class PasswordReset extends Base
|
||||||
$this->passwordReset->disable($user_id);
|
$this->passwordReset->disable($user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
return $this->response->redirect($this->helper->url->to('auth', 'login'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->change($values, $errors);
|
return $this->change($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -114,7 +116,7 @@ class PasswordReset extends Base
|
||||||
private function checkActivation()
|
private function checkActivation()
|
||||||
{
|
{
|
||||||
if ($this->config->get('password_reset', 0) == 0) {
|
if ($this->config->get('password_reset', 0) == 0) {
|
||||||
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
throw AccessForbiddenException::getInstance()->withoutLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Project extends Base
|
class Project extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* List of projects
|
* List of projects
|
||||||
|
|
@ -75,12 +75,9 @@ class Project extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('project', 'share', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('project', 'share', array('project_id' => $project['id'])));
|
||||||
|
} else {
|
||||||
|
$this->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('project/share', array(
|
|
||||||
'project' => $project,
|
|
||||||
'title' => t('Public access'),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -96,15 +93,15 @@ class Project extends Base
|
||||||
$this->projectMetadata->save($project['id'], $this->request->getValues());
|
$this->projectMetadata->save($project['id'], $this->request->getValues());
|
||||||
$this->flash->success(t('Project updated successfully.'));
|
$this->flash->success(t('Project updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('project', 'integrations', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('project', 'integrations', array('project_id' => $project['id'])));
|
||||||
|
} else {
|
||||||
|
$this->response->html($this->helper->layout->project('project/integrations', array(
|
||||||
|
'project' => $project,
|
||||||
|
'title' => t('Integrations'),
|
||||||
|
'webhook_token' => $this->config->get('webhook_token'),
|
||||||
|
'values' => $this->projectMetadata->getAll($project['id']),
|
||||||
|
'errors' => array(),
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('project/integrations', array(
|
|
||||||
'project' => $project,
|
|
||||||
'title' => t('Integrations'),
|
|
||||||
'webhook_token' => $this->config->get('webhook_token'),
|
|
||||||
'values' => $this->projectMetadata->getAll($project['id']),
|
|
||||||
'errors' => array(),
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -120,10 +117,10 @@ class Project extends Base
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
$this->projectNotification->saveSettings($project['id'], $values);
|
$this->projectNotification->saveSettings($project['id'], $values);
|
||||||
$this->flash->success(t('Project updated successfully.'));
|
$this->flash->success(t('Project updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('project', 'notifications', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('project', 'notifications', array('project_id' => $project['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('project/notifications', array(
|
return $this->response->html($this->helper->layout->project('project/notifications', array(
|
||||||
'notifications' => $this->projectNotification->readSettings($project['id']),
|
'notifications' => $this->projectNotification->readSettings($project['id']),
|
||||||
'types' => $this->projectNotificationType->getTypes(),
|
'types' => $this->projectNotificationType->getTypes(),
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
|
|
@ -149,10 +146,10 @@ class Project extends Base
|
||||||
$this->flash->failure(t('Unable to remove this project.'));
|
$this->flash->failure(t('Unable to remove this project.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('project', 'index'));
|
return $this->response->redirect($this->helper->url->to('project', 'index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('project/remove', array(
|
return $this->response->html($this->helper->layout->project('project/remove', array(
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
'title' => t('Remove project')
|
'title' => t('Remove project')
|
||||||
)));
|
)));
|
||||||
|
|
@ -178,10 +175,10 @@ class Project extends Base
|
||||||
$this->flash->failure(t('Unable to clone this project.'));
|
$this->flash->failure(t('Unable to clone this project.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id)));
|
return $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('project/duplicate', array(
|
return $this->response->html($this->helper->layout->project('project/duplicate', array(
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
'title' => t('Clone this project')
|
'title' => t('Clone this project')
|
||||||
)));
|
)));
|
||||||
|
|
@ -205,10 +202,10 @@ class Project extends Base
|
||||||
$this->flash->failure(t('Unable to disable this project.'));
|
$this->flash->failure(t('Unable to disable this project.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('project/disable', array(
|
return $this->response->html($this->helper->layout->project('project/disable', array(
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
'title' => t('Project activation')
|
'title' => t('Project activation')
|
||||||
)));
|
)));
|
||||||
|
|
@ -232,10 +229,10 @@ class Project extends Base
|
||||||
$this->flash->failure(t('Unable to activate this project.'));
|
$this->flash->failure(t('Unable to activate this project.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('project/enable', array(
|
return $this->response->html($this->helper->layout->project('project/enable', array(
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
'title' => t('Project activation')
|
'title' => t('Project activation')
|
||||||
)));
|
)));
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,14 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class ProjectCreation extends Base
|
class ProjectCreation extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a form to create a new project
|
* Display a form to create a new project
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -33,6 +35,8 @@ class ProjectCreation extends Base
|
||||||
* Display a form to create a private project
|
* Display a form to create a private project
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function createPrivate(array $values = array(), array $errors = array())
|
public function createPrivate(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -61,7 +65,7 @@ class ProjectCreation extends Base
|
||||||
$this->flash->failure(t('Unable to create your project.'));
|
$this->flash->failure(t('Unable to create your project.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
return $this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,14 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class ProjectEdit extends Base
|
class ProjectEdit extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* General edition (most common operations)
|
* General edition (most common operations)
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -24,6 +26,8 @@ class ProjectEdit extends Base
|
||||||
* Change start and end dates
|
* Change start and end dates
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function dates(array $values = array(), array $errors = array())
|
public function dates(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -34,6 +38,8 @@ class ProjectEdit extends Base
|
||||||
* Change project description
|
* Change project description
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function description(array $values = array(), array $errors = array())
|
public function description(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -44,6 +50,8 @@ class ProjectEdit extends Base
|
||||||
* Change task priority
|
* Change task priority
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function priority(array $values = array(), array $errors = array())
|
public function priority(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -67,13 +75,13 @@ class ProjectEdit extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->project->update($values)) {
|
if ($this->project->update($values)) {
|
||||||
$this->flash->success(t('Project updated successfully.'));
|
$this->flash->success(t('Project updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('ProjectEdit', $redirect, array('project_id' => $project['id'])), true);
|
return $this->response->redirect($this->helper->url->to('ProjectEdit', $redirect, array('project_id' => $project['id'])), true);
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to update this project.'));
|
$this->flash->failure(t('Unable to update this project.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->$redirect($values, $errors);
|
return $this->$redirect($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class ProjectFile extends Base
|
class ProjectFile extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* File upload form
|
* File upload form
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class ProjectOverview extends Base
|
class ProjectOverview extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show project overview
|
* Show project overview
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -10,7 +11,7 @@ use Kanboard\Core\Security\Role;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class ProjectPermission extends Base
|
class ProjectPermission extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Permissions are only available for team projects
|
* Permissions are only available for team projects
|
||||||
|
|
@ -18,13 +19,14 @@ class ProjectPermission extends Base
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param integer $project_id Default project id
|
* @param integer $project_id Default project id
|
||||||
* @return array
|
* @return array
|
||||||
|
* @throws AccessForbiddenException
|
||||||
*/
|
*/
|
||||||
protected function getProject($project_id = 0)
|
protected function getProject($project_id = 0)
|
||||||
{
|
{
|
||||||
$project = parent::getProject($project_id);
|
$project = parent::getProject($project_id);
|
||||||
|
|
||||||
if ($project['is_private'] == 1) {
|
if ($project['is_private'] == 1) {
|
||||||
$this->forbidden();
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $project;
|
return $project;
|
||||||
|
|
@ -34,6 +36,9 @@ class ProjectPermission extends Base
|
||||||
* Show all permissions
|
* Show all permissions
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws AccessForbiddenException
|
||||||
*/
|
*/
|
||||||
public function index(array $values = array(), array $errors = array())
|
public function index(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use Kanboard\Core\Security\Role;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Projectuser extends Base
|
class Projectuser extends BaseController
|
||||||
{
|
{
|
||||||
private function common()
|
private function common()
|
||||||
{
|
{
|
||||||
|
|
@ -94,7 +94,7 @@ class Projectuser extends Base
|
||||||
*/
|
*/
|
||||||
public function members()
|
public function members()
|
||||||
{
|
{
|
||||||
$this->role(ROLE::PROJECT_MEMBER, 'members', t('People who are project members'), 'Projects where "%s" is member');
|
$this->role(Role::PROJECT_MEMBER, 'members', t('People who are project members'), 'Projects where "%s" is member');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use Kanboard\Filter\TaskProjectsFilter;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Search extends Base
|
class Search extends BaseController
|
||||||
{
|
{
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,18 +2,24 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subtask controller
|
* Subtask controller
|
||||||
*
|
*
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Subtask extends Base
|
class Subtask extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creation form
|
* Creation form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws AccessForbiddenException
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -60,18 +66,22 @@ class Subtask extends Base
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks'), true);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks'), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
return $this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit form
|
* Edit form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws AccessForbiddenException
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
$subtask = $this->getSubTask();
|
$subtask = $this->getSubtask();
|
||||||
|
|
||||||
$this->response->html($this->template->render('subtask/edit', array(
|
$this->response->html($this->template->render('subtask/edit', array(
|
||||||
'values' => empty($values) ? $subtask : $values,
|
'values' => empty($values) ? $subtask : $values,
|
||||||
|
|
@ -106,7 +116,7 @@ class Subtask extends Base
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -158,9 +168,9 @@ class Subtask extends Base
|
||||||
|
|
||||||
if (! empty($values) && $this->helper->user->hasProjectAccess('Subtask', 'movePosition', $project_id)) {
|
if (! empty($values) && $this->helper->user->hasProjectAccess('Subtask', 'movePosition', $project_id)) {
|
||||||
$result = $this->subtask->changePosition($task_id, $values['subtask_id'], $values['position']);
|
$result = $this->subtask->changePosition($task_id, $values['subtask_id'], $values['position']);
|
||||||
return $this->response->json(array('result' => $result));
|
$this->response->json(array('result' => $result));
|
||||||
|
} else {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->forbidden();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use Kanboard\Model\Subtask as SubtaskModel;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class SubtaskRestriction extends Base
|
class SubtaskRestriction extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show popup
|
* Show popup
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class SubtaskStatus extends Base
|
class SubtaskStatus extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Change status to the next status: Toto -> In Progress -> Done
|
* Change status to the next status: Toto -> In Progress -> Done
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
use Kanboard\Core\Controller\PageNotFoundException;
|
||||||
use Kanboard\Model\Swimlane as SwimlaneModel;
|
use Kanboard\Model\Swimlane as SwimlaneModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -10,22 +12,21 @@ use Kanboard\Model\Swimlane as SwimlaneModel;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Swimlane extends Base
|
class Swimlane extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get the swimlane (common method between actions)
|
* Get the swimlane (common method between actions)
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @param integer $project_id
|
|
||||||
* @return array
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
private function getSwimlane($project_id)
|
private function getSwimlane()
|
||||||
{
|
{
|
||||||
$swimlane = $this->swimlane->getById($this->request->getIntegerParam('swimlane_id'));
|
$swimlane = $this->swimlane->getById($this->request->getIntegerParam('swimlane_id'));
|
||||||
|
|
||||||
if (empty($swimlane)) {
|
if (empty($swimlane)) {
|
||||||
$this->flash->failure(t('Swimlane not found.'));
|
throw new PageNotFoundException();
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project_id)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $swimlane;
|
return $swimlane;
|
||||||
|
|
@ -53,6 +54,9 @@ class Swimlane extends Base
|
||||||
* Create a new swimlane
|
* Create a new swimlane
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -79,19 +83,22 @@ class Swimlane extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->swimlane->create($values)) {
|
if ($this->swimlane->create($values)) {
|
||||||
$this->flash->success(t('Your swimlane have been created successfully.'));
|
$this->flash->success(t('Your swimlane have been created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$errors = array('name' => array(t('Another swimlane with the same name exists in the project')));
|
$errors = array('name' => array(t('Another swimlane with the same name exists in the project')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
return $this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit default swimlane (display the form)
|
* Edit default swimlane (display the form)
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function editDefault(array $values = array(), array $errors = array())
|
public function editDefault(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -120,24 +127,27 @@ class Swimlane extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->swimlane->updateDefault($values)) {
|
if ($this->swimlane->updateDefault($values)) {
|
||||||
$this->flash->success(t('The default swimlane have been updated successfully.'));
|
$this->flash->success(t('The default swimlane have been updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])), true);
|
return $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])), true);
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to update this swimlane.'));
|
$this->flash->failure(t('Unable to update this swimlane.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->editDefault($values, $errors);
|
return $this->editDefault($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit a swimlane (display the form)
|
* Edit a swimlane (display the form)
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
$swimlane = $this->getSwimlane($project['id']);
|
$swimlane = $this->getSwimlane();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('swimlane/edit', array(
|
$this->response->html($this->helper->layout->project('swimlane/edit', array(
|
||||||
'values' => empty($values) ? $swimlane : $values,
|
'values' => empty($values) ? $swimlane : $values,
|
||||||
|
|
@ -161,13 +171,13 @@ class Swimlane extends Base
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->swimlane->update($values)) {
|
if ($this->swimlane->update($values)) {
|
||||||
$this->flash->success(t('Swimlane updated successfully.'));
|
$this->flash->success(t('Swimlane updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
return $this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$errors = array('name' => array(t('Another swimlane with the same name exists in the project')));
|
$errors = array('name' => array(t('Another swimlane with the same name exists in the project')));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -178,7 +188,7 @@ class Swimlane extends Base
|
||||||
public function confirm()
|
public function confirm()
|
||||||
{
|
{
|
||||||
$project = $this->getProject();
|
$project = $this->getProject();
|
||||||
$swimlane = $this->getSwimlane($project['id']);
|
$swimlane = $this->getSwimlane();
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->project('swimlane/remove', array(
|
$this->response->html($this->helper->layout->project('swimlane/remove', array(
|
||||||
'project' => $project,
|
'project' => $project,
|
||||||
|
|
@ -296,9 +306,9 @@ class Swimlane extends Base
|
||||||
|
|
||||||
if (! empty($values) && isset($values['swimlane_id']) && isset($values['position'])) {
|
if (! empty($values) && isset($values['swimlane_id']) && isset($values['position'])) {
|
||||||
$result = $this->swimlane->changePosition($project['id'], $values['swimlane_id'], $values['position']);
|
$result = $this->swimlane->changePosition($project['id'], $values['swimlane_id'], $values['position']);
|
||||||
return $this->response->json(array('result' => $result));
|
$this->response->json(array('result' => $result));
|
||||||
|
} else {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->forbidden();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
use Kanboard\Core\Controller\PageNotFoundException;
|
||||||
use Kanboard\Core\DateParser;
|
use Kanboard\Core\DateParser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -10,7 +12,7 @@ use Kanboard\Core\DateParser;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Task extends Base
|
class Task extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Public access (display a task)
|
* Public access (display a task)
|
||||||
|
|
@ -23,17 +25,17 @@ class Task extends Base
|
||||||
|
|
||||||
// Token verification
|
// Token verification
|
||||||
if (empty($project)) {
|
if (empty($project)) {
|
||||||
return $this->forbidden(true);
|
throw AccessForbiddenException::getInstance()->withoutLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
$task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
|
$task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
|
||||||
|
|
||||||
if (empty($task)) {
|
if (empty($task)) {
|
||||||
return $this->notfound(true);
|
throw PageNotFoundException::getInstance()->withoutLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($task['project_id'] != $project['id']) {
|
if ($task['project_id'] != $project['id']) {
|
||||||
return $this->forbidden(true);
|
throw AccessForbiddenException::getInstance()->withoutLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->app('task/public', array(
|
$this->response->html($this->helper->layout->app('task/public', array(
|
||||||
|
|
@ -152,7 +154,7 @@ class Task extends Base
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
|
|
||||||
if (! $this->helper->user->canRemoveTask($task)) {
|
if (! $this->helper->user->canRemoveTask($task)) {
|
||||||
$this->forbidden();
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->request->getStringParam('confirmation') === 'yes') {
|
if ($this->request->getStringParam('confirmation') === 'yes') {
|
||||||
|
|
@ -164,10 +166,10 @@ class Task extends Base
|
||||||
$this->flash->failure(t('Unable to remove this task.'));
|
$this->flash->failure(t('Unable to remove this task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])), true);
|
return $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->template->render('task/remove', array(
|
return $this->response->html($this->template->render('task/remove', array(
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ namespace Kanboard\Controller;
|
||||||
*
|
*
|
||||||
* @package Kanboard\Controller
|
* @package Kanboard\Controller
|
||||||
*/
|
*/
|
||||||
class TaskBulk extends Base
|
class TaskBulk extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Show the form
|
* Show the form
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\PageNotFoundException;
|
||||||
use Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound;
|
use Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -10,12 +11,16 @@ use Kanboard\Core\ExternalLink\ExternalLinkProviderNotFound;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class TaskExternalLink extends Base
|
class TaskExternalLink extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* First creation form
|
* First creation form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
* @throws \Kanboard\Core\Controller\AccessForbiddenException
|
||||||
*/
|
*/
|
||||||
public function find(array $values = array(), array $errors = array())
|
public function find(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -36,11 +41,10 @@ class TaskExternalLink extends Base
|
||||||
*/
|
*/
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
|
$task = $this->getTask();
|
||||||
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
$task = $this->getTask();
|
|
||||||
$values = $this->request->getValues();
|
|
||||||
|
|
||||||
$provider = $this->externalLinkManager->setUserInput($values)->find();
|
$provider = $this->externalLinkManager->setUserInput($values)->find();
|
||||||
$link = $provider->getLink();
|
$link = $provider->getLink();
|
||||||
|
|
||||||
|
|
@ -77,13 +81,18 @@ class TaskExternalLink extends Base
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit form
|
* Edit form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws ExternalLinkProviderNotFound
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
* @throws \Kanboard\Core\Controller\AccessForbiddenException
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -95,7 +104,7 @@ class TaskExternalLink extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($values)) {
|
if (empty($values)) {
|
||||||
return $this->notfound();
|
throw new PageNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$provider = $this->externalLinkManager->getProvider($values['link_type']);
|
$provider = $this->externalLinkManager->getProvider($values['link_type']);
|
||||||
|
|
@ -124,7 +133,7 @@ class TaskExternalLink extends Base
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -139,7 +148,7 @@ class TaskExternalLink extends Base
|
||||||
$link = $this->taskExternalLink->getById($link_id);
|
$link = $this->taskExternalLink->getById($link_id);
|
||||||
|
|
||||||
if (empty($link)) {
|
if (empty($link)) {
|
||||||
return $this->notfound();
|
throw new PageNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->template->render('task_external_link/remove', array(
|
$this->response->html($this->template->render('task_external_link/remove', array(
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class TaskFile extends Base
|
class TaskFile extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Screenshot
|
* Screenshot
|
||||||
|
|
@ -24,7 +24,7 @@ class TaskFile extends Base
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->template->render('task_file/screenshot', array(
|
return $this->response->html($this->template->render('task_file/screenshot', array(
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use Kanboard\Formatter\TaskAutoCompleteFormatter;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class TaskHelper extends Base
|
class TaskHelper extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Task auto-completion (Ajax)
|
* Task auto-completion (Ajax)
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,14 @@ use Kanboard\Core\Csv;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class TaskImport extends Base
|
class TaskImport extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Upload the file and ask settings
|
* Upload the file and ask settings
|
||||||
*
|
*
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function step1(array $values = array(), array $errors = array())
|
public function step1(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -66,7 +69,7 @@ class TaskImport extends Base
|
||||||
*/
|
*/
|
||||||
public function template()
|
public function template()
|
||||||
{
|
{
|
||||||
$this->response->forceDownload('tasks.csv');
|
$this->response->withDownload('tasks.csv');
|
||||||
$this->response->csv(array($this->taskImport->getColumnMapping()));
|
$this->response->csv(array($this->taskImport->getColumnMapping()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\PageNotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TaskInternalLink Controller
|
* TaskInternalLink Controller
|
||||||
*
|
*
|
||||||
|
|
@ -9,20 +11,21 @@ namespace Kanboard\Controller;
|
||||||
* @author Olivier Maridat
|
* @author Olivier Maridat
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class TaskInternalLink extends Base
|
class TaskInternalLink extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get the current link
|
* Get the current link
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @return array
|
* @return array
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
private function getTaskLink()
|
private function getTaskLink()
|
||||||
{
|
{
|
||||||
$link = $this->taskLink->getById($this->request->getIntegerParam('link_id'));
|
$link = $this->taskLink->getById($this->request->getIntegerParam('link_id'));
|
||||||
|
|
||||||
if (empty($link)) {
|
if (empty($link)) {
|
||||||
return $this->notfound();
|
throw new PageNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $link;
|
return $link;
|
||||||
|
|
@ -32,6 +35,10 @@ class TaskInternalLink extends Base
|
||||||
* Creation form
|
* Creation form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
* @throws \Kanboard\Core\Controller\AccessForbiddenException
|
||||||
*/
|
*/
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -67,13 +74,17 @@ class TaskInternalLink extends Base
|
||||||
$this->flash->failure(t('Unable to create your link.'));
|
$this->flash->failure(t('Unable to create your link.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
return $this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit form
|
* Edit form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws PageNotFoundException
|
||||||
|
* @throws \Kanboard\Core\Controller\AccessForbiddenException
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -116,7 +127,7 @@ class TaskInternalLink extends Base
|
||||||
$this->flash->failure(t('Unable to update your link.'));
|
$this->flash->failure(t('Unable to update your link.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class TaskPopover extends Base
|
class TaskPopover extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Change a task assignee directly from the board
|
* Change a task assignee directly from the board
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,16 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class TaskRecurrence extends Base
|
class TaskRecurrence extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Edit recurrence form
|
* Edit recurrence form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\AccessForbiddenException
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -53,9 +57,9 @@ class TaskRecurrence extends Base
|
||||||
$this->flash->failure(t('Unable to update your task.'));
|
$this->flash->failure(t('Unable to update your task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
return $this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,15 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Taskcreation extends Base
|
class Taskcreation extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Display a form to create a new task
|
* Display a form to create a new task
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -63,7 +66,7 @@ class Taskcreation extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->flash->failure(t('Unable to create your task.'));
|
$this->flash->failure(t('Unable to create your task.'));
|
||||||
$this->create($values, $errors);
|
return $this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function afterSave(array $project, array &$values)
|
private function afterSave(array $project, array &$values)
|
||||||
|
|
@ -79,6 +82,6 @@ class Taskcreation extends Base
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id'])), true);
|
return $this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $project['id'])), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Taskduplication extends Base
|
class Taskduplication extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Duplicate a task
|
* Duplicate a task
|
||||||
|
|
@ -25,14 +25,14 @@ class Taskduplication extends Base
|
||||||
|
|
||||||
if ($task_id > 0) {
|
if ($task_id > 0) {
|
||||||
$this->flash->success(t('Task created successfully.'));
|
$this->flash->success(t('Task created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task_id)));
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task_id)));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to create this task.'));
|
$this->flash->failure(t('Unable to create this task.'));
|
||||||
$this->response->redirect($this->helper->url->to('taskduplication', 'duplicate', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
return $this->response->redirect($this->helper->url->to('taskduplication', 'duplicate', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->template->render('task_duplication/duplicate', array(
|
return $this->response->html($this->template->render('task_duplication/duplicate', array(
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
@ -57,13 +57,13 @@ class Taskduplication extends Base
|
||||||
$values['category_id'],
|
$values['category_id'],
|
||||||
$values['owner_id'])) {
|
$values['owner_id'])) {
|
||||||
$this->flash->success(t('Task updated successfully.'));
|
$this->flash->success(t('Task updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task['id'])));
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->flash->failure(t('Unable to update your task.'));
|
$this->flash->failure(t('Unable to update your task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->chooseDestination($task, 'task_duplication/move');
|
return $this->chooseDestination($task, 'task_duplication/move');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -87,14 +87,14 @@ class Taskduplication extends Base
|
||||||
|
|
||||||
if ($task_id > 0) {
|
if ($task_id > 0) {
|
||||||
$this->flash->success(t('Task created successfully.'));
|
$this->flash->success(t('Task created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task_id)));
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task_id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->flash->failure(t('Unable to create your task.'));
|
$this->flash->failure(t('Unable to create your task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->chooseDestination($task, 'task_duplication/copy');
|
return $this->chooseDestination($task, 'task_duplication/copy');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use Kanboard\Core\DateParser;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Taskmodification extends Base
|
class Taskmodification extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Set automatically the start date
|
* Set automatically the start date
|
||||||
|
|
@ -28,6 +28,10 @@ class Taskmodification extends Base
|
||||||
* Edit description form
|
* Edit description form
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\AccessForbiddenException
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function description(array $values = array(), array $errors = array())
|
public function description(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -66,13 +70,17 @@ class Taskmodification extends Base
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->description($values, $errors);
|
return $this->description($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a form to edit a task
|
* Display a form to edit a task
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
|
* @throws \Kanboard\Core\Controller\AccessForbiddenException
|
||||||
|
* @throws \Kanboard\Core\Controller\PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function edit(array $values = array(), array $errors = array())
|
public function edit(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -113,7 +121,7 @@ class Taskmodification extends Base
|
||||||
|
|
||||||
if ($valid && $this->taskModification->update($values)) {
|
if ($valid && $this->taskModification->update($values)) {
|
||||||
$this->flash->success(t('Task updated successfully.'));
|
$this->flash->success(t('Task updated successfully.'));
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])), true);
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to update your task.'));
|
$this->flash->failure(t('Unable to update your task.'));
|
||||||
$this->edit($values, $errors);
|
$this->edit($values, $errors);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Taskstatus extends Base
|
class Taskstatus extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Close a task
|
* Close a task
|
||||||
|
|
@ -55,7 +55,7 @@ class Taskstatus extends Base
|
||||||
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
|
return $this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->template->render($template, array(
|
return $this->response->html($this->template->render($template, array(
|
||||||
'task' => $task,
|
'task' => $task,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Two Factor Auth controller
|
* Two Factor Auth controller
|
||||||
*
|
*
|
||||||
|
|
@ -14,11 +16,13 @@ class Twofactor extends User
|
||||||
* Only the current user can access to 2FA settings
|
* Only the current user can access to 2FA settings
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
|
* @param array $user
|
||||||
|
* @throws AccessForbiddenException
|
||||||
*/
|
*/
|
||||||
private function checkCurrentUser(array $user)
|
private function checkCurrentUser(array $user)
|
||||||
{
|
{
|
||||||
if ($user['id'] != $this->userSession->getId()) {
|
if ($user['id'] != $this->userSession->getId()) {
|
||||||
$this->forbidden();
|
throw new AccessForbiddenException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,7 +149,7 @@ class Twofactor extends User
|
||||||
if ($provider->authenticate()) {
|
if ($provider->authenticate()) {
|
||||||
$this->userSession->validatePostAuthentication();
|
$this->userSession->validatePostAuthentication();
|
||||||
$this->flash->success(t('The two factor authentication code is valid.'));
|
$this->flash->success(t('The two factor authentication code is valid.'));
|
||||||
$this->response->redirect($this->helper->url->to('app', 'index'));
|
$this->response->redirect($this->helper->url->to('DashboardController', 'show'));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('The two factor authentication code is not valid.'));
|
$this->flash->failure(t('The two factor authentication code is not valid.'));
|
||||||
$this->response->redirect($this->helper->url->to('twofactor', 'code'));
|
$this->response->redirect($this->helper->url->to('twofactor', 'code'));
|
||||||
|
|
@ -188,10 +192,10 @@ class Twofactor extends User
|
||||||
'twofactor_secret' => '',
|
'twofactor_secret' => '',
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
|
return $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->user('twofactor/disable', array(
|
return $this->response->html($this->helper->layout->user('twofactor/disable', array(
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\PageNotFoundException;
|
||||||
use Kanboard\Notification\Mail as MailNotification;
|
use Kanboard\Notification\Mail as MailNotification;
|
||||||
use Kanboard\Model\Project as ProjectModel;
|
use Kanboard\Model\Project as ProjectModel;
|
||||||
use Kanboard\Core\Security\Role;
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
@ -12,7 +13,7 @@ use Kanboard\Core\Security\Role;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class User extends Base
|
class User extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* List all users
|
* List all users
|
||||||
|
|
@ -28,39 +29,38 @@ class User extends Base
|
||||||
->setQuery($this->user->getQuery())
|
->setQuery($this->user->getQuery())
|
||||||
->calculate();
|
->calculate();
|
||||||
|
|
||||||
$this->response->html(
|
$this->response->html($this->helper->layout->app('user/index', array(
|
||||||
$this->helper->layout->app('user/index', array(
|
'title' => t('Users').' ('.$paginator->getTotal().')',
|
||||||
'title' => t('Users').' ('.$paginator->getTotal().')',
|
'paginator' => $paginator,
|
||||||
'paginator' => $paginator,
|
)));
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public user profile
|
* Public user profile
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @throws PageNotFoundException
|
||||||
*/
|
*/
|
||||||
public function profile()
|
public function profile()
|
||||||
{
|
{
|
||||||
$user = $this->user->getById($this->request->getIntegerParam('user_id'));
|
$user = $this->user->getById($this->request->getIntegerParam('user_id'));
|
||||||
|
|
||||||
if (empty($user)) {
|
if (empty($user)) {
|
||||||
$this->notfound();
|
throw new PageNotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html(
|
$this->response->html($this->helper->layout->app('user/profile', array(
|
||||||
$this->helper->layout->app('user/profile', array(
|
'title' => $user['name'] ?: $user['username'],
|
||||||
'title' => $user['name'] ?: $user['username'],
|
'user' => $user,
|
||||||
'user' => $user,
|
)));
|
||||||
)
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display a form to create a new user
|
* Display a form to create a new user
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @param array $values
|
||||||
|
* @param array $errors
|
||||||
*/
|
*/
|
||||||
public function create(array $values = array(), array $errors = array())
|
public function create(array $values = array(), array $errors = array())
|
||||||
{
|
{
|
||||||
|
|
@ -101,14 +101,14 @@ class User extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->flash->success(t('User created successfully.'));
|
$this->flash->success(t('User created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user_id)));
|
return $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user_id)));
|
||||||
} else {
|
} else {
|
||||||
$this->flash->failure(t('Unable to create your user.'));
|
$this->flash->failure(t('Unable to create your user.'));
|
||||||
$values['project_id'] = $project_id;
|
$values['project_id'] = $project_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
return $this->create($values, $errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -217,10 +217,10 @@ class User extends Base
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
$this->userNotification->saveSettings($user['id'], $values);
|
$this->userNotification->saveSettings($user['id'], $values);
|
||||||
$this->flash->success(t('User updated successfully.'));
|
$this->flash->success(t('User updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('user', 'notifications', array('user_id' => $user['id'])));
|
return $this->response->redirect($this->helper->url->to('user', 'notifications', array('user_id' => $user['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->user('user/notifications', array(
|
return $this->response->html($this->helper->layout->user('user/notifications', array(
|
||||||
'projects' => $this->projectUserRole->getProjectsByUser($user['id'], array(ProjectModel::ACTIVE)),
|
'projects' => $this->projectUserRole->getProjectsByUser($user['id'], array(ProjectModel::ACTIVE)),
|
||||||
'notifications' => $this->userNotification->readSettings($user['id']),
|
'notifications' => $this->userNotification->readSettings($user['id']),
|
||||||
'types' => $this->userNotificationType->getTypes(),
|
'types' => $this->userNotificationType->getTypes(),
|
||||||
|
|
@ -284,10 +284,10 @@ class User extends Base
|
||||||
$this->flash->failure(t('Unable to update this user.'));
|
$this->flash->failure(t('Unable to update this user.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('user', 'share', array('user_id' => $user['id'])));
|
return $this->response->redirect($this->helper->url->to('user', 'share', array('user_id' => $user['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->user('user/share', array(
|
return $this->response->html($this->helper->layout->user('user/share', array(
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
'title' => t('Public access'),
|
'title' => t('Public access'),
|
||||||
)));
|
)));
|
||||||
|
|
@ -315,11 +315,11 @@ class User extends Base
|
||||||
$this->flash->failure(t('Unable to change the password.'));
|
$this->flash->failure(t('Unable to change the password.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
|
return $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->user('user/password', array(
|
return $this->response->html($this->helper->layout->user('user/password', array(
|
||||||
'values' => $values,
|
'values' => $values,
|
||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
|
@ -357,11 +357,11 @@ class User extends Base
|
||||||
$this->flash->failure(t('Unable to update your user.'));
|
$this->flash->failure(t('Unable to update your user.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
|
return $this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->user('user/edit', array(
|
return $this->response->html($this->helper->layout->user('user/edit', array(
|
||||||
'values' => $values,
|
'values' => $values,
|
||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
|
@ -395,11 +395,11 @@ class User extends Base
|
||||||
$this->flash->failure(t('Unable to update your user.'));
|
$this->flash->failure(t('Unable to update your user.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('user', 'authentication', array('user_id' => $user['id'])));
|
return $this->response->redirect($this->helper->url->to('user', 'authentication', array('user_id' => $user['id'])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->html($this->helper->layout->user('user/authentication', array(
|
return $this->response->html($this->helper->layout->user('user/authentication', array(
|
||||||
'values' => $values,
|
'values' => $values,
|
||||||
'errors' => $errors,
|
'errors' => $errors,
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use Kanboard\Model\User as UserModel;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class UserHelper extends Base
|
class UserHelper extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* User auto-completion (Ajax)
|
* User auto-completion (Ajax)
|
||||||
|
|
@ -39,4 +39,14 @@ class UserHelper extends Base
|
||||||
$users = $this->projectPermission->findUsernames($project_id, $query);
|
$users = $this->projectPermission->findUsernames($project_id, $query);
|
||||||
$this->response->json($users);
|
$this->response->json($users);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the user is connected
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function status()
|
||||||
|
{
|
||||||
|
$this->response->text('OK');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use Kanboard\Core\Csv;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class UserImport extends Base
|
class UserImport extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Upload the file and ask settings
|
* Upload the file and ask settings
|
||||||
|
|
@ -60,7 +60,7 @@ class UserImport extends Base
|
||||||
*/
|
*/
|
||||||
public function template()
|
public function template()
|
||||||
{
|
{
|
||||||
$this->response->forceDownload('users.csv');
|
$this->response->withDownload('users.csv');
|
||||||
$this->response->csv(array($this->userImport->getColumnMapping()));
|
$this->response->csv(array($this->userImport->getColumnMapping()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class UserStatus extends Base
|
class UserStatus extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Confirm remove a user
|
* Confirm remove a user
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class WebNotification extends Base
|
class WebNotification extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Mark all notifications as read
|
* Mark all notifications as read
|
||||||
|
|
@ -20,7 +20,7 @@ class WebNotification extends Base
|
||||||
$user_id = $this->getUserId();
|
$user_id = $this->getUserId();
|
||||||
|
|
||||||
$this->userUnreadNotification->markAllAsRead($user_id);
|
$this->userUnreadNotification->markAllAsRead($user_id);
|
||||||
$this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id)));
|
$this->response->redirect($this->helper->url->to('DashboardController', 'notifications', array('user_id' => $user_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -34,7 +34,7 @@ class WebNotification extends Base
|
||||||
$notification_id = $this->request->getIntegerParam('notification_id');
|
$notification_id = $this->request->getIntegerParam('notification_id');
|
||||||
|
|
||||||
$this->userUnreadNotification->markAsRead($user_id, $notification_id);
|
$this->userUnreadNotification->markAsRead($user_id, $notification_id);
|
||||||
$this->response->redirect($this->helper->url->to('app', 'notifications', array('user_id' => $user_id)));
|
$this->response->redirect($this->helper->url->to('DashboardController', 'notifications', array('user_id' => $user_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getUserId()
|
private function getUserId()
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Controller;
|
||||||
* @package controller
|
* @package controller
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Webhook extends Base
|
class Webhook extends BaseController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Webhook to create a task
|
* Webhook to create a task
|
||||||
|
|
@ -34,9 +34,9 @@ class Webhook extends Base
|
||||||
list($valid, ) = $this->taskValidator->validateCreation($values);
|
list($valid, ) = $this->taskValidator->validateCreation($values);
|
||||||
|
|
||||||
if ($valid && $this->taskCreation->create($values)) {
|
if ($valid && $this->taskCreation->create($values)) {
|
||||||
$this->response->text('OK');
|
return $this->response->text('OK');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->text('FAILED');
|
return $this->response->text('FAILED');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AccessForbiddenException
|
||||||
|
*
|
||||||
|
* @package Kanboard\Core\Controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class AccessForbiddenException extends BaseException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Controller;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AccessForbiddenException
|
||||||
|
*
|
||||||
|
* @package Kanboard\Core\Controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class BaseException extends Exception
|
||||||
|
{
|
||||||
|
protected $withoutLayout = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get object instance
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @param string $message
|
||||||
|
* @return static
|
||||||
|
*/
|
||||||
|
public static function getInstance($message = '')
|
||||||
|
{
|
||||||
|
return new static($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* There is no layout
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return BaseException
|
||||||
|
*/
|
||||||
|
public function withoutLayout()
|
||||||
|
{
|
||||||
|
$this->withoutLayout = true;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if no layout
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function hasLayout()
|
||||||
|
{
|
||||||
|
return $this->withoutLayout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BaseMiddleware
|
||||||
|
*
|
||||||
|
* @package Kanboard\Core\Controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
abstract class BaseMiddleware extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var BaseMiddleware
|
||||||
|
*/
|
||||||
|
protected $nextMiddleware = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute middleware
|
||||||
|
*/
|
||||||
|
abstract public function execute();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set next middleware
|
||||||
|
*
|
||||||
|
* @param BaseMiddleware $nextMiddleware
|
||||||
|
* @return BaseMiddleware
|
||||||
|
*/
|
||||||
|
public function setNextMiddleware($nextMiddleware)
|
||||||
|
{
|
||||||
|
$this->nextMiddleware = $nextMiddleware;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BaseMiddleware
|
||||||
|
*/
|
||||||
|
public function getNextMiddleware()
|
||||||
|
{
|
||||||
|
return $this->nextMiddleware;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move to next middleware
|
||||||
|
*/
|
||||||
|
public function next()
|
||||||
|
{
|
||||||
|
if ($this->nextMiddleware !== null) {
|
||||||
|
if (DEBUG) {
|
||||||
|
$this->logger->debug(__METHOD__.' => ' . get_class($this->nextMiddleware));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->nextMiddleware->execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Controller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PageNotFoundException
|
||||||
|
*
|
||||||
|
* @package Kanboard\Core\Controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class PageNotFoundException extends BaseException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Controller;
|
||||||
|
|
||||||
|
use Kanboard\Controller\AppController;
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
use Kanboard\Middleware\ApplicationAuthorizationMiddleware;
|
||||||
|
use Kanboard\Middleware\AuthenticationMiddleware;
|
||||||
|
use Kanboard\Middleware\BootstrapMiddleware;
|
||||||
|
use Kanboard\Middleware\PostAuthenticationMiddleware;
|
||||||
|
use Kanboard\Middleware\ProjectAuthorizationMiddleware;
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Runner
|
||||||
|
*
|
||||||
|
* @package Kanboard\Core\Controller
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Runner extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Execute middleware and controller
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->executeMiddleware();
|
||||||
|
$this->executeController();
|
||||||
|
} catch (PageNotFoundException $e) {
|
||||||
|
$controllerObject = new AppController($this->container);
|
||||||
|
$controllerObject->notFound($e->hasLayout());
|
||||||
|
} catch (AccessForbiddenException $e) {
|
||||||
|
$controllerObject = new AppController($this->container);
|
||||||
|
$controllerObject->accessForbidden($e->hasLayout());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute all middleware
|
||||||
|
*/
|
||||||
|
protected function executeMiddleware()
|
||||||
|
{
|
||||||
|
if (DEBUG) {
|
||||||
|
$this->logger->debug(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
$bootstrapMiddleware = new BootstrapMiddleware($this->container);
|
||||||
|
$authenticationMiddleware = new AuthenticationMiddleware($this->container);
|
||||||
|
$postAuthenticationMiddleware = new PostAuthenticationMiddleware($this->container);
|
||||||
|
$appAuthorizationMiddleware = new ApplicationAuthorizationMiddleware($this->container);
|
||||||
|
$projectAuthorizationMiddleware = new ProjectAuthorizationMiddleware($this->container);
|
||||||
|
|
||||||
|
$bootstrapMiddleware->setNextMiddleware($authenticationMiddleware);
|
||||||
|
$authenticationMiddleware->setNextMiddleware($postAuthenticationMiddleware);
|
||||||
|
$postAuthenticationMiddleware->setNextMiddleware($appAuthorizationMiddleware);
|
||||||
|
$appAuthorizationMiddleware->setNextMiddleware($projectAuthorizationMiddleware);
|
||||||
|
|
||||||
|
$bootstrapMiddleware->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the controller
|
||||||
|
*/
|
||||||
|
protected function executeController()
|
||||||
|
{
|
||||||
|
$className = $this->getControllerClassName();
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
$this->logger->debug(__METHOD__.' => '.$className.'::'.$this->router->getAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
$controllerObject = new $className($this->container);
|
||||||
|
$controllerObject->{$this->router->getAction()}();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get controller class name
|
||||||
|
*
|
||||||
|
* @access protected
|
||||||
|
* @return string
|
||||||
|
* @throws RuntimeException
|
||||||
|
*/
|
||||||
|
protected function getControllerClassName()
|
||||||
|
{
|
||||||
|
if ($this->router->getPlugin() !== '') {
|
||||||
|
$className = '\Kanboard\Plugin\\'.$this->router->getPlugin().'\Controller\\'.$this->router->getController();
|
||||||
|
} else {
|
||||||
|
$className = '\Kanboard\Controller\\'.$this->router->getController();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! class_exists($className)) {
|
||||||
|
throw new RuntimeException('Controller not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! method_exists($className, $this->router->getAction())) {
|
||||||
|
throw new RuntimeException('Action not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $className;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,72 +13,204 @@ use Kanboard\Core\Csv;
|
||||||
*/
|
*/
|
||||||
class Response extends Base
|
class Response extends Base
|
||||||
{
|
{
|
||||||
|
private $httpStatusCode = 200;
|
||||||
|
private $httpHeaders = array();
|
||||||
|
private $httpBody = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set HTTP status code
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param integer $statusCode
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withStatusCode($statusCode)
|
||||||
|
{
|
||||||
|
$this->httpStatusCode = $statusCode;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set HTTP header
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $header
|
||||||
|
* @param string $value
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withHeader($header, $value)
|
||||||
|
{
|
||||||
|
$this->httpHeaders[$header] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set content type header
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $value
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withContentType($value)
|
||||||
|
{
|
||||||
|
$this->httpHeaders['Content-Type'] = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default security headers
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withSecurityHeaders()
|
||||||
|
{
|
||||||
|
$this->httpHeaders['X-Content-Type-Options'] = 'nosniff';
|
||||||
|
$this->httpHeaders['X-XSS-Protection'] = '1; mode=block';
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set header Content-Security-Policy
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $policies
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withContentSecurityPolicy(array $policies = array())
|
||||||
|
{
|
||||||
|
$values = '';
|
||||||
|
|
||||||
|
foreach ($policies as $policy => $acl) {
|
||||||
|
$values .= $policy.' '.trim($acl).'; ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->withHeader('Content-Security-Policy', $values);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set header X-Frame-Options
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withXframe()
|
||||||
|
{
|
||||||
|
$this->withHeader('X-Frame-Options', 'DENY');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set header Strict-Transport-Security (only if we use HTTPS)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withStrictTransportSecurity()
|
||||||
|
{
|
||||||
|
if ($this->request->isHTTPS()) {
|
||||||
|
$this->withHeader('Strict-Transport-Security', 'max-age=31536000');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set HTTP response body
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $body
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function withBody($body)
|
||||||
|
{
|
||||||
|
$this->httpBody = $body;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send headers to cache a resource
|
* Send headers to cache a resource
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param integer $duration
|
* @param integer $duration
|
||||||
* @param string $etag
|
* @param string $etag
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function cache($duration, $etag = '')
|
public function withCache($duration, $etag = '')
|
||||||
{
|
{
|
||||||
header('Pragma: cache');
|
$this
|
||||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $duration) . ' GMT');
|
->withHeader('Pragma', 'cache')
|
||||||
header('Cache-Control: public, max-age=' . $duration);
|
->withHeader('Expires', gmdate('D, d M Y H:i:s', time() + $duration) . ' GMT')
|
||||||
|
->withHeader('Cache-Control', 'public, max-age=' . $duration)
|
||||||
|
;
|
||||||
|
|
||||||
if ($etag) {
|
if ($etag) {
|
||||||
header('ETag: "' . $etag . '"');
|
$this->withHeader('ETag', '"' . $etag . '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send no cache headers
|
* Send no cache headers
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function nocache()
|
public function withoutCache()
|
||||||
{
|
{
|
||||||
header('Pragma: no-cache');
|
$this->withHeader('Pragma', 'no-cache');
|
||||||
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
|
$this->withHeader('Expires', 'Sat, 26 Jul 1997 05:00:00 GMT');
|
||||||
|
return $this;
|
||||||
// Use no-store due to a Chrome bug: https://code.google.com/p/chromium/issues/detail?id=28035
|
|
||||||
header('Cache-Control: no-store, must-revalidate');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a custom Content-Type header
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $mimetype Mime-type
|
|
||||||
*/
|
|
||||||
public function contentType($mimetype)
|
|
||||||
{
|
|
||||||
header('Content-Type: '.$mimetype);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Force the browser to download an attachment
|
* Force the browser to download an attachment
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $filename File name
|
* @param string $filename
|
||||||
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function forceDownload($filename)
|
public function withDownload($filename)
|
||||||
{
|
{
|
||||||
header('Content-Disposition: attachment; filename="'.$filename.'"');
|
$this->withHeader('Content-Disposition', 'attachment; filename="'.$filename.'"');
|
||||||
header('Content-Transfer-Encoding: binary');
|
$this->withHeader('Content-Transfer-Encoding', 'binary');
|
||||||
header('Content-Type: application/octet-stream');
|
$this->withHeader('Content-Type', 'application/octet-stream');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send headers and body
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function send()
|
||||||
|
{
|
||||||
|
if ($this->httpStatusCode !== 200) {
|
||||||
|
header('Status: '.$this->httpStatusCode);
|
||||||
|
header($this->request->getServerVariable('SERVER_PROTOCOL').' '.$this->httpStatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->httpHeaders as $header => $value) {
|
||||||
|
header($header.': '.$value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! empty($this->httpBody)) {
|
||||||
|
echo $this->httpBody;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a custom HTTP status code
|
* Send a custom HTTP status code
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param integer $status_code HTTP status code
|
* @param integer $statusCode
|
||||||
*/
|
*/
|
||||||
public function status($status_code)
|
public function status($statusCode)
|
||||||
{
|
{
|
||||||
header('Status: '.$status_code);
|
$this->withStatusCode($statusCode);
|
||||||
header($this->request->getServerVariable('SERVER_PROTOCOL').' '.$status_code);
|
$this->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -91,218 +223,149 @@ class Response extends Base
|
||||||
public function redirect($url, $self = false)
|
public function redirect($url, $self = false)
|
||||||
{
|
{
|
||||||
if ($this->request->isAjax()) {
|
if ($this->request->isAjax()) {
|
||||||
header('X-Ajax-Redirect: '.($self ? 'self' : $url));
|
$this->withHeader('X-Ajax-Redirect', $self ? 'self' : $url);
|
||||||
} else {
|
} else {
|
||||||
header('Location: '.$url);
|
$this->withHeader('Location', $url);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit;
|
$this->send();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a CSV response
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param array $data Data to serialize in csv
|
|
||||||
* @param integer $status_code HTTP status code
|
|
||||||
*/
|
|
||||||
public function csv(array $data, $status_code = 200)
|
|
||||||
{
|
|
||||||
$this->status($status_code);
|
|
||||||
$this->nocache();
|
|
||||||
|
|
||||||
header('Content-Type: text/csv');
|
|
||||||
Csv::output($data);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a Json response
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param array $data Data to serialize in json
|
|
||||||
* @param integer $status_code HTTP status code
|
|
||||||
*/
|
|
||||||
public function json(array $data, $status_code = 200)
|
|
||||||
{
|
|
||||||
$this->status($status_code);
|
|
||||||
$this->nocache();
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
echo json_encode($data);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a text response
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $data Raw data
|
|
||||||
* @param integer $status_code HTTP status code
|
|
||||||
*/
|
|
||||||
public function text($data, $status_code = 200)
|
|
||||||
{
|
|
||||||
$this->status($status_code);
|
|
||||||
$this->nocache();
|
|
||||||
header('Content-Type: text/plain; charset=utf-8');
|
|
||||||
echo $data;
|
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a HTML response
|
* Send a HTML response
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $data Raw data
|
* @param string $data
|
||||||
* @param integer $status_code HTTP status code
|
* @param integer $statusCode
|
||||||
*/
|
*/
|
||||||
public function html($data, $status_code = 200)
|
public function html($data, $statusCode = 200)
|
||||||
{
|
{
|
||||||
$this->status($status_code);
|
$this->withStatusCode($statusCode);
|
||||||
$this->nocache();
|
$this->withContentType('text/html; charset=utf-8');
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
$this->withBody($data);
|
||||||
echo $data;
|
$this->send();
|
||||||
exit;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a text response
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $data
|
||||||
|
* @param integer $statusCode
|
||||||
|
*/
|
||||||
|
public function text($data, $statusCode = 200)
|
||||||
|
{
|
||||||
|
$this->withStatusCode($statusCode);
|
||||||
|
$this->withContentType('text/plain; charset=utf-8');
|
||||||
|
$this->withBody($data);
|
||||||
|
$this->send();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a CSV response
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Data to serialize in csv
|
||||||
|
*/
|
||||||
|
public function csv(array $data)
|
||||||
|
{
|
||||||
|
$this->withoutCache();
|
||||||
|
$this->withContentType('text/csv; charset=utf-8');
|
||||||
|
$this->send();
|
||||||
|
Csv::output($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a Json response
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Data to serialize in json
|
||||||
|
* @param integer $statusCode HTTP status code
|
||||||
|
*/
|
||||||
|
public function json(array $data, $statusCode = 200)
|
||||||
|
{
|
||||||
|
$this->withStatusCode($statusCode);
|
||||||
|
$this->withContentType('application/json');
|
||||||
|
$this->withoutCache();
|
||||||
|
$this->withBody(json_encode($data));
|
||||||
|
$this->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a XML response
|
* Send a XML response
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $data Raw data
|
* @param string $data
|
||||||
* @param integer $status_code HTTP status code
|
* @param integer $statusCode
|
||||||
*/
|
*/
|
||||||
public function xml($data, $status_code = 200)
|
public function xml($data, $statusCode = 200)
|
||||||
{
|
{
|
||||||
$this->status($status_code);
|
$this->withStatusCode($statusCode);
|
||||||
$this->nocache();
|
$this->withContentType('text/xml; charset=utf-8');
|
||||||
header('Content-Type: text/xml; charset=utf-8');
|
$this->withoutCache();
|
||||||
echo $data;
|
$this->withBody($data);
|
||||||
exit;
|
$this->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a javascript response
|
* Send a javascript response
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $data Raw data
|
* @param string $data
|
||||||
* @param integer $status_code HTTP status code
|
* @param integer $statusCode
|
||||||
*/
|
*/
|
||||||
public function js($data, $status_code = 200)
|
public function js($data, $statusCode = 200)
|
||||||
{
|
{
|
||||||
$this->status($status_code);
|
$this->withStatusCode($statusCode);
|
||||||
|
$this->withContentType('text/javascript; charset=utf-8');
|
||||||
header('Content-Type: text/javascript; charset=utf-8');
|
$this->withBody($data);
|
||||||
echo $data;
|
$this->send();
|
||||||
|
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a css response
|
* Send a css response
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $data Raw data
|
* @param string $data
|
||||||
* @param integer $status_code HTTP status code
|
* @param integer $statusCode
|
||||||
*/
|
*/
|
||||||
public function css($data, $status_code = 200)
|
public function css($data, $statusCode = 200)
|
||||||
{
|
{
|
||||||
$this->status($status_code);
|
$this->withStatusCode($statusCode);
|
||||||
|
$this->withContentType('text/css; charset=utf-8');
|
||||||
header('Content-Type: text/css; charset=utf-8');
|
$this->withBody($data);
|
||||||
echo $data;
|
$this->send();
|
||||||
|
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a binary response
|
* Send a binary response
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $data Raw data
|
* @param string $data
|
||||||
* @param integer $status_code HTTP status code
|
* @param integer $statusCode
|
||||||
*/
|
*/
|
||||||
public function binary($data, $status_code = 200)
|
public function binary($data, $statusCode = 200)
|
||||||
{
|
{
|
||||||
$this->status($status_code);
|
$this->withStatusCode($statusCode);
|
||||||
$this->nocache();
|
$this->withoutCache();
|
||||||
header('Content-Transfer-Encoding: binary');
|
$this->withHeader('Content-Transfer-Encoding', 'binary');
|
||||||
header('Content-Type: application/octet-stream');
|
$this->withContentType('application/octet-stream');
|
||||||
echo $data;
|
$this->withBody($data);
|
||||||
exit;
|
$this->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a iCal response
|
* Send a iCal response
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $data Raw data
|
* @param string $data
|
||||||
* @param integer $status_code HTTP status code
|
* @param integer $statusCode
|
||||||
*/
|
*/
|
||||||
public function ical($data, $status_code = 200)
|
public function ical($data, $statusCode = 200)
|
||||||
{
|
{
|
||||||
$this->status($status_code);
|
$this->withStatusCode($statusCode);
|
||||||
$this->contentType('text/calendar; charset=utf-8');
|
$this->withContentType('text/calendar; charset=utf-8');
|
||||||
echo $data;
|
$this->withBody($data);
|
||||||
}
|
$this->send();
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the security header: Content-Security-Policy
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param array $policies CSP rules
|
|
||||||
*/
|
|
||||||
public function csp(array $policies = array())
|
|
||||||
{
|
|
||||||
$values = '';
|
|
||||||
|
|
||||||
foreach ($policies as $policy => $acl) {
|
|
||||||
$values .= $policy.' '.trim($acl).'; ';
|
|
||||||
}
|
|
||||||
|
|
||||||
header('Content-Security-Policy: '.$values);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the security header: X-Content-Type-Options
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function nosniff()
|
|
||||||
{
|
|
||||||
header('X-Content-Type-Options: nosniff');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the security header: X-XSS-Protection
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function xss()
|
|
||||||
{
|
|
||||||
header('X-XSS-Protection: 1; mode=block');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the security header: Strict-Transport-Security (only if we use HTTPS)
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function hsts()
|
|
||||||
{
|
|
||||||
if ($this->request->isHTTPS()) {
|
|
||||||
header('Strict-Transport-Security: max-age=31536000');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the security header: X-Frame-Options (deny by default)
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $mode Frame option mode
|
|
||||||
* @param array $urls Allowed urls for the given mode
|
|
||||||
*/
|
|
||||||
public function xframe($mode = 'DENY', array $urls = array())
|
|
||||||
{
|
|
||||||
header('X-Frame-Options: '.$mode.' '.implode(' ', $urls));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -119,8 +119,8 @@ class Route extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'controller' => 'app',
|
'controller' => 'DashboardController',
|
||||||
'action' => 'index',
|
'action' => 'show',
|
||||||
'plugin' => '',
|
'plugin' => '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace Kanboard\Core\Http;
|
namespace Kanboard\Core\Http;
|
||||||
|
|
||||||
use RuntimeException;
|
|
||||||
use Kanboard\Core\Base;
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -13,13 +12,16 @@ use Kanboard\Core\Base;
|
||||||
*/
|
*/
|
||||||
class Router extends Base
|
class Router extends Base
|
||||||
{
|
{
|
||||||
|
const DEFAULT_CONTROLLER = 'DashboardController';
|
||||||
|
const DEFAULT_METHOD = 'show';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plugin name
|
* Plugin name
|
||||||
*
|
*
|
||||||
* @access private
|
* @access private
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $plugin = '';
|
private $currentPluginName = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller
|
* Controller
|
||||||
|
|
@ -27,7 +29,7 @@ class Router extends Base
|
||||||
* @access private
|
* @access private
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $controller = '';
|
private $currentControllerName = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action
|
* Action
|
||||||
|
|
@ -35,7 +37,7 @@ class Router extends Base
|
||||||
* @access private
|
* @access private
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $action = '';
|
private $currentActionName = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get plugin name
|
* Get plugin name
|
||||||
|
|
@ -45,7 +47,7 @@ class Router extends Base
|
||||||
*/
|
*/
|
||||||
public function getPlugin()
|
public function getPlugin()
|
||||||
{
|
{
|
||||||
return $this->plugin;
|
return $this->currentPluginName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -56,7 +58,7 @@ class Router extends Base
|
||||||
*/
|
*/
|
||||||
public function getController()
|
public function getController()
|
||||||
{
|
{
|
||||||
return $this->controller;
|
return $this->currentControllerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -67,7 +69,7 @@ class Router extends Base
|
||||||
*/
|
*/
|
||||||
public function getAction()
|
public function getAction()
|
||||||
{
|
{
|
||||||
return $this->action;
|
return $this->currentActionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -109,11 +111,9 @@ class Router extends Base
|
||||||
$plugin = $route['plugin'];
|
$plugin = $route['plugin'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->controller = ucfirst($this->sanitize($controller, 'app'));
|
$this->currentControllerName = ucfirst($this->sanitize($controller, self::DEFAULT_CONTROLLER));
|
||||||
$this->action = $this->sanitize($action, 'index');
|
$this->currentActionName = $this->sanitize($action, self::DEFAULT_METHOD);
|
||||||
$this->plugin = ucfirst($this->sanitize($plugin));
|
$this->currentPluginName = ucfirst($this->sanitize($plugin));
|
||||||
|
|
||||||
return $this->executeAction();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -128,42 +128,4 @@ class Router extends Base
|
||||||
{
|
{
|
||||||
return preg_match('/^[a-zA-Z_0-9]+$/', $value) ? $value : $default;
|
return preg_match('/^[a-zA-Z_0-9]+$/', $value) ? $value : $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute controller action
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
*/
|
|
||||||
private function executeAction()
|
|
||||||
{
|
|
||||||
$class = $this->getControllerClassName();
|
|
||||||
|
|
||||||
if (! class_exists($class)) {
|
|
||||||
throw new RuntimeException('Controller not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! method_exists($class, $this->action)) {
|
|
||||||
throw new RuntimeException('Action not implemented');
|
|
||||||
}
|
|
||||||
|
|
||||||
$instance = new $class($this->container);
|
|
||||||
$instance->beforeAction();
|
|
||||||
$instance->{$this->action}();
|
|
||||||
return $instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get controller class name
|
|
||||||
*
|
|
||||||
* @access private
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private function getControllerClassName()
|
|
||||||
{
|
|
||||||
if ($this->plugin !== '') {
|
|
||||||
return '\Kanboard\Plugin\\'.$this->plugin.'\Controller\\'.$this->controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
return '\Kanboard\Controller\\'.$this->controller;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ class LayoutHelper extends Base
|
||||||
*/
|
*/
|
||||||
public function dashboard($template, array $params)
|
public function dashboard($template, array $params)
|
||||||
{
|
{
|
||||||
return $this->subLayout('app/layout', 'app/sidebar', $template, $params);
|
return $this->subLayout('dashboard/layout', 'dashboard/sidebar', $template, $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Middleware;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
use Kanboard\Core\Controller\BaseMiddleware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ApplicationAuthorizationMiddleware
|
||||||
|
*
|
||||||
|
* @package Kanboard\Middleware
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ApplicationAuthorizationMiddleware extends BaseMiddleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Execute middleware
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
if (! $this->helper->user->hasAccess($this->router->getController(), $this->router->getAction())) {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Middleware;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
use Kanboard\Core\Controller\BaseMiddleware;
|
||||||
|
use Kanboard\Core\Security\Role;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AuthenticationMiddleware
|
||||||
|
*
|
||||||
|
* @package Kanboard\Middleware
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class AuthenticationMiddleware extends BaseMiddleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Execute middleware
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
if (! $this->authenticationManager->checkCurrentSession()) {
|
||||||
|
throw AccessForbiddenException::getInstance()->withoutLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $this->isPublicAccess()) {
|
||||||
|
$this->handleAuthentication();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function handleAuthentication()
|
||||||
|
{
|
||||||
|
if (! $this->userSession->isLogged() && ! $this->authenticationManager->preAuthentication()) {
|
||||||
|
$this->setNextMiddleware(null);
|
||||||
|
|
||||||
|
if ($this->request->isAjax()) {
|
||||||
|
$this->response->text('Not Authorized', 401);
|
||||||
|
} else {
|
||||||
|
$this->sessionStorage->redirectAfterLogin = $this->request->getUri();
|
||||||
|
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isPublicAccess()
|
||||||
|
{
|
||||||
|
if ($this->applicationAuthorization->isAllowed($this->router->getController(), $this->router->getAction(), Role::APP_PUBLIC)) {
|
||||||
|
$this->setNextMiddleware(null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Middleware;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\BaseMiddleware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BootstrapMiddleware
|
||||||
|
*
|
||||||
|
* @package Kanboard\Middleware
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class BootstrapMiddleware extends BaseMiddleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Execute middleware
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
$this->sessionManager->open();
|
||||||
|
$this->dispatcher->dispatch('app.bootstrap');
|
||||||
|
$this->sendHeaders();
|
||||||
|
$this->next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send HTTP headers
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
private function sendHeaders()
|
||||||
|
{
|
||||||
|
$this->response->withContentSecurityPolicy($this->container['cspRules']);
|
||||||
|
$this->response->withSecurityHeaders();
|
||||||
|
|
||||||
|
if (ENABLE_XFRAME && $this->router->getAction() !== 'readonly') {
|
||||||
|
$this->response->withXframe();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ENABLE_HSTS) {
|
||||||
|
$this->response->withStrictTransportSecurity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Middleware;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\BaseMiddleware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PostAuthenticationMiddleware
|
||||||
|
*
|
||||||
|
* @package Kanboard\Middleware
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class PostAuthenticationMiddleware extends BaseMiddleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Execute middleware
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
$controller = strtolower($this->router->getController());
|
||||||
|
$action = strtolower($this->router->getAction());
|
||||||
|
$ignore = ($controller === 'twofactor' && in_array($action, array('code', 'check'))) || ($controller === 'auth' && $action === 'logout');
|
||||||
|
|
||||||
|
if ($ignore === false && $this->userSession->hasPostAuthentication() && ! $this->userSession->isPostAuthenticationValidated()) {
|
||||||
|
$this->setNextMiddleware(null);
|
||||||
|
|
||||||
|
if ($this->request->isAjax()) {
|
||||||
|
$this->response->text('Not Authorized', 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->response->redirect($this->helper->url->to('twofactor', 'code'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Middleware;
|
||||||
|
|
||||||
|
use Kanboard\Core\Controller\AccessForbiddenException;
|
||||||
|
use Kanboard\Core\Controller\BaseMiddleware;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ProjectAuthorizationMiddleware
|
||||||
|
*
|
||||||
|
* @package Kanboard\Middleware
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class ProjectAuthorizationMiddleware extends BaseMiddleware
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Execute middleware
|
||||||
|
*/
|
||||||
|
public function execute()
|
||||||
|
{
|
||||||
|
$project_id = $this->request->getIntegerParam('project_id');
|
||||||
|
$task_id = $this->request->getIntegerParam('task_id');
|
||||||
|
|
||||||
|
if ($task_id > 0 && $project_id === 0) {
|
||||||
|
$project_id = $this->taskFinder->getProjectId($task_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($project_id > 0 && ! $this->helper->user->hasProjectAccess($this->router->getController(), $this->router->getAction(), $project_id)) {
|
||||||
|
throw new AccessForbiddenException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -31,14 +31,14 @@ class RouteProvider implements ServiceProviderInterface
|
||||||
$container['route']->enable();
|
$container['route']->enable();
|
||||||
|
|
||||||
// Dashboard
|
// Dashboard
|
||||||
$container['route']->addRoute('dashboard', 'app', 'index');
|
$container['route']->addRoute('dashboard', 'DashboardController', 'show');
|
||||||
$container['route']->addRoute('dashboard/:user_id', 'app', 'index');
|
$container['route']->addRoute('dashboard/:user_id', 'DashboardController', 'show');
|
||||||
$container['route']->addRoute('dashboard/:user_id/projects', 'app', 'projects');
|
$container['route']->addRoute('dashboard/:user_id/projects', 'DashboardController', 'projects');
|
||||||
$container['route']->addRoute('dashboard/:user_id/tasks', 'app', 'tasks');
|
$container['route']->addRoute('dashboard/:user_id/tasks', 'DashboardController', 'tasks');
|
||||||
$container['route']->addRoute('dashboard/:user_id/subtasks', 'app', 'subtasks');
|
$container['route']->addRoute('dashboard/:user_id/subtasks', 'DashboardController', 'subtasks');
|
||||||
$container['route']->addRoute('dashboard/:user_id/calendar', 'app', 'calendar');
|
$container['route']->addRoute('dashboard/:user_id/calendar', 'DashboardController', 'calendar');
|
||||||
$container['route']->addRoute('dashboard/:user_id/activity', 'app', 'activity');
|
$container['route']->addRoute('dashboard/:user_id/activity', 'DashboardController', 'activity');
|
||||||
$container['route']->addRoute('dashboard/:user_id/notifications', 'app', 'notifications');
|
$container['route']->addRoute('dashboard/:user_id/notifications', 'DashboardController', 'notifications');
|
||||||
|
|
||||||
// Search routes
|
// Search routes
|
||||||
$container['route']->addRoute('search', 'search', 'index');
|
$container['route']->addRoute('search', 'search', 'index');
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ class BootstrapSubscriber extends BaseSubscriber implements EventSubscriberInter
|
||||||
{
|
{
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
foreach ($this->db->getLogMessages() as $message) {
|
foreach ($this->db->getLogMessages() as $message) {
|
||||||
$this->logger->debug($message);
|
$this->logger->debug('SQL: ' . $message);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->logger->debug('nb_queries={nb}', array('nb' => $this->db->getStatementHandler()->getNbQueries()));
|
$this->logger->debug('nb_queries={nb}', array('nb' => $this->db->getStatementHandler()->getNbQueries()));
|
||||||
|
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
<div class="sidebar">
|
|
||||||
<h2><?= $this->text->e($user['name'] ?: $user['username']) ?></h2>
|
|
||||||
<ul>
|
|
||||||
<li <?= $this->app->checkMenuSelection('app', 'index') ?>>
|
|
||||||
<?= $this->url->link(t('Overview'), 'app', 'index', array('user_id' => $user['id'])) ?>
|
|
||||||
</li>
|
|
||||||
<li <?= $this->app->checkMenuSelection('app', 'projects') ?>>
|
|
||||||
<?= $this->url->link(t('My projects'), 'app', 'projects', array('user_id' => $user['id'])) ?>
|
|
||||||
</li>
|
|
||||||
<li <?= $this->app->checkMenuSelection('app', 'tasks') ?>>
|
|
||||||
<?= $this->url->link(t('My tasks'), 'app', 'tasks', array('user_id' => $user['id'])) ?>
|
|
||||||
</li>
|
|
||||||
<li <?= $this->app->checkMenuSelection('app', 'subtasks') ?>>
|
|
||||||
<?= $this->url->link(t('My subtasks'), 'app', 'subtasks', array('user_id' => $user['id'])) ?>
|
|
||||||
</li>
|
|
||||||
<li <?= $this->app->checkMenuSelection('app', 'calendar') ?>>
|
|
||||||
<?= $this->url->link(t('My calendar'), 'app', 'calendar', array('user_id' => $user['id'])) ?>
|
|
||||||
</li>
|
|
||||||
<li <?= $this->app->checkMenuSelection('app', 'activity') ?>>
|
|
||||||
<?= $this->url->link(t('My activity stream'), 'app', 'activity', array('user_id' => $user['id'])) ?>
|
|
||||||
</li>
|
|
||||||
<li <?= $this->app->checkMenuSelection('app', 'notifications') ?>>
|
|
||||||
<?= $this->url->link(t('My notifications'), 'app', 'notifications', array('user_id' => $user['id'])) ?>
|
|
||||||
</li>
|
|
||||||
<?= $this->hook->render('template:dashboard:sidebar') ?>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><?= t('Application settings') ?></h2>
|
<h2><?= t('Application settings') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" action="<?= $this->url->href('config', 'application') ?>" autocomplete="off">
|
<form method="post" action="<?= $this->url->href('config', 'save', array('redirect' => 'application')) ?>" autocomplete="off">
|
||||||
|
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><?= t('Board settings') ?></h2>
|
<h2><?= t('Board settings') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" action="<?= $this->url->href('config', 'board') ?>" autocomplete="off">
|
<form method="post" action="<?= $this->url->href('config', 'save', array('redirect' => 'board')) ?>" autocomplete="off">
|
||||||
|
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<h2><?= t('Calendar settings') ?></h2>
|
<h2><?= t('Calendar settings') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
<section>
|
<section>
|
||||||
<form method="post" action="<?= $this->url->href('config', 'calendar') ?>" autocomplete="off">
|
<form method="post" action="<?= $this->url->href('config', 'save', array('redirect' => 'calendar')) ?>" autocomplete="off">
|
||||||
|
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
|
|
||||||
|
|
@ -31,4 +31,4 @@
|
||||||
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button>
|
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<h2><?= t('Integration with third-party services') ?></h2>
|
<h2><?= t('Integration with third-party services') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="post" action="<?= $this->url->href('config', 'integrations') ?>" autocomplete="off">
|
<form method="post" action="<?= $this->url->href('config', 'save', array('redirect' => 'integrations')) ?>" autocomplete="off">
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
<?= $this->hook->render('template:config:integrations', array('values' => $values)) ?>
|
<?= $this->hook->render('template:config:integrations', array('values' => $values)) ?>
|
||||||
|
|
||||||
|
|
@ -14,4 +14,4 @@
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button>
|
<button type="submit" class="btn btn-blue"><?= t('Save') ?></button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
<section id="main">
|
<section id="main">
|
||||||
<section class="sidebar-container" id="config-section">
|
<section class="sidebar-container" id="config-section">
|
||||||
|
|
||||||
<?= $this->render($sidebar_template) ?>
|
<?= $this->render($sidebar_template) ?>
|
||||||
|
|
||||||
<div class="sidebar-content">
|
<div class="sidebar-content">
|
||||||
<?= $content_for_sublayout ?>
|
<?= $content_for_sublayout ?>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><?= t('Project settings') ?></h2>
|
<h2><?= t('Project settings') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
<form method="post" action="<?= $this->url->href('config', 'project') ?>" autocomplete="off">
|
<form method="post" action="<?= $this->url->href('config', 'save', array('redirect' => 'project')) ?>" autocomplete="off">
|
||||||
|
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<h2><?= t('Webhook settings') ?></h2>
|
<h2><?= t('Webhook settings') ?></h2>
|
||||||
</div>
|
</div>
|
||||||
<section>
|
<section>
|
||||||
<form method="post" action="<?= $this->url->href('config', 'webhook') ?>" autocomplete="off">
|
<form method="post" action="<?= $this->url->href('config', 'save', array('redirect' => 'webhook')) ?>" autocomplete="off">
|
||||||
|
|
||||||
<?= $this->form->csrf() ?>
|
<?= $this->form->csrf() ?>
|
||||||
|
|
||||||
|
|
@ -32,4 +32,4 @@
|
||||||
<?= $this->url->link(t('Reset token'), 'config', 'token', array('type' => 'webhook'), true) ?>
|
<?= $this->url->link(t('Reset token'), 'config', 'token', array('type' => 'webhook'), true) ?>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><?= $this->url->link(t('My projects'), 'app', 'projects', array('user_id' => $user['id'])) ?> (<?= $paginator->getTotal() ?>)</h2>
|
<h2><?= $this->url->link(t('My projects'), 'DashboardController', 'projects', array('user_id' => $user['id'])) ?> (<?= $paginator->getTotal() ?>)</h2>
|
||||||
</div>
|
</div>
|
||||||
<?php if ($paginator->isEmpty()): ?>
|
<?php if ($paginator->isEmpty()): ?>
|
||||||
<p class="alert"><?= t('Your are not member of any project.') ?></p>
|
<p class="alert"><?= t('Your are not member of any project.') ?></p>
|
||||||
|
|
@ -7,6 +7,6 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?= $this->render('app/projects', array('paginator' => $project_paginator, 'user' => $user)) ?>
|
<?= $this->render('dashboard/projects', array('paginator' => $project_paginator, 'user' => $user)) ?>
|
||||||
<?= $this->render('app/tasks', array('paginator' => $task_paginator, 'user' => $user)) ?>
|
<?= $this->render('dashboard/tasks', array('paginator' => $task_paginator, 'user' => $user)) ?>
|
||||||
<?= $this->render('app/subtasks', array('paginator' => $subtask_paginator, 'user' => $user)) ?>
|
<?= $this->render('dashboard/subtasks', array('paginator' => $subtask_paginator, 'user' => $user)) ?>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<div class="sidebar">
|
||||||
|
<h2><?= $this->text->e($user['name'] ?: $user['username']) ?></h2>
|
||||||
|
<ul>
|
||||||
|
<li <?= $this->app->checkMenuSelection('DashboardController', 'show') ?>>
|
||||||
|
<?= $this->url->link(t('Overview'), 'DashboardController', 'show', array('user_id' => $user['id'])) ?>
|
||||||
|
</li>
|
||||||
|
<li <?= $this->app->checkMenuSelection('DashboardController', 'projects') ?>>
|
||||||
|
<?= $this->url->link(t('My projects'), 'DashboardController', 'projects', array('user_id' => $user['id'])) ?>
|
||||||
|
</li>
|
||||||
|
<li <?= $this->app->checkMenuSelection('DashboardController', 'tasks') ?>>
|
||||||
|
<?= $this->url->link(t('My tasks'), 'DashboardController', 'tasks', array('user_id' => $user['id'])) ?>
|
||||||
|
</li>
|
||||||
|
<li <?= $this->app->checkMenuSelection('DashboardController', 'subtasks') ?>>
|
||||||
|
<?= $this->url->link(t('My subtasks'), 'DashboardController', 'subtasks', array('user_id' => $user['id'])) ?>
|
||||||
|
</li>
|
||||||
|
<li <?= $this->app->checkMenuSelection('DashboardController', 'calendar') ?>>
|
||||||
|
<?= $this->url->link(t('My calendar'), 'DashboardController', 'calendar', array('user_id' => $user['id'])) ?>
|
||||||
|
</li>
|
||||||
|
<li <?= $this->app->checkMenuSelection('DashboardController', 'activity') ?>>
|
||||||
|
<?= $this->url->link(t('My activity stream'), 'DashboardController', 'activity', array('user_id' => $user['id'])) ?>
|
||||||
|
</li>
|
||||||
|
<li <?= $this->app->checkMenuSelection('DashboardController', 'notifications') ?>>
|
||||||
|
<?= $this->url->link(t('My notifications'), 'DashboardController', 'notifications', array('user_id' => $user['id'])) ?>
|
||||||
|
</li>
|
||||||
|
<?= $this->hook->render('template:dashboard:sidebar') ?>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><?= $this->url->link(t('My subtasks'), 'app', 'subtasks', array('user_id' => $user['id'])) ?> (<?= $paginator->getTotal() ?>)</h2>
|
<h2><?= $this->url->link(t('My subtasks'), 'DashboardController', 'subtasks', array('user_id' => $user['id'])) ?> (<?= $paginator->getTotal() ?>)</h2>
|
||||||
</div>
|
</div>
|
||||||
<?php if ($paginator->isEmpty()): ?>
|
<?php if ($paginator->isEmpty()): ?>
|
||||||
<p class="alert"><?= t('There is nothing assigned to you.') ?></p>
|
<p class="alert"><?= t('There is nothing assigned to you.') ?></p>
|
||||||
|
|
@ -40,4 +40,4 @@
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<?= $paginator ?>
|
<?= $paginator ?>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2><?= $this->url->link(t('My tasks'), 'app', 'tasks', array('user_id' => $user['id'])) ?> (<?= $paginator->getTotal() ?>)</h2>
|
<h2><?= $this->url->link(t('My tasks'), 'DashboardController', 'tasks', array('user_id' => $user['id'])) ?> (<?= $paginator->getTotal() ?>)</h2>
|
||||||
</div>
|
</div>
|
||||||
<?php if ($paginator->isEmpty()): ?>
|
<?php if ($paginator->isEmpty()): ?>
|
||||||
<p class="alert"><?= t('There is nothing assigned to you.') ?></p>
|
<p class="alert"><?= t('There is nothing assigned to you.') ?></p>
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<nav>
|
<nav>
|
||||||
<h1>
|
<h1>
|
||||||
<span class="logo">
|
<span class="logo">
|
||||||
<?= $this->url->link('K<span>B</span>', 'app', 'index', array(), false, '', t('Dashboard')) ?>
|
<?= $this->url->link('K<span>B</span>', 'DashboardController', 'show', array(), false, '', t('Dashboard')) ?>
|
||||||
</span>
|
</span>
|
||||||
<span class="title">
|
<span class="title">
|
||||||
<?= $this->text->e($title) ?>
|
<?= $this->text->e($title) ?>
|
||||||
|
|
@ -34,7 +34,7 @@
|
||||||
<li class="user-links">
|
<li class="user-links">
|
||||||
<?php if ($this->user->hasNotifications()): ?>
|
<?php if ($this->user->hasNotifications()): ?>
|
||||||
<span class="notification">
|
<span class="notification">
|
||||||
<?= $this->url->link('<i class="fa fa-bell web-notification-icon"></i>', 'app', 'notifications', array('user_id' => $this->user->getId()), false, '', t('Unread notifications')) ?>
|
<?= $this->url->link('<i class="fa fa-bell web-notification-icon"></i>', 'DashboardController', 'notifications', array('user_id' => $this->user->getId()), false, '', t('Unread notifications')) ?>
|
||||||
</span>
|
</span>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
|
|
@ -63,7 +63,7 @@
|
||||||
<li class="no-hover"><strong><?= $this->text->e($this->user->getFullname()) ?></strong></li>
|
<li class="no-hover"><strong><?= $this->text->e($this->user->getFullname()) ?></strong></li>
|
||||||
<li>
|
<li>
|
||||||
<i class="fa fa-tachometer fa-fw"></i>
|
<i class="fa fa-tachometer fa-fw"></i>
|
||||||
<?= $this->url->link(t('My dashboard'), 'app', 'index', array('user_id' => $this->user->getId())) ?>
|
<?= $this->url->link(t('My dashboard'), 'DashboardController', 'show', array('user_id' => $this->user->getId())) ?>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<i class="fa fa-home fa-fw"></i>
|
<i class="fa fa-home fa-fw"></i>
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue