diff options
Diffstat (limited to 'app')
43 files changed, 454 insertions, 15 deletions
diff --git a/app/Api/Middleware/AuthenticationMiddleware.php b/app/Api/Middleware/AuthenticationMiddleware.php index 8e309593..c4fa874a 100644 --- a/app/Api/Middleware/AuthenticationMiddleware.php +++ b/app/Api/Middleware/AuthenticationMiddleware.php @@ -28,6 +28,7 @@ class AuthenticationMiddleware extends Base implements MiddlewareInterface public function execute($username, $password, $procedureName) { $this->dispatcher->dispatch('app.bootstrap'); + $this->sessionStorage->scope = 'API'; if ($this->isUserAuthenticated($username, $password)) { $this->userSession->initialize($this->userModel->getByUsername($username)); diff --git a/app/Auth/ApiAccessTokenAuth.php b/app/Auth/ApiAccessTokenAuth.php new file mode 100644 index 00000000..12ab21a7 --- /dev/null +++ b/app/Auth/ApiAccessTokenAuth.php @@ -0,0 +1,119 @@ +<?php + +namespace Kanboard\Auth; + +use Kanboard\Core\Base; +use Kanboard\Core\Security\PasswordAuthenticationProviderInterface; +use Kanboard\Model\UserModel; +use Kanboard\User\DatabaseUserProvider; + +/** + * API Access Token Authentication Provider + * + * @package Kanboard\Auth + * @author Frederic Guillot + */ +class ApiAccessTokenAuth extends Base implements PasswordAuthenticationProviderInterface +{ + /** + * User properties + * + * @access protected + * @var array + */ + protected $userInfo = array(); + + /** + * Username + * + * @access protected + * @var string + */ + protected $username = ''; + + /** + * Password + * + * @access protected + * @var string + */ + protected $password = ''; + + /** + * Get authentication provider name + * + * @access public + * @return string + */ + public function getName() + { + return 'API Access Token'; + } + + /** + * Authenticate the user + * + * @access public + * @return boolean + */ + public function authenticate() + { + if (! isset($this->sessionStorage->scope) || $this->sessionStorage->scope !== 'API') { + $this->logger->debug(__METHOD__.': Authentication provider skipped because invalid scope'); + return false; + } + + $user = $this->db + ->table(UserModel::TABLE) + ->columns('id', 'password') + ->eq('username', $this->username) + ->eq('api_access_token', $this->password) + ->notNull('api_access_token') + ->eq('is_active', 1) + ->findOne(); + + if (! empty($user)) { + $this->userInfo = $user; + return true; + } + + return false; + } + + /** + * Get user object + * + * @access public + * @return \Kanboard\User\DatabaseUserProvider + */ + public function getUser() + { + if (empty($this->userInfo)) { + return null; + } + + return new DatabaseUserProvider($this->userInfo); + } + + /** + * Set username + * + * @access public + * @param string $username + */ + public function setUsername($username) + { + $this->username = $username; + } + + /** + * Set password + * + * @access public + * @param string $password + */ + public function setPassword($password) + { + $this->password = $password; + } +} diff --git a/app/Auth/DatabaseAuth.php b/app/Auth/DatabaseAuth.php index ecb42c17..84a1e019 100644 --- a/app/Auth/DatabaseAuth.php +++ b/app/Auth/DatabaseAuth.php @@ -11,7 +11,7 @@ use Kanboard\User\DatabaseUserProvider; /** * Database Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class DatabaseAuth extends Base implements PasswordAuthenticationProviderInterface, SessionCheckProviderInterface diff --git a/app/Auth/LdapAuth.php b/app/Auth/LdapAuth.php index a8dcfcb6..05ffbebf 100644 --- a/app/Auth/LdapAuth.php +++ b/app/Auth/LdapAuth.php @@ -12,7 +12,7 @@ use Kanboard\Core\Security\PasswordAuthenticationProviderInterface; /** * LDAP Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class LdapAuth extends Base implements PasswordAuthenticationProviderInterface diff --git a/app/Auth/RememberMeAuth.php b/app/Auth/RememberMeAuth.php index 5d0a8b2e..e0f4ceb6 100644 --- a/app/Auth/RememberMeAuth.php +++ b/app/Auth/RememberMeAuth.php @@ -7,9 +7,9 @@ use Kanboard\Core\Security\PreAuthenticationProviderInterface; use Kanboard\User\DatabaseUserProvider; /** - * Rember Me Cookie Authentication Provider + * RememberMe Cookie Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class RememberMeAuth extends Base implements PreAuthenticationProviderInterface diff --git a/app/Auth/ReverseProxyAuth.php b/app/Auth/ReverseProxyAuth.php index fdf936b1..02afc302 100644 --- a/app/Auth/ReverseProxyAuth.php +++ b/app/Auth/ReverseProxyAuth.php @@ -10,7 +10,7 @@ use Kanboard\User\ReverseProxyUserProvider; /** * Reverse-Proxy Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class ReverseProxyAuth extends Base implements PreAuthenticationProviderInterface, SessionCheckProviderInterface diff --git a/app/Auth/TotpAuth.php b/app/Auth/TotpAuth.php index 8e1ebe35..abfb2168 100644 --- a/app/Auth/TotpAuth.php +++ b/app/Auth/TotpAuth.php @@ -11,7 +11,7 @@ use Kanboard\Core\Security\PostAuthenticationProviderInterface; /** * TOTP Authentication Provider * - * @package auth + * @package Kanboard\Auth * @author Frederic Guillot */ class TotpAuth extends Base implements PostAuthenticationProviderInterface diff --git a/app/Controller/UserApiAccessController.php b/app/Controller/UserApiAccessController.php new file mode 100644 index 00000000..e03514d5 --- /dev/null +++ b/app/Controller/UserApiAccessController.php @@ -0,0 +1,50 @@ +<?php + +namespace Kanboard\Controller; + +use Kanboard\Core\Security\Token; + +/** + * Class UserApiAccessController + * + * @package Kanboard\Controller + * @author Frederic Guillot + */ +class UserApiAccessController extends BaseController +{ + public function show() + { + $user = $this->getUser(); + + return $this->response->html($this->helper->layout->user('user_api_access/show', array( + 'user' => $user, + 'title' => t('API User Access'), + ))); + } + + public function generate() + { + $user = $this->getUser(); + $this->checkCSRFParam(); + + $this->userModel->update(array( + 'id' => $user['id'], + 'api_access_token' => Token::getToken(), + )); + + $this->response->redirect($this->helper->url->to('UserApiAccessController', 'show', array('user_id' => $user['id']))); + } + + public function remove() + { + $user = $this->getUser(); + $this->checkCSRFParam(); + + $this->userModel->update(array( + 'id' => $user['id'], + 'api_access_token' => null, + )); + + $this->response->redirect($this->helper->url->to('UserApiAccessController', 'show', array('user_id' => $user['id']))); + } +}
\ No newline at end of file diff --git a/app/Core/Session/SessionStorage.php b/app/Core/Session/SessionStorage.php index 9e93602c..e6478d8d 100644 --- a/app/Core/Session/SessionStorage.php +++ b/app/Core/Session/SessionStorage.php @@ -19,6 +19,7 @@ namespace Kanboard\Core\Session; * @property bool $hasSubtaskInProgress * @property bool $hasRememberMe * @property bool $boardCollapsed + * @property string $scope * @property bool $twoFactorBeforeCodeCalled * @property string $twoFactorSecret * @property string $oauthState diff --git a/app/Locale/bs_BA/translations.php b/app/Locale/bs_BA/translations.php index cb9ad9d5..e27a4501 100644 --- a/app/Locale/bs_BA/translations.php +++ b/app/Locale/bs_BA/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/cs_CZ/translations.php b/app/Locale/cs_CZ/translations.php index 8541f303..5091de00 100644 --- a/app/Locale/cs_CZ/translations.php +++ b/app/Locale/cs_CZ/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/da_DK/translations.php b/app/Locale/da_DK/translations.php index 78a6d35e..2ca864e5 100644 --- a/app/Locale/da_DK/translations.php +++ b/app/Locale/da_DK/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/de_DE/translations.php b/app/Locale/de_DE/translations.php index 433b7a2f..950a3b77 100644 --- a/app/Locale/de_DE/translations.php +++ b/app/Locale/de_DE/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Verschieben einer Aufgabe ist nicht erlaubt', 'This value must be in the range %d to %d' => 'Dieser Wert muss im Bereich %d bis %d sein', 'You are not allowed to move this task.' => 'Sie haben nicht die Berechtigung, diese Aufgabe zu verschieben.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/el_GR/translations.php b/app/Locale/el_GR/translations.php index ad17b4ed..7b7d855e 100644 --- a/app/Locale/el_GR/translations.php +++ b/app/Locale/el_GR/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/es_ES/translations.php b/app/Locale/es_ES/translations.php index b3a68751..984d42db 100644 --- a/app/Locale/es_ES/translations.php +++ b/app/Locale/es_ES/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/fi_FI/translations.php b/app/Locale/fi_FI/translations.php index 733625b6..41e51fa1 100644 --- a/app/Locale/fi_FI/translations.php +++ b/app/Locale/fi_FI/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/fr_FR/translations.php b/app/Locale/fr_FR/translations.php index 59f4609e..daac98ed 100644 --- a/app/Locale/fr_FR/translations.php +++ b/app/Locale/fr_FR/translations.php @@ -1279,4 +1279,13 @@ return array( 'Moving a task is not permitted' => 'Déplaçer une tâche n\'est pas autorisé', 'This value must be in the range %d to %d' => 'Cette valeur doit être définie entre %d et %d', 'You are not allowed to move this task.' => 'Vous n\'êtes pas autorisé à déplacer cette tâche.', + 'API User Access' => 'Accès utilisateur de l\'API', + 'Preview' => 'Aperçu', + 'Write' => 'Écrire', + 'Write your text in Markdown' => 'Écrivez votre texte en Markdown', + 'New External Task: %s' => 'Nouvelle tâche externe : %s', + 'No personal API access token registered.' => 'Aucun jeton d\'accès personnel à l\'API enregistré.', + 'Your personal API access token is "%s"' => 'Votre jeton d\'accès personnel à l\'API est « %s »', + 'Remove your token' => 'Supprimer votre jeton', + 'Generate a new token' => 'Générer un nouveau jeton', ); diff --git a/app/Locale/hu_HU/translations.php b/app/Locale/hu_HU/translations.php index b5a23428..784c27ba 100644 --- a/app/Locale/hu_HU/translations.php +++ b/app/Locale/hu_HU/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/id_ID/translations.php b/app/Locale/id_ID/translations.php index e711a512..9398d51d 100644 --- a/app/Locale/id_ID/translations.php +++ b/app/Locale/id_ID/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/it_IT/translations.php b/app/Locale/it_IT/translations.php index 3e27120b..65defe86 100644 --- a/app/Locale/it_IT/translations.php +++ b/app/Locale/it_IT/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Spostare task non è permesso', 'This value must be in the range %d to %d' => 'Questo valore deve essere compreso tra %d e %d', 'You are not allowed to move this task.' => 'Non ti è permesso spostare questo task.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/ja_JP/translations.php b/app/Locale/ja_JP/translations.php index b9feed07..d0487fb7 100644 --- a/app/Locale/ja_JP/translations.php +++ b/app/Locale/ja_JP/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/ko_KR/translations.php b/app/Locale/ko_KR/translations.php index 8c882b8a..a613b467 100644 --- a/app/Locale/ko_KR/translations.php +++ b/app/Locale/ko_KR/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => '할일 이동이 거부되었습니다.', 'This value must be in the range %d to %d' => '값의 범위는 %d 부터 %d 까지 입니다.', 'You are not allowed to move this task.' => '당신은 할일 이동이 거부되었습니다.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/my_MY/translations.php b/app/Locale/my_MY/translations.php index 048d8b4b..be335dec 100644 --- a/app/Locale/my_MY/translations.php +++ b/app/Locale/my_MY/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/nb_NO/translations.php b/app/Locale/nb_NO/translations.php index 0d2a340d..6b49545c 100644 --- a/app/Locale/nb_NO/translations.php +++ b/app/Locale/nb_NO/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/nl_NL/translations.php b/app/Locale/nl_NL/translations.php index e1745c14..44434a4e 100644 --- a/app/Locale/nl_NL/translations.php +++ b/app/Locale/nl_NL/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/pl_PL/translations.php b/app/Locale/pl_PL/translations.php index 164abe0c..51c0fef8 100644 --- a/app/Locale/pl_PL/translations.php +++ b/app/Locale/pl_PL/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/pt_BR/translations.php b/app/Locale/pt_BR/translations.php index 637de30e..c0fa2387 100644 --- a/app/Locale/pt_BR/translations.php +++ b/app/Locale/pt_BR/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Mover uma tarefa não é permitido', 'This value must be in the range %d to %d' => 'Este valor precisa estar no intervalo %d até %d', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/pt_PT/translations.php b/app/Locale/pt_PT/translations.php index 3b8975d9..47763d30 100644 --- a/app/Locale/pt_PT/translations.php +++ b/app/Locale/pt_PT/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Não é permitido mover uma tarefa', 'This value must be in the range %d to %d' => 'Este valor deve estar entre %d e %d', 'You are not allowed to move this task.' => 'Não lhe é permitido mover esta tarefa.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/ru_RU/translations.php b/app/Locale/ru_RU/translations.php index 1e5c02c2..4d821f6a 100644 --- a/app/Locale/ru_RU/translations.php +++ b/app/Locale/ru_RU/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Перемещение задачи не разрешено', 'This value must be in the range %d to %d' => 'Значение должно находиться в диапазоне от %d до %d', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/sr_Latn_RS/translations.php b/app/Locale/sr_Latn_RS/translations.php index 2f061260..470e3390 100644 --- a/app/Locale/sr_Latn_RS/translations.php +++ b/app/Locale/sr_Latn_RS/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/sv_SE/translations.php b/app/Locale/sv_SE/translations.php index f32728e7..2ec4fa82 100644 --- a/app/Locale/sv_SE/translations.php +++ b/app/Locale/sv_SE/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/th_TH/translations.php b/app/Locale/th_TH/translations.php index 4025714a..5e0912fc 100644 --- a/app/Locale/th_TH/translations.php +++ b/app/Locale/th_TH/translations.php @@ -1278,4 +1278,13 @@ return array( // 'Moving a task is not permitted' => '', // 'This value must be in the range %d to %d' => '', // 'You are not allowed to move this task.' => '', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/tr_TR/translations.php b/app/Locale/tr_TR/translations.php index 24399891..1a648bbf 100644 --- a/app/Locale/tr_TR/translations.php +++ b/app/Locale/tr_TR/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => 'Görev taşımaya izin verilmemiş', 'This value must be in the range %d to %d' => 'Bu değer şu aralıkta olmalı: "%d" "%d"', 'You are not allowed to move this task.' => 'Bu görevi taşımaya izniniz yok.', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Locale/zh_CN/translations.php b/app/Locale/zh_CN/translations.php index e27a8a56..c87adbec 100644 --- a/app/Locale/zh_CN/translations.php +++ b/app/Locale/zh_CN/translations.php @@ -1278,4 +1278,13 @@ return array( 'Moving a task is not permitted' => '禁止移动任务', 'This value must be in the range %d to %d' => '输入值必须在%d到%d之间', 'You are not allowed to move this task.' => '你不能移动此任务', + // 'API User Access' => '', + // 'Preview' => '', + // 'Write' => '', + // 'Write your text in Markdown' => '', + // 'New External Task: %s' => '', + // 'No personal API access token registered.' => '', + // 'Your personal API access token is "%s"' => '', + // 'Remove your token' => '', + // 'Generate a new token' => '', ); diff --git a/app/Schema/Mysql.php b/app/Schema/Mysql.php index 17285b12..fac8688a 100644 --- a/app/Schema/Mysql.php +++ b/app/Schema/Mysql.php @@ -6,7 +6,12 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 117; +const VERSION = 118; + +function version_118(PDO $pdo) +{ + $pdo->exec('ALTER TABLE `users` ADD COLUMN `api_access_token` VARCHAR(255) DEFAULT NULL'); +} function version_117(PDO $pdo) { diff --git a/app/Schema/Postgres.php b/app/Schema/Postgres.php index 082c31eb..32a7a744 100644 --- a/app/Schema/Postgres.php +++ b/app/Schema/Postgres.php @@ -6,7 +6,12 @@ use PDO; use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; -const VERSION = 96; +const VERSION = 97; + +function version_97(PDO $pdo) +{ + $pdo->exec('ALTER TABLE "users" ADD COLUMN api_access_token VARCHAR(255) DEFAULT NULL'); +} function version_96(PDO $pdo) { diff --git a/app/Schema/Sql/mysql.sql b/app/Schema/Sql/mysql.sql index b39330e2..0ee88d88 100644 --- a/app/Schema/Sql/mysql.sql +++ b/app/Schema/Sql/mysql.sql @@ -715,6 +715,7 @@ CREATE TABLE `users` ( `role` varchar(25) NOT NULL DEFAULT 'app-user', `is_active` tinyint(1) DEFAULT '1', `avatar_path` varchar(255) DEFAULT NULL, + `api_access_token` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `users_username_idx` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; @@ -738,7 +739,7 @@ CREATE TABLE `users` ( LOCK TABLES `settings` WRITE; /*!40000 ALTER TABLE `settings` DISABLE KEYS */; -INSERT INTO `settings` VALUES ('api_token','f9ae1d30899c88091642f4e996ff97b1e5db516b5edd256793246b18b637',0,0),('application_currency','USD',0,0),('application_datetime_format','m/d/Y H:i',1,1480728474),('application_date_format','m/d/Y',1,1480728474),('application_language','fr_FR',1,1480728474),('application_stylesheet','',1,1480728474),('application_timezone','UTC',1,1480728474),('application_time_format','H:i',1,1480728474),('application_url','',1,1480728474),('board_columns','',0,0),('board_highlight_period','172800',0,0),('board_private_refresh_interval','10',0,0),('board_public_refresh_interval','60',0,0),('calendar_project_tasks','date_started',0,0),('calendar_user_subtasks_time_tracking','0',0,0),('calendar_user_tasks','date_started',0,0),('cfd_include_closed_tasks','1',0,0),('default_color','yellow',0,0),('integration_gravatar','0',0,0),('password_reset','checked',1,1480728474),('project_categories','',0,0),('subtask_restriction','0',0,0),('subtask_time_tracking','1',0,0),('webhook_token','382dae506e2bd5a4e45709c275827b0bbc7bee9f683b2320c78299deb36e',0,0),('webhook_url','',0,0); +INSERT INTO `settings` VALUES ('api_token','f149956cb60c88d01123a28964fc035b1ce4513be454f2a85fe6b4ca3758',0,0),('application_currency','USD',0,0),('application_date_format','m/d/Y',0,0),('application_language','en_US',0,0),('application_stylesheet','',0,0),('application_timezone','UTC',0,0),('application_url','',0,0),('board_columns','',0,0),('board_highlight_period','172800',0,0),('board_private_refresh_interval','10',0,0),('board_public_refresh_interval','60',0,0),('calendar_project_tasks','date_started',0,0),('calendar_user_subtasks_time_tracking','0',0,0),('calendar_user_tasks','date_started',0,0),('cfd_include_closed_tasks','1',0,0),('default_color','yellow',0,0),('integration_gravatar','0',0,0),('password_reset','1',0,0),('project_categories','',0,0),('subtask_restriction','0',0,0),('subtask_time_tracking','1',0,0),('webhook_token','47d1d896b6612234c7543eb3f3a09a0a669f77a079d13ad3d810ccb79896',0,0),('webhook_url','',0,0); /*!40000 ALTER TABLE `settings` ENABLE KEYS */; UNLOCK TABLES; /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; @@ -767,4 +768,4 @@ UNLOCK TABLES; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -INSERT INTO users (username, password, role) VALUES ('admin', '$2y$10$ZYX2JNGPsH/SMc3UBk0rYu2LYCLYRVEqokhOjIULKXs6RjvaV2RBu', 'app-admin');INSERT INTO schema_version VALUES ('117'); +INSERT INTO users (username, password, role) VALUES ('admin', '$2y$10$R1zYk04d96KcHRpd9.r5I.5I6mgKIgUdsaISZYmaDLPIJCUO0FFJG', 'app-admin');INSERT INTO schema_version VALUES ('118'); diff --git a/app/Schema/Sql/postgres.sql b/app/Schema/Sql/postgres.sql index 024c5cda..7a93b9f1 100644 --- a/app/Schema/Sql/postgres.sql +++ b/app/Schema/Sql/postgres.sql @@ -1245,7 +1245,8 @@ CREATE TABLE "users" ( "gitlab_id" integer, "role" character varying(25) DEFAULT 'app-user'::character varying NOT NULL, "is_active" boolean DEFAULT true, - "avatar_path" character varying(255) + "avatar_path" character varying(255), + "api_access_token" character varying(255) DEFAULT NULL::character varying ); @@ -2544,8 +2545,8 @@ INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('board_high INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('board_public_refresh_interval', '60', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('board_private_refresh_interval', '10', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('board_columns', '', 0, 0); -INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('webhook_token', 'c12181512f9cfd66a6b2af4edf199390b922bbb8a259dc5397c2329ed47c', 0, 0); -INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('api_token', '4e05046a5cb5b907da712ab02af98e9752da48bfacc0a625c4c08493bc8f', 0, 0); +INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('webhook_token', '8687190194e06d34c2cd84a57b36f67696c971c2f8e453f96e59eccb8e73', 0, 0); +INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('api_token', '8381164131e3995ca17c754a5b0cf7039d66b9f389b80250978de9fcf2f5', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('application_language', 'en_US', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('application_timezone', 'UTC', 0, 0); INSERT INTO settings (option, value, changed_by, changed_on) VALUES ('application_url', '', 0, 0); @@ -2615,4 +2616,4 @@ SELECT pg_catalog.setval('links_id_seq', 11, true); -- PostgreSQL database dump complete -- -INSERT INTO users (username, password, role) VALUES ('admin', '$2y$10$ZYX2JNGPsH/SMc3UBk0rYu2LYCLYRVEqokhOjIULKXs6RjvaV2RBu', 'app-admin');INSERT INTO schema_version VALUES ('96'); +INSERT INTO users (username, password, role) VALUES ('admin', '$2y$10$R1zYk04d96KcHRpd9.r5I.5I6mgKIgUdsaISZYmaDLPIJCUO0FFJG', 'app-admin');INSERT INTO schema_version VALUES ('97'); diff --git a/app/Schema/Sqlite.php b/app/Schema/Sqlite.php index edf6ce63..11dcd537 100644 --- a/app/Schema/Sqlite.php +++ b/app/Schema/Sqlite.php @@ -6,7 +6,12 @@ use Kanboard\Core\Security\Token; use Kanboard\Core\Security\Role; use PDO; -const VERSION = 107; +const VERSION = 108; + +function version_108(PDO $pdo) +{ + $pdo->exec('ALTER TABLE users ADD COLUMN api_access_token VARCHAR(255) DEFAULT NULL'); +} function version_107(PDO $pdo) { diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php index adff1e63..c2dad0e6 100644 --- a/app/ServiceProvider/AuthenticationProvider.php +++ b/app/ServiceProvider/AuthenticationProvider.php @@ -2,6 +2,7 @@ namespace Kanboard\ServiceProvider; +use Kanboard\Auth\ApiAccessTokenAuth; use Pimple\Container; use Pimple\ServiceProviderInterface; use Kanboard\Core\Security\AuthenticationManager; @@ -44,6 +45,8 @@ class AuthenticationProvider implements ServiceProviderInterface $container['authenticationManager']->register(new LdapAuth($container)); } + $container['authenticationManager']->register(new ApiAccessTokenAuth($container)); + $container['projectAccessMap'] = $this->getProjectAccessMap(); $container['applicationAccessMap'] = $this->getApplicationAccessMap(); $container['apiAccessMap'] = $this->getApiAccessMap(); diff --git a/app/ServiceProvider/RouteProvider.php b/app/ServiceProvider/RouteProvider.php index 0d1a7931..52687647 100644 --- a/app/ServiceProvider/RouteProvider.php +++ b/app/ServiceProvider/RouteProvider.php @@ -158,6 +158,7 @@ class RouteProvider implements ServiceProviderInterface $container['route']->addRoute('user/:user_id/authentication', 'UserCredentialController', 'changeAuthentication'); $container['route']->addRoute('user/:user_id/2fa', 'TwoFactorController', 'index'); $container['route']->addRoute('user/:user_id/avatar', 'AvatarFileController', 'show'); + $container['route']->addRoute('user/:user_id/api', 'UserApiAccessController', 'show'); // Groups $container['route']->addRoute('groups', 'GroupListController', 'index'); diff --git a/app/Template/user_api_access/show.php b/app/Template/user_api_access/show.php new file mode 100644 index 00000000..3d58e0d5 --- /dev/null +++ b/app/Template/user_api_access/show.php @@ -0,0 +1,17 @@ +<div class="page-header"> + <h2><?= t('API User Access') ?></h2> +</div> + +<p class="alert"> + <?php if (empty($user['api_access_token'])): ?> + <?= t('No personal API access token registered.') ?> + <?php else: ?> + <?= t('Your personal API access token is "%s"', $user['api_access_token']) ?> + <?php endif ?> +</p> + +<?php if (! empty($user['api_access_token'])): ?> + <?= $this->url->link(t('Remove your token'), 'UserApiAccessController', 'remove', array('user_id' => $user['id']), true, 'btn btn-red') ?> +<?php endif ?> + +<?= $this->url->link(t('Generate a new token'), 'UserApiAccessController', 'generate', array('user_id' => $user['id']), true, 'btn btn-blue') ?> diff --git a/app/Template/user_view/sidebar.php b/app/Template/user_view/sidebar.php index a80daefa..ef494e42 100644 --- a/app/Template/user_view/sidebar.php +++ b/app/Template/user_view/sidebar.php @@ -90,6 +90,11 @@ <?= $this->url->link(t('Integrations'), 'UserViewController', 'integrations', array('user_id' => $user['id'])) ?> </li> <?php endif ?> + <?php if ($this->user->hasAccess('UserApiAccessController', 'show')): ?> + <li <?= $this->app->checkMenuSelection('UserApiAccessController', 'show') ?>> + <?= $this->url->link(t('API'), 'UserApiAccessController', 'show', array('user_id' => $user['id'])) ?> + </li> + <?php endif ?> <?php endif ?> <?php if ($this->user->hasAccess('UserCredentialController', 'changeAuthentication')): ?> |