summaryrefslogtreecommitdiff
path: root/app/Controller/Base.php
diff options
context:
space:
mode:
Diffstat (limited to 'app/Controller/Base.php')
-rw-r--r--app/Controller/Base.php263
1 files changed, 115 insertions, 148 deletions
diff --git a/app/Controller/Base.php b/app/Controller/Base.php
index a8e22fd8..fcd07b99 100644
--- a/app/Controller/Base.php
+++ b/app/Controller/Base.php
@@ -2,166 +2,171 @@
namespace Controller;
-use Core\Tool;
-use Core\Registry;
+use Pimple\Container;
use Core\Security;
+use Core\Request;
+use Core\Response;
+use Core\Template;
+use Core\Session;
use Model\LastLogin;
+use Symfony\Component\EventDispatcher\Event;
/**
* Base controller
*
* @package controller
* @author Frederic Guillot
- *
- * @property \Model\Acl $acl
- * @property \Model\Authentication $authentication
- * @property \Model\Action $action
- * @property \Model\Board $board
- * @property \Model\Category $category
- * @property \Model\Color $color
- * @property \Model\Comment $comment
- * @property \Model\Config $config
- * @property \Model\File $file
- * @property \Model\LastLogin $lastLogin
- * @property \Model\Notification $notification
- * @property \Model\Project $project
- * @property \Model\ProjectPermission $projectPermission
- * @property \Model\SubTask $subTask
- * @property \Model\Task $task
- * @property \Model\TaskHistory $taskHistory
- * @property \Model\TaskExport $taskExport
- * @property \Model\TaskFinder $taskFinder
- * @property \Model\TaskPermission $taskPermission
- * @property \Model\TaskValidator $taskValidator
- * @property \Model\CommentHistory $commentHistory
- * @property \Model\SubtaskHistory $subtaskHistory
- * @property \Model\TimeTracking $timeTracking
- * @property \Model\User $user
- * @property \Model\Webhook $webhook
*/
-abstract class Base
+abstract class Base extends \Core\Base
{
/**
* Request instance
*
- * @accesss public
+ * @accesss protected
* @var \Core\Request
*/
- public $request;
+ protected $request;
/**
* Response instance
*
- * @accesss public
+ * @accesss protected
* @var \Core\Response
*/
- public $response;
-
- /**
- * Template instance
- *
- * @accesss public
- * @var \Core\Template
- */
- public $template;
-
- /**
- * Session instance
- *
- * @accesss public
- * @var \Core\Session
- */
- public $session;
-
- /**
- * Registry instance
- *
- * @access private
- * @var \Core\Registry
- */
- private $registry;
+ protected $response;
/**
* Constructor
*
* @access public
- * @param \Core\Registry $registry Registry instance
+ * @param \Pimple\Container $container
*/
- public function __construct(Registry $registry)
+ public function __construct(Container $container)
{
- $this->registry = $registry;
+ $this->container = $container;
+ $this->request = new Request;
+ $this->response = new Response;
+
+ if (DEBUG) {
+ $this->container['logger']->debug('START_REQUEST='.$_SERVER['REQUEST_URI']);
+ }
}
/**
- * Load automatically models
+ * Destructor
*
* @access public
- * @param string $name Model name
- * @return mixed
*/
- public function __get($name)
+ public function __destruct()
{
- return Tool::loadModel($this->registry, $name);
+ if (DEBUG) {
+
+ foreach ($this->container['db']->getLogMessages() as $message) {
+ $this->container['logger']->debug($message);
+ }
+
+ $this->container['logger']->debug('SQL_QUERIES={nb}', array('nb' => $this->container['db']->nb_queries));
+ $this->container['logger']->debug('RENDERING={time}', array('time' => microtime(true) - @$_SERVER['REQUEST_TIME_FLOAT']));
+ $this->container['logger']->debug('END_REQUEST='.$_SERVER['REQUEST_URI']);
+ }
}
/**
- * Method executed before each action
+ * Send HTTP headers
*
- * @access public
+ * @access private
*/
- public function beforeAction($controller, $action)
+ private function sendHeaders($action)
{
- // Start the session
- $this->session->open(BASE_URL_DIRECTORY, SESSION_SAVE_PATH);
-
// HTTP secure headers
- $this->response->csp(array('style-src' => "'self' 'unsafe-inline'"));
+ $this->response->csp(array('style-src' => "'self' 'unsafe-inline'", 'img-src' => '*'));
$this->response->nosniff();
$this->response->xss();
// Allow the public board iframe inclusion
- if ($action !== 'readonly') {
+ if (ENABLE_XFRAME && $action !== 'readonly') {
$this->response->xframe();
}
if (ENABLE_HSTS) {
$this->response->hsts();
}
+ }
+
+ /**
+ * Method executed before each action
+ *
+ * @access public
+ */
+ public function beforeAction($controller, $action)
+ {
+ // Start the session
+ $this->session->open(BASE_URL_DIRECTORY);
+ $this->sendHeaders($action);
+ $this->container['dispatcher']->dispatch('session.bootstrap', new Event);
- $this->config->setupTranslations();
- $this->config->setupTimezone();
+ if (! $this->acl->isPublicAction($controller, $action)) {
+ $this->handleAuthentication();
+ $this->handle2FA($controller, $action);
+ $this->handleAuthorization($controller, $action);
- // Authentication
- if (! $this->authentication->isAuthenticated($controller, $action)) {
- $this->response->redirect('?controller=user&action=login&redirect_query='.urlencode($this->request->getQueryString()));
+ $this->session['has_subtask_inprogress'] = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
}
+ }
- // Check if the user is allowed to see this page
- if (! $this->acl->isPageAccessAllowed($controller, $action)) {
- $this->response->redirect('?controller=user&action=forbidden');
+ /**
+ * Check authentication
+ *
+ * @access public
+ */
+ public function handleAuthentication()
+ {
+ if (! $this->authentication->isAuthenticated()) {
+
+ if ($this->request->isAjax()) {
+ $this->response->text('Not Authorized', 401);
+ }
+
+ $this->response->redirect($this->helper->url->to('auth', 'login', array('redirect_query' => urlencode($this->request->getQueryString()))));
}
+ }
- // Attach events
- $this->attachEvents();
+ /**
+ * Check 2FA
+ *
+ * @access public
+ */
+ public function handle2FA($controller, $action)
+ {
+ $ignore = ($controller === 'twofactor' && in_array($action, array('code', 'check'))) || ($controller === 'auth' && $action === 'logout');
+
+ if ($ignore === false && $this->userSession->has2FA() && ! $this->userSession->check2FA()) {
+
+ if ($this->request->isAjax()) {
+ $this->response->text('Not Authorized', 401);
+ }
+
+ $this->response->redirect($this->helper->url->to('twofactor', 'code'));
+ }
}
/**
- * Attach events
+ * Check page access and authorization
*
- * @access private
+ * @access public
*/
- private function attachEvents()
+ public function handleAuthorization($controller, $action)
{
- $models = array(
- 'projectActivity', // Order is important
- 'action',
- 'project',
- 'webhook',
- 'notification',
- );
-
- foreach ($models as $model) {
- $this->$model->attachEvents();
+ $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 (! $this->acl->isAllowed($controller, $action, $project_id)) {
+ $this->forbidden();
}
}
@@ -173,7 +178,7 @@ abstract class Base
*/
public function notfound($no_layout = false)
{
- $this->response->html($this->template->layout('app_notfound', array(
+ $this->response->html($this->template->layout('app/notfound', array(
'title' => t('Page not found'),
'no_layout' => $no_layout,
)));
@@ -187,7 +192,7 @@ abstract class Base
*/
public function forbidden($no_layout = false)
{
- $this->response->html($this->template->layout('app_forbidden', array(
+ $this->response->html($this->template->layout('app/forbidden', array(
'title' => t('Access Forbidden'),
'no_layout' => $no_layout,
)));
@@ -206,19 +211,6 @@ abstract class Base
}
/**
- * Check if the current user have access to the given project
- *
- * @access protected
- * @param integer $project_id Project id
- */
- protected function checkProjectPermissions($project_id)
- {
- if ($this->acl->isRegularUser() && ! $this->projectPermission->isUserAllowed($project_id, $this->acl->getUserId())) {
- $this->forbidden();
- }
- }
-
- /**
* Redirection when there is no project in the database
*
* @access protected
@@ -239,14 +231,12 @@ abstract class Base
*/
protected function taskLayout($template, array $params)
{
- if (isset($params['task']) && $this->taskPermission->canRemoveTask($params['task']) === false) {
- $params['hide_remove_menu'] = true;
- }
-
- $content = $this->template->load($template, $params);
+ $content = $this->template->render($template, $params);
$params['task_content_for_layout'] = $content;
+ $params['title'] = $params['task']['project_name'].' > '.$params['task']['title'];
+ $params['board_selector'] = $this->projectPermission->getAllowedProjects($this->userSession->getId());
- return $this->template->layout('task_layout', $params);
+ return $this->template->layout('task/layout', $params);
}
/**
@@ -257,13 +247,15 @@ abstract class Base
* @param array $params Template parameters
* @return string
*/
- protected function projectLayout($template, array $params)
+ protected function projectLayout($template, array $params, $sidebar_template = 'project/sidebar')
{
- $content = $this->template->load($template, $params);
+ $content = $this->template->render($template, $params);
$params['project_content_for_layout'] = $content;
- $params['menu'] = 'projects';
+ $params['title'] = $params['project']['name'] === $params['title'] ? $params['title'] : $params['project']['name'].' > '.$params['title'];
+ $params['board_selector'] = $this->projectPermission->getAllowedProjects($this->userSession->getId());
+ $params['sidebar_template'] = $sidebar_template;
- return $this->template->layout('project_layout', $params);
+ return $this->template->layout('project/layout', $params);
}
/**
@@ -276,12 +268,10 @@ abstract class Base
{
$task = $this->taskFinder->getDetails($this->request->getIntegerParam('task_id'));
- if (! $task) {
+ if (empty($task)) {
$this->notfound();
}
- $this->checkProjectPermissions($task['project_id']);
-
return $task;
}
@@ -297,34 +287,11 @@ abstract class Base
$project_id = $this->request->getIntegerParam('project_id', $project_id);
$project = $this->project->getById($project_id);
- if (! $project) {
+ if (empty($project)) {
$this->session->flashError(t('Project not found.'));
$this->response->redirect('?controller=project');
}
- $this->checkProjectPermissions($project['id']);
-
- return $project;
- }
-
- /**
- * Common method to get a project with administration rights
- *
- * @access protected
- * @return array
- */
- protected function getProjectManagement()
- {
- $project = $this->project->getById($this->request->getIntegerParam('project_id'));
-
- if (! $project) {
- $this->notfound();
- }
-
- if ($this->acl->isRegularUser() && ! $this->projectPermission->adminAllowed($project['id'], $this->acl->getUserId())) {
- $this->forbidden();
- }
-
return $project;
}
}