mirror of
https://github.com/YunoHost-Apps/kanboard_ynh.git
synced 2024-09-03 19:36:17 +02:00
Update to v1.0.21
This commit is contained in:
parent
ebc752ab9d
commit
04e1e77a7a
121 changed files with 2487 additions and 947 deletions
|
@ -33,7 +33,7 @@ From command line:
|
||||||
|
|
||||||
Infos
|
Infos
|
||||||
-----
|
-----
|
||||||
Kanboard v1.0.19
|
Kanboard v1.0.21
|
||||||
|
|
||||||
Yunohost forum thread: <https://forum.yunohost.org/t/kanboard-package/78>
|
Yunohost forum thread: <https://forum.yunohost.org/t/kanboard-package/78>
|
||||||
|
|
||||||
|
@ -42,8 +42,8 @@ Kanboard and SSOwat
|
||||||
Kanboard use SSOwat for user authentification (it means it use the user that the web server (nginx) sent him throught SSOwat), but can't list all user of the system.
|
Kanboard use SSOwat for user authentification (it means it use the user that the web server (nginx) sent him throught SSOwat), but can't list all user of the system.
|
||||||
If you wish to add a user, just log in with that user into Kanboard so the software knows him and displays it.
|
If you wish to add a user, just log in with that user into Kanboard so the software knows him and displays it.
|
||||||
|
|
||||||
Dev infos
|
Developper infos
|
||||||
---------
|
----------------
|
||||||
|
|
||||||
Update package:
|
Update package:
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
define('DEBUG', false);
|
define('DEBUG', false);
|
||||||
|
|
||||||
// Debug file path
|
// Debug file path
|
||||||
define('DEBUG_FILE', __DIR__.'/data/debug.log');
|
define('DEBUG_FILE', __DIR__.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'debug.log');
|
||||||
|
|
||||||
// Plugins directory
|
// Plugins directory
|
||||||
define('PLUGINS_DIR', 'data/plugins');
|
define('PLUGINS_DIR', 'plugins');
|
||||||
|
|
||||||
// Folder for uploaded files, don't forget the trailing slash
|
// Folder for uploaded files
|
||||||
define('FILES_DIR', 'data/files/');
|
define('FILES_DIR', 'data'.DIRECTORY_SEPARATOR.'files');
|
||||||
|
|
||||||
// E-mail address for the "From" header (notifications)
|
// E-mail address for the "From" header (notifications)
|
||||||
define('MAIL_FROM', 'yuno_email');
|
define('MAIL_FROM', 'yuno_email');
|
||||||
|
@ -146,7 +146,7 @@ define('GITHUB_OAUTH_AUTHORIZE_URL', 'https://github.com/login/oauth/authorize')
|
||||||
// Github oauth2 token url
|
// Github oauth2 token url
|
||||||
define('GITHUB_OAUTH_TOKEN_URL', 'https://github.com/login/oauth/access_token');
|
define('GITHUB_OAUTH_TOKEN_URL', 'https://github.com/login/oauth/access_token');
|
||||||
|
|
||||||
// Github API url (don't forget the slash at the end)
|
// Github API url (don't forget the trailing slash)
|
||||||
define('GITHUB_API_URL', 'https://api.github.com/');
|
define('GITHUB_API_URL', 'https://api.github.com/');
|
||||||
|
|
||||||
// Enable/disable Gitlab authentication
|
// Enable/disable Gitlab authentication
|
||||||
|
@ -164,7 +164,7 @@ define('GITLAB_OAUTH_AUTHORIZE_URL', 'https://gitlab.com/oauth/authorize');
|
||||||
// Gitlab oauth2 token url
|
// Gitlab oauth2 token url
|
||||||
define('GITLAB_OAUTH_TOKEN_URL', 'https://gitlab.com/oauth/token');
|
define('GITLAB_OAUTH_TOKEN_URL', 'https://gitlab.com/oauth/token');
|
||||||
|
|
||||||
// Gitlab API url endpoint (don't forget the slash at the end)
|
// Gitlab API url endpoint (don't forget the trailing slash)
|
||||||
define('GITLAB_API_URL', 'https://gitlab.com/api/v3/');
|
define('GITLAB_API_URL', 'https://gitlab.com/api/v3/');
|
||||||
|
|
||||||
// Enable/disable the reverse proxy authentication
|
// Enable/disable the reverse proxy authentication
|
||||||
|
|
|
@ -1,11 +1,50 @@
|
||||||
|
Version 1.0.21
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Breaking changes:
|
||||||
|
|
||||||
|
* Projects with duplicate name are now allowed:
|
||||||
|
For Postgres and Mysql the unique constraint is removed by database migration
|
||||||
|
However Sqlite does not support alter table, only new databases will have the unique constraint removed
|
||||||
|
|
||||||
|
New features:
|
||||||
|
|
||||||
|
* New automatic action: Assign a category based on a link
|
||||||
|
* Added Bosnian translation
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
|
||||||
|
* Dropdown menu entry are now clickable outside of the html link
|
||||||
|
* Improve error handling of plugins
|
||||||
|
* Use PHP7 function random_bytes() to generate tokens if available
|
||||||
|
* CSV task export show the assignee name in addition to the assignee username
|
||||||
|
* Add new hooks for plugins
|
||||||
|
* Remove workaround for "INSERT ON DUPLICATE KEY UPDATE..."
|
||||||
|
|
||||||
|
Internal code refactoring:
|
||||||
|
|
||||||
|
* Rewrite of session management
|
||||||
|
* Move some classes to a new namespace Kanboard\Core\Http
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* Loading cs_CZ locale display the wrong language in datetime picker
|
||||||
|
* Datepicker is closed unexpectedly on blur event
|
||||||
|
* Fix bug in daily project summary CSV export
|
||||||
|
* Fix PHP error when adding a new user with email notification enabled
|
||||||
|
* Add missing template for activity stream to show event "file.create"
|
||||||
|
* Fix wrong value for PLUGINS_DIR in config.default.php
|
||||||
|
* Make CSV export compatible with PHP 5.3
|
||||||
|
* Avoid Safari to append .html at the end of downloaded files
|
||||||
|
|
||||||
Version 1.0.20
|
Version 1.0.20
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
Breaking changes:
|
Breaking changes:
|
||||||
|
|
||||||
- Add namespace Kanboard (update your plugins)
|
* Add namespace Kanboard (update your plugins)
|
||||||
- Move Mailgun, Sendgrid, Postmark, Slack, Hipchat and Jabber to plugins
|
* Move Mailgun, Sendgrid, Postmark, Slack, Hipchat and Jabber to plugins
|
||||||
- ReverseProxy authentication check for each request that the username match the user session
|
* ReverseProxy authentication check for each request that the username match the user session
|
||||||
|
|
||||||
New features:
|
New features:
|
||||||
|
|
||||||
|
|
|
@ -241,7 +241,7 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
$this->container['logger']->debug(get_called_class().' => '.($result ? 'true' : 'false'));
|
$this->logger->debug(get_called_class().' => '.($result ? 'true' : 'false'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
|
90
sources/app/Action/TaskAssignCategoryLink.php
Normal file
90
sources/app/Action/TaskAssignCategoryLink.php
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Action;
|
||||||
|
|
||||||
|
use Kanboard\Model\TaskLink;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a category automatically according to a task link
|
||||||
|
*
|
||||||
|
* @package action
|
||||||
|
* @author Olivier Maridat
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class TaskAssignCategoryLink extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the list of compatible events
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getCompatibleEvents()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
TaskLink::EVENT_CREATE_UPDATE,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the required parameter for the action (defined by the user)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getActionRequiredParameters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'category_id' => t('Category'),
|
||||||
|
'link_id' => t('Link type'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the required parameter for the event
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
public function getEventRequiredParameters()
|
||||||
|
{
|
||||||
|
return array(
|
||||||
|
'task_id',
|
||||||
|
'link_id',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the action (change the category)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Event data dictionary
|
||||||
|
* @return bool True if the action was executed or false when not executed
|
||||||
|
*/
|
||||||
|
public function doAction(array $data)
|
||||||
|
{
|
||||||
|
$values = array(
|
||||||
|
'id' => $data['task_id'],
|
||||||
|
'category_id' => isset($data['category_id']) ? $data['category_id'] : $this->getParam('category_id'),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->taskModification->update($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the event data meet the action condition
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $data Event data dictionary
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function hasRequiredCondition(array $data)
|
||||||
|
{
|
||||||
|
if ($data['link_id'] == $this->getParam('link_id')) {
|
||||||
|
$task = $this->taskFinder->getById($data['task_id']);
|
||||||
|
return empty($task['category_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ class Auth extends Base
|
||||||
|
|
||||||
if ($username !== 'jsonrpc' && ! $this->authentication->hasCaptcha($username) && $this->authentication->authenticate($username, $password)) {
|
if ($username !== 'jsonrpc' && ! $this->authentication->hasCaptcha($username) && $this->authentication->authenticate($username, $password)) {
|
||||||
$this->checkProcedurePermission(true, $method);
|
$this->checkProcedurePermission(true, $method);
|
||||||
$this->userSession->refresh($this->user->getByUsername($username));
|
$this->userSession->initialize($this->user->getByUsername($username));
|
||||||
} elseif ($username === 'jsonrpc' && $password === $this->config->get('api_token')) {
|
} elseif ($username === 'jsonrpc' && $password === $this->config->get('api_token')) {
|
||||||
$this->checkProcedurePermission(false, $method);
|
$this->checkProcedurePermission(false, $method);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Me extends Base
|
||||||
{
|
{
|
||||||
public function getMe()
|
public function getMe()
|
||||||
{
|
{
|
||||||
return $this->session['user'];
|
return $this->sessionStorage->user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMyDashboard()
|
public function getMyDashboard()
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Database extends Base
|
||||||
->findOne();
|
->findOne();
|
||||||
|
|
||||||
if (is_array($user) && password_verify($password, $user['password'])) {
|
if (is_array($user) && password_verify($password, $user['password'])) {
|
||||||
$this->userSession->refresh($user);
|
$this->userSession->initialize($user);
|
||||||
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Github extends Base
|
||||||
$user = $this->user->getByGithubId($github_id);
|
$user = $this->user->getByGithubId($github_id);
|
||||||
|
|
||||||
if (! empty($user)) {
|
if (! empty($user)) {
|
||||||
$this->userSession->refresh($user);
|
$this->userSession->initialize($user);
|
||||||
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ class Gitlab extends Base
|
||||||
$user = $this->user->getByGitlabId($gitlab_id);
|
$user = $this->user->getByGitlabId($gitlab_id);
|
||||||
|
|
||||||
if (! empty($user)) {
|
if (! empty($user)) {
|
||||||
$this->userSession->refresh($user);
|
$this->userSession->initialize($user);
|
||||||
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ class Google extends Base
|
||||||
$user = $this->user->getByGoogleId($google_id);
|
$user = $this->user->getByGoogleId($google_id);
|
||||||
|
|
||||||
if (! empty($user)) {
|
if (! empty($user)) {
|
||||||
$this->userSession->refresh($user);
|
$this->userSession->initialize($user);
|
||||||
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,7 +237,7 @@ class Ldap extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
// We open the session
|
// We open the session
|
||||||
$this->userSession->refresh($user);
|
$this->userSession->initialize($user);
|
||||||
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
namespace Kanboard\Auth;
|
namespace Kanboard\Auth;
|
||||||
|
|
||||||
use Kanboard\Core\Base;
|
use Kanboard\Core\Base;
|
||||||
use Kanboard\Core\Request;
|
use Kanboard\Core\Http\Request;
|
||||||
use Kanboard\Event\AuthEvent;
|
use Kanboard\Event\AuthEvent;
|
||||||
use Kanboard\Core\Security;
|
use Kanboard\Core\Security\Token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RememberMe model
|
* RememberMe model
|
||||||
|
@ -101,10 +101,10 @@ class RememberMe extends Base
|
||||||
);
|
);
|
||||||
|
|
||||||
// Create the session
|
// Create the session
|
||||||
$this->userSession->refresh($this->user->getById($record['user_id']));
|
$this->userSession->initialize($this->user->getById($record['user_id']));
|
||||||
|
|
||||||
// Do not ask 2FA for remember me session
|
// Do not ask 2FA for remember me session
|
||||||
$this->session['2fa_validated'] = true;
|
$this->sessionStorage->postAuth['validated'] = true;
|
||||||
|
|
||||||
$this->container['dispatcher']->dispatch(
|
$this->container['dispatcher']->dispatch(
|
||||||
'auth.success',
|
'auth.success',
|
||||||
|
@ -165,8 +165,8 @@ class RememberMe extends Base
|
||||||
*/
|
*/
|
||||||
public function create($user_id, $ip, $user_agent)
|
public function create($user_id, $ip, $user_agent)
|
||||||
{
|
{
|
||||||
$token = hash('sha256', $user_id.$user_agent.$ip.Security::generateToken());
|
$token = hash('sha256', $user_id.$user_agent.$ip.Token::getToken());
|
||||||
$sequence = Security::generateToken();
|
$sequence = Token::getToken();
|
||||||
$expiration = time() + self::EXPIRATION;
|
$expiration = time() + self::EXPIRATION;
|
||||||
|
|
||||||
$this->cleanup($user_id);
|
$this->cleanup($user_id);
|
||||||
|
@ -216,7 +216,7 @@ class RememberMe extends Base
|
||||||
*/
|
*/
|
||||||
public function update($token)
|
public function update($token)
|
||||||
{
|
{
|
||||||
$new_sequence = Security::generateToken();
|
$new_sequence = Token::getToken();
|
||||||
|
|
||||||
$this->db
|
$this->db
|
||||||
->table(self::TABLE)
|
->table(self::TABLE)
|
||||||
|
|
|
@ -48,7 +48,7 @@ class ReverseProxy extends Base
|
||||||
$user = $this->user->getByUsername($login);
|
$user = $this->user->getByUsername($login);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->userSession->refresh($user);
|
$this->userSession->initialize($user);
|
||||||
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
$this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -119,9 +119,9 @@ class Action extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->action->create($values) !== false) {
|
if ($this->action->create($values) !== false) {
|
||||||
$this->session->flash(t('Your automatic action have been created successfully.'));
|
$this->flash->success(t('Your automatic action have been created successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create your automatic action.'));
|
$this->flash->failure(t('Unable to create your automatic action.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,9 +158,9 @@ class Action extends Base
|
||||||
$action = $this->action->getById($this->request->getIntegerParam('action_id'));
|
$action = $this->action->getById($this->request->getIntegerParam('action_id'));
|
||||||
|
|
||||||
if (! empty($action) && $this->action->remove($action['id'])) {
|
if (! empty($action) && $this->action->remove($action['id'])) {
|
||||||
$this->session->flash(t('Action removed successfully.'));
|
$this->flash->success(t('Action removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this action.'));
|
$this->flash->failure(t('Unable to remove this action.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('action', 'index', array('project_id' => $project['id'])));
|
||||||
|
|
|
@ -43,9 +43,11 @@ class Auth extends Base
|
||||||
list($valid, $errors) = $this->authentication->validateForm($values);
|
list($valid, $errors) = $this->authentication->validateForm($values);
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if (! empty($this->session['login_redirect']) && ! filter_var($this->session['login_redirect'], FILTER_VALIDATE_URL)) {
|
if (isset($this->sessionStorage->redirectAfterLogin)
|
||||||
$redirect = $this->session['login_redirect'];
|
&& ! empty($this->sessionStorage->redirectAfterLogin)
|
||||||
unset($this->session['login_redirect']);
|
&& ! filter_var($this->sessionStorage->redirectAfterLogin, FILTER_VALIDATE_URL)) {
|
||||||
|
$redirect = $this->sessionStorage->redirectAfterLogin;
|
||||||
|
unset($this->sessionStorage->redirectAfterLogin);
|
||||||
$this->response->redirect($redirect);
|
$this->response->redirect($redirect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +65,7 @@ class Auth extends Base
|
||||||
public function logout()
|
public function logout()
|
||||||
{
|
{
|
||||||
$this->authentication->backend('rememberMe')->destroy($this->userSession->getId());
|
$this->authentication->backend('rememberMe')->destroy($this->userSession->getId());
|
||||||
$this->session->close();
|
$this->sessionManager->close();
|
||||||
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +80,7 @@ class Auth extends Base
|
||||||
|
|
||||||
$builder = new CaptchaBuilder;
|
$builder = new CaptchaBuilder;
|
||||||
$builder->build();
|
$builder->build();
|
||||||
$this->session['captcha'] = $builder->getPhrase();
|
$this->sessionStorage->captcha = $builder->getPhrase();
|
||||||
$builder->output();
|
$builder->output();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
use Pimple\Container;
|
use Pimple\Container;
|
||||||
use Kanboard\Core\Security;
|
|
||||||
use Kanboard\Core\Request;
|
|
||||||
use Kanboard\Core\Response;
|
|
||||||
use Symfony\Component\EventDispatcher\Event;
|
use Symfony\Component\EventDispatcher\Event;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -16,22 +13,6 @@ use Symfony\Component\EventDispatcher\Event;
|
||||||
*/
|
*/
|
||||||
abstract class Base extends \Kanboard\Core\Base
|
abstract class Base extends \Kanboard\Core\Base
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Request instance
|
|
||||||
*
|
|
||||||
* @accesss protected
|
|
||||||
* @var \Kanboard\Core\Request
|
|
||||||
*/
|
|
||||||
protected $request;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response instance
|
|
||||||
*
|
|
||||||
* @accesss protected
|
|
||||||
* @var \Kanboard\Core\Response
|
|
||||||
*/
|
|
||||||
protected $response;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
@ -41,11 +22,9 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
public function __construct(Container $container)
|
public function __construct(Container $container)
|
||||||
{
|
{
|
||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
$this->request = new Request;
|
|
||||||
$this->response = new Response;
|
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
$this->container['logger']->debug('START_REQUEST='.$_SERVER['REQUEST_URI']);
|
$this->logger->debug('START_REQUEST='.$_SERVER['REQUEST_URI']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,14 +36,14 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
public function __destruct()
|
public function __destruct()
|
||||||
{
|
{
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
foreach ($this->container['db']->getLogMessages() as $message) {
|
foreach ($this->db->getLogMessages() as $message) {
|
||||||
$this->container['logger']->debug($message);
|
$this->logger->debug($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->container['logger']->debug('SQL_QUERIES={nb}', array('nb' => $this->container['db']->nbQueries));
|
$this->logger->debug('SQL_QUERIES={nb}', array('nb' => $this->container['db']->nbQueries));
|
||||||
$this->container['logger']->debug('RENDERING={time}', array('time' => microtime(true) - @$_SERVER['REQUEST_TIME_FLOAT']));
|
$this->logger->debug('RENDERING={time}', array('time' => microtime(true) - @$_SERVER['REQUEST_TIME_FLOAT']));
|
||||||
$this->container['logger']->debug('MEMORY='.$this->helper->text->bytes(memory_get_usage()));
|
$this->logger->debug('MEMORY='.$this->helper->text->bytes(memory_get_usage()));
|
||||||
$this->container['logger']->debug('END_REQUEST='.$_SERVER['REQUEST_URI']);
|
$this->logger->debug('END_REQUEST='.$_SERVER['REQUEST_URI']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,8 +76,7 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
*/
|
*/
|
||||||
public function beforeAction($controller, $action)
|
public function beforeAction($controller, $action)
|
||||||
{
|
{
|
||||||
// Start the session
|
$this->sessionManager->open();
|
||||||
$this->session->open($this->helper->url->dir());
|
|
||||||
$this->sendHeaders($action);
|
$this->sendHeaders($action);
|
||||||
$this->container['dispatcher']->dispatch('session.bootstrap', new Event);
|
$this->container['dispatcher']->dispatch('session.bootstrap', new Event);
|
||||||
|
|
||||||
|
@ -107,7 +85,7 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
$this->handle2FA($controller, $action);
|
$this->handle2FA($controller, $action);
|
||||||
$this->handleAuthorization($controller, $action);
|
$this->handleAuthorization($controller, $action);
|
||||||
|
|
||||||
$this->session['has_subtask_inprogress'] = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
|
$this->sessionStorage->hasSubtaskInProgress = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +101,7 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
$this->response->text('Not Authorized', 401);
|
$this->response->text('Not Authorized', 401);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->session['login_redirect'] = $this->request->getUri();
|
$this->sessionStorage->redirectAfterLogin = $this->request->getUri();
|
||||||
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
$this->response->redirect($this->helper->url->to('auth', 'login'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,7 +179,7 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
*/
|
*/
|
||||||
protected function checkCSRFParam()
|
protected function checkCSRFParam()
|
||||||
{
|
{
|
||||||
if (! Security::validateCSRFToken($this->request->getStringParam('csrf_token'))) {
|
if (! $this->token->validateCSRFToken($this->request->getStringParam('csrf_token'))) {
|
||||||
$this->forbidden();
|
$this->forbidden();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,7 +268,7 @@ abstract class Base extends \Kanboard\Core\Base
|
||||||
$project = $this->project->getById($project_id);
|
$project = $this->project->getById($project_id);
|
||||||
|
|
||||||
if (empty($project)) {
|
if (empty($project)) {
|
||||||
$this->session->flashError(t('Project not found.'));
|
$this->flash->failure(t('Project not found.'));
|
||||||
$this->response->redirect($this->helper->url->to('project', 'index'));
|
$this->response->redirect($this->helper->url->to('project', 'index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -242,9 +242,9 @@ class Board extends Base
|
||||||
list($valid, ) = $this->taskValidator->validateAssigneeModification($values);
|
list($valid, ) = $this->taskValidator->validateAssigneeModification($values);
|
||||||
|
|
||||||
if ($valid && $this->taskModification->update($values)) {
|
if ($valid && $this->taskModification->update($values)) {
|
||||||
$this->session->flash(t('Task updated successfully.'));
|
$this->flash->success(t('Task updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update your task.'));
|
$this->flash->failure(t('Unable to update your task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id'])));
|
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id'])));
|
||||||
|
@ -279,9 +279,9 @@ class Board extends Base
|
||||||
list($valid, ) = $this->taskValidator->validateCategoryModification($values);
|
list($valid, ) = $this->taskValidator->validateCategoryModification($values);
|
||||||
|
|
||||||
if ($valid && $this->taskModification->update($values)) {
|
if ($valid && $this->taskModification->update($values)) {
|
||||||
$this->session->flash(t('Task updated successfully.'));
|
$this->flash->success(t('Task updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update your task.'));
|
$this->flash->failure(t('Unable to update your task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id'])));
|
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $values['project_id'])));
|
||||||
|
|
|
@ -22,7 +22,7 @@ class Category extends Base
|
||||||
$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->session->flashError(t('Category not found.'));
|
$this->flash->failure(t('Category not found.'));
|
||||||
$this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project_id)));
|
$this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,10 +61,10 @@ class Category extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->category->create($values)) {
|
if ($this->category->create($values)) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create your category.'));
|
$this->flash->failure(t('Unable to create your category.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,10 +103,10 @@ class Category extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->category->update($values)) {
|
if ($this->category->update($values)) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update your category.'));
|
$this->flash->failure(t('Unable to update your category.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,9 +142,9 @@ class Category extends Base
|
||||||
$category = $this->getCategory($project['id']);
|
$category = $this->getCategory($project['id']);
|
||||||
|
|
||||||
if ($this->category->remove($category['id'])) {
|
if ($this->category->remove($category['id'])) {
|
||||||
$this->session->flash(t('Category removed successfully.'));
|
$this->flash->success(t('Category removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this category.'));
|
$this->flash->failure(t('Unable to remove this category.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('category', 'index', array('project_id' => $project['id'])));
|
||||||
|
|
|
@ -55,10 +55,10 @@ class Column extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->board->addColumn($project['id'], $data['title'], $data['task_limit'], $data['description'])) {
|
if ($this->board->addColumn($project['id'], $data['title'], $data['task_limit'], $data['description'])) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this board.'));
|
$this->flash->failure(t('Unable to update this board.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,10 +98,10 @@ class Column extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->board->updateColumn($values['id'], $values['title'], $values['task_limit'], $values['description'])) {
|
if ($this->board->updateColumn($values['id'], $values['title'], $values['task_limit'], $values['description'])) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this board.'));
|
$this->flash->failure(t('Unable to update this board.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,9 +155,9 @@ class Column extends Base
|
||||||
$column = $this->board->getColumn($this->request->getIntegerParam('column_id'));
|
$column = $this->board->getColumn($this->request->getIntegerParam('column_id'));
|
||||||
|
|
||||||
if (! empty($column) && $this->board->removeColumn($column['id'])) {
|
if (! empty($column) && $this->board->removeColumn($column['id'])) {
|
||||||
$this->session->flash(t('Column removed successfully.'));
|
$this->flash->success(t('Column removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this column.'));
|
$this->flash->failure(t('Unable to remove this column.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('column', 'index', array('project_id' => $project['id'])));
|
||||||
|
|
|
@ -82,9 +82,9 @@ class Comment extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->comment->create($values)) {
|
if ($this->comment->create($values)) {
|
||||||
$this->session->flash(t('Comment added successfully.'));
|
$this->flash->success(t('Comment added successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create your comment.'));
|
$this->flash->failure(t('Unable to create your comment.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ajax) {
|
if ($ajax) {
|
||||||
|
@ -131,9 +131,9 @@ class Comment extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->comment->update($values)) {
|
if ($this->comment->update($values)) {
|
||||||
$this->session->flash(t('Comment updated successfully.'));
|
$this->flash->success(t('Comment updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update your comment.'));
|
$this->flash->failure(t('Unable to update your comment.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comment-'.$comment['id']));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comment-'.$comment['id']));
|
||||||
|
@ -171,9 +171,9 @@ class Comment extends Base
|
||||||
$comment = $this->getComment();
|
$comment = $this->getComment();
|
||||||
|
|
||||||
if ($this->comment->remove($comment['id'])) {
|
if ($this->comment->remove($comment['id'])) {
|
||||||
$this->session->flash(t('Comment removed successfully.'));
|
$this->flash->success(t('Comment removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this comment.'));
|
$this->flash->failure(t('Unable to remove this comment.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id']), 'comments'));
|
||||||
|
|
|
@ -53,9 +53,9 @@ class Config extends Base
|
||||||
|
|
||||||
if ($this->config->save($values)) {
|
if ($this->config->save($values)) {
|
||||||
$this->config->reload();
|
$this->config->reload();
|
||||||
$this->session->flash(t('Settings saved successfully.'));
|
$this->flash->success(t('Settings saved successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to save your settings.'));
|
$this->flash->failure(t('Unable to save your settings.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('config', $redirect));
|
$this->response->redirect($this->helper->url->to('config', $redirect));
|
||||||
|
@ -210,7 +210,7 @@ class Config extends Base
|
||||||
{
|
{
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
$this->config->optimizeDatabase();
|
$this->config->optimizeDatabase();
|
||||||
$this->session->flash(t('Database optimization done.'));
|
$this->flash->success(t('Database optimization done.'));
|
||||||
$this->response->redirect($this->helper->url->to('config', 'index'));
|
$this->response->redirect($this->helper->url->to('config', 'index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,7 +226,7 @@ class Config extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
$this->config->regenerateToken($type.'_token');
|
$this->config->regenerateToken($type.'_token');
|
||||||
|
|
||||||
$this->session->flash(t('Token regenerated.'));
|
$this->flash->success(t('Token regenerated.'));
|
||||||
$this->response->redirect($this->helper->url->to('config', $type));
|
$this->response->redirect($this->helper->url->to('config', $type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,10 +55,10 @@ 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->session->flash(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'));
|
$this->response->redirect($this->helper->url->to('currency', 'index'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to add this currency rate.'));
|
$this->flash->failure(t('Unable to add this currency rate.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,9 +76,9 @@ class Currency extends Base
|
||||||
|
|
||||||
if ($this->config->save($values)) {
|
if ($this->config->save($values)) {
|
||||||
$this->config->reload();
|
$this->config->reload();
|
||||||
$this->session->flash(t('Settings saved successfully.'));
|
$this->flash->success(t('Settings saved successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to save your settings.'));
|
$this->flash->failure(t('Unable to save your settings.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('currency', 'index'));
|
$this->response->redirect($this->helper->url->to('currency', 'index'));
|
||||||
|
|
|
@ -44,10 +44,10 @@ class Customfilter extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->customFilter->create($values)) {
|
if ($this->customFilter->create($values)) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create your custom filter.'));
|
$this->flash->failure(t('Unable to create your custom filter.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@ class Customfilter extends Base
|
||||||
$this->checkPermission($project, $filter);
|
$this->checkPermission($project, $filter);
|
||||||
|
|
||||||
if ($this->customFilter->remove($filter['id'])) {
|
if ($this->customFilter->remove($filter['id'])) {
|
||||||
$this->session->flash(t('Custom filter removed successfully.'));
|
$this->flash->success(t('Custom filter removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this custom filter.'));
|
$this->flash->failure(t('Unable to remove this custom filter.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
||||||
|
@ -123,10 +123,10 @@ class Customfilter extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->customFilter->update($values)) {
|
if ($this->customFilter->update($values)) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('customfilter', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update custom filter.'));
|
$this->flash->failure(t('Unable to update custom filter.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ class Export extends Base
|
||||||
*/
|
*/
|
||||||
public function summary()
|
public function summary()
|
||||||
{
|
{
|
||||||
$this->common('ProjectDailyColumnStats', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export'));
|
$this->common('projectDailyColumnStats', 'getAggregatedMetrics', t('Summary'), 'summary', t('Daily project summary export'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,7 +22,7 @@ class File extends Base
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
|
|
||||||
if ($this->request->isPost() && $this->file->uploadScreenshot($task['project_id'], $task['id'], $this->request->getValue('screenshot')) !== false) {
|
if ($this->request->isPost() && $this->file->uploadScreenshot($task['project_id'], $task['id'], $this->request->getValue('screenshot')) !== false) {
|
||||||
$this->session->flash(t('Screenshot uploaded successfully.'));
|
$this->flash->success(t('Screenshot uploaded successfully.'));
|
||||||
|
|
||||||
if ($this->request->getStringParam('redirect') === 'board') {
|
if ($this->request->getStringParam('redirect') === 'board') {
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
||||||
|
@ -62,7 +62,7 @@ class File extends Base
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
|
|
||||||
if (! $this->file->uploadFiles($task['project_id'], $task['id'], 'files')) {
|
if (! $this->file->uploadFiles($task['project_id'], $task['id'], 'files')) {
|
||||||
$this->session->flashError(t('Unable to upload the file.'));
|
$this->flash->failure(t('Unable to upload the file.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
|
@ -166,9 +166,9 @@ class File extends Base
|
||||||
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
$file = $this->file->getById($this->request->getIntegerParam('file_id'));
|
||||||
|
|
||||||
if ($file['task_id'] == $task['id'] && $this->file->remove($file['id'])) {
|
if ($file['task_id'] == $task['id'] && $this->file->remove($file['id'])) {
|
||||||
$this->session->flash(t('File removed successfully.'));
|
$this->flash->success(t('File removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this file.'));
|
$this->flash->failure(t('Unable to remove this file.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])));
|
||||||
|
|
|
@ -135,10 +135,10 @@ class Gantt extends Base
|
||||||
$task_id = $this->taskCreation->create($values);
|
$task_id = $this->taskCreation->create($values);
|
||||||
|
|
||||||
if ($task_id !== false) {
|
if ($task_id !== false) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('gantt', 'project', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create your task.'));
|
$this->flash->failure(t('Unable to create your task.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,10 +71,10 @@ 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->session->flash(t('Link added successfully.'));
|
$this->flash->success(t('Link added successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('link', 'index'));
|
$this->response->redirect($this->helper->url->to('link', 'index'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create your link.'));
|
$this->flash->failure(t('Unable to create your link.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,10 +112,10 @@ class Link extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->link->update($values)) {
|
if ($this->link->update($values)) {
|
||||||
$this->session->flash(t('Link updated successfully.'));
|
$this->flash->success(t('Link updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('link', 'index'));
|
$this->response->redirect($this->helper->url->to('link', 'index'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update your link.'));
|
$this->flash->failure(t('Unable to update your link.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,9 +148,9 @@ class Link extends Base
|
||||||
$link = $this->getLink();
|
$link = $this->getLink();
|
||||||
|
|
||||||
if ($this->link->remove($link['id'])) {
|
if ($this->link->remove($link['id'])) {
|
||||||
$this->session->flash(t('Link removed successfully.'));
|
$this->flash->success(t('Link removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this link.'));
|
$this->flash->failure(t('Unable to remove this link.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('link', 'index'));
|
$this->response->redirect($this->helper->url->to('link', 'index'));
|
||||||
|
|
|
@ -51,9 +51,9 @@ class Oauth extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->authentication->backend($backend)->unlink($this->userSession->getId())) {
|
if ($this->authentication->backend($backend)->unlink($this->userSession->getId())) {
|
||||||
$this->session->flash(t('Your external account is not linked anymore to your profile.'));
|
$this->flash->success(t('Your external account is not linked anymore to your profile.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to unlink your external account.'));
|
$this->flash->failure(t('Unable to unlink your external account.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('user', 'external', array('user_id' => $this->userSession->getId())));
|
$this->response->redirect($this->helper->url->to('user', 'external', array('user_id' => $this->userSession->getId())));
|
||||||
|
@ -99,9 +99,9 @@ class Oauth extends Base
|
||||||
private function link($backend, $profile)
|
private function link($backend, $profile)
|
||||||
{
|
{
|
||||||
if (empty($profile)) {
|
if (empty($profile)) {
|
||||||
$this->session->flashError(t('External authentication failed'));
|
$this->flash->failure(t('External authentication failed'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flash(t('Your external account is linked to your profile successfully.'));
|
$this->flash->success(t('Your external account is linked to your profile successfully.'));
|
||||||
$this->authentication->backend($backend)->updateUser($this->userSession->getId(), $profile);
|
$this->authentication->backend($backend)->updateUser($this->userSession->getId(), $profile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,9 +70,9 @@ class Project extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->project->{$switch.'PublicAccess'}($project['id'])) {
|
if ($this->project->{$switch.'PublicAccess'}($project['id'])) {
|
||||||
$this->session->flash(t('Project updated successfully.'));
|
$this->flash->success(t('Project updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this project.'));
|
$this->flash->failure(t('Unable to update this project.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$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'])));
|
||||||
|
@ -95,7 +95,7 @@ class Project extends Base
|
||||||
|
|
||||||
if ($this->request->isPost()) {
|
if ($this->request->isPost()) {
|
||||||
$this->projectMetadata->save($project['id'], $this->request->getValues());
|
$this->projectMetadata->save($project['id'], $this->request->getValues());
|
||||||
$this->session->flash(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'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ class Project extends Base
|
||||||
if ($this->request->isPost()) {
|
if ($this->request->isPost()) {
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
$this->projectNotification->saveSettings($project['id'], $values);
|
$this->projectNotification->saveSettings($project['id'], $values);
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('project', 'notifications', array('project_id' => $project['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,10 +173,10 @@ class Project extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->project->update($values)) {
|
if ($this->project->update($values)) {
|
||||||
$this->session->flash(t('Project updated successfully.'));
|
$this->flash->success(t('Project updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('project', 'edit', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('project', 'edit', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this project.'));
|
$this->flash->failure(t('Unable to update this project.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,9 +212,9 @@ class Project extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->project->update($values)) {
|
if ($this->project->update($values)) {
|
||||||
$this->session->flash(t('Project updated successfully.'));
|
$this->flash->success(t('Project updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this project.'));
|
$this->flash->failure(t('Unable to update this project.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,9 +233,9 @@ class Project extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->projectPermission->addMember($values['project_id'], $values['user_id'])) {
|
if ($this->projectPermission->addMember($values['project_id'], $values['user_id'])) {
|
||||||
$this->session->flash(t('Project updated successfully.'));
|
$this->flash->success(t('Project updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this project.'));
|
$this->flash->failure(t('Unable to update this project.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,9 +261,9 @@ class Project extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->projectPermission->changeRole($values['project_id'], $values['user_id'], $values['is_owner'])) {
|
if ($this->projectPermission->changeRole($values['project_id'], $values['user_id'], $values['is_owner'])) {
|
||||||
$this->session->flash(t('Project updated successfully.'));
|
$this->flash->success(t('Project updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this project.'));
|
$this->flash->failure(t('Unable to update this project.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,9 +288,9 @@ class Project extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->projectPermission->revokeMember($values['project_id'], $values['user_id'])) {
|
if ($this->projectPermission->revokeMember($values['project_id'], $values['user_id'])) {
|
||||||
$this->session->flash(t('Project updated successfully.'));
|
$this->flash->success(t('Project updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this project.'));
|
$this->flash->failure(t('Unable to update this project.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,9 +310,9 @@ class Project extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->project->remove($project['id'])) {
|
if ($this->project->remove($project['id'])) {
|
||||||
$this->session->flash(t('Project removed successfully.'));
|
$this->flash->success(t('Project removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this project.'));
|
$this->flash->failure(t('Unable to remove this project.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('project', 'index'));
|
$this->response->redirect($this->helper->url->to('project', 'index'));
|
||||||
|
@ -338,9 +338,9 @@ class Project extends Base
|
||||||
if ($this->request->getStringParam('duplicate') === 'yes') {
|
if ($this->request->getStringParam('duplicate') === 'yes') {
|
||||||
$values = array_keys($this->request->getValues());
|
$values = array_keys($this->request->getValues());
|
||||||
if ($this->projectDuplication->duplicate($project['id'], $values) !== false) {
|
if ($this->projectDuplication->duplicate($project['id'], $values) !== false) {
|
||||||
$this->session->flash(t('Project cloned successfully.'));
|
$this->flash->success(t('Project cloned successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to clone this project.'));
|
$this->flash->failure(t('Unable to clone this project.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('project', 'index'));
|
$this->response->redirect($this->helper->url->to('project', 'index'));
|
||||||
|
@ -365,9 +365,9 @@ class Project extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->project->disable($project['id'])) {
|
if ($this->project->disable($project['id'])) {
|
||||||
$this->session->flash(t('Project disabled successfully.'));
|
$this->flash->success(t('Project disabled successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id'])));
|
||||||
|
@ -392,9 +392,9 @@ class Project extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->project->enable($project['id'])) {
|
if ($this->project->enable($project['id'])) {
|
||||||
$this->session->flash(t('Project activated successfully.'));
|
$this->flash->success(t('Project activated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project['id'])));
|
||||||
|
@ -438,11 +438,11 @@ class Project extends Base
|
||||||
$project_id = $this->project->create($values, $this->userSession->getId(), true);
|
$project_id = $this->project->create($values, $this->userSession->getId(), true);
|
||||||
|
|
||||||
if ($project_id > 0) {
|
if ($project_id > 0) {
|
||||||
$this->session->flash(t('Your project have been created successfully.'));
|
$this->flash->success(t('Your project have been created successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id)));
|
$this->response->redirect($this->helper->url->to('project', 'show', array('project_id' => $project_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->session->flashError(t('Unable to create your project.'));
|
$this->flash->failure(t('Unable to create your project.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
$this->create($values, $errors);
|
||||||
|
|
|
@ -67,9 +67,9 @@ class Subtask extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->subtask->create($values)) {
|
if ($this->subtask->create($values)) {
|
||||||
$this->session->flash(t('Sub-task added successfully.'));
|
$this->flash->success(t('Sub-task added successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create your sub-task.'));
|
$this->flash->failure(t('Unable to create your sub-task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($values['another_subtask']) && $values['another_subtask'] == 1) {
|
if (isset($values['another_subtask']) && $values['another_subtask'] == 1) {
|
||||||
|
@ -117,9 +117,9 @@ class Subtask extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->subtask->update($values)) {
|
if ($this->subtask->update($values)) {
|
||||||
$this->session->flash(t('Sub-task updated successfully.'));
|
$this->flash->success(t('Sub-task updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update your sub-task.'));
|
$this->flash->failure(t('Unable to update your sub-task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks'));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks'));
|
||||||
|
@ -156,9 +156,9 @@ class Subtask extends Base
|
||||||
$subtask = $this->getSubtask();
|
$subtask = $this->getSubtask();
|
||||||
|
|
||||||
if ($this->subtask->remove($subtask['id'])) {
|
if ($this->subtask->remove($subtask['id'])) {
|
||||||
$this->session->flash(t('Sub-task removed successfully.'));
|
$this->flash->success(t('Sub-task removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this sub-task.'));
|
$this->flash->failure(t('Unable to remove this sub-task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks'));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id']), 'subtasks'));
|
||||||
|
@ -178,7 +178,7 @@ class Subtask extends Base
|
||||||
$this->subtask->toggleStatus($subtask['id']);
|
$this->subtask->toggleStatus($subtask['id']);
|
||||||
|
|
||||||
if ($redirect === 'board') {
|
if ($redirect === 'board') {
|
||||||
$this->session['has_subtask_inprogress'] = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
|
$this->sessionStorage->hasSubtaskInProgress = $this->subtask->hasSubtaskInProgress($this->userSession->getId());
|
||||||
|
|
||||||
$this->response->html($this->template->render('board/tooltip_subtasks', array(
|
$this->response->html($this->template->render('board/tooltip_subtasks', array(
|
||||||
'subtasks' => $this->subtask->getAll($task['id']),
|
'subtasks' => $this->subtask->getAll($task['id']),
|
||||||
|
|
|
@ -24,7 +24,7 @@ class Swimlane extends Base
|
||||||
$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->session->flashError(t('Swimlane not found.'));
|
$this->flash->failure(t('Swimlane not found.'));
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project_id)));
|
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,10 +64,10 @@ class Swimlane extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->swimlane->create($values)) {
|
if ($this->swimlane->create($values)) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create your swimlane.'));
|
$this->flash->failure(t('Unable to create your swimlane.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,10 +88,10 @@ class Swimlane extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->swimlane->updateDefault($values)) {
|
if ($this->swimlane->updateDefault($values)) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this swimlane.'));
|
$this->flash->failure(t('Unable to update this swimlane.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,10 +130,10 @@ class Swimlane extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->swimlane->update($values)) {
|
if ($this->swimlane->update($values)) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this swimlane.'));
|
$this->flash->failure(t('Unable to update this swimlane.'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,9 +169,9 @@ class Swimlane extends Base
|
||||||
$swimlane_id = $this->request->getIntegerParam('swimlane_id');
|
$swimlane_id = $this->request->getIntegerParam('swimlane_id');
|
||||||
|
|
||||||
if ($this->swimlane->remove($project['id'], $swimlane_id)) {
|
if ($this->swimlane->remove($project['id'], $swimlane_id)) {
|
||||||
$this->session->flash(t('Swimlane removed successfully.'));
|
$this->flash->success(t('Swimlane removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this swimlane.'));
|
$this->flash->failure(t('Unable to remove this swimlane.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
|
@ -189,9 +189,9 @@ class Swimlane extends Base
|
||||||
$swimlane_id = $this->request->getIntegerParam('swimlane_id');
|
$swimlane_id = $this->request->getIntegerParam('swimlane_id');
|
||||||
|
|
||||||
if ($this->swimlane->disable($project['id'], $swimlane_id)) {
|
if ($this->swimlane->disable($project['id'], $swimlane_id)) {
|
||||||
$this->session->flash(t('Swimlane updated successfully.'));
|
$this->flash->success(t('Swimlane updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this swimlane.'));
|
$this->flash->failure(t('Unable to update this swimlane.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
|
@ -209,9 +209,9 @@ class Swimlane extends Base
|
||||||
$swimlane_id = $this->request->getIntegerParam('swimlane_id');
|
$swimlane_id = $this->request->getIntegerParam('swimlane_id');
|
||||||
|
|
||||||
if ($this->swimlane->enable($project['id'], $swimlane_id)) {
|
if ($this->swimlane->enable($project['id'], $swimlane_id)) {
|
||||||
$this->session->flash(t('Swimlane updated successfully.'));
|
$this->flash->success(t('Swimlane updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update this swimlane.'));
|
$this->flash->failure(t('Unable to update this swimlane.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('swimlane', 'index', array('project_id' => $project['id'])));
|
||||||
|
|
|
@ -159,9 +159,9 @@ class Task extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->task->remove($task['id'])) {
|
if ($this->task->remove($task['id'])) {
|
||||||
$this->session->flash(t('Task removed successfully.'));
|
$this->flash->success(t('Task removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
||||||
|
|
|
@ -52,9 +52,9 @@ class TaskImport extends Base
|
||||||
$csv->read($filename, array($this->taskImport, 'import'));
|
$csv->read($filename, array($this->taskImport, 'import'));
|
||||||
|
|
||||||
if ($this->taskImport->counter > 0) {
|
if ($this->taskImport->counter > 0) {
|
||||||
$this->session->flash(t('%d task(s) have been imported successfully.', $this->taskImport->counter));
|
$this->flash->success(t('%d task(s) have been imported successfully.', $this->taskImport->counter));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Nothing have been imported!'));
|
$this->flash->failure(t('Nothing have been imported!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('taskImport', 'step1', array('project_id' => $project['id'])));
|
$this->response->redirect($this->helper->url->to('taskImport', 'step1', array('project_id' => $project['id'])));
|
||||||
|
|
|
@ -59,10 +59,10 @@ class Taskcreation extends Base
|
||||||
list($valid, $errors) = $this->taskValidator->validateCreation($values);
|
list($valid, $errors) = $this->taskValidator->validateCreation($values);
|
||||||
|
|
||||||
if ($valid && $this->taskCreation->create($values)) {
|
if ($valid && $this->taskCreation->create($values)) {
|
||||||
$this->session->flash(t('Task created successfully.'));
|
$this->flash->success(t('Task created successfully.'));
|
||||||
$this->afterSave($project, $values);
|
$this->afterSave($project, $values);
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to create your task.'));
|
$this->flash->failure(t('Unable to create your task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
$this->create($values, $errors);
|
||||||
|
|
|
@ -24,10 +24,10 @@ class Taskduplication extends Base
|
||||||
$task_id = $this->taskDuplication->duplicate($task['id']);
|
$task_id = $this->taskDuplication->duplicate($task['id']);
|
||||||
|
|
||||||
if ($task_id > 0) {
|
if ($task_id > 0) {
|
||||||
$this->session->flash(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)));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task_id)));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('taskduplication', 'duplicate', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,11 +56,11 @@ class Taskduplication extends Base
|
||||||
$values['column_id'],
|
$values['column_id'],
|
||||||
$values['category_id'],
|
$values['category_id'],
|
||||||
$values['owner_id'])) {
|
$values['owner_id'])) {
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->session->flashError(t('Unable to update your task.'));
|
$this->flash->failure(t('Unable to update your task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->chooseDestination($task, 'task_duplication/move');
|
$this->chooseDestination($task, 'task_duplication/move');
|
||||||
|
@ -86,12 +86,12 @@ class Taskduplication extends Base
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($task_id > 0) {
|
if ($task_id > 0) {
|
||||||
$this->session->flash(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)));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $values['project_id'], 'task_id' => $task_id)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->session->flashError(t('Unable to create your task.'));
|
$this->flash->failure(t('Unable to create your task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->chooseDestination($task, 'task_duplication/copy');
|
$this->chooseDestination($task, 'task_duplication/copy');
|
||||||
|
|
|
@ -73,7 +73,7 @@ class Tasklink extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->taskLink->create($values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
|
if ($this->taskLink->create($values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
|
||||||
$this->session->flash(t('Link added successfully.'));
|
$this->flash->success(t('Link added successfully.'));
|
||||||
|
|
||||||
if ($ajax) {
|
if ($ajax) {
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
||||||
|
@ -83,7 +83,7 @@ class Tasklink extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors = array('title' => array(t('The exact same link already exists')));
|
$errors = array('title' => array(t('The exact same link already exists')));
|
||||||
$this->session->flashError(t('Unable to create your link.'));
|
$this->flash->failure(t('Unable to create your link.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->create($values, $errors);
|
$this->create($values, $errors);
|
||||||
|
@ -129,11 +129,11 @@ class Tasklink extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->taskLink->update($values['id'], $values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
|
if ($this->taskLink->update($values['id'], $values['task_id'], $values['opposite_task_id'], $values['link_id'])) {
|
||||||
$this->session->flash(t('Link updated successfully.'));
|
$this->flash->success(t('Link updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->session->flashError(t('Unable to update your link.'));
|
$this->flash->failure(t('Unable to update your link.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->edit($values, $errors);
|
$this->edit($values, $errors);
|
||||||
|
@ -166,9 +166,9 @@ class Tasklink extends Base
|
||||||
$task = $this->getTask();
|
$task = $this->getTask();
|
||||||
|
|
||||||
if ($this->taskLink->remove($this->request->getIntegerParam('link_id'))) {
|
if ($this->taskLink->remove($this->request->getIntegerParam('link_id'))) {
|
||||||
$this->session->flash(t('Link removed successfully.'));
|
$this->flash->success(t('Link removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this link.'));
|
$this->flash->failure(t('Unable to remove this link.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
$this->response->redirect($this->helper->url->to('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links');
|
||||||
|
|
|
@ -35,9 +35,9 @@ class Taskmodification extends Base
|
||||||
list($valid, ) = $this->taskValidator->validateTimeModification($values);
|
list($valid, ) = $this->taskValidator->validateTimeModification($values);
|
||||||
|
|
||||||
if ($valid && $this->taskModification->update($values)) {
|
if ($valid && $this->taskModification->update($values)) {
|
||||||
$this->session->flash(t('Task updated successfully.'));
|
$this->flash->success(t('Task updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
||||||
|
@ -60,9 +60,9 @@ class Taskmodification extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->taskModification->update($values)) {
|
if ($this->taskModification->update($values)) {
|
||||||
$this->session->flash(t('Task updated successfully.'));
|
$this->flash->success(t('Task updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update your task.'));
|
$this->flash->failure(t('Unable to update your task.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ajax) {
|
if ($ajax) {
|
||||||
|
@ -140,7 +140,7 @@ class Taskmodification extends Base
|
||||||
list($valid, $errors) = $this->taskValidator->validateModification($values);
|
list($valid, $errors) = $this->taskValidator->validateModification($values);
|
||||||
|
|
||||||
if ($valid && $this->taskModification->update($values)) {
|
if ($valid && $this->taskModification->update($values)) {
|
||||||
$this->session->flash(t('Task updated successfully.'));
|
$this->flash->success(t('Task updated successfully.'));
|
||||||
|
|
||||||
if ($this->request->isAjax()) {
|
if ($this->request->isAjax()) {
|
||||||
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
$this->response->redirect($this->helper->url->to('board', 'show', array('project_id' => $task['project_id'])));
|
||||||
|
@ -148,7 +148,7 @@ class Taskmodification extends Base
|
||||||
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to update your task.'));
|
$this->flash->failure(t('Unable to update your task.'));
|
||||||
$this->edit($values, $errors);
|
$this->edit($values, $errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,9 +169,9 @@ class Taskmodification extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->taskModification->update($values)) {
|
if ($this->taskModification->update($values)) {
|
||||||
$this->session->flash(t('Task updated successfully.'));
|
$this->flash->success(t('Task updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('task', 'show', array('project_id' => $task['project_id'], 'task_id' => $task['id'])));
|
||||||
|
|
|
@ -40,9 +40,9 @@ class Taskstatus extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->taskStatus->$method($task['id'])) {
|
if ($this->taskStatus->$method($task['id'])) {
|
||||||
$this->session->flash($success_message);
|
$this->flash->success($success_message);
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError($failure_message);
|
$this->flash->failure($failure_message);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->request->getStringParam('redirect') === 'board') {
|
if ($this->request->getStringParam('redirect') === 'board') {
|
||||||
|
|
|
@ -72,9 +72,9 @@ class Twofactor extends User
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow the user to test or disable the feature
|
// Allow the user to test or disable the feature
|
||||||
$_SESSION['user']['twofactor_activated'] = false;
|
$this->userSession->disable2FA();
|
||||||
|
|
||||||
$this->session->flash(t('User updated successfully.'));
|
$this->flash->success(t('User updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('twofactor', 'index', array('user_id' => $user['id'])));
|
$this->response->redirect($this->helper->url->to('twofactor', 'index', array('user_id' => $user['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,9 +92,9 @@ class Twofactor extends User
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
|
if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
|
||||||
$this->session->flash(t('The two factor authentication code is valid.'));
|
$this->flash->success(t('The two factor authentication code is valid.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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', 'index', array('user_id' => $user['id'])));
|
$this->response->redirect($this->helper->url->to('twofactor', 'index', array('user_id' => $user['id'])));
|
||||||
|
@ -114,11 +114,11 @@ class Twofactor extends User
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
|
|
||||||
if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
|
if (! empty($values['code']) && $otp->checkTotp(Base32::decode($user['twofactor_secret']), $values['code'])) {
|
||||||
$this->session['2fa_validated'] = true;
|
$this->sessionStorage->postAuth['validated'] = true;
|
||||||
$this->session->flash(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('app', 'index'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Controller;
|
namespace Kanboard\Controller;
|
||||||
|
|
||||||
use Kanboard\Model\NotificationType;
|
use Kanboard\Notification\Mail as MailNotification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User controller
|
* User controller
|
||||||
|
@ -95,13 +95,13 @@ class User extends Base
|
||||||
$this->projectPermission->addMember($project_id, $user_id);
|
$this->projectPermission->addMember($project_id, $user_id);
|
||||||
|
|
||||||
if (! empty($values['notifications_enabled'])) {
|
if (! empty($values['notifications_enabled'])) {
|
||||||
$this->userNotificationType->saveSelectedTypes($user_id, array(NotificationType::TYPE_EMAIL));
|
$this->userNotificationType->saveSelectedTypes($user_id, array(MailNotification::TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->session->flash(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)));
|
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user_id)));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ class User extends Base
|
||||||
if ($this->request->isPost()) {
|
if ($this->request->isPost()) {
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
$this->userNotification->saveSettings($user['id'], $values);
|
$this->userNotification->saveSettings($user['id'], $values);
|
||||||
$this->session->flash(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'])));
|
$this->response->redirect($this->helper->url->to('user', 'notifications', array('user_id' => $user['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ class User extends Base
|
||||||
if ($this->request->isPost()) {
|
if ($this->request->isPost()) {
|
||||||
$values = $this->request->getValues();
|
$values = $this->request->getValues();
|
||||||
$this->userMetadata->save($user['id'], $values);
|
$this->userMetadata->save($user['id'], $values);
|
||||||
$this->session->flash(t('User updated successfully.'));
|
$this->flash->success(t('User updated successfully.'));
|
||||||
$this->response->redirect($this->helper->url->to('user', 'integrations', array('user_id' => $user['id'])));
|
$this->response->redirect($this->helper->url->to('user', 'integrations', array('user_id' => $user['id'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,9 +263,9 @@ class User extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->user->{$switch.'PublicAccess'}($user['id'])) {
|
if ($this->user->{$switch.'PublicAccess'}($user['id'])) {
|
||||||
$this->session->flash(t('User updated successfully.'));
|
$this->flash->success(t('User updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('user', 'share', array('user_id' => $user['id'])));
|
||||||
|
@ -294,9 +294,9 @@ class User extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->user->update($values)) {
|
if ($this->user->update($values)) {
|
||||||
$this->session->flash(t('Password modified successfully.'));
|
$this->flash->success(t('Password modified successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
|
||||||
|
@ -343,9 +343,9 @@ class User extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->user->update($values)) {
|
if ($this->user->update($values)) {
|
||||||
$this->session->flash(t('User updated successfully.'));
|
$this->flash->success(t('User updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('user', 'show', array('user_id' => $user['id'])));
|
||||||
|
@ -380,9 +380,9 @@ class User extends Base
|
||||||
|
|
||||||
if ($valid) {
|
if ($valid) {
|
||||||
if ($this->user->update($values)) {
|
if ($this->user->update($values)) {
|
||||||
$this->session->flash(t('User updated successfully.'));
|
$this->flash->success(t('User updated successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(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'])));
|
$this->response->redirect($this->helper->url->to('user', 'authentication', array('user_id' => $user['id'])));
|
||||||
|
@ -409,9 +409,9 @@ class User extends Base
|
||||||
$this->checkCSRFParam();
|
$this->checkCSRFParam();
|
||||||
|
|
||||||
if ($this->user->remove($user['id'])) {
|
if ($this->user->remove($user['id'])) {
|
||||||
$this->session->flash(t('User removed successfully.'));
|
$this->flash->success(t('User removed successfully.'));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Unable to remove this user.'));
|
$this->flash->failure(t('Unable to remove this user.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('user', 'index'));
|
$this->response->redirect($this->helper->url->to('user', 'index'));
|
||||||
|
|
|
@ -46,9 +46,9 @@ class UserImport extends Base
|
||||||
$csv->read($filename, array($this->userImport, 'import'));
|
$csv->read($filename, array($this->userImport, 'import'));
|
||||||
|
|
||||||
if ($this->userImport->counter > 0) {
|
if ($this->userImport->counter > 0) {
|
||||||
$this->session->flash(t('%d user(s) have been imported successfully.', $this->userImport->counter));
|
$this->flash->success(t('%d user(s) have been imported successfully.', $this->userImport->counter));
|
||||||
} else {
|
} else {
|
||||||
$this->session->flashError(t('Nothing have been imported!'));
|
$this->flash->failure(t('Nothing have been imported!'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->response->redirect($this->helper->url->to('userImport', 'step1'));
|
$this->response->redirect($this->helper->url->to('userImport', 'step1'));
|
||||||
|
|
|
@ -10,20 +10,24 @@ use Pimple\Container;
|
||||||
* @package core
|
* @package core
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*
|
*
|
||||||
|
* @property \Kanboard\Core\Session\SessionManager $sessionManager
|
||||||
|
* @property \Kanboard\Core\Session\SessionStorage $sessionStorage
|
||||||
|
* @property \Kanboard\Core\Session\FlashMessage $flash
|
||||||
* @property \Kanboard\Core\Helper $helper
|
* @property \Kanboard\Core\Helper $helper
|
||||||
* @property \Kanboard\Core\Mail\Client $emailClient
|
* @property \Kanboard\Core\Mail\Client $emailClient
|
||||||
* @property \Kanboard\Core\HttpClient $httpClient
|
|
||||||
* @property \Kanboard\Core\Paginator $paginator
|
* @property \Kanboard\Core\Paginator $paginator
|
||||||
* @property \Kanboard\Core\Request $request
|
* @property \Kanboard\Core\Http\Client $httpClient
|
||||||
* @property \Kanboard\Core\Session $session
|
* @property \Kanboard\Core\Http\Request $request
|
||||||
|
* @property \Kanboard\Core\Http\Router $router
|
||||||
|
* @property \Kanboard\Core\Http\Response $response
|
||||||
* @property \Kanboard\Core\Template $template
|
* @property \Kanboard\Core\Template $template
|
||||||
* @property \Kanboard\Core\OAuth2 $oauth
|
* @property \Kanboard\Core\OAuth2 $oauth
|
||||||
* @property \Kanboard\Core\Router $router
|
|
||||||
* @property \Kanboard\Core\Lexer $lexer
|
* @property \Kanboard\Core\Lexer $lexer
|
||||||
* @property \Kanboard\Core\ObjectStorage\ObjectStorageInterface $objectStorage
|
* @property \Kanboard\Core\ObjectStorage\ObjectStorageInterface $objectStorage
|
||||||
* @property \Kanboard\Core\Cache\Cache $memoryCache
|
* @property \Kanboard\Core\Cache\Cache $memoryCache
|
||||||
* @property \Kanboard\Core\Plugin\Hook $hook
|
* @property \Kanboard\Core\Plugin\Hook $hook
|
||||||
* @property \Kanboard\Core\Plugin\Loader $pluginLoader
|
* @property \Kanboard\Core\Plugin\Loader $pluginLoader
|
||||||
|
* @property \Kanboard\Core\Security\Token $token
|
||||||
* @property \Kanboard\Integration\BitbucketWebhook $bitbucketWebhook
|
* @property \Kanboard\Integration\BitbucketWebhook $bitbucketWebhook
|
||||||
* @property \Kanboard\Integration\GithubWebhook $githubWebhook
|
* @property \Kanboard\Integration\GithubWebhook $githubWebhook
|
||||||
* @property \Kanboard\Integration\GitlabWebhook $gitlabWebhook
|
* @property \Kanboard\Integration\GitlabWebhook $gitlabWebhook
|
||||||
|
|
|
@ -93,8 +93,7 @@ class Csv
|
||||||
{
|
{
|
||||||
if (! empty($value)) {
|
if (! empty($value)) {
|
||||||
$value = trim(strtolower($value));
|
$value = trim(strtolower($value));
|
||||||
return $value === '1' || $value{0}
|
return $value === '1' || $value{0} === 't' ? 1 : 0;
|
||||||
=== 't' ? 1 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -164,10 +163,14 @@ class Csv
|
||||||
*/
|
*/
|
||||||
public function write($filename, array $rows)
|
public function write($filename, array $rows)
|
||||||
{
|
{
|
||||||
$file = new SplFileObject($filename, 'w');
|
$fp = fopen($filename, 'w');
|
||||||
|
|
||||||
|
if (is_resource($fp)) {
|
||||||
foreach ($rows as $row) {
|
foreach ($rows as $row) {
|
||||||
$file->fputcsv($row, $this->delimiter, $this->enclosure);
|
fputcsv($fp, $row, $this->delimiter, $this->enclosure);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose($fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Kanboard\Core;
|
namespace Kanboard\Core\Http;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP client
|
* HTTP client
|
||||||
*
|
*
|
||||||
* @package core
|
* @package http
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class HttpClient extends Base
|
class Client extends Base
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* HTTP connection timeout in seconds
|
* HTTP connection timeout in seconds
|
||||||
|
@ -99,6 +101,36 @@ class HttpClient extends Base
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$stream = @fopen(trim($url), 'r', false, stream_context_create($this->getContext($method, $content, $headers)));
|
||||||
|
$response = '';
|
||||||
|
|
||||||
|
if (is_resource($stream)) {
|
||||||
|
$response = stream_get_contents($stream);
|
||||||
|
} else {
|
||||||
|
$this->logger->error('HttpClient: request failed');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
$this->logger->debug('HttpClient: url='.$url);
|
||||||
|
$this->logger->debug('HttpClient: payload='.$content);
|
||||||
|
$this->logger->debug('HttpClient: metadata='.var_export(@stream_get_meta_data($stream), true));
|
||||||
|
$this->logger->debug('HttpClient: response='.$response);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get stream context
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @param string $method
|
||||||
|
* @param string $content
|
||||||
|
* @param string[] $headers
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getContext($method, $content, array $headers)
|
||||||
|
{
|
||||||
$default_headers = array(
|
$default_headers = array(
|
||||||
'User-Agent: '.self::HTTP_USER_AGENT,
|
'User-Agent: '.self::HTTP_USER_AGENT,
|
||||||
'Connection: close',
|
'Connection: close',
|
||||||
|
@ -126,22 +158,6 @@ class HttpClient extends Base
|
||||||
$context['http']['request_fulluri'] = true;
|
$context['http']['request_fulluri'] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$stream = @fopen(trim($url), 'r', false, stream_context_create($context));
|
return $context;
|
||||||
$response = '';
|
|
||||||
|
|
||||||
if (is_resource($stream)) {
|
|
||||||
$response = stream_get_contents($stream);
|
|
||||||
} else {
|
|
||||||
$this->container['logger']->error('HttpClient: request failed');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG) {
|
|
||||||
$this->container['logger']->debug('HttpClient: url='.$url);
|
|
||||||
$this->container['logger']->debug('HttpClient: payload='.$content);
|
|
||||||
$this->container['logger']->debug('HttpClient: metadata='.var_export(@stream_get_meta_data($stream), true));
|
|
||||||
$this->container['logger']->debug('HttpClient: response='.$response);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $response;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,16 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Kanboard\Core;
|
namespace Kanboard\Core\Http;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request class
|
* Request class
|
||||||
*
|
*
|
||||||
* @package core
|
* @package http
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Request
|
class Request extends Base
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get URL string parameter
|
* Get URL string parameter
|
||||||
|
@ -57,7 +59,8 @@ class Request
|
||||||
*/
|
*/
|
||||||
public function getValues()
|
public function getValues()
|
||||||
{
|
{
|
||||||
if (! empty($_POST) && Security::validateCSRFFormToken($_POST)) {
|
if (! empty($_POST) && ! empty($_POST['csrf_token']) && $this->token->validateCSRFToken($_POST['csrf_token'])) {
|
||||||
|
unset($_POST['csrf_token']);
|
||||||
return $_POST;
|
return $_POST;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Kanboard\Core;
|
namespace Kanboard\Core\Http;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
use Kanboard\Core\Csv;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response class
|
* Response class
|
||||||
*
|
*
|
||||||
* @package core
|
* @package http
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Response
|
class Response extends Base
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Send no cache headers
|
* Send no cache headers
|
||||||
|
@ -44,6 +47,8 @@ class Response
|
||||||
public function forceDownload($filename)
|
public function forceDownload($filename)
|
||||||
{
|
{
|
||||||
header('Content-Disposition: attachment; filename="'.$filename.'"');
|
header('Content-Disposition: attachment; filename="'.$filename.'"');
|
||||||
|
header('Content-Transfer-Encoding: binary');
|
||||||
|
header('Content-Type: application/octet-stream');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -1,13 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Kanboard\Core;
|
namespace Kanboard\Core\Http;
|
||||||
|
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Router class
|
* Router class
|
||||||
*
|
*
|
||||||
* @package core
|
* @package http
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Router extends Base
|
class Router extends Base
|
|
@ -51,7 +51,7 @@ class Client extends Base
|
||||||
$author = 'Kanboard';
|
$author = 'Kanboard';
|
||||||
|
|
||||||
if ($this->userSession->isLogged()) {
|
if ($this->userSession->isLogged()) {
|
||||||
$author = e('%s via Kanboard', $this->user->getFullname($this->session['user']));
|
$author = e('%s via Kanboard', $this->helper->user->getFullname());
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getTransport(MAIL_TRANSPORT)->sendEmail($email, $name, $subject, $html, $author);
|
$this->getTransport(MAIL_TRANSPORT)->sendEmail($email, $name, $subject, $html, $author);
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace Kanboard\Core\Plugin;
|
||||||
|
|
||||||
use DirectoryIterator;
|
use DirectoryIterator;
|
||||||
use PDOException;
|
use PDOException;
|
||||||
|
use LogicException;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
use Kanboard\Core\Tool;
|
use Kanboard\Core\Tool;
|
||||||
|
|
||||||
|
@ -59,6 +60,11 @@ class Loader extends \Kanboard\Core\Base
|
||||||
public function load($plugin)
|
public function load($plugin)
|
||||||
{
|
{
|
||||||
$class = '\Kanboard\Plugin\\'.$plugin.'\\Plugin';
|
$class = '\Kanboard\Plugin\\'.$plugin.'\\Plugin';
|
||||||
|
|
||||||
|
if (! class_exists($class)) {
|
||||||
|
throw new LogicException('Unable to load this plugin class '.$class);
|
||||||
|
}
|
||||||
|
|
||||||
$instance = new $class($this->container);
|
$instance = new $class($this->container);
|
||||||
|
|
||||||
Tool::buildDic($this->container, $instance->getClasses());
|
Tool::buildDic($this->container, $instance->getClasses());
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Kanboard\Core;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Security class
|
|
||||||
*
|
|
||||||
* @package core
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Security
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Generate a random token with different methods: openssl or /dev/urandom or fallback to uniqid()
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @access public
|
|
||||||
* @return string Random token
|
|
||||||
*/
|
|
||||||
public static function generateToken()
|
|
||||||
{
|
|
||||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
|
||||||
return bin2hex(\openssl_random_pseudo_bytes(30));
|
|
||||||
} elseif (ini_get('open_basedir') === '' && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
|
||||||
return hash('sha256', file_get_contents('/dev/urandom', false, null, 0, 30));
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash('sha256', uniqid(mt_rand(), true));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate and store a CSRF token in the current session
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @access public
|
|
||||||
* @return string Random token
|
|
||||||
*/
|
|
||||||
public static function getCSRFToken()
|
|
||||||
{
|
|
||||||
$nonce = self::generateToken();
|
|
||||||
|
|
||||||
if (empty($_SESSION['csrf_tokens'])) {
|
|
||||||
$_SESSION['csrf_tokens'] = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['csrf_tokens'][$nonce] = true;
|
|
||||||
|
|
||||||
return $nonce;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the token exists for the current session (a token can be used only one time)
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @access public
|
|
||||||
* @param string $token CSRF token
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function validateCSRFToken($token)
|
|
||||||
{
|
|
||||||
if (isset($_SESSION['csrf_tokens'][$token])) {
|
|
||||||
unset($_SESSION['csrf_tokens'][$token]);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the token used in a form is correct and then remove the value
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @access public
|
|
||||||
* @param array $values Form values
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function validateCSRFFormToken(array &$values)
|
|
||||||
{
|
|
||||||
if (! empty($values['csrf_token']) && self::validateCSRFToken($values['csrf_token'])) {
|
|
||||||
unset($values['csrf_token']);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
69
sources/app/Core/Security/Token.php
Normal file
69
sources/app/Core/Security/Token.php
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Security;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Token Handler
|
||||||
|
*
|
||||||
|
* @package security
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class Token extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Generate a random token with different methods: openssl or /dev/urandom or fallback to uniqid()
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @return string Random token
|
||||||
|
*/
|
||||||
|
public static function getToken()
|
||||||
|
{
|
||||||
|
if (function_exists('random_bytes')) {
|
||||||
|
return bin2hex(random_bytes(30));
|
||||||
|
} elseif (function_exists('openssl_random_pseudo_bytes')) {
|
||||||
|
return bin2hex(openssl_random_pseudo_bytes(30));
|
||||||
|
} elseif (ini_get('open_basedir') === '' && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
|
||||||
|
return hash('sha256', file_get_contents('/dev/urandom', false, null, 0, 30));
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash('sha256', uniqid(mt_rand(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate and store a CSRF token in the current session
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return string Random token
|
||||||
|
*/
|
||||||
|
public function getCSRFToken()
|
||||||
|
{
|
||||||
|
if (! isset($this->sessionStorage->csrf)) {
|
||||||
|
$this->sessionStorage->csrf = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$nonce = self::getToken();
|
||||||
|
$this->sessionStorage->csrf[$nonce] = true;
|
||||||
|
|
||||||
|
return $nonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the token exists for the current session (a token can be used only one time)
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $token CSRF token
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function validateCSRFToken($token)
|
||||||
|
{
|
||||||
|
if (isset($this->sessionStorage->csrf[$token])) {
|
||||||
|
unset($this->sessionStorage->csrf[$token]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,143 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Kanboard\Core;
|
|
||||||
|
|
||||||
use ArrayAccess;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Session class
|
|
||||||
*
|
|
||||||
* @package core
|
|
||||||
* @author Frederic Guillot
|
|
||||||
*/
|
|
||||||
class Session implements ArrayAccess
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Return true if the session is open
|
|
||||||
*
|
|
||||||
* @static
|
|
||||||
* @access public
|
|
||||||
* @return boolean
|
|
||||||
*/
|
|
||||||
public static function isOpen()
|
|
||||||
{
|
|
||||||
return session_id() !== '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a session
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $base_path Cookie path
|
|
||||||
*/
|
|
||||||
public function open($base_path = '/')
|
|
||||||
{
|
|
||||||
// HttpOnly and secure flags for session cookie
|
|
||||||
session_set_cookie_params(
|
|
||||||
SESSION_DURATION,
|
|
||||||
$base_path ?: '/',
|
|
||||||
null,
|
|
||||||
Request::isHTTPS(),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
// Avoid session id in the URL
|
|
||||||
ini_set('session.use_only_cookies', '1');
|
|
||||||
|
|
||||||
// Enable strict mode
|
|
||||||
if (version_compare(PHP_VERSION, '7.0.0') < 0) {
|
|
||||||
ini_set('session.use_strict_mode', '1');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure session ID integrity
|
|
||||||
ini_set('session.entropy_file', '/dev/urandom');
|
|
||||||
ini_set('session.entropy_length', '32');
|
|
||||||
ini_set('session.hash_bits_per_character', 6);
|
|
||||||
|
|
||||||
// If the session was autostarted with session.auto_start = 1 in php.ini destroy it
|
|
||||||
if (isset($_SESSION)) {
|
|
||||||
session_destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Custom session name
|
|
||||||
session_name('__S');
|
|
||||||
|
|
||||||
// Start the session
|
|
||||||
session_start();
|
|
||||||
|
|
||||||
// Regenerate the session id to avoid session fixation issue
|
|
||||||
if (empty($_SESSION['__validated'])) {
|
|
||||||
session_regenerate_id(true);
|
|
||||||
$_SESSION['__validated'] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destroy the session
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
*/
|
|
||||||
public function close()
|
|
||||||
{
|
|
||||||
// Flush all sessions variables
|
|
||||||
$_SESSION = array();
|
|
||||||
|
|
||||||
// Destroy the session cookie
|
|
||||||
$params = session_get_cookie_params();
|
|
||||||
|
|
||||||
setcookie(
|
|
||||||
session_name(),
|
|
||||||
'',
|
|
||||||
time() - 42000,
|
|
||||||
$params['path'],
|
|
||||||
$params['domain'],
|
|
||||||
$params['secure'],
|
|
||||||
$params['httponly']
|
|
||||||
);
|
|
||||||
|
|
||||||
// Destroy session data
|
|
||||||
session_destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a flash message (success notification)
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $message Message
|
|
||||||
*/
|
|
||||||
public function flash($message)
|
|
||||||
{
|
|
||||||
$_SESSION['flash_message'] = $message;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a flash error message (error notification)
|
|
||||||
*
|
|
||||||
* @access public
|
|
||||||
* @param string $message Message
|
|
||||||
*/
|
|
||||||
public function flashError($message)
|
|
||||||
{
|
|
||||||
$_SESSION['flash_error_message'] = $message;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function offsetSet($offset, $value)
|
|
||||||
{
|
|
||||||
$_SESSION[$offset] = $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function offsetExists($offset)
|
|
||||||
{
|
|
||||||
return isset($_SESSION[$offset]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function offsetUnset($offset)
|
|
||||||
{
|
|
||||||
unset($_SESSION[$offset]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function offsetGet($offset)
|
|
||||||
{
|
|
||||||
return isset($_SESSION[$offset]) ? $_SESSION[$offset] : null;
|
|
||||||
}
|
|
||||||
}
|
|
71
sources/app/Core/Session/FlashMessage.php
Normal file
71
sources/app/Core/Session/FlashMessage.php
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Session;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session Flash Message
|
||||||
|
*
|
||||||
|
* @package session
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class FlashMessage extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Add success message
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $message
|
||||||
|
*/
|
||||||
|
public function success($message)
|
||||||
|
{
|
||||||
|
$this->setMessage('success', $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add failure message
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $message
|
||||||
|
*/
|
||||||
|
public function failure($message)
|
||||||
|
{
|
||||||
|
$this->setMessage('failure', $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new flash message
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @param string $message
|
||||||
|
*/
|
||||||
|
public function setMessage($key, $message)
|
||||||
|
{
|
||||||
|
if (! isset($this->sessionStorage->flash)) {
|
||||||
|
$this->sessionStorage->flash = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sessionStorage->flash[$key] = $message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get flash message
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param string $key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getMessage($key)
|
||||||
|
{
|
||||||
|
$message = '';
|
||||||
|
|
||||||
|
if (isset($this->sessionStorage->flash[$key])) {
|
||||||
|
$message = $this->sessionStorage->flash[$key];
|
||||||
|
unset($this->sessionStorage->flash[$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $message;
|
||||||
|
}
|
||||||
|
}
|
102
sources/app/Core/Session/SessionManager.php
Normal file
102
sources/app/Core/Session/SessionManager.php
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Session;
|
||||||
|
|
||||||
|
use Kanboard\Core\Base;
|
||||||
|
use Kanboard\Core\Http\Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session Manager
|
||||||
|
*
|
||||||
|
* @package session
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*/
|
||||||
|
class SessionManager extends Base
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Return true if the session is open
|
||||||
|
*
|
||||||
|
* @static
|
||||||
|
* @access public
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function isOpen()
|
||||||
|
{
|
||||||
|
return session_id() !== '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new session
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function open()
|
||||||
|
{
|
||||||
|
$this->configure();
|
||||||
|
|
||||||
|
if (ini_get('session.auto_start') == 1) {
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
session_name('KB_SID');
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
$this->container['sessionStorage']->setStorage($_SESSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the session
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
// Destroy the session cookie
|
||||||
|
$params = session_get_cookie_params();
|
||||||
|
|
||||||
|
setcookie(
|
||||||
|
session_name(),
|
||||||
|
'',
|
||||||
|
time() - 42000,
|
||||||
|
$params['path'],
|
||||||
|
$params['domain'],
|
||||||
|
$params['secure'],
|
||||||
|
$params['httponly']
|
||||||
|
);
|
||||||
|
|
||||||
|
session_unset();
|
||||||
|
session_destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define session settings
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
*/
|
||||||
|
private function configure()
|
||||||
|
{
|
||||||
|
// Session cookie: HttpOnly and secure flags
|
||||||
|
session_set_cookie_params(
|
||||||
|
SESSION_DURATION,
|
||||||
|
$this->helper->url->dir() ?: '/',
|
||||||
|
null,
|
||||||
|
Request::isHTTPS(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
// Avoid session id in the URL
|
||||||
|
ini_set('session.use_only_cookies', '1');
|
||||||
|
ini_set('session.use_trans_sid', '0');
|
||||||
|
|
||||||
|
// Enable strict mode
|
||||||
|
ini_set('session.use_strict_mode', '1');
|
||||||
|
|
||||||
|
// Better session hash
|
||||||
|
ini_set('session.hash_function', 'sha512');
|
||||||
|
ini_set('session.hash_bits_per_character', 6);
|
||||||
|
|
||||||
|
// Set an additional entropy
|
||||||
|
ini_set('session.entropy_file', '/dev/urandom');
|
||||||
|
ini_set('session.entropy_length', '256');
|
||||||
|
}
|
||||||
|
}
|
72
sources/app/Core/Session/SessionStorage.php
Normal file
72
sources/app/Core/Session/SessionStorage.php
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Kanboard\Core\Session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session Storage
|
||||||
|
*
|
||||||
|
* @package session
|
||||||
|
* @author Frederic Guillot
|
||||||
|
*
|
||||||
|
* @property array $config
|
||||||
|
* @property array $user
|
||||||
|
* @property array $flash
|
||||||
|
* @property array $csrf
|
||||||
|
* @property array $postAuth
|
||||||
|
* @property array $filters
|
||||||
|
* @property string $redirectAfterLogin
|
||||||
|
* @property string $captcha
|
||||||
|
* @property string $commentSorting
|
||||||
|
* @property bool $hasSubtaskInProgress
|
||||||
|
* @property bool $boardCollapsed
|
||||||
|
*/
|
||||||
|
class SessionStorage
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Pointer to external storage
|
||||||
|
*
|
||||||
|
* @access private
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $storage = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set external storage
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @param array $storage External session storage (example: $_SESSION)
|
||||||
|
*/
|
||||||
|
public function setStorage(array &$storage)
|
||||||
|
{
|
||||||
|
$this->storage =& $storage;
|
||||||
|
|
||||||
|
// Load dynamically existing session variables into object properties
|
||||||
|
foreach ($storage as $key => $value) {
|
||||||
|
$this->$key = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all session variables
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getAll()
|
||||||
|
{
|
||||||
|
$session = get_object_vars($this);
|
||||||
|
unset($session['storage']);
|
||||||
|
|
||||||
|
return $session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy class properties to external storage
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
$this->storage = $this->getAll();
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,7 @@ class Tool
|
||||||
* @access public
|
* @access public
|
||||||
* @param Container $container
|
* @param Container $container
|
||||||
* @param array $namespaces
|
* @param array $namespaces
|
||||||
|
* @return Container
|
||||||
*/
|
*/
|
||||||
public static function buildDIC(Container $container, array $namespaces)
|
public static function buildDIC(Container $container, array $namespaces)
|
||||||
{
|
{
|
||||||
|
@ -50,6 +51,8 @@ class Tool
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $container;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -62,18 +62,17 @@ class App extends \Kanboard\Core\Base
|
||||||
*/
|
*/
|
||||||
public function flashMessage()
|
public function flashMessage()
|
||||||
{
|
{
|
||||||
$html = '';
|
$success_message = $this->flash->getMessage('success');
|
||||||
|
$failure_message = $this->flash->getMessage('failure');
|
||||||
|
|
||||||
if (isset($this->session['flash_message'])) {
|
if (! empty($success_message)) {
|
||||||
$html = '<div class="alert alert-success alert-fade-out">'.$this->helper->e($this->session['flash_message']).'</div>';
|
return '<div class="alert alert-success alert-fade-out">'.$this->helper->e($success_message).'</div>';
|
||||||
unset($this->session['flash_message']);
|
|
||||||
unset($this->session['flash_error_message']);
|
|
||||||
} elseif (isset($this->session['flash_error_message'])) {
|
|
||||||
$html = '<div class="alert alert-error">'.$this->helper->e($this->session['flash_error_message']).'</div>';
|
|
||||||
unset($this->session['flash_message']);
|
|
||||||
unset($this->session['flash_error_message']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $html;
|
if (! empty($failure_message)) {
|
||||||
|
return '<div class="alert alert-error">'.$this->helper->e($failure_message).'</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Helper;
|
namespace Kanboard\Helper;
|
||||||
|
|
||||||
use Kanboard\Core\Security;
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Form helpers
|
* Form helpers
|
||||||
|
@ -10,7 +10,7 @@ use Kanboard\Core\Security;
|
||||||
* @package helper
|
* @package helper
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Form extends \Kanboard\Core\Base
|
class Form extends Base
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Hidden CSRF token field
|
* Hidden CSRF token field
|
||||||
|
@ -20,7 +20,7 @@ class Form extends \Kanboard\Core\Base
|
||||||
*/
|
*/
|
||||||
public function csrf()
|
public function csrf()
|
||||||
{
|
{
|
||||||
return '<input type="hidden" name="csrf_token" value="'.Security::getCSRFToken().'"/>';
|
return '<input type="hidden" name="csrf_token" value="'.$this->token->getCSRFToken().'"/>';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,7 +20,7 @@ class Subtask extends \Kanboard\Core\Base
|
||||||
*/
|
*/
|
||||||
public function toggleStatus(array $subtask, $redirect)
|
public function toggleStatus(array $subtask, $redirect)
|
||||||
{
|
{
|
||||||
if ($subtask['status'] == 0 && isset($this->session['has_subtask_inprogress']) && $this->session['has_subtask_inprogress'] === true) {
|
if ($subtask['status'] == 0 && isset($this->sessionStorage->hasSubtaskInProgress) && $this->sessionStorage->hasSubtaskInProgress === true) {
|
||||||
return $this->helper->url->link(
|
return $this->helper->url->link(
|
||||||
trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']),
|
trim($this->template->render('subtask/icons', array('subtask' => $subtask))) . $this->helper->e($subtask['title']),
|
||||||
'subtask',
|
'subtask',
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
namespace Kanboard\Helper;
|
namespace Kanboard\Helper;
|
||||||
|
|
||||||
use Kanboard\Core\Request;
|
use Kanboard\Core\Http\Request;
|
||||||
use Kanboard\Core\Security;
|
use Kanboard\Core\Base;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Url helpers
|
* Url helpers
|
||||||
|
@ -11,7 +11,7 @@ use Kanboard\Core\Security;
|
||||||
* @package helper
|
* @package helper
|
||||||
* @author Frederic Guillot
|
* @author Frederic Guillot
|
||||||
*/
|
*/
|
||||||
class Url extends \Kanboard\Core\Base
|
class Url extends Base
|
||||||
{
|
{
|
||||||
private $base = '';
|
private $base = '';
|
||||||
private $directory = '';
|
private $directory = '';
|
||||||
|
@ -158,7 +158,7 @@ class Url extends \Kanboard\Core\Base
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($csrf) {
|
if ($csrf) {
|
||||||
$qs['csrf_token'] = Security::getCSRFToken();
|
$qs['csrf_token'] = $this->token->getCSRFToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! empty($qs)) {
|
if (! empty($qs)) {
|
||||||
|
|
|
@ -136,7 +136,7 @@ class User extends \Kanboard\Core\Base
|
||||||
*/
|
*/
|
||||||
public function getFullname(array $user = array())
|
public function getFullname(array $user = array())
|
||||||
{
|
{
|
||||||
return $this->user->getFullname(empty($user) ? $_SESSION['user'] : $user);
|
return $this->user->getFullname(empty($user) ? $this->sessionStorage->user : $user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
1071
sources/app/Locale/bs_BA/translations.php
Normal file
1071
sources/app/Locale/bs_BA/translations.php
Normal file
File diff suppressed because it is too large
Load diff
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'ID je vyžadováno',
|
'The id is required' => 'ID je vyžadováno',
|
||||||
'The project id is required' => 'ID projektu je vyžadováno',
|
'The project id is required' => 'ID projektu je vyžadováno',
|
||||||
'The project name is required' => 'Jméno projektu je vyžadováno',
|
'The project name is required' => 'Jméno projektu je vyžadováno',
|
||||||
'This project must be unique' => 'Jméno projektu musí být jedinečné',
|
|
||||||
'The title is required' => 'Nadpis je vyžadován',
|
'The title is required' => 'Nadpis je vyžadován',
|
||||||
'Settings saved successfully.' => 'Nastavení bylo úspěšně uloženo',
|
'Settings saved successfully.' => 'Nastavení bylo úspěšně uloženo',
|
||||||
'Unable to save your settings.' => 'Vaše nastavení nelze uložit.',
|
'Unable to save your settings.' => 'Vaše nastavení nelze uložit.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Id\'et er krævet',
|
'The id is required' => 'Id\'et er krævet',
|
||||||
'The project id is required' => 'Projektets id er krævet',
|
'The project id is required' => 'Projektets id er krævet',
|
||||||
'The project name is required' => 'Projektets navn er krævet',
|
'The project name is required' => 'Projektets navn er krævet',
|
||||||
'This project must be unique' => 'Projektets navn skal være unikt',
|
|
||||||
'The title is required' => 'Titel er krævet',
|
'The title is required' => 'Titel er krævet',
|
||||||
'Settings saved successfully.' => 'Indstillinger gemt.',
|
'Settings saved successfully.' => 'Indstillinger gemt.',
|
||||||
'Unable to save your settings.' => 'Indstillinger kunne ikke gemmes.',
|
'Unable to save your settings.' => 'Indstillinger kunne ikke gemmes.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Die ID ist anzugeben',
|
'The id is required' => 'Die ID ist anzugeben',
|
||||||
'The project id is required' => 'Die Projekt ID ist anzugeben',
|
'The project id is required' => 'Die Projekt ID ist anzugeben',
|
||||||
'The project name is required' => 'Der Projektname ist anzugeben',
|
'The project name is required' => 'Der Projektname ist anzugeben',
|
||||||
'This project must be unique' => 'Der Projektname muss eindeutig sein',
|
|
||||||
'The title is required' => 'Der Titel ist anzugeben',
|
'The title is required' => 'Der Titel ist anzugeben',
|
||||||
'Settings saved successfully.' => 'Einstellungen erfolgreich gespeichert.',
|
'Settings saved successfully.' => 'Einstellungen erfolgreich gespeichert.',
|
||||||
'Unable to save your settings.' => 'Speichern der Einstellungen nicht möglich.',
|
'Unable to save your settings.' => 'Speichern der Einstellungen nicht möglich.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'El identificador es obligatorio',
|
'The id is required' => 'El identificador es obligatorio',
|
||||||
'The project id is required' => 'El identificador del proyecto es obligatorio',
|
'The project id is required' => 'El identificador del proyecto es obligatorio',
|
||||||
'The project name is required' => 'El nombre del proyecto es obligatorio',
|
'The project name is required' => 'El nombre del proyecto es obligatorio',
|
||||||
'This project must be unique' => 'El nombre del proyecto debe ser único',
|
|
||||||
'The title is required' => 'El título es obligatorio',
|
'The title is required' => 'El título es obligatorio',
|
||||||
'Settings saved successfully.' => 'Parámetros guardados correctamente.',
|
'Settings saved successfully.' => 'Parámetros guardados correctamente.',
|
||||||
'Unable to save your settings.' => 'No se pueden guardar sus parámetros.',
|
'Unable to save your settings.' => 'No se pueden guardar sus parámetros.',
|
||||||
|
@ -984,84 +983,89 @@ return array(
|
||||||
'Table of contents' => 'Tabla de contenido',
|
'Table of contents' => 'Tabla de contenido',
|
||||||
'Gantt' => 'Gantt',
|
'Gantt' => 'Gantt',
|
||||||
'Help with project permissions' => 'Ayuda con permisos del proyecto',
|
'Help with project permissions' => 'Ayuda con permisos del proyecto',
|
||||||
// 'Author' => '',
|
'Author' => 'Autor',
|
||||||
// 'Version' => '',
|
'Version' => 'Versión',
|
||||||
// 'Plugins' => '',
|
'Plugins' => 'Plugins',
|
||||||
// 'There is no plugin loaded.' => '',
|
'There is no plugin loaded.' => 'No hay ningún plugin cargado',
|
||||||
// 'Set maximum column height' => '',
|
'Set maximum column height' => 'Establecer altura máxima de la columna',
|
||||||
// 'Remove maximum column height' => '',
|
'Remove maximum column height' => 'Eliminar altura máxima de la columna',
|
||||||
// 'My notifications' => '',
|
'My notifications' => 'Mis notificaciones',
|
||||||
// 'Custom filters' => '',
|
'Custom filters' => 'Filtros personalizados',
|
||||||
// 'Your custom filter have been created successfully.' => '',
|
'Your custom filter have been created successfully.' => 'Tus filtros personalizados han sido creados exitosamente',
|
||||||
// 'Unable to create your custom filter.' => '',
|
'Unable to create your custom filter.' => 'No se ha podido crear tu filtro personalizado',
|
||||||
// 'Custom filter removed successfully.' => '',
|
'Custom filter removed successfully.' => 'Filtro personalizado ha sido eliminado exitosamente',
|
||||||
// 'Unable to remove this custom filter.' => '',
|
'Unable to remove this custom filter.' => 'No se ha podido eliminar tu filtro personalizado',
|
||||||
// 'Edit custom filter' => '',
|
'Edit custom filter' => 'Modificar filtro personalizado',
|
||||||
// 'Your custom filter have been updated successfully.' => '',
|
'Your custom filter have been updated successfully.' => 'Tu filtro personalizado ha sido actualizado exitosamente',
|
||||||
// 'Unable to update custom filter.' => '',
|
'Unable to update custom filter.' => 'No se ha podido actualizar tu filtro personalizado',
|
||||||
// 'Web' => '',
|
'Web' => 'Web',
|
||||||
// 'New attachment on task #%d: %s' => '',
|
'New attachment on task #%d: %s' => 'Nuevo adjunto en la tarea #%d: %s',
|
||||||
// 'New comment on task #%d' => '',
|
'New comment on task #%d' => 'Nuevo comentario en la tarea #%d',
|
||||||
// 'Comment updated on task #%d' => '',
|
'Comment updated on task #%d' => 'Comentario actualizado en la tarea #%d',
|
||||||
// 'New subtask on task #%d' => '',
|
'New subtask on task #%d' => 'Nueva subtarea en la tarea #%d',
|
||||||
// 'Subtask updated on task #%d' => '',
|
'Subtask updated on task #%d' => 'La subtarea en la tarea #%d ha sido actualizada',
|
||||||
// 'New task #%d: %s' => '',
|
'New task #%d: %s' => 'Nueva tarea #%d: %s',
|
||||||
// 'Task updated #%d' => '',
|
'Task updated #%d' => 'Tarea actualizada #%d',
|
||||||
// 'Task #%d closed' => '',
|
'Task #%d closed' => 'Tarea #%d ha sido cerrada',
|
||||||
// 'Task #%d opened' => '',
|
'Task #%d opened' => 'Tarea #%d ha sido abierta',
|
||||||
// 'Column changed for task #%d' => '',
|
'Column changed for task #%d' => 'Columna para tarea #%d ha sido cambiada',
|
||||||
// 'New position for task #%d' => '',
|
'New position for task #%d' => 'Nueva posición para tarea #%d',
|
||||||
// 'Swimlane changed for task #%d' => '',
|
'Swimlane changed for task #%d' => 'Se cambió el swimlane de la tarea #%d',
|
||||||
// 'Assignee changed on task #%d' => '',
|
'Assignee changed on task #%d' => 'Se cambió el asignado de la tarea #%d',
|
||||||
// '%d overdue tasks' => '',
|
'%d overdue tasks' => '%d tareas atrasadas',
|
||||||
// 'Task #%d is overdue' => '',
|
'Task #%d is overdue' => 'La tarea #%d está atrasada',
|
||||||
// 'No new notifications.' => '',
|
'No new notifications.' => 'No hay nuevas notificaciones',
|
||||||
// 'Mark all as read' => '',
|
'Mark all as read' => 'Marcar todo como leído',
|
||||||
// 'Mark as read' => '',
|
'Mark as read' => 'Marcar como leído',
|
||||||
// 'Total number of tasks in this column across all swimlanes' => '',
|
'Total number of tasks in this column across all swimlanes' => 'Número total de tareas en esta columna por todas las swimlanes',
|
||||||
// 'Collapse swimlane' => '',
|
'Collapse swimlane' => 'Contraer swimlane',
|
||||||
// 'Expand swimlane' => '',
|
'Expand swimlane' => 'Ampliar swimlane',
|
||||||
// 'Add a new filter' => '',
|
'Add a new filter' => 'Añadir nuevo filtro',
|
||||||
// 'Share with all project members' => '',
|
'Share with all project members' => 'Compartir con todos los miembros del proyecto',
|
||||||
// 'Shared' => '',
|
'Shared' => 'Compartido',
|
||||||
// 'Owner' => '',
|
'Owner' => 'Dueño',
|
||||||
// 'Unread notifications' => '',
|
'Unread notifications' => 'Notificaciones sin leer',
|
||||||
// 'My filters' => '',
|
'My filters' => 'Mis filtros',
|
||||||
// 'Notification methods:' => '',
|
'Notification methods:' => 'Métodos de notificación',
|
||||||
// 'Import tasks from CSV file' => '',
|
'Import tasks from CSV file' => 'Importar tareas desde archivo CSV',
|
||||||
// 'Unable to read your file' => '',
|
'Unable to read your file' => 'No es posible leer el archivo',
|
||||||
// '%d task(s) have been imported successfully.' => '',
|
'%d task(s) have been imported successfully.' => '%d tarea(s) han sido importadas exitosamente',
|
||||||
// 'Nothing have been imported!' => '',
|
'Nothing have been imported!' => 'No se ha importado nada!',
|
||||||
// 'Import users from CSV file' => '',
|
'Import users from CSV file' => 'Importar usuarios desde archivo CSV',
|
||||||
// '%d user(s) have been imported successfully.' => '',
|
'%d user(s) have been imported successfully.' => '%d usuario(s) se han importado exitosamente',
|
||||||
// 'Comma' => '',
|
'Comma' => 'Coma',
|
||||||
// 'Semi-colon' => '',
|
'Semi-colon' => 'Punto y coma',
|
||||||
// 'Tab' => '',
|
'Tab' => 'Tabulación',
|
||||||
// 'Vertical bar' => '',
|
'Vertical bar' => 'Pleca',
|
||||||
// 'Double Quote' => '',
|
'Double Quote' => 'Comilla doble',
|
||||||
// 'Single Quote' => '',
|
'Single Quote' => 'Comilla sencilla',
|
||||||
// '%s attached a file to the task #%d' => '',
|
'%s attached a file to the task #%d' => '%s adjuntó un archivo a la tarea #%d',
|
||||||
// 'There is no column or swimlane activated in your project!' => '',
|
'There is no column or swimlane activated in your project!' => 'No hay ninguna columna o swimlane activada en su proyecto!',
|
||||||
// 'Append filter (instead of replacement)' => '',
|
'Append filter (instead of replacement)' => 'Añadir filtro (en vez de reemplazar)',
|
||||||
// 'Append/Replace' => '',
|
'Append/Replace' => 'Añadir/Reemplazar',
|
||||||
// 'Append' => '',
|
'Append' => 'Añadir',
|
||||||
// 'Replace' => '',
|
'Replace' => 'Reemplazar',
|
||||||
// 'There is no notification method registered.' => '',
|
'There is no notification method registered.' => 'No hay método de notificación registrado',
|
||||||
// 'Import' => '',
|
'Import' => 'Importar',
|
||||||
// 'change sorting' => '',
|
'change sorting' => 'Cambiar orden',
|
||||||
// 'Tasks Importation' => '',
|
'Tasks Importation' => 'Importación de tareas',
|
||||||
// 'Delimiter' => '',
|
'Delimiter' => 'Delimitador',
|
||||||
// 'Enclosure' => '',
|
// 'Enclosure' => '',
|
||||||
// 'CSV File' => '',
|
'CSV File' => 'Archivo CSV',
|
||||||
// 'Instructions' => '',
|
'Instructions' => 'Indicaciones',
|
||||||
// 'Your file must use the predefined CSV format' => '',
|
'Your file must use the predefined CSV format' => 'Su archivo debe utilizar el formato CSV predeterminado',
|
||||||
// 'Your file must be encoded in UTF-8' => '',
|
'Your file must be encoded in UTF-8' => 'Su archivo debe ser codificado en UTF-8',
|
||||||
// 'The first row must be the header' => '',
|
'The first row must be the header' => 'La primera fila debe ser el encabezado',
|
||||||
// 'Duplicates are not verified for you' => '',
|
'Duplicates are not verified for you' => 'Los duplicados no serán verificados',
|
||||||
// 'The due date must use the ISO format: YYYY-MM-DD' => '',
|
'The due date must use the ISO format: YYYY-MM-DD' => 'La fecha de entrega debe utilizar el formato ISO: AAAA-MM-DD',
|
||||||
// 'Download CSV template' => '',
|
'Download CSV template' => 'Descargar plantilla CSV',
|
||||||
// 'No external integration registered.' => '',
|
'No external integration registered.' => 'No se ha registrado integración externa',
|
||||||
// 'Duplicates are not imported' => '',
|
'Duplicates are not imported' => 'Los duplicados no son importados',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
'Usernames must be lowercase and unique' => 'Los nombres de usuario deben ser únicos y contener sólo minúsculas',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
'Passwords will be encrypted if present' => 'Las contraseñas serán cifradas si es que existen',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'ID vaaditaan',
|
'The id is required' => 'ID vaaditaan',
|
||||||
'The project id is required' => 'Projektin ID on pakollinen',
|
'The project id is required' => 'Projektin ID on pakollinen',
|
||||||
'The project name is required' => 'Projektin nimi on pakollinen',
|
'The project name is required' => 'Projektin nimi on pakollinen',
|
||||||
'This project must be unique' => 'Projektin nimi täytyy olla uniikki',
|
|
||||||
'The title is required' => 'Otsikko vaaditaan',
|
'The title is required' => 'Otsikko vaaditaan',
|
||||||
'Settings saved successfully.' => 'Asetukset tallennettu onnistuneesti.',
|
'Settings saved successfully.' => 'Asetukset tallennettu onnistuneesti.',
|
||||||
'Unable to save your settings.' => 'Asetusten tallentaminen epäonnistui.',
|
'Unable to save your settings.' => 'Asetusten tallentaminen epäonnistui.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'L\'identifiant est obligatoire',
|
'The id is required' => 'L\'identifiant est obligatoire',
|
||||||
'The project id is required' => 'L\'identifiant du projet est obligatoire',
|
'The project id is required' => 'L\'identifiant du projet est obligatoire',
|
||||||
'The project name is required' => 'Le nom du projet est obligatoire',
|
'The project name is required' => 'Le nom du projet est obligatoire',
|
||||||
'This project must be unique' => 'Le nom du projet doit être unique',
|
|
||||||
'The title is required' => 'Le titre est obligatoire',
|
'The title is required' => 'Le titre est obligatoire',
|
||||||
'Settings saved successfully.' => 'Paramètres sauvegardés avec succès.',
|
'Settings saved successfully.' => 'Paramètres sauvegardés avec succès.',
|
||||||
'Unable to save your settings.' => 'Impossible de sauvegarder vos réglages.',
|
'Unable to save your settings.' => 'Impossible de sauvegarder vos réglages.',
|
||||||
|
@ -1066,4 +1065,10 @@ return array(
|
||||||
'Duplicates are not imported' => 'Les doublons ne sont pas importés',
|
'Duplicates are not imported' => 'Les doublons ne sont pas importés',
|
||||||
'Usernames must be lowercase and unique' => 'Les noms d\'utilisateurs doivent être en minuscule et unique',
|
'Usernames must be lowercase and unique' => 'Les noms d\'utilisateurs doivent être en minuscule et unique',
|
||||||
'Passwords will be encrypted if present' => 'Les mots de passe seront chiffrés si présent',
|
'Passwords will be encrypted if present' => 'Les mots de passe seront chiffrés si présent',
|
||||||
|
'%s attached a new file to the task %s' => '%s a attaché un nouveau fichier à la tâche %s',
|
||||||
|
'Link type' => 'Type de lien',
|
||||||
|
'Assign automatically a category based on a link' => 'Assigner automatiquement une catégorie en fonction d\'un lien',
|
||||||
|
'BAM - Konvertibile Mark' => 'BAM - Mark convertible',
|
||||||
|
'Assignee Username' => 'Utilisateur assigné',
|
||||||
|
'Assignee Name' => 'Nom de l\'assigné',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Az ID-t (azonosítót) meg kell adni',
|
'The id is required' => 'Az ID-t (azonosítót) meg kell adni',
|
||||||
'The project id is required' => 'A projekt ID-t (azonosítót) meg kell adni',
|
'The project id is required' => 'A projekt ID-t (azonosítót) meg kell adni',
|
||||||
'The project name is required' => 'A projekt nevét meg kell adni',
|
'The project name is required' => 'A projekt nevét meg kell adni',
|
||||||
'This project must be unique' => 'A projekt nevének egyedinek kell lennie',
|
|
||||||
'The title is required' => 'A címet meg kell adni',
|
'The title is required' => 'A címet meg kell adni',
|
||||||
'Settings saved successfully.' => 'A beállítások sikeresen mentve.',
|
'Settings saved successfully.' => 'A beállítások sikeresen mentve.',
|
||||||
'Unable to save your settings.' => 'A beállítások mentése sikertelen.',
|
'Unable to save your settings.' => 'A beállítások mentése sikertelen.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Id diperlukan',
|
'The id is required' => 'Id diperlukan',
|
||||||
'The project id is required' => 'Id proyek diperlukan',
|
'The project id is required' => 'Id proyek diperlukan',
|
||||||
'The project name is required' => 'Nama proyek diperlukan',
|
'The project name is required' => 'Nama proyek diperlukan',
|
||||||
'This project must be unique' => 'Proyek ini harus unik',
|
|
||||||
'The title is required' => 'Judul diperlukan',
|
'The title is required' => 'Judul diperlukan',
|
||||||
'Settings saved successfully.' => 'Pengaturan berhasil disimpan.',
|
'Settings saved successfully.' => 'Pengaturan berhasil disimpan.',
|
||||||
'Unable to save your settings.' => 'Tidak dapat menyimpan pengaturan anda.',
|
'Unable to save your settings.' => 'Tidak dapat menyimpan pengaturan anda.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Si richiede l\'identificatore',
|
'The id is required' => 'Si richiede l\'identificatore',
|
||||||
'The project id is required' => 'Si richiede l\'identificatore del progetto',
|
'The project id is required' => 'Si richiede l\'identificatore del progetto',
|
||||||
'The project name is required' => 'Si richiede il nome del progetto',
|
'The project name is required' => 'Si richiede il nome del progetto',
|
||||||
'This project must be unique' => 'Il nome del progetto deve essere unico',
|
|
||||||
'The title is required' => 'Si richiede un titolo',
|
'The title is required' => 'Si richiede un titolo',
|
||||||
'Settings saved successfully.' => 'Impostazioni salvate correttamente.',
|
'Settings saved successfully.' => 'Impostazioni salvate correttamente.',
|
||||||
'Unable to save your settings.' => 'Non si possono salvare le impostazioni.',
|
'Unable to save your settings.' => 'Non si possono salvare le impostazioni.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'ID が必要です',
|
'The id is required' => 'ID が必要です',
|
||||||
'The project id is required' => 'プロジェクト ID が必要です',
|
'The project id is required' => 'プロジェクト ID が必要です',
|
||||||
'The project name is required' => 'プロジェクト名が必要です',
|
'The project name is required' => 'プロジェクト名が必要です',
|
||||||
'This project must be unique' => 'プロジェクト名がすでに使われています',
|
|
||||||
'The title is required' => 'タイトルが必要です',
|
'The title is required' => 'タイトルが必要です',
|
||||||
'Settings saved successfully.' => '設定を保存しました。',
|
'Settings saved successfully.' => '設定を保存しました。',
|
||||||
'Unable to save your settings.' => '設定の保存に失敗しました。',
|
'Unable to save your settings.' => '設定の保存に失敗しました。',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Id\'en er pøøkrevet',
|
'The id is required' => 'Id\'en er pøøkrevet',
|
||||||
'The project id is required' => 'Prosjektet-id er påkrevet',
|
'The project id is required' => 'Prosjektet-id er påkrevet',
|
||||||
'The project name is required' => 'Prosjektnavn er påkrevet',
|
'The project name is required' => 'Prosjektnavn er påkrevet',
|
||||||
'This project must be unique' => 'Prosjektnavnet skal være unikt',
|
|
||||||
'The title is required' => 'Tittel er pårevet',
|
'The title is required' => 'Tittel er pårevet',
|
||||||
'Settings saved successfully.' => 'Innstillinger lagret.',
|
'Settings saved successfully.' => 'Innstillinger lagret.',
|
||||||
'Unable to save your settings.' => 'Innstillinger kunne ikke lagres.',
|
'Unable to save your settings.' => 'Innstillinger kunne ikke lagres.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Het id is verplicht',
|
'The id is required' => 'Het id is verplicht',
|
||||||
'The project id is required' => 'Het project id is verplicht',
|
'The project id is required' => 'Het project id is verplicht',
|
||||||
'The project name is required' => 'De projectnaam is verplicht',
|
'The project name is required' => 'De projectnaam is verplicht',
|
||||||
'This project must be unique' => 'Dit project moet uniek zijn',
|
|
||||||
'The title is required' => 'De titel is verplicht',
|
'The title is required' => 'De titel is verplicht',
|
||||||
'Settings saved successfully.' => 'Instellingen succesvol opgeslagen.',
|
'Settings saved successfully.' => 'Instellingen succesvol opgeslagen.',
|
||||||
'Unable to save your settings.' => 'Instellingen opslaan niet gelukt.',
|
'Unable to save your settings.' => 'Instellingen opslaan niet gelukt.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'ID jest wymagane',
|
'The id is required' => 'ID jest wymagane',
|
||||||
'The project id is required' => 'ID projektu jest wymagane',
|
'The project id is required' => 'ID projektu jest wymagane',
|
||||||
'The project name is required' => 'Nazwa projektu jest wymagana',
|
'The project name is required' => 'Nazwa projektu jest wymagana',
|
||||||
'This project must be unique' => 'Projekt musi być unikalny',
|
|
||||||
'The title is required' => 'Tutył jest wymagany',
|
'The title is required' => 'Tutył jest wymagany',
|
||||||
'Settings saved successfully.' => 'Ustawienia zapisane.',
|
'Settings saved successfully.' => 'Ustawienia zapisane.',
|
||||||
'Unable to save your settings.' => 'Nie udało się zapisać ustawień.',
|
'Unable to save your settings.' => 'Nie udało się zapisać ustawień.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -68,7 +68,7 @@ return array(
|
||||||
'Disable' => 'Desativar',
|
'Disable' => 'Desativar',
|
||||||
'Enable' => 'Ativar',
|
'Enable' => 'Ativar',
|
||||||
'New project' => 'Novo projeto',
|
'New project' => 'Novo projeto',
|
||||||
'Do you really want to remove this project: "%s"?' => 'Você realmente deseja remover este projeto: "%s" ?',
|
'Do you really want to remove this project: "%s"?' => 'Você realmente deseja remover este projeto: "%s"?',
|
||||||
'Remove project' => 'Remover projeto',
|
'Remove project' => 'Remover projeto',
|
||||||
'Edit the board for "%s"' => 'Editar o board para "%s"',
|
'Edit the board for "%s"' => 'Editar o board para "%s"',
|
||||||
'All projects' => 'Todos os projetos',
|
'All projects' => 'Todos os projetos',
|
||||||
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'O ID é obrigatório',
|
'The id is required' => 'O ID é obrigatório',
|
||||||
'The project id is required' => 'O ID do projeto é obrigatório',
|
'The project id is required' => 'O ID do projeto é obrigatório',
|
||||||
'The project name is required' => 'O nome do projeto é obrigatório',
|
'The project name is required' => 'O nome do projeto é obrigatório',
|
||||||
'This project must be unique' => 'Este projeto deve ser único',
|
|
||||||
'The title is required' => 'O título é obrigatório',
|
'The title is required' => 'O título é obrigatório',
|
||||||
'Settings saved successfully.' => 'Configurações salvas com sucesso.',
|
'Settings saved successfully.' => 'Configurações salvas com sucesso.',
|
||||||
'Unable to save your settings.' => 'Não é possível salvar suas configurações.',
|
'Unable to save your settings.' => 'Não é possível salvar suas configurações.',
|
||||||
|
@ -167,8 +166,8 @@ return array(
|
||||||
'%d closed tasks' => '%d tarefas finalizadas',
|
'%d closed tasks' => '%d tarefas finalizadas',
|
||||||
'No task for this project' => 'Não há tarefa para este projeto',
|
'No task for this project' => 'Não há tarefa para este projeto',
|
||||||
'Public link' => 'Link público',
|
'Public link' => 'Link público',
|
||||||
'Change assignee' => 'Mudar a designação',
|
'Change assignee' => 'Alterar designação',
|
||||||
'Change assignee for the task "%s"' => 'Modificar designação para a tarefa "%s"',
|
'Change assignee for the task "%s"' => 'Alterar designação para a tarefa "%s"',
|
||||||
'Timezone' => 'Fuso horário',
|
'Timezone' => 'Fuso horário',
|
||||||
'Sorry, I didn\'t find this information in my database!' => 'Desculpe, não encontrei esta informação no meu banco de dados!',
|
'Sorry, I didn\'t find this information in my database!' => 'Desculpe, não encontrei esta informação no meu banco de dados!',
|
||||||
'Page not found' => 'Página não encontrada',
|
'Page not found' => 'Página não encontrada',
|
||||||
|
@ -217,7 +216,7 @@ return array(
|
||||||
'Remove an automatic action' => 'Remover uma ação automática',
|
'Remove an automatic action' => 'Remover uma ação automática',
|
||||||
'Assign the task to a specific user' => 'Designar a tarefa para um usuário específico',
|
'Assign the task to a specific user' => 'Designar a tarefa para um usuário específico',
|
||||||
'Assign the task to the person who does the action' => 'Designar a tarefa para a pessoa que executa a ação',
|
'Assign the task to the person who does the action' => 'Designar a tarefa para a pessoa que executa a ação',
|
||||||
'Duplicate the task to another project' => 'Duplicar a tarefa para um outro projeto',
|
'Duplicate the task to another project' => 'Duplicar a tarefa para outro projeto',
|
||||||
'Move a task to another column' => 'Mover a tarefa para outra coluna',
|
'Move a task to another column' => 'Mover a tarefa para outra coluna',
|
||||||
'Task modification' => 'Modificação de tarefa',
|
'Task modification' => 'Modificação de tarefa',
|
||||||
'Task creation' => 'Criação de tarefa',
|
'Task creation' => 'Criação de tarefa',
|
||||||
|
@ -274,7 +273,7 @@ return array(
|
||||||
'Task removed successfully.' => 'Tarefa removida com sucesso.',
|
'Task removed successfully.' => 'Tarefa removida com sucesso.',
|
||||||
'Unable to remove this task.' => 'Não foi possível remover esta tarefa.',
|
'Unable to remove this task.' => 'Não foi possível remover esta tarefa.',
|
||||||
'Remove a task' => 'Remover uma tarefa',
|
'Remove a task' => 'Remover uma tarefa',
|
||||||
'Do you really want to remove this task: "%s"?' => 'Você realmente deseja remover esta tarefa: "%s"',
|
'Do you really want to remove this task: "%s"?' => 'Você realmente deseja remover esta tarefa: "%s"?',
|
||||||
'Assign automatically a color based on a category' => 'Atribuir automaticamente uma cor com base em uma categoria',
|
'Assign automatically a color based on a category' => 'Atribuir automaticamente uma cor com base em uma categoria',
|
||||||
'Assign automatically a category based on a color' => 'Atribuir automaticamente uma categoria com base em uma cor',
|
'Assign automatically a category based on a color' => 'Atribuir automaticamente uma categoria com base em uma cor',
|
||||||
'Task creation or modification' => 'Criação ou modificação de tarefa',
|
'Task creation or modification' => 'Criação ou modificação de tarefa',
|
||||||
|
@ -287,12 +286,12 @@ return array(
|
||||||
'Your category have been updated successfully.' => 'A sua categoria foi atualizada com sucesso.',
|
'Your category have been updated successfully.' => 'A sua categoria foi atualizada com sucesso.',
|
||||||
'Unable to update your category.' => 'Não foi possível atualizar a sua categoria.',
|
'Unable to update your category.' => 'Não foi possível atualizar a sua categoria.',
|
||||||
'Remove a category' => 'Remover uma categoria',
|
'Remove a category' => 'Remover uma categoria',
|
||||||
'Category removed successfully.' => 'Categoria removido com sucesso.',
|
'Category removed successfully.' => 'Categoria removida com sucesso.',
|
||||||
'Unable to remove this category.' => 'Não foi possível remover esta categoria.',
|
'Unable to remove this category.' => 'Não foi possível remover esta categoria.',
|
||||||
'Category modification for the project "%s"' => 'Modificação de categoria para o projeto "%s"',
|
'Category modification for the project "%s"' => 'Modificação de categoria para o projeto "%s"',
|
||||||
'Category Name' => 'Nome da Categoria',
|
'Category Name' => 'Nome da categoria',
|
||||||
'Add a new category' => 'Adicionar uma nova categoria',
|
'Add a new category' => 'Adicionar uma nova categoria',
|
||||||
'Do you really want to remove this category: "%s"?' => 'Você realmente deseja remover esta categoria: "%s"',
|
'Do you really want to remove this category: "%s"?' => 'Você realmente deseja remover esta categoria: "%s"?',
|
||||||
'All categories' => 'Todas as categorias',
|
'All categories' => 'Todas as categorias',
|
||||||
'No category' => 'Nenhum categoria',
|
'No category' => 'Nenhum categoria',
|
||||||
'The name is required' => 'O nome é obrigatório',
|
'The name is required' => 'O nome é obrigatório',
|
||||||
|
@ -300,7 +299,7 @@ return array(
|
||||||
'Unable to remove this file.' => 'Não foi possível remover este arquivo.',
|
'Unable to remove this file.' => 'Não foi possível remover este arquivo.',
|
||||||
'File removed successfully.' => 'Arquivo removido com sucesso.',
|
'File removed successfully.' => 'Arquivo removido com sucesso.',
|
||||||
'Attach a document' => 'Anexar um documento',
|
'Attach a document' => 'Anexar um documento',
|
||||||
'Do you really want to remove this file: "%s"?' => 'Você realmente deseja remover este arquivo: "%s"',
|
'Do you really want to remove this file: "%s"?' => 'Você realmente deseja remover este arquivo: "%s"?',
|
||||||
'Attachments' => 'Anexos',
|
'Attachments' => 'Anexos',
|
||||||
'Edit the task' => 'Editar a tarefa',
|
'Edit the task' => 'Editar a tarefa',
|
||||||
'Edit the description' => 'Editar a descrição',
|
'Edit the description' => 'Editar a descrição',
|
||||||
|
@ -331,7 +330,7 @@ return array(
|
||||||
'Unable to update your sub-task.' => 'Não foi possível atualizar a sua subtarefa.',
|
'Unable to update your sub-task.' => 'Não foi possível atualizar a sua subtarefa.',
|
||||||
'Unable to create your sub-task.' => 'Não é possível criar a sua subtarefa.',
|
'Unable to create your sub-task.' => 'Não é possível criar a sua subtarefa.',
|
||||||
'Sub-task added successfully.' => 'Subtarefa adicionada com sucesso.',
|
'Sub-task added successfully.' => 'Subtarefa adicionada com sucesso.',
|
||||||
'Maximum size: ' => 'Tamanho máximo:',
|
'Maximum size: ' => 'Tamanho máximo: ',
|
||||||
'Unable to upload the file.' => 'Não foi possível carregar o arquivo.',
|
'Unable to upload the file.' => 'Não foi possível carregar o arquivo.',
|
||||||
'Display another project' => 'Exibir outro projeto',
|
'Display another project' => 'Exibir outro projeto',
|
||||||
'Login with my Github Account' => 'Entrar com minha Conta do Github',
|
'Login with my Github Account' => 'Entrar com minha Conta do Github',
|
||||||
|
@ -461,7 +460,7 @@ return array(
|
||||||
'Database' => 'Banco de dados',
|
'Database' => 'Banco de dados',
|
||||||
'About' => 'Sobre',
|
'About' => 'Sobre',
|
||||||
'Database driver:' => 'Driver do banco de dados:',
|
'Database driver:' => 'Driver do banco de dados:',
|
||||||
'Board settings' => 'Configurações do Board',
|
'Board settings' => 'Configurações do board',
|
||||||
'URL and token' => 'URL e token',
|
'URL and token' => 'URL e token',
|
||||||
'Webhook settings' => 'Configurações do Webhook',
|
'Webhook settings' => 'Configurações do Webhook',
|
||||||
'URL for task creation:' => 'URL para a criação da tarefa:',
|
'URL for task creation:' => 'URL para a criação da tarefa:',
|
||||||
|
@ -475,7 +474,7 @@ return array(
|
||||||
'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Frequência em segundos (0 para desativar este recurso, 10 segundos por padrão)',
|
'Frequency in second (0 to disable this feature, 10 seconds by default)' => 'Frequência em segundos (0 para desativar este recurso, 10 segundos por padrão)',
|
||||||
'Application URL' => 'URL da Aplicação',
|
'Application URL' => 'URL da Aplicação',
|
||||||
'Example: http://example.kanboard.net/ (used by email notifications)' => 'Exemplo: http://example.kanboard.net/ (utilizado nas notificações por e-mail)',
|
'Example: http://example.kanboard.net/ (used by email notifications)' => 'Exemplo: http://example.kanboard.net/ (utilizado nas notificações por e-mail)',
|
||||||
'Token regenerated.' => 'Token ',
|
'Token regenerated.' => 'Novo token gerado.',
|
||||||
'Date format' => 'Formato de data',
|
'Date format' => 'Formato de data',
|
||||||
'ISO format is always accepted, example: "%s" and "%s"' => 'O formato ISO é sempre aceito, exemplo: "%s" e "%s"',
|
'ISO format is always accepted, example: "%s" and "%s"' => 'O formato ISO é sempre aceito, exemplo: "%s" e "%s"',
|
||||||
'New private project' => 'Novo projeto privado',
|
'New private project' => 'Novo projeto privado',
|
||||||
|
@ -562,7 +561,7 @@ return array(
|
||||||
'Unable to remove this swimlane.' => 'Não foi possível remover esta swimlane.',
|
'Unable to remove this swimlane.' => 'Não foi possível remover esta swimlane.',
|
||||||
'Unable to update this swimlane.' => 'Não foi possível atualizar esta swimlane.',
|
'Unable to update this swimlane.' => 'Não foi possível atualizar esta swimlane.',
|
||||||
'Your swimlane have been created successfully.' => 'Sua swimlane foi criada com sucesso.',
|
'Your swimlane have been created successfully.' => 'Sua swimlane foi criada com sucesso.',
|
||||||
'Example: "Bug, Feature Request, Improvement"' => 'Exemplo: "Bug, Feature Request, Improvement"',
|
'Example: "Bug, Feature Request, Improvement"' => 'Exemplo: "Bug, Solicitação de Recurso, Melhoria"',
|
||||||
'Default categories for new projects (Comma-separated)' => 'Categorias padrões para novos projetos (separadas por vírgula)',
|
'Default categories for new projects (Comma-separated)' => 'Categorias padrões para novos projetos (separadas por vírgula)',
|
||||||
'Gitlab commit received' => 'Gitlab commit received',
|
'Gitlab commit received' => 'Gitlab commit received',
|
||||||
'Gitlab issue opened' => 'Gitlab issue opened',
|
'Gitlab issue opened' => 'Gitlab issue opened',
|
||||||
|
@ -574,7 +573,7 @@ return array(
|
||||||
'Role for this project' => 'Função para este projeto',
|
'Role for this project' => 'Função para este projeto',
|
||||||
'Project manager' => 'Gerente do projeto',
|
'Project manager' => 'Gerente do projeto',
|
||||||
'Project member' => 'Membro do projeto',
|
'Project member' => 'Membro do projeto',
|
||||||
'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Um gerente do projeto pode alterar as configurações do projeto e ter mais privilégios que um usuário padrão.',
|
'A project manager can change the settings of the project and have more privileges than a standard user.' => 'Um gerente de projeto pode alterar as configurações do projeto e ter mais privilégios que um usuário padrão.',
|
||||||
'Gitlab Issue' => 'Gitlab Issue',
|
'Gitlab Issue' => 'Gitlab Issue',
|
||||||
'Subtask Id' => 'ID da subtarefa',
|
'Subtask Id' => 'ID da subtarefa',
|
||||||
'Subtasks' => 'Subtarefas',
|
'Subtasks' => 'Subtarefas',
|
||||||
|
@ -582,13 +581,13 @@ return array(
|
||||||
'Subtasks exportation for "%s"' => 'Subtarefas exportadas para "%s"',
|
'Subtasks exportation for "%s"' => 'Subtarefas exportadas para "%s"',
|
||||||
'Task Title' => 'Título da Tarefa',
|
'Task Title' => 'Título da Tarefa',
|
||||||
'Untitled' => 'Sem título',
|
'Untitled' => 'Sem título',
|
||||||
'Application default' => 'Aplicação padrão',
|
'Application default' => 'Padrão da aplicação',
|
||||||
'Language:' => 'Idioma',
|
'Language:' => 'Idioma',
|
||||||
'Timezone:' => 'Fuso horário',
|
'Timezone:' => 'Fuso horário',
|
||||||
'All columns' => 'Todas as colunas',
|
'All columns' => 'Todas as colunas',
|
||||||
'Calendar' => 'Calendário',
|
'Calendar' => 'Calendário',
|
||||||
'Next' => 'Próximo',
|
'Next' => 'Próximo',
|
||||||
// '#%d' => '',
|
'#%d' => '#%d',
|
||||||
'All swimlanes' => 'Todas as swimlanes',
|
'All swimlanes' => 'Todas as swimlanes',
|
||||||
'All colors' => 'Todas as cores',
|
'All colors' => 'Todas as cores',
|
||||||
'Moved to column %s' => 'Mover para a coluna %s',
|
'Moved to column %s' => 'Mover para a coluna %s',
|
||||||
|
@ -598,7 +597,7 @@ return array(
|
||||||
'Edit column "%s"' => 'Editar a coluna "%s"',
|
'Edit column "%s"' => 'Editar a coluna "%s"',
|
||||||
'Select the new status of the subtask: "%s"' => 'Selecionar um novo status para a subtarefa: "%s"',
|
'Select the new status of the subtask: "%s"' => 'Selecionar um novo status para a subtarefa: "%s"',
|
||||||
'Subtask timesheet' => 'Gestão de tempo das subtarefas',
|
'Subtask timesheet' => 'Gestão de tempo das subtarefas',
|
||||||
'There is nothing to show.' => 'Não há nada para mostrar',
|
'There is nothing to show.' => 'Não há nada para mostrar.',
|
||||||
'Time Tracking' => 'Gestão de tempo',
|
'Time Tracking' => 'Gestão de tempo',
|
||||||
'You already have one subtask in progress' => 'Você já tem um subtarefa em andamento',
|
'You already have one subtask in progress' => 'Você já tem um subtarefa em andamento',
|
||||||
'Which parts of the project do you want to duplicate?' => 'Quais partes do projeto você deseja duplicar?',
|
'Which parts of the project do you want to duplicate?' => 'Quais partes do projeto você deseja duplicar?',
|
||||||
|
@ -610,11 +609,11 @@ return array(
|
||||||
'End' => 'Fim',
|
'End' => 'Fim',
|
||||||
'Task age in days' => 'Idade da tarefa em dias',
|
'Task age in days' => 'Idade da tarefa em dias',
|
||||||
'Days in this column' => 'Dias nesta coluna',
|
'Days in this column' => 'Dias nesta coluna',
|
||||||
// '%dd' => '',
|
'%dd' => '%dd',
|
||||||
'Add a link' => 'Adicionar uma associação',
|
'Add a link' => 'Adicionar uma associação',
|
||||||
'Add a new link' => 'Adicionar uma nova associação',
|
'Add a new link' => 'Adicionar uma nova associação',
|
||||||
'Do you really want to remove this link: "%s"?' => 'Você realmente deseja remover esta associação: "%s"?',
|
'Do you really want to remove this link: "%s"?' => 'Você realmente deseja remover esta associação: "%s"?',
|
||||||
'Do you really want to remove this link with task #%d?' => 'Você realmente deseja remover esta associação com a tarefa n°%d?',
|
'Do you really want to remove this link with task #%d?' => 'Você realmente deseja remover esta associação com a tarefa #%d?',
|
||||||
'Field required' => 'Campo requerido',
|
'Field required' => 'Campo requerido',
|
||||||
'Link added successfully.' => 'Associação criada com sucesso.',
|
'Link added successfully.' => 'Associação criada com sucesso.',
|
||||||
'Link updated successfully.' => 'Associação atualizada com sucesso.',
|
'Link updated successfully.' => 'Associação atualizada com sucesso.',
|
||||||
|
@ -637,8 +636,8 @@ return array(
|
||||||
'is blocked by' => 'está bloqueada por',
|
'is blocked by' => 'está bloqueada por',
|
||||||
'duplicates' => 'duplica',
|
'duplicates' => 'duplica',
|
||||||
'is duplicated by' => 'é duplicada por',
|
'is duplicated by' => 'é duplicada por',
|
||||||
'is a child of' => 'é um filho de',
|
'is a child of' => 'é filha de',
|
||||||
'is a parent of' => 'é um parente do',
|
'is a parent of' => 'é mãe de',
|
||||||
'targets milestone' => 'visa um milestone',
|
'targets milestone' => 'visa um milestone',
|
||||||
'is a milestone of' => 'é um milestone de',
|
'is a milestone of' => 'é um milestone de',
|
||||||
'fixes' => 'corrige',
|
'fixes' => 'corrige',
|
||||||
|
@ -698,12 +697,12 @@ return array(
|
||||||
'%s remove the assignee of the task %s' => '%s removeu a pessoa designada para a tarefa %s',
|
'%s remove the assignee of the task %s' => '%s removeu a pessoa designada para a tarefa %s',
|
||||||
'Enable Gravatar images' => 'Ativar imagens do Gravatar',
|
'Enable Gravatar images' => 'Ativar imagens do Gravatar',
|
||||||
'Information' => 'Informações',
|
'Information' => 'Informações',
|
||||||
'Check two factor authentication code' => 'Verificação do código de autenticação à fator duplo',
|
'Check two factor authentication code' => 'Verifique o código de autenticação em duas etapas',
|
||||||
'The two factor authentication code is not valid.' => 'O código de autenticação à fator duplo não é válido',
|
'The two factor authentication code is not valid.' => 'O código de autenticação em duas etapas não é válido.',
|
||||||
'The two factor authentication code is valid.' => 'O código de autenticação à fator duplo é válido',
|
'The two factor authentication code is valid.' => 'O código de autenticação em duas etapas é válido.',
|
||||||
'Code' => 'Código',
|
'Code' => 'Código',
|
||||||
'Two factor authentication' => 'Autenticação à fator duplo',
|
'Two factor authentication' => 'Autenticação em duas etapas',
|
||||||
'Enable/disable two factor authentication' => 'Ativar/Desativar autenticação à fator duplo',
|
'Enable/disable two factor authentication' => 'Ativar/desativar autenticação em duas etapas',
|
||||||
'This QR code contains the key URI: ' => 'Este Código QR contém a chave URI:',
|
'This QR code contains the key URI: ' => 'Este Código QR contém a chave URI:',
|
||||||
'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => 'Salve esta chave secreta no seu software TOTP (por exemplo Google Authenticator ou FreeOTP).',
|
'Save the secret key in your TOTP software (by example Google Authenticator or FreeOTP).' => 'Salve esta chave secreta no seu software TOTP (por exemplo Google Authenticator ou FreeOTP).',
|
||||||
'Check my code' => 'Verifique o meu código',
|
'Check my code' => 'Verifique o meu código',
|
||||||
|
@ -717,19 +716,19 @@ return array(
|
||||||
'Burndown chart for "%s"' => 'Gráfico de Burndown para "%s"',
|
'Burndown chart for "%s"' => 'Gráfico de Burndown para "%s"',
|
||||||
'Burndown chart' => 'Gráfico de Burndown',
|
'Burndown chart' => 'Gráfico de Burndown',
|
||||||
'This chart show the task complexity over the time (Work Remaining).' => 'Este gráfico mostra a complexidade da tarefa ao longo do tempo (Trabalho Restante).',
|
'This chart show the task complexity over the time (Work Remaining).' => 'Este gráfico mostra a complexidade da tarefa ao longo do tempo (Trabalho Restante).',
|
||||||
'Screenshot taken %s' => 'Screenshot tomada em %s',
|
'Screenshot taken %s' => 'Captura de tela tirada em %s',
|
||||||
'Add a screenshot' => 'Adicionar uma Screenshot',
|
'Add a screenshot' => 'Adicionar uma captura de tela',
|
||||||
'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => 'Tomar um screenshot e pressione CTRL + V ou ⌘ + V para colar aqui.',
|
'Take a screenshot and press CTRL+V or ⌘+V to paste here.' => 'Tire uma captura de tela e pressione CTRL + V ou ⌘ + V para colar aqui.',
|
||||||
'Screenshot uploaded successfully.' => 'Screenshot enviada com sucesso.',
|
'Screenshot uploaded successfully.' => 'Captura de tela enviada com sucesso.',
|
||||||
'SEK - Swedish Krona' => 'SEK - Coroa sueca',
|
'SEK - Swedish Krona' => 'SEK - Coroa sueca',
|
||||||
'The project identifier is an optional alphanumeric code used to identify your project.' => 'O identificador de projeto é um código alfanumérico opcional utilizado para identificar o seu projeto.',
|
'The project identifier is an optional alphanumeric code used to identify your project.' => 'O identificador de projeto é um código alfanumérico opcional utilizado para identificar o seu projeto.',
|
||||||
'Identifier' => 'Identificador',
|
'Identifier' => 'Identificador',
|
||||||
'Disable two factor authentication' => 'Desativar autenticação à dois fatores',
|
'Disable two factor authentication' => 'Desativar autenticação em duas etapas',
|
||||||
'Do you really want to disable the two factor authentication for this user: "%s"?' => 'Você deseja realmente desativar a autenticação à dois fatores para esse usuário: "%s"?',
|
'Do you really want to disable the two factor authentication for this user: "%s"?' => 'Você realmente deseja desativar a autenticação em duas etapas para este usuário: "%s"?',
|
||||||
'Edit link' => 'Editar um link',
|
'Edit link' => 'Editar um link',
|
||||||
'Start to type task title...' => 'Digite o título do trabalho...',
|
'Start to type task title...' => 'Digite o título do trabalho...',
|
||||||
'A task cannot be linked to itself' => 'Uma tarefa não pode ser ligada a si própria',
|
'A task cannot be linked to itself' => 'Uma tarefa não pode ser vinculada a si própria',
|
||||||
'The exact same link already exists' => 'Um link idêntico jà existe',
|
'The exact same link already exists' => 'Um link idêntico já existe',
|
||||||
'Recurrent task is scheduled to be generated' => 'A tarefa recorrente está programada para ser criada',
|
'Recurrent task is scheduled to be generated' => 'A tarefa recorrente está programada para ser criada',
|
||||||
'Recurring information' => 'Informação sobre a recorrência',
|
'Recurring information' => 'Informação sobre a recorrência',
|
||||||
'Score' => 'Complexidade',
|
'Score' => 'Complexidade',
|
||||||
|
@ -739,7 +738,7 @@ return array(
|
||||||
'Edit recurrence' => 'Modificar a recorrência',
|
'Edit recurrence' => 'Modificar a recorrência',
|
||||||
'Generate recurrent task' => 'Gerar uma tarefa recorrente',
|
'Generate recurrent task' => 'Gerar uma tarefa recorrente',
|
||||||
'Trigger to generate recurrent task' => 'Trigger para gerar tarefa recorrente',
|
'Trigger to generate recurrent task' => 'Trigger para gerar tarefa recorrente',
|
||||||
'Factor to calculate new due date' => 'Fator para o cálculo do nova data limite',
|
'Factor to calculate new due date' => 'Fator para o cálculo da nova data limite',
|
||||||
'Timeframe to calculate new due date' => 'Escala de tempo para o cálculo da nova data limite',
|
'Timeframe to calculate new due date' => 'Escala de tempo para o cálculo da nova data limite',
|
||||||
'Base date to calculate new due date' => 'Data a ser utilizada para calcular a nova data limite',
|
'Base date to calculate new due date' => 'Data a ser utilizada para calcular a nova data limite',
|
||||||
'Action date' => 'Data da ação',
|
'Action date' => 'Data da ação',
|
||||||
|
@ -770,8 +769,8 @@ return array(
|
||||||
'iCal feed' => 'Subscrição iCal',
|
'iCal feed' => 'Subscrição iCal',
|
||||||
'Preferences' => 'Preferências',
|
'Preferences' => 'Preferências',
|
||||||
'Security' => 'Segurança',
|
'Security' => 'Segurança',
|
||||||
'Two factor authentication disabled' => 'Autenticação à fator duplo desativado',
|
'Two factor authentication disabled' => 'Autenticação em duas etapas desativada',
|
||||||
'Two factor authentication enabled' => 'Autenticação à fator duplo activado',
|
'Two factor authentication enabled' => 'Autenticação em duas etapas ativada',
|
||||||
'Unable to update this user.' => 'Impossível de atualizar esse usuário.',
|
'Unable to update this user.' => 'Impossível de atualizar esse usuário.',
|
||||||
'There is no user management for private projects.' => 'Não há gerenciamento de usuários para projetos privados.',
|
'There is no user management for private projects.' => 'Não há gerenciamento de usuários para projetos privados.',
|
||||||
'User that will receive the email' => 'O usuário que vai receber o e-mail',
|
'User that will receive the email' => 'O usuário que vai receber o e-mail',
|
||||||
|
@ -795,7 +794,7 @@ return array(
|
||||||
'Column change' => 'Mudança de coluna',
|
'Column change' => 'Mudança de coluna',
|
||||||
'Position change' => 'Mudança de posição',
|
'Position change' => 'Mudança de posição',
|
||||||
'Swimlane change' => 'Mudança de swimlane',
|
'Swimlane change' => 'Mudança de swimlane',
|
||||||
'Assignee change' => 'Mudança do designado',
|
'Assignee change' => 'Mudança de designação',
|
||||||
'[%s] Overdue tasks' => '[%s] Tarefas atrasadas',
|
'[%s] Overdue tasks' => '[%s] Tarefas atrasadas',
|
||||||
'Notification' => 'Notificação',
|
'Notification' => 'Notificação',
|
||||||
'%s moved the task #%d to the first swimlane' => '%s moveu a tarefa #%d para a primeira swimlane',
|
'%s moved the task #%d to the first swimlane' => '%s moveu a tarefa #%d para a primeira swimlane',
|
||||||
|
@ -804,7 +803,7 @@ return array(
|
||||||
'Gravatar' => 'Gravatar',
|
'Gravatar' => 'Gravatar',
|
||||||
'%s moved the task %s to the first swimlane' => '%s moveu a tarefa %s para a primeira swimlane',
|
'%s moved the task %s to the first swimlane' => '%s moveu a tarefa %s para a primeira swimlane',
|
||||||
'%s moved the task %s to the swimlane "%s"' => '%s moveu a tarefa %s para a swimlane "%s"',
|
'%s moved the task %s to the swimlane "%s"' => '%s moveu a tarefa %s para a swimlane "%s"',
|
||||||
'This report contains all subtasks information for the given date range.' => 'Este relatório contém informações de todas as sub-tarefas para o período selecionado.',
|
'This report contains all subtasks information for the given date range.' => 'Este relatório contém informações de todas as subtarefas para o período selecionado.',
|
||||||
'This report contains all tasks information for the given date range.' => 'Este relatório contém informações de todas as tarefas para o período selecionado.',
|
'This report contains all tasks information for the given date range.' => 'Este relatório contém informações de todas as tarefas para o período selecionado.',
|
||||||
'Project activities for %s' => 'Atividade do projeto "%s"',
|
'Project activities for %s' => 'Atividade do projeto "%s"',
|
||||||
'view the board on Kanboard' => 'ver o painel no Kanboard',
|
'view the board on Kanboard' => 'ver o painel no Kanboard',
|
||||||
|
@ -825,7 +824,7 @@ return array(
|
||||||
'Time estimated changed: %sh' => 'O tempo estimado foi mudado/ %sh',
|
'Time estimated changed: %sh' => 'O tempo estimado foi mudado/ %sh',
|
||||||
'The field "%s" have been updated' => 'O campo "%s" foi atualizada',
|
'The field "%s" have been updated' => 'O campo "%s" foi atualizada',
|
||||||
'The description have been modified' => 'A descrição foi modificada',
|
'The description have been modified' => 'A descrição foi modificada',
|
||||||
'Do you really want to close the task "%s" as well as all subtasks?' => 'Você realmente quer fechar a tarefa "%s" e todas as suas sub-tarefas?',
|
'Do you really want to close the task "%s" as well as all subtasks?' => 'Você realmente deseja finalizar a tarefa "%s" e todas as suas subtarefas?',
|
||||||
'Swimlane: %s' => 'Swimlane: %s',
|
'Swimlane: %s' => 'Swimlane: %s',
|
||||||
'I want to receive notifications for:' => 'Eu quero receber as notificações para:',
|
'I want to receive notifications for:' => 'Eu quero receber as notificações para:',
|
||||||
'All tasks' => 'Todas as tarefas',
|
'All tasks' => 'Todas as tarefas',
|
||||||
|
@ -844,7 +843,7 @@ return array(
|
||||||
'<30m' => '<30m',
|
'<30m' => '<30m',
|
||||||
'Stop timer' => 'Stop timer',
|
'Stop timer' => 'Stop timer',
|
||||||
'Start timer' => 'Start timer',
|
'Start timer' => 'Start timer',
|
||||||
'Add project member' => 'Adicionar um membro ao projeto',
|
'Add project member' => 'Adicionar membro ao projeto',
|
||||||
'Enable notifications' => 'Ativar as notificações',
|
'Enable notifications' => 'Ativar as notificações',
|
||||||
'My activity stream' => 'Meu feed de atividades',
|
'My activity stream' => 'Meu feed de atividades',
|
||||||
'My calendar' => 'Minha agenda',
|
'My calendar' => 'Minha agenda',
|
||||||
|
@ -868,7 +867,7 @@ return array(
|
||||||
'Switch to the list view' => 'Mudar par o modo Lista',
|
'Switch to the list view' => 'Mudar par o modo Lista',
|
||||||
'Go to the search/filter box' => 'Ir para o campo de pesquisa',
|
'Go to the search/filter box' => 'Ir para o campo de pesquisa',
|
||||||
'There is no activity yet.' => 'Não há nenhuma atividade ainda.',
|
'There is no activity yet.' => 'Não há nenhuma atividade ainda.',
|
||||||
'No tasks found.' => 'Nenhuma tarefa encontrada',
|
'No tasks found.' => 'Nenhuma tarefa encontrada.',
|
||||||
'Keyboard shortcut: "%s"' => 'Tecla de atalho: "%s"',
|
'Keyboard shortcut: "%s"' => 'Tecla de atalho: "%s"',
|
||||||
'List' => 'Lista',
|
'List' => 'Lista',
|
||||||
'Filter' => 'Filtro',
|
'Filter' => 'Filtro',
|
||||||
|
@ -918,7 +917,7 @@ return array(
|
||||||
'Default task color' => 'Cor padrão para as tarefas',
|
'Default task color' => 'Cor padrão para as tarefas',
|
||||||
'Hide sidebar' => 'Esconder a barra lateral',
|
'Hide sidebar' => 'Esconder a barra lateral',
|
||||||
'Expand sidebar' => 'Expandir a barra lateral',
|
'Expand sidebar' => 'Expandir a barra lateral',
|
||||||
'This feature does not work with all browsers.' => 'Esta funcionalidade não é compatível com todos os navegadores',
|
'This feature does not work with all browsers.' => 'Esta funcionalidade não é compatível com todos os navegadores.',
|
||||||
'There is no destination project available.' => 'Não há nenhum projeto de destino disponível.',
|
'There is no destination project available.' => 'Não há nenhum projeto de destino disponível.',
|
||||||
'Trigger automatically subtask time tracking' => 'Ativar automaticamente o monitoramento do tempo para as subtarefas',
|
'Trigger automatically subtask time tracking' => 'Ativar automaticamente o monitoramento do tempo para as subtarefas',
|
||||||
'Include closed tasks in the cumulative flow diagram' => 'Incluir as tarefas fechadas no diagrama de fluxo acumulado',
|
'Include closed tasks in the cumulative flow diagram' => 'Incluir as tarefas fechadas no diagrama de fluxo acumulado',
|
||||||
|
@ -932,7 +931,7 @@ return array(
|
||||||
'contributors' => 'contribuidores',
|
'contributors' => 'contribuidores',
|
||||||
'License:' => 'Licença:',
|
'License:' => 'Licença:',
|
||||||
'License' => 'Licença',
|
'License' => 'Licença',
|
||||||
'Project Administrator' => 'Administrador de Projeto',
|
'Project Administrator' => 'Administrador de projeto',
|
||||||
'Enter the text below' => 'Entre o texto abaixo',
|
'Enter the text below' => 'Entre o texto abaixo',
|
||||||
'Gantt chart for %s' => 'Gráfico de Gantt para %s',
|
'Gantt chart for %s' => 'Gráfico de Gantt para %s',
|
||||||
'Sort by position' => 'Ordenar por posição',
|
'Sort by position' => 'Ordenar por posição',
|
||||||
|
@ -959,7 +958,7 @@ return array(
|
||||||
'Project members' => 'Membros de projeto',
|
'Project members' => 'Membros de projeto',
|
||||||
'Gantt chart for all projects' => 'Gráfico de Gantt para todos os projetos',
|
'Gantt chart for all projects' => 'Gráfico de Gantt para todos os projetos',
|
||||||
'Projects list' => 'Lista dos projetos',
|
'Projects list' => 'Lista dos projetos',
|
||||||
'Gantt chart for this project' => 'Gráfico de Gantt para este projecto',
|
'Gantt chart for this project' => 'Gráfico de Gantt para este projeto',
|
||||||
'Project board' => 'Painel do projeto',
|
'Project board' => 'Painel do projeto',
|
||||||
'End date:' => 'Data de término:',
|
'End date:' => 'Data de término:',
|
||||||
'There is no start date or end date for this project.' => 'Não há data de início ou data de término para este projeto.',
|
'There is no start date or end date for this project.' => 'Não há data de início ou data de término para este projeto.',
|
||||||
|
@ -1028,40 +1027,45 @@ return array(
|
||||||
'Unread notifications' => 'Notificações não lidas',
|
'Unread notifications' => 'Notificações não lidas',
|
||||||
'My filters' => 'Meus filtros',
|
'My filters' => 'Meus filtros',
|
||||||
'Notification methods:' => 'Métodos de notificação:',
|
'Notification methods:' => 'Métodos de notificação:',
|
||||||
// 'Import tasks from CSV file' => '',
|
'Import tasks from CSV file' => 'Importar tarefas a partir de arquivo CSV',
|
||||||
// 'Unable to read your file' => '',
|
'Unable to read your file' => 'Não foi possível ler seu arquivo',
|
||||||
// '%d task(s) have been imported successfully.' => '',
|
'%d task(s) have been imported successfully.' => '%d tarefa(s) importada(s) com sucesso.',
|
||||||
// 'Nothing have been imported!' => '',
|
'Nothing have been imported!' => 'Nada foi importado!',
|
||||||
// 'Import users from CSV file' => '',
|
'Import users from CSV file' => 'Importar usuários a partir de arquivo CSV',
|
||||||
// '%d user(s) have been imported successfully.' => '',
|
'%d user(s) have been imported successfully.' => '%d usuário(s) importado(s) com sucesso.',
|
||||||
// 'Comma' => '',
|
'Comma' => 'Vírgula',
|
||||||
// 'Semi-colon' => '',
|
'Semi-colon' => 'Ponto e vírgula',
|
||||||
// 'Tab' => '',
|
'Tab' => 'Tab',
|
||||||
// 'Vertical bar' => '',
|
'Vertical bar' => 'Barra vertical',
|
||||||
// 'Double Quote' => '',
|
'Double Quote' => 'Aspas duplas',
|
||||||
// 'Single Quote' => '',
|
'Single Quote' => 'Aspas simples',
|
||||||
// '%s attached a file to the task #%d' => '',
|
'%s attached a file to the task #%d' => '%s anexou um arquivo à tarefa #%d',
|
||||||
// 'There is no column or swimlane activated in your project!' => '',
|
'There is no column or swimlane activated in your project!' => 'Não há coluna ou swimlane ativa em seu projeto!',
|
||||||
// 'Append filter (instead of replacement)' => '',
|
'Append filter (instead of replacement)' => 'Adicionar filtro (em vez de substituir)',
|
||||||
// 'Append/Replace' => '',
|
'Append/Replace' => 'Adicionar/Substituir',
|
||||||
// 'Append' => '',
|
'Append' => 'Adicionar',
|
||||||
// 'Replace' => '',
|
'Replace' => 'Substituir',
|
||||||
// 'There is no notification method registered.' => '',
|
'There is no notification method registered.' => 'Não há metodo de notificação registrado.',
|
||||||
// 'Import' => '',
|
'Import' => 'Importar',
|
||||||
// 'change sorting' => '',
|
'change sorting' => 'alterar ordenação',
|
||||||
// 'Tasks Importation' => '',
|
'Tasks Importation' => 'Importação de Tarefas',
|
||||||
// 'Delimiter' => '',
|
'Delimiter' => 'Separador',
|
||||||
// 'Enclosure' => '',
|
'Enclosure' => 'Delimitador de campos',
|
||||||
// 'CSV File' => '',
|
'CSV File' => 'Arquivo CSV',
|
||||||
// 'Instructions' => '',
|
'Instructions' => 'Instruções',
|
||||||
// 'Your file must use the predefined CSV format' => '',
|
'Your file must use the predefined CSV format' => 'Seu arquivo deve utilizar o formato CSV pré-definido',
|
||||||
// 'Your file must be encoded in UTF-8' => '',
|
'Your file must be encoded in UTF-8' => 'Seu arquivo deve estar codificado em UTF-8',
|
||||||
// 'The first row must be the header' => '',
|
'The first row must be the header' => 'A primeira linha deve ser o cabeçalho',
|
||||||
// 'Duplicates are not verified for you' => '',
|
'Duplicates are not verified for you' => 'Registros duplicados não são verificados',
|
||||||
// 'The due date must use the ISO format: YYYY-MM-DD' => '',
|
'The due date must use the ISO format: YYYY-MM-DD' => 'A data de vencimento deve utilizar o formato ISO: YYYY-MM-DD',
|
||||||
// 'Download CSV template' => '',
|
'Download CSV template' => 'Baixar modelo de arquivo CSV',
|
||||||
// 'No external integration registered.' => '',
|
'No external integration registered.' => 'Nenhuma integração externa registrada.',
|
||||||
// 'Duplicates are not imported' => '',
|
'Duplicates are not imported' => 'Registros duplicados não são importados',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
'Usernames must be lowercase and unique' => 'Nomes de usuário devem ser únicos e em letras minúsculas',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
'Passwords will be encrypted if present' => 'Senhas serão encriptadas, se presentes',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'O ID é obrigatório',
|
'The id is required' => 'O ID é obrigatório',
|
||||||
'The project id is required' => 'O ID do projecto é obrigatório',
|
'The project id is required' => 'O ID do projecto é obrigatório',
|
||||||
'The project name is required' => 'O nome do projecto é obrigatório',
|
'The project name is required' => 'O nome do projecto é obrigatório',
|
||||||
'This project must be unique' => 'Este projecto deve ser único',
|
|
||||||
'The title is required' => 'O título é obrigatório',
|
'The title is required' => 'O título é obrigatório',
|
||||||
'Settings saved successfully.' => 'Configurações guardadas com sucesso.',
|
'Settings saved successfully.' => 'Configurações guardadas com sucesso.',
|
||||||
'Unable to save your settings.' => 'Não é possível guardar as suas configurações.',
|
'Unable to save your settings.' => 'Não é possível guardar as suas configurações.',
|
||||||
|
@ -1027,41 +1026,46 @@ return array(
|
||||||
'Owner' => 'Dono',
|
'Owner' => 'Dono',
|
||||||
'Unread notifications' => 'Notificações por ler',
|
'Unread notifications' => 'Notificações por ler',
|
||||||
'My filters' => 'Os meus filtros',
|
'My filters' => 'Os meus filtros',
|
||||||
'Notification methods:' => 'Metodos de notificação:',
|
'Notification methods:' => 'Métodos de notificação:',
|
||||||
// 'Import tasks from CSV file' => '',
|
'Import tasks from CSV file' => 'Importar tarefas de um ficheiro CSV',
|
||||||
// 'Unable to read your file' => '',
|
'Unable to read your file' => 'Não foi possivel ler o ficheiro',
|
||||||
// '%d task(s) have been imported successfully.' => '',
|
'%d task(s) have been imported successfully.' => '%d tarefa(s) importada(s) com successo.',
|
||||||
// 'Nothing have been imported!' => '',
|
'Nothing have been imported!' => 'Nada foi importado',
|
||||||
// 'Import users from CSV file' => '',
|
'Import users from CSV file' => 'Importar utilizadores de um ficheiro CSV',
|
||||||
// '%d user(s) have been imported successfully.' => '',
|
'%d user(s) have been imported successfully.' => '%d utilizadore(s) importados com successo.',
|
||||||
// 'Comma' => '',
|
'Comma' => 'Vírgula',
|
||||||
// 'Semi-colon' => '',
|
'Semi-colon' => 'Ponto e Vírgula',
|
||||||
// 'Tab' => '',
|
'Tab' => 'Tabulação',
|
||||||
// 'Vertical bar' => '',
|
'Vertical bar' => 'Barra vertical',
|
||||||
// 'Double Quote' => '',
|
'Double Quote' => 'Aspas',
|
||||||
// 'Single Quote' => '',
|
'Single Quote' => 'Plica',
|
||||||
// '%s attached a file to the task #%d' => '',
|
'%s attached a file to the task #%d' => '%s anexou um ficheiro à tarefa #%d',
|
||||||
// 'There is no column or swimlane activated in your project!' => '',
|
'There is no column or swimlane activated in your project!' => 'Não existe nenhuma coluna ou swimlane activado no seu projecto!',
|
||||||
// 'Append filter (instead of replacement)' => '',
|
'Append filter (instead of replacement)' => 'Acrescentar filtro (em vez de substituir)',
|
||||||
// 'Append/Replace' => '',
|
'Append/Replace' => 'Acrescentar/Substituir',
|
||||||
// 'Append' => '',
|
'Append' => 'Acrescentar',
|
||||||
// 'Replace' => '',
|
'Replace' => 'Substituir',
|
||||||
// 'There is no notification method registered.' => '',
|
'There is no notification method registered.' => 'Não existe método de notificação registrado.',
|
||||||
// 'Import' => '',
|
'Import' => 'Importar',
|
||||||
// 'change sorting' => '',
|
'change sorting' => 'alterar ordernação',
|
||||||
// 'Tasks Importation' => '',
|
'Tasks Importation' => 'Importação de Tarefas',
|
||||||
// 'Delimiter' => '',
|
'Delimiter' => 'Delimitador',
|
||||||
// 'Enclosure' => '',
|
'Enclosure' => 'Clausura',
|
||||||
// 'CSV File' => '',
|
'CSV File' => 'Ficheiro CSV',
|
||||||
// 'Instructions' => '',
|
'Instructions' => 'Instruções',
|
||||||
// 'Your file must use the predefined CSV format' => '',
|
'Your file must use the predefined CSV format' => 'O seu ficheiro tem de usar um formato CSV pre-definido',
|
||||||
// 'Your file must be encoded in UTF-8' => '',
|
'Your file must be encoded in UTF-8' => 'O seu ficheiro tem de estar codificado como UTF-8',
|
||||||
// 'The first row must be the header' => '',
|
'The first row must be the header' => 'A primeira linha tem de ser o cabeçalho',
|
||||||
// 'Duplicates are not verified for you' => '',
|
'Duplicates are not verified for you' => 'Duplicados não são verificados por si',
|
||||||
// 'The due date must use the ISO format: YYYY-MM-DD' => '',
|
'The due date must use the ISO format: YYYY-MM-DD' => 'A data de expiração tem de estar no formato ISO: AAAA-MM-DD',
|
||||||
// 'Download CSV template' => '',
|
'Download CSV template' => 'Descarregar template CSV',
|
||||||
// 'No external integration registered.' => '',
|
'No external integration registered.' => 'Nenhuma integração externa registrada.',
|
||||||
// 'Duplicates are not imported' => '',
|
'Duplicates are not imported' => 'Duplicados não são importados',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
'Usernames must be lowercase and unique' => 'Utilizadores tem de estar em letra pequena e ser unicos',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
'Passwords will be encrypted if present' => 'Senhas serão encriptadas se presentes',
|
||||||
|
'%s attached a new file to the task %s' => '%s anexou um novo ficheiro à tarefa %s',
|
||||||
|
'Assign automatically a category based on a link' => 'Assignar automáticamente a categoria baseada num link',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Необходим ID',
|
'The id is required' => 'Необходим ID',
|
||||||
'The project id is required' => 'Необходим ID проекта',
|
'The project id is required' => 'Необходим ID проекта',
|
||||||
'The project name is required' => 'Необходимо имя проекта',
|
'The project name is required' => 'Необходимо имя проекта',
|
||||||
'This project must be unique' => 'Проект должен быть уникальным',
|
|
||||||
'The title is required' => 'Необходим заголовок',
|
'The title is required' => 'Необходим заголовок',
|
||||||
'Settings saved successfully.' => 'Параметры успешно сохранены.',
|
'Settings saved successfully.' => 'Параметры успешно сохранены.',
|
||||||
'Unable to save your settings.' => 'Невозможно сохранить параметры.',
|
'Unable to save your settings.' => 'Невозможно сохранить параметры.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'ID je obavezan',
|
'The id is required' => 'ID je obavezan',
|
||||||
'The project id is required' => 'ID projekta je obavezan',
|
'The project id is required' => 'ID projekta je obavezan',
|
||||||
'The project name is required' => 'Naziv projekta je obavezan',
|
'The project name is required' => 'Naziv projekta je obavezan',
|
||||||
'This project must be unique' => 'Projekat mora biti jedinstven',
|
|
||||||
'The title is required' => 'Naslov je obavezan',
|
'The title is required' => 'Naslov je obavezan',
|
||||||
'Settings saved successfully.' => 'Podešavanja uspešno snimljena.',
|
'Settings saved successfully.' => 'Podešavanja uspešno snimljena.',
|
||||||
'Unable to save your settings.' => 'Nemoguće snimanje podešavanja.',
|
'Unable to save your settings.' => 'Nemoguće snimanje podešavanja.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Aktuellt ID måste anges',
|
'The id is required' => 'Aktuellt ID måste anges',
|
||||||
'The project id is required' => 'Projekt-ID måste anges',
|
'The project id is required' => 'Projekt-ID måste anges',
|
||||||
'The project name is required' => 'Ett projektnamn måste anges',
|
'The project name is required' => 'Ett projektnamn måste anges',
|
||||||
'This project must be unique' => 'Detta projekt måste vara unikt',
|
|
||||||
'The title is required' => 'En titel måste anges.',
|
'The title is required' => 'En titel måste anges.',
|
||||||
'Settings saved successfully.' => 'Inställningarna har sparats.',
|
'Settings saved successfully.' => 'Inställningarna har sparats.',
|
||||||
'Unable to save your settings.' => 'Kunde inte spara dina ändringar',
|
'Unable to save your settings.' => 'Kunde inte spara dina ändringar',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'ต้องการไอดี',
|
'The id is required' => 'ต้องการไอดี',
|
||||||
'The project id is required' => 'ต้องการไอดีโปรเจค',
|
'The project id is required' => 'ต้องการไอดีโปรเจค',
|
||||||
'The project name is required' => 'ต้องการชื่อโปรเจค',
|
'The project name is required' => 'ต้องการชื่อโปรเจค',
|
||||||
'This project must be unique' => 'ชื่อโปรเจคต้องไม่ซ้ำ',
|
|
||||||
'The title is required' => 'ต้องการหัวเรื่อง',
|
'The title is required' => 'ต้องการหัวเรื่อง',
|
||||||
'Settings saved successfully.' => 'บันทึกการตั้งค่าเรียบร้อยแล้ว',
|
'Settings saved successfully.' => 'บันทึกการตั้งค่าเรียบร้อยแล้ว',
|
||||||
'Unable to save your settings.' => 'ไม่สามารถบันทึกการตั้งค่าได้',
|
'Unable to save your settings.' => 'ไม่สามารถบันทึกการตั้งค่าได้',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => 'Kod gerekli',
|
'The id is required' => 'Kod gerekli',
|
||||||
'The project id is required' => 'Proje kodu gerekli',
|
'The project id is required' => 'Proje kodu gerekli',
|
||||||
'The project name is required' => 'Proje adı gerekli',
|
'The project name is required' => 'Proje adı gerekli',
|
||||||
'This project must be unique' => 'Bu projenin tekil olması gerekli',
|
|
||||||
'The title is required' => 'Başlık gerekli',
|
'The title is required' => 'Başlık gerekli',
|
||||||
'Settings saved successfully.' => 'Ayarlar başarıyla kaydedildi.',
|
'Settings saved successfully.' => 'Ayarlar başarıyla kaydedildi.',
|
||||||
'Unable to save your settings.' => 'Ayarlarınız kaydedilemedi.',
|
'Unable to save your settings.' => 'Ayarlarınız kaydedilemedi.',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -124,7 +124,6 @@ return array(
|
||||||
'The id is required' => '需要指定id',
|
'The id is required' => '需要指定id',
|
||||||
'The project id is required' => '需要指定项目id',
|
'The project id is required' => '需要指定项目id',
|
||||||
'The project name is required' => '需要指定项目名称',
|
'The project name is required' => '需要指定项目名称',
|
||||||
'This project must be unique' => '项目名称必须唯一',
|
|
||||||
'The title is required' => '需要指定标题',
|
'The title is required' => '需要指定标题',
|
||||||
'Settings saved successfully.' => '设置成功保存。',
|
'Settings saved successfully.' => '设置成功保存。',
|
||||||
'Unable to save your settings.' => '无法保存你的设置。',
|
'Unable to save your settings.' => '无法保存你的设置。',
|
||||||
|
@ -1064,4 +1063,9 @@ return array(
|
||||||
// 'Duplicates are not imported' => '',
|
// 'Duplicates are not imported' => '',
|
||||||
// 'Usernames must be lowercase and unique' => '',
|
// 'Usernames must be lowercase and unique' => '',
|
||||||
// 'Passwords will be encrypted if present' => '',
|
// 'Passwords will be encrypted if present' => '',
|
||||||
|
// '%s attached a new file to the task %s' => '',
|
||||||
|
// 'Assign automatically a category based on a link' => '',
|
||||||
|
// 'BAM - Konvertibile Mark' => '',
|
||||||
|
// 'Assignee Username' => '',
|
||||||
|
// 'Assignee Name' => '',
|
||||||
);
|
);
|
||||||
|
|
|
@ -73,6 +73,7 @@ class Action extends Base
|
||||||
'TaskAssignColorUser' => t('Assign a color to a specific user'),
|
'TaskAssignColorUser' => t('Assign a color to a specific user'),
|
||||||
'TaskAssignColorCategory' => t('Assign automatically a color based on a category'),
|
'TaskAssignColorCategory' => t('Assign automatically a color based on a category'),
|
||||||
'TaskAssignCategoryColor' => t('Assign automatically a category based on a color'),
|
'TaskAssignCategoryColor' => t('Assign automatically a category based on a color'),
|
||||||
|
'TaskAssignCategoryLink' => t('Assign automatically a category based on a link'),
|
||||||
'CommentCreation' => t('Create a comment from an external provider'),
|
'CommentCreation' => t('Create a comment from an external provider'),
|
||||||
'TaskCreation' => t('Create a task from an external provider'),
|
'TaskCreation' => t('Create a task from an external provider'),
|
||||||
'TaskLogMoveAnotherColumn' => t('Add a comment log when moving the task between columns'),
|
'TaskLogMoveAnotherColumn' => t('Add a comment log when moving the task between columns'),
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Kanboard\Model;
|
namespace Kanboard\Model;
|
||||||
|
|
||||||
use Kanboard\Core\Request;
|
use Kanboard\Core\Http\Request;
|
||||||
use SimpleValidator\Validator;
|
use SimpleValidator\Validator;
|
||||||
use SimpleValidator\Validators;
|
use SimpleValidator\Validators;
|
||||||
use Gregwar\Captcha\CaptchaBuilder;
|
use Gregwar\Captcha\CaptchaBuilder;
|
||||||
|
@ -45,11 +45,11 @@ class Authentication extends Base
|
||||||
|
|
||||||
// Check if the user session match an existing user
|
// Check if the user session match an existing user
|
||||||
$userNotFound = ! $this->user->exists($this->userSession->getId());
|
$userNotFound = ! $this->user->exists($this->userSession->getId());
|
||||||
$reverseProxyWrongUser = REVERSE_PROXY_AUTH && $this->backend('reverseProxy')->getUsername() !== $_SESSION['user']['username'];
|
$reverseProxyWrongUser = REVERSE_PROXY_AUTH && $this->backend('reverseProxy')->getUsername() !== $this->userSession->getUsername();
|
||||||
|
|
||||||
if ($userNotFound || $reverseProxyWrongUser) {
|
if ($userNotFound || $reverseProxyWrongUser) {
|
||||||
$this->backend('rememberMe')->destroy($this->userSession->getId());
|
$this->backend('rememberMe')->destroy($this->userSession->getId());
|
||||||
$this->session->close();
|
$this->sessionManager->close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,8 +176,12 @@ class Authentication extends Base
|
||||||
public function validateFormCaptcha(array $values)
|
public function validateFormCaptcha(array $values)
|
||||||
{
|
{
|
||||||
if ($this->hasCaptcha($values['username'])) {
|
if ($this->hasCaptcha($values['username'])) {
|
||||||
|
if (! isset($this->sessionStorage->captcha)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$builder = new CaptchaBuilder;
|
$builder = new CaptchaBuilder;
|
||||||
$builder->setPhrase($this->session['captcha']);
|
$builder->setPhrase($this->sessionStorage->captcha);
|
||||||
return $builder->testPhrase(isset($values['captcha']) ? $values['captcha'] : '');
|
return $builder->testPhrase(isset($values['captcha']) ? $values['captcha'] : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
namespace Kanboard\Model;
|
namespace Kanboard\Model;
|
||||||
|
|
||||||
use Kanboard\Core\Translator;
|
use Kanboard\Core\Translator;
|
||||||
use Kanboard\Core\Security;
|
use Kanboard\Core\Security\Token;
|
||||||
use Kanboard\Core\Session;
|
use Kanboard\Core\Session\SessionManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config model
|
* Config model
|
||||||
|
@ -35,6 +35,7 @@ class Config extends Setting
|
||||||
'RSD' => t('RSD - Serbian dinar'),
|
'RSD' => t('RSD - Serbian dinar'),
|
||||||
'SEK' => t('SEK - Swedish Krona'),
|
'SEK' => t('SEK - Swedish Krona'),
|
||||||
'NOK' => t('NOK - Norwegian Krone'),
|
'NOK' => t('NOK - Norwegian Krone'),
|
||||||
|
'BAM' => t('BAM - Konvertibile Mark'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +70,7 @@ class Config extends Setting
|
||||||
// Sorted by value
|
// Sorted by value
|
||||||
$languages = array(
|
$languages = array(
|
||||||
'id_ID' => 'Bahasa Indonesia',
|
'id_ID' => 'Bahasa Indonesia',
|
||||||
|
'bs_BA' => 'Bosanski',
|
||||||
'cs_CZ' => 'Čeština',
|
'cs_CZ' => 'Čeština',
|
||||||
'da_DK' => 'Dansk',
|
'da_DK' => 'Dansk',
|
||||||
'de_DE' => 'Deutsch',
|
'de_DE' => 'Deutsch',
|
||||||
|
@ -108,7 +110,7 @@ class Config extends Setting
|
||||||
public function getJsLanguageCode()
|
public function getJsLanguageCode()
|
||||||
{
|
{
|
||||||
$languages = array(
|
$languages = array(
|
||||||
'cs_CZ' => 'cz',
|
'cs_CZ' => 'cs',
|
||||||
'da_DK' => 'da',
|
'da_DK' => 'da',
|
||||||
'de_DE' => 'de',
|
'de_DE' => 'de',
|
||||||
'en_US' => 'en',
|
'en_US' => 'en',
|
||||||
|
@ -145,8 +147,8 @@ class Config extends Setting
|
||||||
*/
|
*/
|
||||||
public function getCurrentLanguage()
|
public function getCurrentLanguage()
|
||||||
{
|
{
|
||||||
if ($this->userSession->isLogged() && ! empty($this->session['user']['language'])) {
|
if ($this->userSession->isLogged() && ! empty($this->sessionStorage->user['language'])) {
|
||||||
return $this->session['user']['language'];
|
return $this->sessionStorage->user['language'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->get('application_language', 'en_US');
|
return $this->get('application_language', 'en_US');
|
||||||
|
@ -162,17 +164,17 @@ class Config extends Setting
|
||||||
*/
|
*/
|
||||||
public function get($name, $default_value = '')
|
public function get($name, $default_value = '')
|
||||||
{
|
{
|
||||||
if (! Session::isOpen()) {
|
if (! SessionManager::isOpen()) {
|
||||||
return $this->getOption($name, $default_value);
|
return $this->getOption($name, $default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache config in session
|
// Cache config in session
|
||||||
if (! isset($this->session['config'][$name])) {
|
if (! isset($this->sessionStorage->config[$name])) {
|
||||||
$this->session['config'] = $this->getAll();
|
$this->sessionStorage->config = $this->getAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! empty($this->session['config'][$name])) {
|
if (! empty($this->sessionStorage->config[$name])) {
|
||||||
return $this->session['config'][$name];
|
return $this->sessionStorage->config[$name];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $default_value;
|
return $default_value;
|
||||||
|
@ -185,7 +187,7 @@ class Config extends Setting
|
||||||
*/
|
*/
|
||||||
public function reload()
|
public function reload()
|
||||||
{
|
{
|
||||||
$this->session['config'] = $this->getAll();
|
$this->sessionStorage->config = $this->getAll();
|
||||||
$this->setupTranslations();
|
$this->setupTranslations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,8 +209,8 @@ class Config extends Setting
|
||||||
*/
|
*/
|
||||||
public function getCurrentTimezone()
|
public function getCurrentTimezone()
|
||||||
{
|
{
|
||||||
if ($this->userSession->isLogged() && ! empty($this->session['user']['timezone'])) {
|
if ($this->userSession->isLogged() && ! empty($this->sessionStorage->user['timezone'])) {
|
||||||
return $this->session['user']['timezone'];
|
return $this->sessionStorage->user['timezone'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->get('application_timezone', 'UTC');
|
return $this->get('application_timezone', 'UTC');
|
||||||
|
@ -265,7 +267,7 @@ class Config extends Setting
|
||||||
*/
|
*/
|
||||||
public function regenerateToken($option)
|
public function regenerateToken($option)
|
||||||
{
|
{
|
||||||
$this->save(array($option => Security::generateToken()));
|
$this->save(array($option => Token::getToken()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace Kanboard\Model;
|
||||||
|
|
||||||
use SimpleValidator\Validator;
|
use SimpleValidator\Validator;
|
||||||
use SimpleValidator\Validators;
|
use SimpleValidator\Validators;
|
||||||
use Kanboard\Core\Security;
|
use Kanboard\Core\Security\Token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project model
|
* Project model
|
||||||
|
@ -491,7 +491,7 @@ class Project extends Base
|
||||||
$this->db
|
$this->db
|
||||||
->table(self::TABLE)
|
->table(self::TABLE)
|
||||||
->eq('id', $project_id)
|
->eq('id', $project_id)
|
||||||
->save(array('is_public' => 1, 'token' => Security::generateToken()));
|
->save(array('is_public' => 1, 'token' => Token::getToken()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -527,7 +527,6 @@ class Project extends Base
|
||||||
new Validators\MaxLength('start_date', t('The maximum length is %d characters', 10), 10),
|
new Validators\MaxLength('start_date', t('The maximum length is %d characters', 10), 10),
|
||||||
new Validators\MaxLength('end_date', t('The maximum length is %d characters', 10), 10),
|
new Validators\MaxLength('end_date', t('The maximum length is %d characters', 10), 10),
|
||||||
new Validators\AlphaNumeric('identifier', t('This value must be alphanumeric')) ,
|
new Validators\AlphaNumeric('identifier', t('This value must be alphanumeric')) ,
|
||||||
new Validators\Unique('name', t('This project must be unique'), $this->db->getConnection(), self::TABLE),
|
|
||||||
new Validators\Unique('identifier', t('The identifier must be unique'), $this->db->getConnection(), self::TABLE),
|
new Validators\Unique('identifier', t('The identifier must be unique'), $this->db->getConnection(), self::TABLE),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,40 +34,51 @@ class ProjectDailyColumnStats extends Base
|
||||||
{
|
{
|
||||||
$status = $this->config->get('cfd_include_closed_tasks') == 1 ? array(Task::STATUS_OPEN, Task::STATUS_CLOSED) : array(Task::STATUS_OPEN);
|
$status = $this->config->get('cfd_include_closed_tasks') == 1 ? array(Task::STATUS_OPEN, Task::STATUS_CLOSED) : array(Task::STATUS_OPEN);
|
||||||
|
|
||||||
return $this->db->transaction(function (Database $db) use ($project_id, $date, $status) {
|
$this->db->startTransaction();
|
||||||
|
|
||||||
$column_ids = $db->table(Board::TABLE)->eq('project_id', $project_id)->findAllByColumn('id');
|
$column_ids = $this->db->table(Board::TABLE)->eq('project_id', $project_id)->findAllByColumn('id');
|
||||||
|
|
||||||
foreach ($column_ids as $column_id) {
|
foreach ($column_ids as $column_id) {
|
||||||
|
|
||||||
// This call will fail if the record already exists
|
$exists = $this->db->table(ProjectDailyColumnStats::TABLE)
|
||||||
// (cross database driver hack for INSERT..ON DUPLICATE KEY UPDATE)
|
|
||||||
$db->table(ProjectDailyColumnStats::TABLE)->insert(array(
|
|
||||||
'day' => $date,
|
|
||||||
'project_id' => $project_id,
|
|
||||||
'column_id' => $column_id,
|
|
||||||
'total' => 0,
|
|
||||||
'score' => 0,
|
|
||||||
));
|
|
||||||
|
|
||||||
$db->table(ProjectDailyColumnStats::TABLE)
|
|
||||||
->eq('project_id', $project_id)
|
->eq('project_id', $project_id)
|
||||||
->eq('column_id', $column_id)
|
->eq('column_id', $column_id)
|
||||||
->eq('day', $date)
|
->eq('day', $date)
|
||||||
->update(array(
|
->exists();
|
||||||
'score' => $db->table(Task::TABLE)
|
|
||||||
|
$score = $this->db->table(Task::TABLE)
|
||||||
->eq('project_id', $project_id)
|
->eq('project_id', $project_id)
|
||||||
->eq('column_id', $column_id)
|
->eq('column_id', $column_id)
|
||||||
->eq('is_active', Task::STATUS_OPEN)
|
->eq('is_active', Task::STATUS_OPEN)
|
||||||
->sum('score'),
|
->sum('score');
|
||||||
'total' => $db->table(Task::TABLE)
|
|
||||||
|
$total = $this->db->table(Task::TABLE)
|
||||||
->eq('project_id', $project_id)
|
->eq('project_id', $project_id)
|
||||||
->eq('column_id', $column_id)
|
->eq('column_id', $column_id)
|
||||||
->in('is_active', $status)
|
->in('is_active', $status)
|
||||||
->count()
|
->count();
|
||||||
|
|
||||||
|
if ($exists) {
|
||||||
|
$this->db->table(ProjectDailyColumnStats::TABLE)
|
||||||
|
->eq('project_id', $project_id)
|
||||||
|
->eq('column_id', $column_id)
|
||||||
|
->eq('day', $date)
|
||||||
|
->update(array('score' => $score, 'total' => $total));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$this->db->table(ProjectDailyColumnStats::TABLE)->insert(array(
|
||||||
|
'day' => $date,
|
||||||
|
'project_id' => $project_id,
|
||||||
|
'column_id' => $column_id,
|
||||||
|
'total' => $total,
|
||||||
|
'score' => $score,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
$this->db->closeTransaction();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -29,27 +29,35 @@ class ProjectDailyStats extends Base
|
||||||
*/
|
*/
|
||||||
public function updateTotals($project_id, $date)
|
public function updateTotals($project_id, $date)
|
||||||
{
|
{
|
||||||
|
$this->db->startTransaction();
|
||||||
|
|
||||||
$lead_cycle_time = $this->projectAnalytic->getAverageLeadAndCycleTime($project_id);
|
$lead_cycle_time = $this->projectAnalytic->getAverageLeadAndCycleTime($project_id);
|
||||||
|
|
||||||
return $this->db->transaction(function (Database $db) use ($project_id, $date, $lead_cycle_time) {
|
$exists = $this->db->table(ProjectDailyStats::TABLE)
|
||||||
|
->eq('day', $date)
|
||||||
|
->eq('project_id', $project_id)
|
||||||
|
->exists();
|
||||||
|
|
||||||
// This call will fail if the record already exists
|
if ($exists) {
|
||||||
// (cross database driver hack for INSERT..ON DUPLICATE KEY UPDATE)
|
$this->db->table(ProjectDailyStats::TABLE)
|
||||||
$db->table(ProjectDailyStats::TABLE)->insert(array(
|
|
||||||
'day' => $date,
|
|
||||||
'project_id' => $project_id,
|
|
||||||
'avg_lead_time' => 0,
|
|
||||||
'avg_cycle_time' => 0,
|
|
||||||
));
|
|
||||||
|
|
||||||
$db->table(ProjectDailyStats::TABLE)
|
|
||||||
->eq('project_id', $project_id)
|
->eq('project_id', $project_id)
|
||||||
->eq('day', $date)
|
->eq('day', $date)
|
||||||
->update(array(
|
->update(array(
|
||||||
'avg_lead_time' => $lead_cycle_time['avg_lead_time'],
|
'avg_lead_time' => $lead_cycle_time['avg_lead_time'],
|
||||||
'avg_cycle_time' => $lead_cycle_time['avg_cycle_time'],
|
'avg_cycle_time' => $lead_cycle_time['avg_cycle_time'],
|
||||||
));
|
));
|
||||||
});
|
} else {
|
||||||
|
$this->db->table(ProjectDailyStats::TABLE)->insert(array(
|
||||||
|
'day' => $date,
|
||||||
|
'project_id' => $project_id,
|
||||||
|
'avg_lead_time' => $lead_cycle_time['avg_lead_time'],
|
||||||
|
'avg_cycle_time' => $lead_cycle_time['avg_cycle_time'],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->db->closeTransaction();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -58,6 +58,7 @@ class TaskExport extends Base
|
||||||
tasks.date_due,
|
tasks.date_due,
|
||||||
creators.username AS creator_username,
|
creators.username AS creator_username,
|
||||||
users.username AS assignee_username,
|
users.username AS assignee_username,
|
||||||
|
users.name AS assignee_name,
|
||||||
tasks.score,
|
tasks.score,
|
||||||
tasks.title,
|
tasks.title,
|
||||||
tasks.date_creation,
|
tasks.date_creation,
|
||||||
|
@ -129,7 +130,8 @@ class TaskExport extends Base
|
||||||
e('Color'),
|
e('Color'),
|
||||||
e('Due date'),
|
e('Due date'),
|
||||||
e('Creator'),
|
e('Creator'),
|
||||||
e('Assignee'),
|
e('Assignee Username'),
|
||||||
|
e('Assignee Name'),
|
||||||
e('Complexity'),
|
e('Complexity'),
|
||||||
e('Title'),
|
e('Title'),
|
||||||
e('Creation date'),
|
e('Creation date'),
|
||||||
|
|
|
@ -5,8 +5,8 @@ namespace Kanboard\Model;
|
||||||
use PicoDb\Database;
|
use PicoDb\Database;
|
||||||
use SimpleValidator\Validator;
|
use SimpleValidator\Validator;
|
||||||
use SimpleValidator\Validators;
|
use SimpleValidator\Validators;
|
||||||
use Kanboard\Core\Session;
|
use Kanboard\Core\Session\SessionManager;
|
||||||
use Kanboard\Core\Security;
|
use Kanboard\Core\Security\Token;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User model
|
* User model
|
||||||
|
@ -320,8 +320,8 @@ class User extends Base
|
||||||
$result = $this->db->table(self::TABLE)->eq('id', $values['id'])->update($values);
|
$result = $this->db->table(self::TABLE)->eq('id', $values['id'])->update($values);
|
||||||
|
|
||||||
// If the user is connected refresh his session
|
// If the user is connected refresh his session
|
||||||
if (Session::isOpen() && $this->userSession->getId() == $values['id']) {
|
if (SessionManager::isOpen() && $this->userSession->getId() == $values['id']) {
|
||||||
$this->userSession->refresh();
|
$this->userSession->initialize($this->getById($this->userSession->getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
|
@ -383,7 +383,7 @@ class User extends Base
|
||||||
return $this->db
|
return $this->db
|
||||||
->table(self::TABLE)
|
->table(self::TABLE)
|
||||||
->eq('id', $user_id)
|
->eq('id', $user_id)
|
||||||
->save(array('token' => Security::generateToken()));
|
->save(array('token' => Token::getToken()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -587,7 +587,7 @@ class User extends Base
|
||||||
if ($v->execute()) {
|
if ($v->execute()) {
|
||||||
|
|
||||||
// Check password
|
// Check password
|
||||||
if ($this->authentication->authenticate($this->session['user']['username'], $values['current_password'])) {
|
if ($this->authentication->authenticate($this->userSession->getUsername(), $values['current_password'])) {
|
||||||
return array(true, array());
|
return array(true, array());
|
||||||
} else {
|
} else {
|
||||||
return array(false, array('current_password' => array(t('Wrong password'))));
|
return array(false, array('current_password' => array(t('Wrong password'))));
|
||||||
|
|
|
@ -11,17 +11,13 @@ namespace Kanboard\Model;
|
||||||
class UserSession extends Base
|
class UserSession extends Base
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Update user session information
|
* Update user session
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param array $user User data
|
* @param array $user
|
||||||
*/
|
*/
|
||||||
public function refresh(array $user = array())
|
public function initialize(array $user)
|
||||||
{
|
{
|
||||||
if (empty($user)) {
|
|
||||||
$user = $this->user->getById($this->userSession->getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($user['password'])) {
|
if (isset($user['password'])) {
|
||||||
unset($user['password']);
|
unset($user['password']);
|
||||||
}
|
}
|
||||||
|
@ -31,12 +27,13 @@ class UserSession extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
$user['id'] = (int) $user['id'];
|
$user['id'] = (int) $user['id'];
|
||||||
$user['is_admin'] = (bool) $user['is_admin'];
|
$user['is_admin'] = isset($user['is_admin']) ? (bool) $user['is_admin'] : false;
|
||||||
$user['is_project_admin'] = (bool) $user['is_project_admin'];
|
$user['is_project_admin'] = isset($user['is_project_admin']) ? (bool) $user['is_project_admin'] : false;
|
||||||
$user['is_ldap_user'] = (bool) $user['is_ldap_user'];
|
$user['is_ldap_user'] = isset($user['is_ldap_user']) ? (bool) $user['is_ldap_user'] : false;
|
||||||
$user['twofactor_activated'] = (bool) $user['twofactor_activated'];
|
$user['twofactor_activated'] = isset($user['twofactor_activated']) ? (bool) $user['twofactor_activated'] : false;
|
||||||
|
|
||||||
$this->session['user'] = $user;
|
$this->sessionStorage->user = $user;
|
||||||
|
$this->sessionStorage->postAuth = array('validated' => false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,7 +44,7 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function check2FA()
|
public function check2FA()
|
||||||
{
|
{
|
||||||
return isset($this->session['2fa_validated']) && $this->session['2fa_validated'] === true;
|
return isset($this->sessionStorage->postAuth['validated']) && $this->sessionStorage->postAuth['validated'] === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,7 +55,17 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function has2FA()
|
public function has2FA()
|
||||||
{
|
{
|
||||||
return isset($this->session['user']['twofactor_activated']) && $this->session['user']['twofactor_activated'] === true;
|
return isset($this->sessionStorage->user['twofactor_activated']) && $this->sessionStorage->user['twofactor_activated'] === true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable 2FA for the current session
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
*/
|
||||||
|
public function disable2FA()
|
||||||
|
{
|
||||||
|
$this->sessionStorage->user['twofactor_activated'] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,7 +76,7 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function isAdmin()
|
public function isAdmin()
|
||||||
{
|
{
|
||||||
return isset($this->session['user']['is_admin']) && $this->session['user']['is_admin'] === true;
|
return isset($this->sessionStorage->user['is_admin']) && $this->sessionStorage->user['is_admin'] === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,7 +87,7 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function isProjectAdmin()
|
public function isProjectAdmin()
|
||||||
{
|
{
|
||||||
return isset($this->session['user']['is_project_admin']) && $this->session['user']['is_project_admin'] === true;
|
return isset($this->sessionStorage->user['is_project_admin']) && $this->sessionStorage->user['is_project_admin'] === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,7 +98,18 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function getId()
|
public function getId()
|
||||||
{
|
{
|
||||||
return isset($this->session['user']['id']) ? (int) $this->session['user']['id'] : 0;
|
return isset($this->sessionStorage->user['id']) ? (int) $this->sessionStorage->user['id'] : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get username
|
||||||
|
*
|
||||||
|
* @access public
|
||||||
|
* @return integer
|
||||||
|
*/
|
||||||
|
public function getUsername()
|
||||||
|
{
|
||||||
|
return isset($this->sessionStorage->user['username']) ? $this->sessionStorage->user['username'] : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -102,7 +120,7 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function isLogged()
|
public function isLogged()
|
||||||
{
|
{
|
||||||
return ! empty($this->session['user']);
|
return isset($this->sessionStorage->user) && ! empty($this->sessionStorage->user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,7 +132,7 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function getFilters($project_id)
|
public function getFilters($project_id)
|
||||||
{
|
{
|
||||||
return ! empty($_SESSION['filters'][$project_id]) ? $_SESSION['filters'][$project_id] : 'status:open';
|
return ! empty($this->sessionStorage->filters[$project_id]) ? $this->sessionStorage->filters[$project_id] : 'status:open';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,7 +144,7 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function setFilters($project_id, $filters)
|
public function setFilters($project_id, $filters)
|
||||||
{
|
{
|
||||||
$_SESSION['filters'][$project_id] = $filters;
|
$this->sessionStorage->filters[$project_id] = $filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,7 +156,7 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function isBoardCollapsed($project_id)
|
public function isBoardCollapsed($project_id)
|
||||||
{
|
{
|
||||||
return ! empty($_SESSION['board_collapsed'][$project_id]) ? $_SESSION['board_collapsed'][$project_id] : false;
|
return ! empty($this->sessionStorage->boardCollapsed[$project_id]) ? $this->sessionStorage->boardCollapsed[$project_id] : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -146,11 +164,11 @@ class UserSession extends Base
|
||||||
*
|
*
|
||||||
* @access public
|
* @access public
|
||||||
* @param integer $project_id
|
* @param integer $project_id
|
||||||
* @param boolean $collapsed
|
* @param boolean $is_collapsed
|
||||||
*/
|
*/
|
||||||
public function setBoardDisplayMode($project_id, $collapsed)
|
public function setBoardDisplayMode($project_id, $is_collapsed)
|
||||||
{
|
{
|
||||||
$_SESSION['board_collapsed'][$project_id] = $collapsed;
|
$this->sessionStorage->boardCollapsed[$project_id] = $is_collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,7 +179,7 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function setCommentSorting($order)
|
public function setCommentSorting($order)
|
||||||
{
|
{
|
||||||
$this->session['comment_sorting'] = $order;
|
$this->sessionStorage->commentSorting = $order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -172,6 +190,6 @@ class UserSession extends Base
|
||||||
*/
|
*/
|
||||||
public function getCommentSorting()
|
public function getCommentSorting()
|
||||||
{
|
{
|
||||||
return $this->session['comment_sorting'] ?: 'ASC';
|
return empty($this->sessionStorage->commentSorting) ? 'ASC' : $this->sessionStorage->commentSorting;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,13 @@ use Kanboard\Model\Subtask;
|
||||||
*/
|
*/
|
||||||
class Mail extends Base implements NotificationInterface
|
class Mail extends Base implements NotificationInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Notification type
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TYPE = 'email';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send notification to a user
|
* Send notification to a user
|
||||||
*
|
*
|
||||||
|
|
|
@ -12,6 +12,13 @@ use Kanboard\Core\Base;
|
||||||
*/
|
*/
|
||||||
class Web extends Base implements NotificationInterface
|
class Web extends Base implements NotificationInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Notification type
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const TYPE = 'web';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send notification to a user
|
* Send notification to a user
|
||||||
*
|
*
|
||||||
|
|
|
@ -3,9 +3,15 @@
|
||||||
namespace Schema;
|
namespace Schema;
|
||||||
|
|
||||||
use PDO;
|
use PDO;
|
||||||
use Kanboard\Core\Security;
|
use Kanboard\Core\Security\Token;
|
||||||
|
|
||||||
const VERSION = 93;
|
const VERSION = 94;
|
||||||
|
|
||||||
|
function version_94(PDO $pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE `projects` DROP INDEX `name`');
|
||||||
|
$pdo->exec('ALTER TABLE `projects` DROP INDEX `name_2`');
|
||||||
|
}
|
||||||
|
|
||||||
function version_93(PDO $pdo)
|
function version_93(PDO $pdo)
|
||||||
{
|
{
|
||||||
|
@ -869,7 +875,7 @@ function version_20(PDO $pdo)
|
||||||
function version_19(PDO $pdo)
|
function version_19(PDO $pdo)
|
||||||
{
|
{
|
||||||
$pdo->exec("ALTER TABLE config ADD COLUMN api_token VARCHAR(255) DEFAULT ''");
|
$pdo->exec("ALTER TABLE config ADD COLUMN api_token VARCHAR(255) DEFAULT ''");
|
||||||
$pdo->exec("UPDATE config SET api_token='".Security::generateToken()."'");
|
$pdo->exec("UPDATE config SET api_token='".Token::getToken()."'");
|
||||||
}
|
}
|
||||||
|
|
||||||
function version_18(PDO $pdo)
|
function version_18(PDO $pdo)
|
||||||
|
@ -1091,6 +1097,6 @@ function version_1(PDO $pdo)
|
||||||
$pdo->exec("
|
$pdo->exec("
|
||||||
INSERT INTO config
|
INSERT INTO config
|
||||||
(webhooks_token)
|
(webhooks_token)
|
||||||
VALUES ('".Security::generateToken()."')
|
VALUES ('".Token::getToken()."')
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,14 @@
|
||||||
namespace Schema;
|
namespace Schema;
|
||||||
|
|
||||||
use PDO;
|
use PDO;
|
||||||
use Kanboard\Core\Security;
|
use Kanboard\Core\Security\Token;
|
||||||
|
|
||||||
const VERSION = 73;
|
const VERSION = 74;
|
||||||
|
|
||||||
|
function version_74(PDO $pdo)
|
||||||
|
{
|
||||||
|
$pdo->exec('ALTER TABLE projects DROP CONSTRAINT IF EXISTS projects_name_key');
|
||||||
|
}
|
||||||
|
|
||||||
function version_73(PDO $pdo)
|
function version_73(PDO $pdo)
|
||||||
{
|
{
|
||||||
|
@ -994,6 +999,6 @@ function version_1(PDO $pdo)
|
||||||
$pdo->exec("
|
$pdo->exec("
|
||||||
INSERT INTO config
|
INSERT INTO config
|
||||||
(webhooks_token, api_token)
|
(webhooks_token, api_token)
|
||||||
VALUES ('".Security::generateToken()."', '".Security::generateToken()."')
|
VALUES ('".Token::getToken()."', '".Token::getToken()."')
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Schema;
|
namespace Schema;
|
||||||
|
|
||||||
use Kanboard\Core\Security;
|
use Kanboard\Core\Security\Token;
|
||||||
use PDO;
|
use PDO;
|
||||||
|
|
||||||
const VERSION = 88;
|
const VERSION = 88;
|
||||||
|
@ -799,7 +799,7 @@ function version_20(PDO $pdo)
|
||||||
function version_19(PDO $pdo)
|
function version_19(PDO $pdo)
|
||||||
{
|
{
|
||||||
$pdo->exec("ALTER TABLE config ADD COLUMN api_token TEXT DEFAULT ''");
|
$pdo->exec("ALTER TABLE config ADD COLUMN api_token TEXT DEFAULT ''");
|
||||||
$pdo->exec("UPDATE config SET api_token='".Security::generateToken()."'");
|
$pdo->exec("UPDATE config SET api_token='".Token::getToken()."'");
|
||||||
}
|
}
|
||||||
|
|
||||||
function version_18(PDO $pdo)
|
function version_18(PDO $pdo)
|
||||||
|
@ -1026,7 +1026,7 @@ function version_1(PDO $pdo)
|
||||||
$pdo->exec("
|
$pdo->exec("
|
||||||
CREATE TABLE projects (
|
CREATE TABLE projects (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
name TEXT NOCASE NOT NULL UNIQUE,
|
name TEXT NOCASE NOT NULL,
|
||||||
is_active INTEGER DEFAULT 1
|
is_active INTEGER DEFAULT 1
|
||||||
)
|
)
|
||||||
");
|
");
|
||||||
|
@ -1068,6 +1068,6 @@ function version_1(PDO $pdo)
|
||||||
$pdo->exec("
|
$pdo->exec("
|
||||||
INSERT INTO config
|
INSERT INTO config
|
||||||
(webhooks_token)
|
(webhooks_token)
|
||||||
VALUES ('".Security::generateToken()."')
|
VALUES ('".Token::getToken()."')
|
||||||
");
|
");
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,11 @@ use Kanboard\Core\ObjectStorage\FileStorage;
|
||||||
use Kanboard\Core\Paginator;
|
use Kanboard\Core\Paginator;
|
||||||
use Kanboard\Core\OAuth2;
|
use Kanboard\Core\OAuth2;
|
||||||
use Kanboard\Core\Tool;
|
use Kanboard\Core\Tool;
|
||||||
|
use Kanboard\Core\Http\Client as HttpClient;
|
||||||
use Kanboard\Model\UserNotificationType;
|
use Kanboard\Model\UserNotificationType;
|
||||||
use Kanboard\Model\ProjectNotificationType;
|
use Kanboard\Model\ProjectNotificationType;
|
||||||
|
use Kanboard\Notification\Mail as MailNotification;
|
||||||
|
use Kanboard\Notification\Web as WebNotification;
|
||||||
|
|
||||||
class ClassProvider implements ServiceProviderInterface
|
class ClassProvider implements ServiceProviderInterface
|
||||||
{
|
{
|
||||||
|
@ -81,19 +84,23 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
'Core' => array(
|
'Core' => array(
|
||||||
'DateParser',
|
'DateParser',
|
||||||
'Helper',
|
'Helper',
|
||||||
'HttpClient',
|
|
||||||
'Lexer',
|
'Lexer',
|
||||||
'Request',
|
|
||||||
'Router',
|
|
||||||
'Session',
|
|
||||||
'Template',
|
'Template',
|
||||||
),
|
),
|
||||||
|
'Core\Http' => array(
|
||||||
|
'Request',
|
||||||
|
'Response',
|
||||||
|
'Router',
|
||||||
|
),
|
||||||
'Core\Cache' => array(
|
'Core\Cache' => array(
|
||||||
'MemoryCache',
|
'MemoryCache',
|
||||||
),
|
),
|
||||||
'Core\Plugin' => array(
|
'Core\Plugin' => array(
|
||||||
'Hook',
|
'Hook',
|
||||||
),
|
),
|
||||||
|
'Core\Security' => array(
|
||||||
|
'Token',
|
||||||
|
),
|
||||||
'Integration' => array(
|
'Integration' => array(
|
||||||
'BitbucketWebhook',
|
'BitbucketWebhook',
|
||||||
'GithubWebhook',
|
'GithubWebhook',
|
||||||
|
@ -113,6 +120,10 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
return new OAuth2($c);
|
return new OAuth2($c);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$container['httpClient'] = function ($c) {
|
||||||
|
return new HttpClient($c);
|
||||||
|
};
|
||||||
|
|
||||||
$container['htmlConverter'] = function () {
|
$container['htmlConverter'] = function () {
|
||||||
return new HtmlConverter(array('strip_tags' => true));
|
return new HtmlConverter(array('strip_tags' => true));
|
||||||
};
|
};
|
||||||
|
@ -131,8 +142,8 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
|
|
||||||
$container['userNotificationType'] = function ($container) {
|
$container['userNotificationType'] = function ($container) {
|
||||||
$type = new UserNotificationType($container);
|
$type = new UserNotificationType($container);
|
||||||
$type->setType('email', t('Email'), '\Kanboard\Notification\Mail');
|
$type->setType(MailNotification::TYPE, t('Email'), '\Kanboard\Notification\Mail');
|
||||||
$type->setType('web', t('Web'), '\Kanboard\Notification\Web');
|
$type->setType(WebNotification::TYPE, t('Web'), '\Kanboard\Notification\Web');
|
||||||
return $type;
|
return $type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -146,5 +157,7 @@ class ClassProvider implements ServiceProviderInterface
|
||||||
$container['pluginLoader'] = new Loader($container);
|
$container['pluginLoader'] = new Loader($container);
|
||||||
|
|
||||||
$container['cspRules'] = array('style-src' => "'self' 'unsafe-inline'", 'img-src' => '* data:');
|
$container['cspRules'] = array('style-src' => "'self' 'unsafe-inline'", 'img-src' => '* data:');
|
||||||
|
|
||||||
|
return $container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ class DatabaseProvider implements ServiceProviderInterface
|
||||||
$container['db'] = $this->getInstance();
|
$container['db'] = $this->getInstance();
|
||||||
$container['db']->stopwatch = DEBUG;
|
$container['db']->stopwatch = DEBUG;
|
||||||
$container['db']->logQueries = DEBUG;
|
$container['db']->logQueries = DEBUG;
|
||||||
|
|
||||||
|
return $container;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue