summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/Api/AuthApi.php82
-rw-r--r--app/Api/BaseApi.php45
-rw-r--r--app/Api/Middleware/AuthenticationApiMiddleware.php130
-rw-r--r--app/Core/Base.php1
-rw-r--r--app/ServiceProvider/ApiProvider.php74
-rw-r--r--app/common.php1
-rw-r--r--composer.json2
-rw-r--r--composer.lock17
-rw-r--r--jsonrpc.php46
9 files changed, 218 insertions, 180 deletions
diff --git a/app/Api/AuthApi.php b/app/Api/AuthApi.php
deleted file mode 100644
index 1cbce5ae..00000000
--- a/app/Api/AuthApi.php
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-
-namespace Kanboard\Api;
-
-use JsonRPC\Exception\AuthenticationFailureException;
-
-/**
- * Base class
- *
- * @package Kanboard\Api
- * @author Frederic Guillot
- */
-class AuthApi extends BaseApi
-{
- /**
- * Check api credentials
- *
- * @access public
- * @param string $username
- * @param string $password
- * @param string $class
- * @param string $method
- * @throws AuthenticationFailureException
- */
- public function checkCredentials($username, $password, $class, $method)
- {
- $this->dispatcher->dispatch('app.bootstrap');
-
- if ($this->isUserAuthenticated($username, $password)) {
- $this->checkProcedurePermission(true, $method);
- $this->userSession->initialize($this->userModel->getByUsername($username));
- } elseif ($this->isAppAuthenticated($username, $password)) {
- $this->checkProcedurePermission(false, $method);
- } else {
- $this->logger->error('API authentication failure for '.$username);
- throw new AuthenticationFailureException('Wrong credentials');
- }
- }
-
- /**
- * Check user credentials
- *
- * @access public
- * @param string $username
- * @param string $password
- * @return boolean
- */
- private function isUserAuthenticated($username, $password)
- {
- return $username !== 'jsonrpc' &&
- ! $this->userLockingModel->isLocked($username) &&
- $this->authenticationManager->passwordAuthentication($username, $password);
- }
-
- /**
- * Check administrative credentials
- *
- * @access public
- * @param string $username
- * @param string $password
- * @return boolean
- */
- private function isAppAuthenticated($username, $password)
- {
- return $username === 'jsonrpc' && $password === $this->getApiToken();
- }
-
- /**
- * Get API Token
- *
- * @access private
- * @return string
- */
- private function getApiToken()
- {
- if (defined('API_AUTHENTICATION_TOKEN')) {
- return API_AUTHENTICATION_TOKEN;
- }
-
- return $this->configModel->get('api_token');
- }
-}
diff --git a/app/Api/BaseApi.php b/app/Api/BaseApi.php
index ae41e5b5..9f69aa65 100644
--- a/app/Api/BaseApi.php
+++ b/app/Api/BaseApi.php
@@ -13,51 +13,6 @@ use Kanboard\Core\Base;
*/
abstract class BaseApi extends Base
{
- private $user_allowed_procedures = array(
- 'getMe',
- 'getMyDashboard',
- 'getMyActivityStream',
- 'createMyPrivateProject',
- 'getMyProjectsList',
- 'getMyProjects',
- 'getMyOverdueTasks',
- );
-
- private $both_allowed_procedures = array(
- 'getTimezone',
- 'getVersion',
- 'getDefaultTaskColor',
- 'getDefaultTaskColors',
- 'getColorList',
- 'getProjectById',
- 'getTask',
- 'getTaskByReference',
- 'getAllTasks',
- 'openTask',
- 'closeTask',
- 'moveTaskPosition',
- 'createTask',
- 'updateTask',
- 'getBoard',
- 'getProjectActivity',
- 'getOverdueTasksByProject',
- 'searchTasks',
- );
-
- public function checkProcedurePermission($is_user, $procedure)
- {
- $is_both_procedure = in_array($procedure, $this->both_allowed_procedures);
- $is_user_procedure = in_array($procedure, $this->user_allowed_procedures);
-
- if ($is_user && ! $is_both_procedure && ! $is_user_procedure) {
- throw new AccessDeniedException('Permission denied');
- } elseif (! $is_user && ! $is_both_procedure && $is_user_procedure) {
- throw new AccessDeniedException('Permission denied');
- }
-
- $this->logger->debug('API call: '.$procedure);
- }
-
public function checkProjectPermission($project_id)
{
if ($this->userSession->isLogged() && ! $this->projectPermissionModel->isUserAllowed($project_id, $this->userSession->getId())) {
diff --git a/app/Api/Middleware/AuthenticationApiMiddleware.php b/app/Api/Middleware/AuthenticationApiMiddleware.php
new file mode 100644
index 00000000..5f63e1a1
--- /dev/null
+++ b/app/Api/Middleware/AuthenticationApiMiddleware.php
@@ -0,0 +1,130 @@
+<?php
+
+namespace Kanboard\Api\Middleware;
+
+use JsonRPC\Exception\AccessDeniedException;
+use JsonRPC\Exception\AuthenticationFailureException;
+use JsonRPC\MiddlewareInterface;
+use Kanboard\Core\Base;
+
+/**
+ * Class AuthenticationApiMiddleware
+ *
+ * @package Kanboard\Api\Middleware
+ * @author Frederic Guillot
+ */
+class AuthenticationApiMiddleware extends Base implements MiddlewareInterface
+{
+ private $user_allowed_procedures = array(
+ 'getMe',
+ 'getMyDashboard',
+ 'getMyActivityStream',
+ 'createMyPrivateProject',
+ 'getMyProjectsList',
+ 'getMyProjects',
+ 'getMyOverdueTasks',
+ );
+
+ private $both_allowed_procedures = array(
+ 'getTimezone',
+ 'getVersion',
+ 'getDefaultTaskColor',
+ 'getDefaultTaskColors',
+ 'getColorList',
+ 'getProjectById',
+ 'getTask',
+ 'getTaskByReference',
+ 'getAllTasks',
+ 'openTask',
+ 'closeTask',
+ 'moveTaskPosition',
+ 'createTask',
+ 'updateTask',
+ 'getBoard',
+ 'getProjectActivity',
+ 'getOverdueTasksByProject',
+ 'searchTasks',
+ );
+
+ /**
+ * Execute Middleware
+ *
+ * @access public
+ * @param string $username
+ * @param string $password
+ * @param string $procedureName
+ * @throws AccessDeniedException
+ * @throws AuthenticationFailureException
+ */
+ public function execute($username, $password, $procedureName)
+ {
+ $this->dispatcher->dispatch('app.bootstrap');
+
+ if ($this->isUserAuthenticated($username, $password)) {
+ $this->checkProcedurePermission(true, $procedureName);
+ $this->userSession->initialize($this->userModel->getByUsername($username));
+ } elseif ($this->isAppAuthenticated($username, $password)) {
+ $this->checkProcedurePermission(false, $procedureName);
+ } else {
+ $this->logger->error('API authentication failure for '.$username);
+ throw new AuthenticationFailureException('Wrong credentials');
+ }
+ }
+
+ /**
+ * Check user credentials
+ *
+ * @access public
+ * @param string $username
+ * @param string $password
+ * @return boolean
+ */
+ private function isUserAuthenticated($username, $password)
+ {
+ return $username !== 'jsonrpc' &&
+ ! $this->userLockingModel->isLocked($username) &&
+ $this->authenticationManager->passwordAuthentication($username, $password);
+ }
+
+ /**
+ * Check administrative credentials
+ *
+ * @access public
+ * @param string $username
+ * @param string $password
+ * @return boolean
+ */
+ private function isAppAuthenticated($username, $password)
+ {
+ return $username === 'jsonrpc' && $password === $this->getApiToken();
+ }
+
+ /**
+ * Get API Token
+ *
+ * @access private
+ * @return string
+ */
+ private function getApiToken()
+ {
+ if (defined('API_AUTHENTICATION_TOKEN')) {
+ return API_AUTHENTICATION_TOKEN;
+ }
+
+ return $this->configModel->get('api_token');
+ }
+
+ public function checkProcedurePermission($is_user, $procedure)
+ {
+ $is_both_procedure = in_array($procedure, $this->both_allowed_procedures);
+ $is_user_procedure = in_array($procedure, $this->user_allowed_procedures);
+
+ if ($is_user && ! $is_both_procedure && ! $is_user_procedure) {
+ throw new AccessDeniedException('Permission denied');
+ } elseif (! $is_user && ! $is_both_procedure && $is_user_procedure) {
+ throw new AccessDeniedException('Permission denied');
+ }
+
+ $this->logger->debug('API call: '.$procedure);
+ }
+}
diff --git a/app/Core/Base.php b/app/Core/Base.php
index 99c093e4..725bd7c0 100644
--- a/app/Core/Base.php
+++ b/app/Core/Base.php
@@ -140,6 +140,7 @@ use Pimple\Container;
* @property \Psr\Log\LoggerInterface $logger
* @property \PicoDb\Database $db
* @property \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher
+ * @property \JsonRPC\Server $api
*/
abstract class Base
{
diff --git a/app/ServiceProvider/ApiProvider.php b/app/ServiceProvider/ApiProvider.php
new file mode 100644
index 00000000..19d945f6
--- /dev/null
+++ b/app/ServiceProvider/ApiProvider.php
@@ -0,0 +1,74 @@
+<?php
+
+namespace Kanboard\ServiceProvider;
+
+use JsonRPC\Server;
+use Kanboard\Api\ActionApi;
+use Kanboard\Api\AppApi;
+use Kanboard\Api\BoardApi;
+use Kanboard\Api\CategoryApi;
+use Kanboard\Api\ColumnApi;
+use Kanboard\Api\CommentApi;
+use Kanboard\Api\FileApi;
+use Kanboard\Api\GroupApi;
+use Kanboard\Api\GroupMemberApi;
+use Kanboard\Api\LinkApi;
+use Kanboard\Api\MeApi;
+use Kanboard\Api\Middleware\AuthenticationApiMiddleware;
+use Kanboard\Api\ProjectApi;
+use Kanboard\Api\ProjectPermissionApi;
+use Kanboard\Api\SubtaskApi;
+use Kanboard\Api\SwimlaneApi;
+use Kanboard\Api\TaskApi;
+use Kanboard\Api\TaskLinkApi;
+use Kanboard\Api\UserApi;
+use Pimple\Container;
+use Pimple\ServiceProviderInterface;
+
+/**
+ * Class ApiProvider
+ *
+ * @package Kanboard\ServiceProvider
+ * @author Frederic Guillot
+ */
+class ApiProvider implements ServiceProviderInterface
+{
+ /**
+ * Registers services on the given container.
+ *
+ * @param Container $container
+ * @return Container
+ */
+ public function register(Container $container)
+ {
+ $server = new Server();
+ $server->setAuthenticationHeader(API_AUTHENTICATION_HEADER);
+ $server->getMiddlewareHandler()
+ ->withMiddleware(new AuthenticationApiMiddleware($container))
+ ;
+
+ $server->getProcedureHandler()
+ ->withObject(new MeApi($container))
+ ->withObject(new ActionApi($container))
+ ->withObject(new AppApi($container))
+ ->withObject(new BoardApi($container))
+ ->withObject(new ColumnApi($container))
+ ->withObject(new CategoryApi($container))
+ ->withObject(new CommentApi($container))
+ ->withObject(new FileApi($container))
+ ->withObject(new LinkApi($container))
+ ->withObject(new ProjectApi($container))
+ ->withObject(new ProjectPermissionApi($container))
+ ->withObject(new SubtaskApi($container))
+ ->withObject(new SwimlaneApi($container))
+ ->withObject(new TaskApi($container))
+ ->withObject(new TaskLinkApi($container))
+ ->withObject(new UserApi($container))
+ ->withObject(new GroupApi($container))
+ ->withObject(new GroupMemberApi($container))
+ ;
+
+ $container['api'] = $server;
+ return $container;
+ }
+}
diff --git a/app/common.php b/app/common.php
index 4781ddb4..e73d3a64 100644
--- a/app/common.php
+++ b/app/common.php
@@ -47,4 +47,5 @@ $container->register(new Kanboard\ServiceProvider\ExternalLinkProvider());
$container->register(new Kanboard\ServiceProvider\AvatarProvider());
$container->register(new Kanboard\ServiceProvider\FilterProvider());
$container->register(new Kanboard\ServiceProvider\QueueProvider());
+$container->register(new Kanboard\ServiceProvider\ApiProvider());
$container->register(new Kanboard\ServiceProvider\PluginProvider());
diff --git a/composer.json b/composer.json
index 0e80840c..f49bdd8a 100644
--- a/composer.json
+++ b/composer.json
@@ -26,7 +26,7 @@
"christian-riesen/otp" : "1.4",
"eluceo/ical": "0.8.0",
"erusev/parsedown" : "1.6.0",
- "fguillot/json-rpc" : "1.1.0",
+ "fguillot/json-rpc" : "1.2.0",
"fguillot/picodb" : "1.0.12",
"fguillot/simpleLogger" : "1.0.1",
"fguillot/simple-validator" : "1.0.0",
diff --git a/composer.lock b/composer.lock
index 951c835b..1df4e429 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "cb6d74d2ba01afcd7988f4ab99d614a5",
- "content-hash": "8c9fce0f4478875b9b4dc1ae53738159",
+ "hash": "d47d835e84b436f531274f700ec39305",
+ "content-hash": "643b9cebc73b39d76b6b47eb759d054d",
"packages": [
{
"name": "christian-riesen/base32",
@@ -203,21 +203,24 @@
},
{
"name": "fguillot/json-rpc",
- "version": "v1.1.0",
+ "version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/fguillot/JsonRPC.git",
- "reference": "e915dab71940e7ac251955c785570048f460d332"
+ "reference": "b002320b10aa1eeb7aee83f7b703cd6a6e99ff78"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/e915dab71940e7ac251955c785570048f460d332",
- "reference": "e915dab71940e7ac251955c785570048f460d332",
+ "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/b002320b10aa1eeb7aee83f7b703cd6a6e99ff78",
+ "reference": "b002320b10aa1eeb7aee83f7b703cd6a6e99ff78",
"shasum": ""
},
"require": {
"php": ">=5.3.4"
},
+ "require-dev": {
+ "phpunit/phpunit": "4.8.*"
+ },
"type": "library",
"autoload": {
"psr-0": {
@@ -235,7 +238,7 @@
],
"description": "Simple Json-RPC client/server library that just works",
"homepage": "https://github.com/fguillot/JsonRPC",
- "time": "2016-04-27 02:48:10"
+ "time": "2016-05-29 13:06:36"
},
{
"name": "fguillot/picodb",
diff --git a/jsonrpc.php b/jsonrpc.php
index c0dc5c56..50e8f89b 100644
--- a/jsonrpc.php
+++ b/jsonrpc.php
@@ -2,48 +2,4 @@
require __DIR__.'/app/common.php';
-use JsonRPC\Server;
-use Kanboard\Api\AuthApi;
-use Kanboard\Api\MeApi;
-use Kanboard\Api\ActionApi;
-use Kanboard\Api\AppApi;
-use Kanboard\Api\BoardApi;
-use Kanboard\Api\ColumnApi;
-use Kanboard\Api\CategoryApi;
-use Kanboard\Api\CommentApi;
-use Kanboard\Api\FileApi;
-use Kanboard\Api\LinkApi;
-use Kanboard\Api\ProjectApi;
-use Kanboard\Api\ProjectPermissionApi;
-use Kanboard\Api\SubtaskApi;
-use Kanboard\Api\SwimlaneApi;
-use Kanboard\Api\TaskApi;
-use Kanboard\Api\TaskLinkApi;
-use Kanboard\Api\UserApi;
-use Kanboard\Api\GroupApi;
-use Kanboard\Api\GroupMemberApi;
-
-$server = new Server;
-$server->setAuthenticationHeader(API_AUTHENTICATION_HEADER);
-$server->before(array(new AuthApi($container), 'checkCredentials'));
-
-$server->attach(new MeApi($container));
-$server->attach(new ActionApi($container));
-$server->attach(new AppApi($container));
-$server->attach(new BoardApi($container));
-$server->attach(new ColumnApi($container));
-$server->attach(new CategoryApi($container));
-$server->attach(new CommentApi($container));
-$server->attach(new FileApi($container));
-$server->attach(new LinkApi($container));
-$server->attach(new ProjectApi($container));
-$server->attach(new ProjectPermissionApi($container));
-$server->attach(new SubtaskApi($container));
-$server->attach(new SwimlaneApi($container));
-$server->attach(new TaskApi($container));
-$server->attach(new TaskLinkApi($container));
-$server->attach(new UserApi($container));
-$server->attach(new GroupApi($container));
-$server->attach(new GroupMemberApi($container));
-
-echo $server->execute();
+echo $container['api']->execute();