summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authori00171 <anton.delitsch@implema.se>2016-06-26 18:35:25 +0200
committeri00171 <anton.delitsch@implema.se>2016-06-26 18:35:25 +0200
commit47039d32c84ba699867920d2c3cb47a34b199b9d (patch)
tree4fbc2ec34889baeab00085e0509055dca7daee6a
parent911be6ed00c1ece5d9ef2c16e80899bb7bffad67 (diff)
parentc110dffefe259c13e60193fb81ebb9d4b79504de (diff)
Merge branch 'master' of https://github.com/fguillot/kanboard
-rw-r--r--.docker/crontab/cronjob.alpine (renamed from .docker/crontab/kanboard)0
-rw-r--r--.docker/crontab/cronjob.debian1
-rw-r--r--.dockerignore6
-rw-r--r--ChangeLog11
-rw-r--r--Dockerfile3
-rw-r--r--Makefile23
-rw-r--r--app/Api/Authorization/ActionAuthorization.php19
-rw-r--r--app/Api/Authorization/CategoryAuthorization.php19
-rw-r--r--app/Api/Authorization/ColumnAuthorization.php19
-rw-r--r--app/Api/Authorization/CommentAuthorization.php19
-rw-r--r--app/Api/Authorization/ProcedureAuthorization.php32
-rw-r--r--app/Api/Authorization/ProjectAuthorization.php35
-rw-r--r--app/Api/Authorization/SubtaskAuthorization.php19
-rw-r--r--app/Api/Authorization/TaskAuthorization.php19
-rw-r--r--app/Api/Authorization/TaskFileAuthorization.php19
-rw-r--r--app/Api/Authorization/TaskLinkAuthorization.php19
-rw-r--r--app/Api/Authorization/UserAuthorization.php22
-rw-r--r--app/Api/Middleware/AuthenticationMiddleware.php (renamed from app/Api/Middleware/AuthenticationApiMiddleware.php)59
-rw-r--r--app/Api/Procedure/ActionProcedure.php (renamed from app/Api/ActionApi.php)12
-rw-r--r--app/Api/Procedure/AppProcedure.php (renamed from app/Api/AppApi.php)8
-rw-r--r--app/Api/Procedure/BaseProcedure.php (renamed from app/Api/BaseApi.php)41
-rw-r--r--app/Api/Procedure/BoardProcedure.php (renamed from app/Api/BoardApi.php)11
-rw-r--r--app/Api/Procedure/CategoryProcedure.php (renamed from app/Api/CategoryApi.php)16
-rw-r--r--app/Api/Procedure/ColumnProcedure.php (renamed from app/Api/ColumnApi.php)15
-rw-r--r--app/Api/Procedure/CommentProcedure.php (renamed from app/Api/CommentApi.php)16
-rw-r--r--app/Api/Procedure/GroupMemberProcedure.php (renamed from app/Api/GroupMemberApi.php)8
-rw-r--r--app/Api/Procedure/GroupProcedure.php (renamed from app/Api/GroupApi.php)8
-rw-r--r--app/Api/Procedure/LinkProcedure.php (renamed from app/Api/LinkApi.php)8
-rw-r--r--app/Api/Procedure/MeProcedure.php (renamed from app/Api/MeApi.php)6
-rw-r--r--app/Api/Procedure/ProjectPermissionProcedure.php (renamed from app/Api/ProjectPermissionApi.php)34
-rw-r--r--app/Api/Procedure/ProjectProcedure.php113
-rw-r--r--app/Api/Procedure/SubtaskProcedure.php (renamed from app/Api/SubtaskApi.php)16
-rw-r--r--app/Api/Procedure/SubtaskTimeTrackingProcedure.php39
-rw-r--r--app/Api/Procedure/SwimlaneProcedure.php (renamed from app/Api/SwimlaneApi.php)21
-rw-r--r--app/Api/Procedure/TaskFileProcedure.php (renamed from app/Api/FileApi.php)53
-rw-r--r--app/Api/Procedure/TaskLinkProcedure.php (renamed from app/Api/TaskLinkApi.php)14
-rw-r--r--app/Api/Procedure/TaskProcedure.php (renamed from app/Api/TaskApi.php)44
-rw-r--r--app/Api/Procedure/UserProcedure.php (renamed from app/Api/UserApi.php)17
-rw-r--r--app/Api/ProjectApi.php87
-rw-r--r--app/Api/SubtaskTimeTrackingApi.php34
-rw-r--r--app/Core/Base.php4
-rw-r--r--app/Model/ActionModel.php12
-rw-r--r--app/Model/CategoryModel.php12
-rw-r--r--app/Model/ColumnModel.php12
-rw-r--r--app/Model/CommentModel.php16
-rw-r--r--app/Model/SubtaskModel.php16
-rw-r--r--app/Model/TaskFileModel.php16
-rw-r--r--app/Model/TaskLinkModel.php16
-rw-r--r--app/ServiceProvider/ApiProvider.php83
-rw-r--r--app/ServiceProvider/AuthenticationProvider.php57
-rw-r--r--app/Validator/ProjectValidator.php8
-rw-r--r--composer.json33
-rw-r--r--composer.lock176
-rw-r--r--doc/api-authentication.markdown55
-rw-r--r--doc/api-json-rpc.markdown12
-rw-r--r--doc/api-project-permission-procedures.markdown33
-rw-r--r--doc/api-project-procedures.markdown10
-rw-r--r--doc/requirements.markdown2
-rw-r--r--doc/tests.markdown49
-rw-r--r--tests/configs/config.mysql.php12
-rw-r--r--tests/configs/config.postgres.php12
-rw-r--r--tests/configs/config.sqlite.php8
-rw-r--r--tests/docker/Dockerfile.xenial24
-rw-r--r--tests/docker/compose.integration.mysql.yaml27
-rw-r--r--tests/docker/compose.integration.postgres.yaml26
-rw-r--r--tests/docker/compose.integration.sqlite.yaml16
-rwxr-xr-xtests/docker/entrypoint.sh33
-rw-r--r--tests/docker/supervisord.conf6
-rw-r--r--tests/integration.mysql.xml14
-rw-r--r--tests/integration.postgres.xml13
-rw-r--r--tests/integration.sqlite.xml9
-rw-r--r--tests/integration/ActionProcedureTest.php66
-rw-r--r--tests/integration/ApiTest.php928
-rw-r--r--tests/integration/AppProcedureTest.php (renamed from tests/integration/AppTest.php)24
-rw-r--r--tests/integration/Base.php62
-rw-r--r--tests/integration/BaseProcedureTest.php122
-rw-r--r--tests/integration/BoardProcedureTest.php25
-rw-r--r--tests/integration/BoardTest.php21
-rw-r--r--tests/integration/CategoryProcedureTest.php76
-rw-r--r--tests/integration/ColumnProcedureTest.php69
-rw-r--r--tests/integration/ColumnTest.php65
-rw-r--r--tests/integration/CommentProcedureTest.php63
-rw-r--r--tests/integration/GroupMemberProcedureTest.php53
-rw-r--r--tests/integration/GroupMemberTest.php47
-rw-r--r--tests/integration/GroupProcedureTest.php50
-rw-r--r--tests/integration/GroupTest.php48
-rw-r--r--tests/integration/LinkProcedureTest.php70
-rw-r--r--tests/integration/MeProcedureTest.php68
-rw-r--r--tests/integration/MeTest.php247
-rw-r--r--tests/integration/OverdueTaskProcedureTest.php43
-rw-r--r--tests/integration/ProcedureAuthorizationTest.php306
-rw-r--r--tests/integration/ProjectPermissionProcedureTest.php89
-rw-r--r--tests/integration/ProjectPermissionTest.php64
-rw-r--r--tests/integration/ProjectProcedureTest.php119
-rw-r--r--tests/integration/SubtaskProcedureTest.php64
-rw-r--r--tests/integration/SwimlaneProcedureTest.php93
-rw-r--r--tests/integration/SwimlaneTest.php103
-rw-r--r--tests/integration/TaskFileProcedureTest.php67
-rw-r--r--tests/integration/TaskLinkProcedureTest.php68
-rw-r--r--tests/integration/TaskProcedureTest.php55
-rw-r--r--tests/integration/TaskTest.php132
-rw-r--r--tests/integration/UserProcedureTest.php63
-rw-r--r--tests/integration/UserTest.php18
-rw-r--r--tests/units/Model/ActionModelTest.php (renamed from tests/units/Model/ActionTest.php)20
-rw-r--r--tests/units/Model/CategoryModelTest.php (renamed from tests/units/Model/CategoryTest.php)14
-rw-r--r--tests/units/Model/CommentTest.php86
-rw-r--r--tests/units/Model/SubtaskModelTest.php (renamed from tests/units/Model/SubtaskTest.php)156
-rw-r--r--tests/units/Model/TaskFileModelTest.php (renamed from tests/units/Model/TaskFileTest.php)15
-rw-r--r--tests/units/Model/TaskLinkModelTest.php211
-rw-r--r--tests/units/Model/TaskLinkTest.php196
-rw-r--r--tests/units/Validator/ProjectValidatorTest.php12
111 files changed, 3251 insertions, 2634 deletions
diff --git a/.docker/crontab/kanboard b/.docker/crontab/cronjob.alpine
index 91ad044e..91ad044e 100644
--- a/.docker/crontab/kanboard
+++ b/.docker/crontab/cronjob.alpine
diff --git a/.docker/crontab/cronjob.debian b/.docker/crontab/cronjob.debian
new file mode 100644
index 00000000..40310d4f
--- /dev/null
+++ b/.docker/crontab/cronjob.debian
@@ -0,0 +1 @@
+@daily www-data cd /var/www/html/kanboard && ./kanboard cronjob >/dev/null 2>&1
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 00000000..569d36ca
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,6 @@
+.git
+.git*
+data/*
+Makefile
+.*.yml
+*.json \ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
index 7a6f4edf..883cc6cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,11 +1,18 @@
Version 1.0.31 (unreleased)
--------------
+New features:
+
+* Added application and project roles validation for API procedure calls
+* Added new API call: "getProjectByIdentifier"
+
Improvements:
+* Added argument owner_id and identifier to project API calls
+* Rewrite integration tests to run with Docker containers
* Use the same task form layout everywhere
-* Remove some tasks dropdown menus that are now available with task edit form
-* Make embedded documentation available in multiple languages
+* Removed some tasks dropdown menus that are now available with task edit form
+* Make embedded documentation readable in multiple languages (if a translation is available)
Bug fixes:
diff --git a/Dockerfile b/Dockerfile
index 6f523373..aa9eb9cf 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -24,8 +24,7 @@ COPY .docker/php/conf.d/local.ini /etc/php5/conf.d/
COPY .docker/php/php-fpm.conf /etc/php5/
COPY .docker/nginx/nginx.conf /etc/nginx/
COPY .docker/kanboard/config.php /var/www/kanboard/
-COPY .docker/kanboard/config.php /var/www/kanboard/
-COPY .docker/crontab/kanboard /var/spool/cron/crontabs/nginx
+COPY .docker/crontab/cronjob.alpine /var/spool/cron/crontabs/nginx
EXPOSE 80
diff --git a/Makefile b/Makefile
index 6ffba241..47e9d389 100644
--- a/Makefile
+++ b/Makefile
@@ -58,7 +58,28 @@ test-postgres:
unittest: test-sqlite test-mysql test-postgres
test-browser:
- @ phpunit -c tests/acceptance.xml
+ @ phpunit -c tests/acceptance.xml
+
+integration-test-mysql:
+ @ composer install
+ @ docker-compose -f tests/docker/compose.integration.mysql.yaml build
+ @ docker-compose -f tests/docker/compose.integration.mysql.yaml up -d mysql app
+ @ docker-compose -f tests/docker/compose.integration.mysql.yaml up tests
+ @ docker-compose -f tests/docker/compose.integration.mysql.yaml down
+
+integration-test-postgres:
+ @ composer install
+ @ docker-compose -f tests/docker/compose.integration.postgres.yaml build
+ @ docker-compose -f tests/docker/compose.integration.postgres.yaml up -d postgres app
+ @ docker-compose -f tests/docker/compose.integration.postgres.yaml up tests
+ @ docker-compose -f tests/docker/compose.integration.postgres.yaml down
+
+integration-test-sqlite:
+ @ composer install
+ @ docker-compose -f tests/docker/compose.integration.sqlite.yaml build
+ @ docker-compose -f tests/docker/compose.integration.sqlite.yaml up -d app
+ @ docker-compose -f tests/docker/compose.integration.sqlite.yaml up tests
+ @ docker-compose -f tests/docker/compose.integration.sqlite.yaml down
sql:
@ pg_dump --schema-only --no-owner --no-privileges --quote-all-identifiers -n public --file app/Schema/Sql/postgres.sql kanboard
diff --git a/app/Api/Authorization/ActionAuthorization.php b/app/Api/Authorization/ActionAuthorization.php
new file mode 100644
index 00000000..4b41ad82
--- /dev/null
+++ b/app/Api/Authorization/ActionAuthorization.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+/**
+ * Class ActionAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class ActionAuthorization extends ProjectAuthorization
+{
+ public function check($class, $method, $action_id)
+ {
+ if ($this->userSession->isLogged()) {
+ $this->checkProjectPermission($class, $method, $this->actionModel->getProjectId($action_id));
+ }
+ }
+}
diff --git a/app/Api/Authorization/CategoryAuthorization.php b/app/Api/Authorization/CategoryAuthorization.php
new file mode 100644
index 00000000..f17265a2
--- /dev/null
+++ b/app/Api/Authorization/CategoryAuthorization.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+/**
+ * Class CategoryAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class CategoryAuthorization extends ProjectAuthorization
+{
+ public function check($class, $method, $category_id)
+ {
+ if ($this->userSession->isLogged()) {
+ $this->checkProjectPermission($class, $method, $this->categoryModel->getProjectId($category_id));
+ }
+ }
+}
diff --git a/app/Api/Authorization/ColumnAuthorization.php b/app/Api/Authorization/ColumnAuthorization.php
new file mode 100644
index 00000000..37aecda2
--- /dev/null
+++ b/app/Api/Authorization/ColumnAuthorization.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+/**
+ * Class ColumnAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class ColumnAuthorization extends ProjectAuthorization
+{
+ public function check($class, $method, $column_id)
+ {
+ if ($this->userSession->isLogged()) {
+ $this->checkProjectPermission($class, $method, $this->columnModel->getProjectId($column_id));
+ }
+ }
+}
diff --git a/app/Api/Authorization/CommentAuthorization.php b/app/Api/Authorization/CommentAuthorization.php
new file mode 100644
index 00000000..ed15512e
--- /dev/null
+++ b/app/Api/Authorization/CommentAuthorization.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+/**
+ * Class CommentAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class CommentAuthorization extends ProjectAuthorization
+{
+ public function check($class, $method, $comment_id)
+ {
+ if ($this->userSession->isLogged()) {
+ $this->checkProjectPermission($class, $method, $this->commentModel->getProjectId($comment_id));
+ }
+ }
+}
diff --git a/app/Api/Authorization/ProcedureAuthorization.php b/app/Api/Authorization/ProcedureAuthorization.php
new file mode 100644
index 00000000..070a6371
--- /dev/null
+++ b/app/Api/Authorization/ProcedureAuthorization.php
@@ -0,0 +1,32 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+use JsonRPC\Exception\AccessDeniedException;
+use Kanboard\Core\Base;
+
+/**
+ * Class ProcedureAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class ProcedureAuthorization extends Base
+{
+ private $userSpecificProcedures = array(
+ 'getMe',
+ 'getMyDashboard',
+ 'getMyActivityStream',
+ 'createMyPrivateProject',
+ 'getMyProjectsList',
+ 'getMyProjects',
+ 'getMyOverdueTasks',
+ );
+
+ public function check($procedure)
+ {
+ if (! $this->userSession->isLogged() && in_array($procedure, $this->userSpecificProcedures)) {
+ throw new AccessDeniedException('This procedure is not available with the API credentials');
+ }
+ }
+}
diff --git a/app/Api/Authorization/ProjectAuthorization.php b/app/Api/Authorization/ProjectAuthorization.php
new file mode 100644
index 00000000..21ecf311
--- /dev/null
+++ b/app/Api/Authorization/ProjectAuthorization.php
@@ -0,0 +1,35 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+use JsonRPC\Exception\AccessDeniedException;
+use Kanboard\Core\Base;
+
+/**
+ * Class ProjectAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class ProjectAuthorization extends Base
+{
+ public function check($class, $method, $project_id)
+ {
+ if ($this->userSession->isLogged()) {
+ $this->checkProjectPermission($class, $method, $project_id);
+ }
+ }
+
+ protected function checkProjectPermission($class, $method, $project_id)
+ {
+ if (empty($project_id)) {
+ throw new AccessDeniedException('Project not found');
+ }
+
+ $role = $this->projectUserRoleModel->getUserRole($project_id, $this->userSession->getId());
+
+ if (! $this->apiProjectAuthorization->isAllowed($class, $method, $role)) {
+ throw new AccessDeniedException('Project access denied');
+ }
+ }
+}
diff --git a/app/Api/Authorization/SubtaskAuthorization.php b/app/Api/Authorization/SubtaskAuthorization.php
new file mode 100644
index 00000000..fcb57929
--- /dev/null
+++ b/app/Api/Authorization/SubtaskAuthorization.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+/**
+ * Class SubtaskAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class SubtaskAuthorization extends ProjectAuthorization
+{
+ public function check($class, $method, $subtask_id)
+ {
+ if ($this->userSession->isLogged()) {
+ $this->checkProjectPermission($class, $method, $this->subtaskModel->getProjectId($subtask_id));
+ }
+ }
+}
diff --git a/app/Api/Authorization/TaskAuthorization.php b/app/Api/Authorization/TaskAuthorization.php
new file mode 100644
index 00000000..db93b76b
--- /dev/null
+++ b/app/Api/Authorization/TaskAuthorization.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+/**
+ * Class TaskAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class TaskAuthorization extends ProjectAuthorization
+{
+ public function check($class, $method, $category_id)
+ {
+ if ($this->userSession->isLogged()) {
+ $this->checkProjectPermission($class, $method, $this->taskFinderModel->getProjectId($category_id));
+ }
+ }
+}
diff --git a/app/Api/Authorization/TaskFileAuthorization.php b/app/Api/Authorization/TaskFileAuthorization.php
new file mode 100644
index 00000000..e40783eb
--- /dev/null
+++ b/app/Api/Authorization/TaskFileAuthorization.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+/**
+ * Class TaskFileAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class TaskFileAuthorization extends ProjectAuthorization
+{
+ public function check($class, $method, $file_id)
+ {
+ if ($this->userSession->isLogged()) {
+ $this->checkProjectPermission($class, $method, $this->taskFileModel->getProjectId($file_id));
+ }
+ }
+}
diff --git a/app/Api/Authorization/TaskLinkAuthorization.php b/app/Api/Authorization/TaskLinkAuthorization.php
new file mode 100644
index 00000000..2f5fc8d5
--- /dev/null
+++ b/app/Api/Authorization/TaskLinkAuthorization.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+/**
+ * Class TaskLinkAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class TaskLinkAuthorization extends ProjectAuthorization
+{
+ public function check($class, $method, $task_link_id)
+ {
+ if ($this->userSession->isLogged()) {
+ $this->checkProjectPermission($class, $method, $this->taskLinkModel->getProjectId($task_link_id));
+ }
+ }
+}
diff --git a/app/Api/Authorization/UserAuthorization.php b/app/Api/Authorization/UserAuthorization.php
new file mode 100644
index 00000000..3fd6865c
--- /dev/null
+++ b/app/Api/Authorization/UserAuthorization.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace Kanboard\Api\Authorization;
+
+use JsonRPC\Exception\AccessDeniedException;
+use Kanboard\Core\Base;
+
+/**
+ * Class UserAuthorization
+ *
+ * @package Kanboard\Api\Authorization
+ * @author Frederic Guillot
+ */
+class UserAuthorization extends Base
+{
+ public function check($class, $method)
+ {
+ if ($this->userSession->isLogged() && ! $this->apiAuthorization->isAllowed($class, $method, $this->userSession->getRole())) {
+ throw new AccessDeniedException('You are not allowed to access to this resource');
+ }
+ }
+}
diff --git a/app/Api/Middleware/AuthenticationApiMiddleware.php b/app/Api/Middleware/AuthenticationMiddleware.php
index b16e10b8..8e309593 100644
--- a/app/Api/Middleware/AuthenticationApiMiddleware.php
+++ b/app/Api/Middleware/AuthenticationMiddleware.php
@@ -13,46 +13,8 @@ use Kanboard\Core\Base;
* @package Kanboard\Api\Middleware
* @author Frederic Guillot
*/
-class AuthenticationApiMiddleware extends Base implements MiddlewareInterface
+class AuthenticationMiddleware 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',
- 'getSubTask',
- 'getTask',
- 'getTaskByReference',
- 'getTimeSpent',
- 'getAllTasks',
- 'getAllSubTasks',
- 'hasTimer',
- 'logStartTime',
- 'logEndTime',
- 'openTask',
- 'closeTask',
- 'moveTaskPosition',
- 'createTask',
- 'createSubtask',
- 'updateTask',
- 'getBoard',
- 'getProjectActivity',
- 'getOverdueTasksByProject',
- 'searchTasks',
- );
-
/**
* Execute Middleware
*
@@ -68,11 +30,8 @@ class AuthenticationApiMiddleware extends Base implements MiddlewareInterface
$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 {
+ } elseif (! $this->isAppAuthenticated($username, $password)) {
$this->logger->error('API authentication failure for '.$username);
throw new AuthenticationFailureException('Wrong credentials');
}
@@ -120,18 +79,4 @@ class AuthenticationApiMiddleware extends Base implements MiddlewareInterface
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/Api/ActionApi.php b/app/Api/Procedure/ActionProcedure.php
index 116742d8..4043dbb9 100644
--- a/app/Api/ActionApi.php
+++ b/app/Api/Procedure/ActionProcedure.php
@@ -1,16 +1,17 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
-use Kanboard\Core\Base;
+use Kanboard\Api\Authorization\ActionAuthorization;
+use Kanboard\Api\Authorization\ProjectAuthorization;
/**
* Action API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class ActionApi extends Base
+class ActionProcedure extends BaseProcedure
{
public function getAvailableActions()
{
@@ -29,16 +30,19 @@ class ActionApi extends Base
public function removeAction($action_id)
{
+ ActionAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAction', $action_id);
return $this->actionModel->remove($action_id);
}
public function getActions($project_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getActions', $project_id);
return $this->actionModel->getAllByProject($project_id);
}
public function createAction($project_id, $event_name, $action_name, array $params)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createAction', $project_id);
$values = array(
'project_id' => $project_id,
'event_name' => $event_name,
diff --git a/app/Api/AppApi.php b/app/Api/Procedure/AppProcedure.php
index 637de5c5..60af4a60 100644
--- a/app/Api/AppApi.php
+++ b/app/Api/Procedure/AppProcedure.php
@@ -1,16 +1,14 @@
<?php
-namespace Kanboard\Api;
-
-use Kanboard\Core\Base;
+namespace Kanboard\Api\Procedure;
/**
* App API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class AppApi extends Base
+class AppProcedure extends BaseProcedure
{
public function getTimezone()
{
diff --git a/app/Api/BaseApi.php b/app/Api/Procedure/BaseProcedure.php
index 9f69aa65..e31b3027 100644
--- a/app/Api/BaseApi.php
+++ b/app/Api/Procedure/BaseProcedure.php
@@ -1,30 +1,24 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
-use JsonRPC\Exception\AccessDeniedException;
+use Kanboard\Api\Authorization\ProcedureAuthorization;
+use Kanboard\Api\Authorization\UserAuthorization;
use Kanboard\Core\Base;
+use ReflectionClass;
/**
* Base class
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-abstract class BaseApi extends Base
+abstract class BaseProcedure extends Base
{
- public function checkProjectPermission($project_id)
+ public function beforeProcedure($procedure)
{
- if ($this->userSession->isLogged() && ! $this->projectPermissionModel->isUserAllowed($project_id, $this->userSession->getId())) {
- throw new AccessDeniedException('Permission denied');
- }
- }
-
- public function checkTaskPermission($task_id)
- {
- if ($this->userSession->isLogged()) {
- $this->checkProjectPermission($this->taskFinderModel->getProjectId($task_id));
- }
+ ProcedureAuthorization::getInstance($this->container)->check($procedure);
+ UserAuthorization::getInstance($this->container)->check($this->getClassName(), $procedure);
}
protected function formatTask($task)
@@ -71,4 +65,21 @@ abstract class BaseApi extends Base
return $projects;
}
+
+ protected function filterValues(array $values)
+ {
+ foreach ($values as $key => $value) {
+ if (is_null($value)) {
+ unset($values[$key]);
+ }
+ }
+
+ return $values;
+ }
+
+ protected function getClassName()
+ {
+ $reflection = new ReflectionClass(get_called_class());
+ return $reflection->getShortName();
+ }
}
diff --git a/app/Api/BoardApi.php b/app/Api/Procedure/BoardProcedure.php
index 70f21c0e..674b5466 100644
--- a/app/Api/BoardApi.php
+++ b/app/Api/Procedure/BoardProcedure.php
@@ -1,21 +1,22 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
+use Kanboard\Api\Authorization\ProjectAuthorization;
use Kanboard\Formatter\BoardFormatter;
/**
* Board API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class BoardApi extends BaseApi
+class BoardProcedure extends BaseProcedure
{
public function getBoard($project_id)
{
- $this->checkProjectPermission($project_id);
-
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getBoard', $project_id);
+
return BoardFormatter::getInstance($this->container)
->withProjectId($project_id)
->withQuery($this->taskFinderModel->getExtendedQuery())
diff --git a/app/Api/CategoryApi.php b/app/Api/Procedure/CategoryProcedure.php
index c56cfb35..3ebbd908 100644
--- a/app/Api/CategoryApi.php
+++ b/app/Api/Procedure/CategoryProcedure.php
@@ -1,34 +1,40 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
-use Kanboard\Core\Base;
+use Kanboard\Api\Authorization\CategoryAuthorization;
+use Kanboard\Api\Authorization\ProjectAuthorization;
/**
* Category API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class CategoryApi extends Base
+class CategoryProcedure extends BaseProcedure
{
public function getCategory($category_id)
{
+ CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'getCategory', $category_id);
return $this->categoryModel->getById($category_id);
}
public function getAllCategories($project_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllCategories', $project_id);
return $this->categoryModel->getAll($project_id);
}
public function removeCategory($category_id)
{
+ CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeCategory', $category_id);
return $this->categoryModel->remove($category_id);
}
public function createCategory($project_id, $name)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createCategory', $project_id);
+
$values = array(
'project_id' => $project_id,
'name' => $name,
@@ -40,6 +46,8 @@ class CategoryApi extends Base
public function updateCategory($id, $name)
{
+ CategoryAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateCategory', $id);
+
$values = array(
'id' => $id,
'name' => $name,
diff --git a/app/Api/ColumnApi.php b/app/Api/Procedure/ColumnProcedure.php
index aa4026f6..ab9d173b 100644
--- a/app/Api/ColumnApi.php
+++ b/app/Api/Procedure/ColumnProcedure.php
@@ -1,42 +1,51 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
+
+use Kanboard\Api\Authorization\ColumnAuthorization;
+use Kanboard\Api\Authorization\ProjectAuthorization;
/**
* Column API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class ColumnApi extends BaseApi
+class ColumnProcedure extends BaseProcedure
{
public function getColumns($project_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getColumns', $project_id);
return $this->columnModel->getAll($project_id);
}
public function getColumn($column_id)
{
+ ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'getColumn', $column_id);
return $this->columnModel->getById($column_id);
}
public function updateColumn($column_id, $title, $task_limit = 0, $description = '')
{
+ ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateColumn', $column_id);
return $this->columnModel->update($column_id, $title, $task_limit, $description);
}
public function addColumn($project_id, $title, $task_limit = 0, $description = '')
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addColumn', $project_id);
return $this->columnModel->create($project_id, $title, $task_limit, $description);
}
public function removeColumn($column_id)
{
+ ColumnAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeColumn', $column_id);
return $this->columnModel->remove($column_id);
}
public function changeColumnPosition($project_id, $column_id, $position)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeColumnPosition', $project_id);
return $this->columnModel->changePosition($project_id, $column_id, $position);
}
}
diff --git a/app/Api/CommentApi.php b/app/Api/Procedure/CommentProcedure.php
index 8358efee..019a49bb 100644
--- a/app/Api/CommentApi.php
+++ b/app/Api/Procedure/CommentProcedure.php
@@ -1,34 +1,40 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
-use Kanboard\Core\Base;
+use Kanboard\Api\Authorization\CommentAuthorization;
+use Kanboard\Api\Authorization\TaskAuthorization;
/**
* Comment API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class CommentApi extends Base
+class CommentProcedure extends BaseProcedure
{
public function getComment($comment_id)
{
+ CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'getComment', $comment_id);
return $this->commentModel->getById($comment_id);
}
public function getAllComments($task_id)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllComments', $task_id);
return $this->commentModel->getAll($task_id);
}
public function removeComment($comment_id)
{
+ CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeComment', $comment_id);
return $this->commentModel->remove($comment_id);
}
public function createComment($task_id, $user_id, $content, $reference = '')
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createComment', $task_id);
+
$values = array(
'task_id' => $task_id,
'user_id' => $user_id,
@@ -43,6 +49,8 @@ class CommentApi extends Base
public function updateComment($id, $content)
{
+ CommentAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateComment', $id);
+
$values = array(
'id' => $id,
'comment' => $content,
diff --git a/app/Api/GroupMemberApi.php b/app/Api/Procedure/GroupMemberProcedure.php
index e09f6975..081d6ac8 100644
--- a/app/Api/GroupMemberApi.php
+++ b/app/Api/Procedure/GroupMemberProcedure.php
@@ -1,16 +1,14 @@
<?php
-namespace Kanboard\Api;
-
-use Kanboard\Core\Base;
+namespace Kanboard\Api\Procedure;
/**
* Group Member API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class GroupMemberApi extends Base
+class GroupMemberProcedure extends BaseProcedure
{
public function getMemberGroups($user_id)
{
diff --git a/app/Api/GroupApi.php b/app/Api/Procedure/GroupProcedure.php
index 1701edc3..804940a2 100644
--- a/app/Api/GroupApi.php
+++ b/app/Api/Procedure/GroupProcedure.php
@@ -1,16 +1,14 @@
<?php
-namespace Kanboard\Api;
-
-use Kanboard\Core\Base;
+namespace Kanboard\Api\Procedure;
/**
* Group API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class GroupApi extends Base
+class GroupProcedure extends BaseProcedure
{
public function createGroup($name, $external_id = '')
{
diff --git a/app/Api/LinkApi.php b/app/Api/Procedure/LinkProcedure.php
index d8e525e4..b4cecf3a 100644
--- a/app/Api/LinkApi.php
+++ b/app/Api/Procedure/LinkProcedure.php
@@ -1,16 +1,14 @@
<?php
-namespace Kanboard\Api;
-
-use Kanboard\Core\Base;
+namespace Kanboard\Api\Procedure;
/**
* Link API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class LinkApi extends Base
+class LinkProcedure extends BaseProcedure
{
/**
* Get a link by id
diff --git a/app/Api/MeApi.php b/app/Api/Procedure/MeProcedure.php
index 497749b6..e59e6522 100644
--- a/app/Api/MeApi.php
+++ b/app/Api/Procedure/MeProcedure.php
@@ -1,16 +1,16 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
use Kanboard\Model\SubtaskModel;
/**
* Me API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class MeApi extends BaseApi
+class MeProcedure extends BaseProcedure
{
public function getMe()
{
diff --git a/app/Api/ProjectPermissionApi.php b/app/Api/Procedure/ProjectPermissionProcedure.php
index 703cd0f3..e22e1d62 100644
--- a/app/Api/ProjectPermissionApi.php
+++ b/app/Api/Procedure/ProjectPermissionProcedure.php
@@ -1,73 +1,69 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
-use Kanboard\Core\Base;
+use Kanboard\Api\Authorization\ProjectAuthorization;
use Kanboard\Core\Security\Role;
/**
* Project Permission API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class ProjectPermissionApi extends Base
+class ProjectPermissionProcedure extends BaseProcedure
{
public function getProjectUsers($project_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectUsers', $project_id);
return $this->projectUserRoleModel->getAllUsers($project_id);
}
public function getAssignableUsers($project_id, $prepend_unassigned = false)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAssignableUsers', $project_id);
return $this->projectUserRoleModel->getAssignableUsersList($project_id, $prepend_unassigned);
}
public function addProjectUser($project_id, $user_id, $role = Role::PROJECT_MEMBER)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addProjectUser', $project_id);
return $this->projectUserRoleModel->addUser($project_id, $user_id, $role);
}
public function addProjectGroup($project_id, $group_id, $role = Role::PROJECT_MEMBER)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addProjectGroup', $project_id);
return $this->projectGroupRoleModel->addGroup($project_id, $group_id, $role);
}
public function removeProjectUser($project_id, $user_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectUser', $project_id);
return $this->projectUserRoleModel->removeUser($project_id, $user_id);
}
public function removeProjectGroup($project_id, $group_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProjectGroup', $project_id);
return $this->projectGroupRoleModel->removeGroup($project_id, $group_id);
}
public function changeProjectUserRole($project_id, $user_id, $role)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeProjectUserRole', $project_id);
return $this->projectUserRoleModel->changeUserRole($project_id, $user_id, $role);
}
public function changeProjectGroupRole($project_id, $group_id, $role)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeProjectGroupRole', $project_id);
return $this->projectGroupRoleModel->changeGroupRole($project_id, $group_id, $role);
}
- // Deprecated
- public function getMembers($project_id)
+ public function getProjectUserRole($project_id, $user_id)
{
- return $this->getProjectUsers($project_id);
- }
-
- // Deprecated
- public function revokeUser($project_id, $user_id)
- {
- return $this->removeProjectUser($project_id, $user_id);
- }
-
- // Deprecated
- public function allowUser($project_id, $user_id)
- {
- return $this->addProjectUser($project_id, $user_id);
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectUserRole', $project_id);
+ return $this->projectUserRoleModel->getUserRole($project_id, $user_id);
}
}
diff --git a/app/Api/Procedure/ProjectProcedure.php b/app/Api/Procedure/ProjectProcedure.php
new file mode 100644
index 00000000..a580c8d9
--- /dev/null
+++ b/app/Api/Procedure/ProjectProcedure.php
@@ -0,0 +1,113 @@
+<?php
+
+namespace Kanboard\Api\Procedure;
+
+use Kanboard\Api\Authorization\ProjectAuthorization;
+
+/**
+ * Project API controller
+ *
+ * @package Kanboard\Api\Procedure
+ * @author Frederic Guillot
+ */
+class ProjectProcedure extends BaseProcedure
+{
+ public function getProjectById($project_id)
+ {
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectById', $project_id);
+ return $this->formatProject($this->projectModel->getById($project_id));
+ }
+
+ public function getProjectByName($name)
+ {
+ $project = $this->projectModel->getByName($name);
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectByName', $project['id']);
+ return $this->formatProject($project);
+ }
+
+ public function getProjectByIdentifier($identifier)
+ {
+ $project = $this->formatProject($this->projectModel->getByIdentifier($identifier));
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectByIdentifier', $project['id']);
+ return $this->formatProject($project);
+ }
+
+ public function getAllProjects()
+ {
+ return $this->formatProjects($this->projectModel->getAll());
+ }
+
+ public function removeProject($project_id)
+ {
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeProject', $project_id);
+ return $this->projectModel->remove($project_id);
+ }
+
+ public function enableProject($project_id)
+ {
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableProject', $project_id);
+ return $this->projectModel->enable($project_id);
+ }
+
+ public function disableProject($project_id)
+ {
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableProject', $project_id);
+ return $this->projectModel->disable($project_id);
+ }
+
+ public function enableProjectPublicAccess($project_id)
+ {
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableProjectPublicAccess', $project_id);
+ return $this->projectModel->enablePublicAccess($project_id);
+ }
+
+ public function disableProjectPublicAccess($project_id)
+ {
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableProjectPublicAccess', $project_id);
+ return $this->projectModel->disablePublicAccess($project_id);
+ }
+
+ public function getProjectActivities(array $project_ids)
+ {
+ foreach ($project_ids as $project_id) {
+ ProjectAuthorization::getInstance($this->container)
+ ->check($this->getClassName(), 'getProjectActivities', $project_id);
+ }
+
+ return $this->helper->projectActivity->getProjectsEvents($project_ids);
+ }
+
+ public function getProjectActivity($project_id)
+ {
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getProjectActivity', $project_id);
+ return $this->helper->projectActivity->getProjectEvents($project_id);
+ }
+
+ public function createProject($name, $description = null, $owner_id = 0, $identifier = null)
+ {
+ $values = $this->filterValues(array(
+ 'name' => $name,
+ 'description' => $description,
+ 'identifier' => $identifier,
+ ));
+
+ list($valid, ) = $this->projectValidator->validateCreation($values);
+ return $valid ? $this->projectModel->create($values, $owner_id, $this->userSession->isLogged()) : false;
+ }
+
+ public function updateProject($project_id, $name = null, $description = null, $owner_id = null, $identifier = null)
+ {
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateProject', $project_id);
+
+ $values = $this->filterValues(array(
+ 'id' => $project_id,
+ 'name' => $name,
+ 'description' => $description,
+ 'owner_id' => $owner_id,
+ 'identifier' => $identifier,
+ ));
+
+ list($valid, ) = $this->projectValidator->validateModification($values);
+ return $valid && $this->projectModel->update($values);
+ }
+}
diff --git a/app/Api/SubtaskApi.php b/app/Api/Procedure/SubtaskProcedure.php
index 5764ff7d..e2400912 100644
--- a/app/Api/SubtaskApi.php
+++ b/app/Api/Procedure/SubtaskProcedure.php
@@ -1,34 +1,40 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
-use Kanboard\Core\Base;
+use Kanboard\Api\Authorization\SubtaskAuthorization;
+use Kanboard\Api\Authorization\TaskAuthorization;
/**
* Subtask API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class SubtaskApi extends Base
+class SubtaskProcedure extends BaseProcedure
{
public function getSubtask($subtask_id)
{
+ SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSubtask', $subtask_id);
return $this->subtaskModel->getById($subtask_id);
}
public function getAllSubtasks($task_id)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllSubtasks', $task_id);
return $this->subtaskModel->getAll($task_id);
}
public function removeSubtask($subtask_id)
{
+ SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeSubtask', $subtask_id);
return $this->subtaskModel->remove($subtask_id);
}
public function createSubtask($task_id, $title, $user_id = 0, $time_estimated = 0, $time_spent = 0, $status = 0)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createSubtask', $task_id);
+
$values = array(
'title' => $title,
'task_id' => $task_id,
@@ -44,6 +50,8 @@ class SubtaskApi extends Base
public function updateSubtask($id, $task_id, $title = null, $user_id = null, $time_estimated = null, $time_spent = null, $status = null)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateSubtask', $task_id);
+
$values = array(
'id' => $id,
'task_id' => $task_id,
diff --git a/app/Api/Procedure/SubtaskTimeTrackingProcedure.php b/app/Api/Procedure/SubtaskTimeTrackingProcedure.php
new file mode 100644
index 00000000..5d1988d6
--- /dev/null
+++ b/app/Api/Procedure/SubtaskTimeTrackingProcedure.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Kanboard\Api\Procedure;
+
+use Kanboard\Api\Authorization\SubtaskAuthorization;
+
+/**
+ * Subtask Time Tracking API controller
+ *
+ * @package Kanboard\Api\Procedure
+ * @author Frederic Guillot
+ * @author Nikolaos Georgakis
+ */
+class SubtaskTimeTrackingProcedure extends BaseProcedure
+{
+ public function hasSubtaskTimer($subtask_id, $user_id)
+ {
+ SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'hasSubtaskTimer', $subtask_id);
+ return $this->subtaskTimeTrackingModel->hasTimer($subtask_id, $user_id);
+ }
+
+ public function logSubtaskStartTime($subtask_id, $user_id)
+ {
+ SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'logSubtaskStartTime', $subtask_id);
+ return $this->subtaskTimeTrackingModel->logStartTime($subtask_id, $user_id);
+ }
+
+ public function logSubtaskEndTime($subtask_id,$user_id)
+ {
+ SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'logSubtaskEndTime', $subtask_id);
+ return $this->subtaskTimeTrackingModel->logEndTime($subtask_id, $user_id);
+ }
+
+ public function getSubtaskTimeSpent($subtask_id,$user_id)
+ {
+ SubtaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSubtaskTimeSpent', $subtask_id);
+ return $this->subtaskTimeTrackingModel->getTimeSpent($subtask_id, $user_id);
+ }
+}
diff --git a/app/Api/SwimlaneApi.php b/app/Api/Procedure/SwimlaneProcedure.php
index c3c56a71..9b7d181d 100644
--- a/app/Api/SwimlaneApi.php
+++ b/app/Api/Procedure/SwimlaneProcedure.php
@@ -1,34 +1,39 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
-use Kanboard\Core\Base;
+use Kanboard\Api\Authorization\ProjectAuthorization;
/**
* Swimlane API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class SwimlaneApi extends Base
+class SwimlaneProcedure extends BaseProcedure
{
public function getActiveSwimlanes($project_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getActiveSwimlanes', $project_id);
return $this->swimlaneModel->getSwimlanes($project_id);
}
public function getAllSwimlanes($project_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllSwimlanes', $project_id);
return $this->swimlaneModel->getAll($project_id);
}
public function getSwimlaneById($swimlane_id)
{
- return $this->swimlaneModel->getById($swimlane_id);
+ $swimlane = $this->swimlaneModel->getById($swimlane_id);
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSwimlaneById', $swimlane['project_id']);
+ return $swimlane;
}
public function getSwimlaneByName($project_id, $name)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getSwimlaneByName', $project_id);
return $this->swimlaneModel->getByName($project_id, $name);
}
@@ -39,11 +44,13 @@ class SwimlaneApi extends Base
public function getDefaultSwimlane($project_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getDefaultSwimlane', $project_id);
return $this->swimlaneModel->getDefault($project_id);
}
public function addSwimlane($project_id, $name, $description = '')
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'addSwimlane', $project_id);
return $this->swimlaneModel->create(array('project_id' => $project_id, 'name' => $name, 'description' => $description));
}
@@ -60,21 +67,25 @@ class SwimlaneApi extends Base
public function removeSwimlane($project_id, $swimlane_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeSwimlane', $project_id);
return $this->swimlaneModel->remove($project_id, $swimlane_id);
}
public function disableSwimlane($project_id, $swimlane_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'disableSwimlane', $project_id);
return $this->swimlaneModel->disable($project_id, $swimlane_id);
}
public function enableSwimlane($project_id, $swimlane_id)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'enableSwimlane', $project_id);
return $this->swimlaneModel->enable($project_id, $swimlane_id);
}
public function changeSwimlanePosition($project_id, $swimlane_id, $position)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'changeSwimlanePosition', $project_id);
return $this->swimlaneModel->changePosition($project_id, $swimlane_id, $position);
}
}
diff --git a/app/Api/FileApi.php b/app/Api/Procedure/TaskFileProcedure.php
index 1ed3aeb9..5aa7ea0b 100644
--- a/app/Api/FileApi.php
+++ b/app/Api/Procedure/TaskFileProcedure.php
@@ -1,29 +1,36 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
+use Kanboard\Api\Authorization\ProjectAuthorization;
+use Kanboard\Api\Authorization\TaskAuthorization;
+use Kanboard\Api\Authorization\TaskFileAuthorization;
use Kanboard\Core\ObjectStorage\ObjectStorageException;
/**
- * File API controller
+ * Task File API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class FileApi extends BaseApi
+class TaskFileProcedure extends BaseProcedure
{
public function getTaskFile($file_id)
{
+ TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskFile', $file_id);
return $this->taskFileModel->getById($file_id);
}
public function getAllTaskFiles($task_id)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTaskFiles', $task_id);
return $this->taskFileModel->getAll($task_id);
}
public function downloadTaskFile($file_id)
{
+ TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'downloadTaskFile', $file_id);
+
try {
$file = $this->taskFileModel->getById($file_id);
@@ -33,12 +40,14 @@ class FileApi extends BaseApi
} catch (ObjectStorageException $e) {
$this->logger->error($e->getMessage());
}
-
+
return '';
}
public function createTaskFile($project_id, $task_id, $filename, $blob)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTaskFile', $project_id);
+
try {
return $this->taskFileModel->uploadContent($task_id, $filename, $blob);
} catch (ObjectStorageException $e) {
@@ -49,43 +58,13 @@ class FileApi extends BaseApi
public function removeTaskFile($file_id)
{
+ TaskFileAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTaskFile', $file_id);
return $this->taskFileModel->remove($file_id);
}
public function removeAllTaskFiles($task_id)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeAllTaskFiles', $task_id);
return $this->taskFileModel->removeAll($task_id);
}
-
- // Deprecated procedures
-
- public function getFile($file_id)
- {
- return $this->getTaskFile($file_id);
- }
-
- public function getAllFiles($task_id)
- {
- return $this->getAllTaskFiles($task_id);
- }
-
- public function downloadFile($file_id)
- {
- return $this->downloadTaskFile($file_id);
- }
-
- public function createFile($project_id, $task_id, $filename, $blob)
- {
- return $this->createTaskFile($project_id, $task_id, $filename, $blob);
- }
-
- public function removeFile($file_id)
- {
- return $this->removeTaskFile($file_id);
- }
-
- public function removeAllFiles($task_id)
- {
- return $this->removeAllTaskFiles($task_id);
- }
}
diff --git a/app/Api/TaskLinkApi.php b/app/Api/Procedure/TaskLinkProcedure.php
index bb809133..375266fb 100644
--- a/app/Api/TaskLinkApi.php
+++ b/app/Api/Procedure/TaskLinkProcedure.php
@@ -1,16 +1,17 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
-use Kanboard\Core\Base;
+use Kanboard\Api\Authorization\TaskAuthorization;
+use Kanboard\Api\Authorization\TaskLinkAuthorization;
/**
* TaskLink API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class TaskLinkApi extends Base
+class TaskLinkProcedure extends BaseProcedure
{
/**
* Get a task link
@@ -21,6 +22,7 @@ class TaskLinkApi extends Base
*/
public function getTaskLinkById($task_link_id)
{
+ TaskLinkAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskLinkById', $task_link_id);
return $this->taskLinkModel->getById($task_link_id);
}
@@ -33,6 +35,7 @@ class TaskLinkApi extends Base
*/
public function getAllTaskLinks($task_id)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTaskLinks', $task_id);
return $this->taskLinkModel->getAll($task_id);
}
@@ -47,6 +50,7 @@ class TaskLinkApi extends Base
*/
public function createTaskLink($task_id, $opposite_task_id, $link_id)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTaskLink', $task_id);
return $this->taskLinkModel->create($task_id, $opposite_task_id, $link_id);
}
@@ -62,6 +66,7 @@ class TaskLinkApi extends Base
*/
public function updateTaskLink($task_link_id, $task_id, $opposite_task_id, $link_id)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTaskLink', $task_id);
return $this->taskLinkModel->update($task_link_id, $task_id, $opposite_task_id, $link_id);
}
@@ -74,6 +79,7 @@ class TaskLinkApi extends Base
*/
public function removeTaskLink($task_link_id)
{
+ TaskLinkAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTaskLink', $task_link_id);
return $this->taskLinkModel->remove($task_link_id);
}
}
diff --git a/app/Api/TaskApi.php b/app/Api/Procedure/TaskProcedure.php
index ddb3ac54..2d29a4ef 100644
--- a/app/Api/TaskApi.php
+++ b/app/Api/Procedure/TaskProcedure.php
@@ -1,39 +1,41 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
+use Kanboard\Api\Authorization\ProjectAuthorization;
+use Kanboard\Api\Authorization\TaskAuthorization;
use Kanboard\Filter\TaskProjectFilter;
use Kanboard\Model\TaskModel;
/**
* Task API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class TaskApi extends BaseApi
+class TaskProcedure extends BaseProcedure
{
public function searchTasks($project_id, $query)
{
- $this->checkProjectPermission($project_id);
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'searchTasks', $project_id);
return $this->taskLexer->build($query)->withFilter(new TaskProjectFilter($project_id))->toArray();
}
public function getTask($task_id)
{
- $this->checkTaskPermission($task_id);
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTask', $task_id);
return $this->formatTask($this->taskFinderModel->getById($task_id));
}
public function getTaskByReference($project_id, $reference)
{
- $this->checkProjectPermission($project_id);
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getTaskByReference', $project_id);
return $this->formatTask($this->taskFinderModel->getByReference($project_id, $reference));
}
public function getAllTasks($project_id, $status_id = TaskModel::STATUS_OPEN)
{
- $this->checkProjectPermission($project_id);
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getAllTasks', $project_id);
return $this->formatTasks($this->taskFinderModel->getAll($project_id, $status_id));
}
@@ -44,40 +46,43 @@ class TaskApi extends BaseApi
public function getOverdueTasksByProject($project_id)
{
- $this->checkProjectPermission($project_id);
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'getOverdueTasksByProject', $project_id);
return $this->taskFinderModel->getOverdueTasksByProject($project_id);
}
public function openTask($task_id)
{
- $this->checkTaskPermission($task_id);
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'openTask', $task_id);
return $this->taskStatusModel->open($task_id);
}
public function closeTask($task_id)
{
- $this->checkTaskPermission($task_id);
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'closeTask', $task_id);
return $this->taskStatusModel->close($task_id);
}
public function removeTask($task_id)
{
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'removeTask', $task_id);
return $this->taskModel->remove($task_id);
}
public function moveTaskPosition($project_id, $task_id, $column_id, $position, $swimlane_id = 0)
{
- $this->checkProjectPermission($project_id);
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskPosition', $project_id);
return $this->taskPositionModel->movePosition($project_id, $task_id, $column_id, $position, $swimlane_id);
}
public function moveTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'moveTaskToProject', $project_id);
return $this->taskDuplicationModel->moveToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id);
}
public function duplicateTaskToProject($task_id, $project_id, $swimlane_id = null, $column_id = null, $category_id = null, $owner_id = null)
{
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'duplicateTaskToProject', $project_id);
return $this->taskDuplicationModel->duplicateToProject($task_id, $project_id, $swimlane_id, $column_id, $category_id, $owner_id);
}
@@ -86,8 +91,8 @@ class TaskApi extends BaseApi
$recurrence_status = 0, $recurrence_trigger = 0, $recurrence_factor = 0, $recurrence_timeframe = 0,
$recurrence_basedate = 0, $reference = '')
{
- $this->checkProjectPermission($project_id);
-
+ ProjectAuthorization::getInstance($this->container)->check($this->getClassName(), 'createTask', $project_id);
+
if ($owner_id !== 0 && ! $this->projectPermissionModel->isAssignable($project_id, $owner_id)) {
return false;
}
@@ -127,8 +132,7 @@ class TaskApi extends BaseApi
$recurrence_status = null, $recurrence_trigger = null, $recurrence_factor = null,
$recurrence_timeframe = null, $recurrence_basedate = null, $reference = null)
{
- $this->checkTaskPermission($id);
-
+ TaskAuthorization::getInstance($this->container)->check($this->getClassName(), 'updateTask', $id);
$project_id = $this->taskFinderModel->getProjectId($id);
if ($project_id === 0) {
@@ -139,7 +143,7 @@ class TaskApi extends BaseApi
return false;
}
- $values = array(
+ $values = $this->filterValues(array(
'id' => $id,
'title' => $title,
'color_id' => $color_id,
@@ -155,13 +159,7 @@ class TaskApi extends BaseApi
'recurrence_basedate' => $recurrence_basedate,
'reference' => $reference,
'priority' => $priority,
- );
-
- foreach ($values as $key => $value) {
- if (is_null($value)) {
- unset($values[$key]);
- }
- }
+ ));
list($valid) = $this->taskValidator->validateApiModification($values);
return $valid && $this->taskModificationModel->update($values);
diff --git a/app/Api/UserApi.php b/app/Api/Procedure/UserProcedure.php
index 88d75527..145f85bf 100644
--- a/app/Api/UserApi.php
+++ b/app/Api/Procedure/UserProcedure.php
@@ -1,8 +1,7 @@
<?php
-namespace Kanboard\Api;
+namespace Kanboard\Api\Procedure;
-use Kanboard\Core\Base;
use LogicException;
use Kanboard\Core\Security\Role;
use Kanboard\Core\Ldap\Client as LdapClient;
@@ -12,10 +11,10 @@ use Kanboard\Core\Ldap\User as LdapUser;
/**
* User API controller
*
- * @package Kanboard\Api
+ * @package Kanboard\Api\Procedure
* @author Frederic Guillot
*/
-class UserApi extends Base
+class UserProcedure extends BaseProcedure
{
public function getUser($user_id)
{
@@ -118,19 +117,13 @@ class UserApi extends Base
public function updateUser($id, $username = null, $name = null, $email = null, $role = null)
{
- $values = array(
+ $values = $this->filterValues(array(
'id' => $id,
'username' => $username,
'name' => $name,
'email' => $email,
'role' => $role,
- );
-
- foreach ($values as $key => $value) {
- if (is_null($value)) {
- unset($values[$key]);
- }
- }
+ ));
list($valid, ) = $this->userValidator->validateApiModification($values);
return $valid && $this->userModel->update($values);
diff --git a/app/Api/ProjectApi.php b/app/Api/ProjectApi.php
deleted file mode 100644
index 29a9cd79..00000000
--- a/app/Api/ProjectApi.php
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-
-namespace Kanboard\Api;
-
-/**
- * Project API controller
- *
- * @package Kanboard\Api
- * @author Frederic Guillot
- */
-class ProjectApi extends BaseApi
-{
- public function getProjectById($project_id)
- {
- $this->checkProjectPermission($project_id);
- return $this->formatProject($this->projectModel->getById($project_id));
- }
-
- public function getProjectByName($name)
- {
- return $this->formatProject($this->projectModel->getByName($name));
- }
-
- public function getAllProjects()
- {
- return $this->formatProjects($this->projectModel->getAll());
- }
-
- public function removeProject($project_id)
- {
- return $this->projectModel->remove($project_id);
- }
-
- public function enableProject($project_id)
- {
- return $this->projectModel->enable($project_id);
- }
-
- public function disableProject($project_id)
- {
- return $this->projectModel->disable($project_id);
- }
-
- public function enableProjectPublicAccess($project_id)
- {
- return $this->projectModel->enablePublicAccess($project_id);
- }
-
- public function disableProjectPublicAccess($project_id)
- {
- return $this->projectModel->disablePublicAccess($project_id);
- }
-
- public function getProjectActivities(array $project_ids)
- {
- return $this->helper->projectActivity->getProjectsEvents($project_ids);
- }
-
- public function getProjectActivity($project_id)
- {
- $this->checkProjectPermission($project_id);
- return $this->helper->projectActivity->getProjectEvents($project_id);
- }
-
- public function createProject($name, $description = null)
- {
- $values = array(
- 'name' => $name,
- 'description' => $description
- );
-
- list($valid, ) = $this->projectValidator->validateCreation($values);
- return $valid ? $this->projectModel->create($values) : false;
- }
-
- public function updateProject($id, $name, $description = null)
- {
- $values = array(
- 'id' => $id,
- 'name' => $name,
- 'description' => $description
- );
-
- list($valid, ) = $this->projectValidator->validateModification($values);
- return $valid && $this->projectModel->update($values);
- }
-}
diff --git a/app/Api/SubtaskTimeTrackingApi.php b/app/Api/SubtaskTimeTrackingApi.php
deleted file mode 100644
index 0e700b31..00000000
--- a/app/Api/SubtaskTimeTrackingApi.php
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-
-namespace Kanboard\Api;
-
-use Kanboard\Core\Base;
-
-/**
- * Subtask Time Tracking API controller
- *
- * @package api
- * @author Nikolaos Georgakis
- */
-class SubtaskTimeTrackingApi extends Base
-{
- public function hasTimer($subtask_id,$user_id)
- {
- return $this->subtaskTimeTrackingModel->hasTimer($subtask_id,$user_id);
- }
-
- public function logStartTime($subtask_id,$user_id)
- {
- return $this->subtaskTimeTrackingModel->logStartTime($subtask_id,$user_id);
- }
-
- public function logEndTime($subtask_id,$user_id)
- {
- return $this->subtaskTimeTrackingModel->logEndTime($subtask_id,$user_id);
- }
-
- public function getTimeSpent($subtask_id,$user_id)
- {
- return $this->subtaskTimeTrackingModel->getTimeSpent($subtask_id,$user_id);
- }
-}
diff --git a/app/Core/Base.php b/app/Core/Base.php
index e5dd6ad9..eacca65d 100644
--- a/app/Core/Base.php
+++ b/app/Core/Base.php
@@ -35,8 +35,12 @@ use Pimple\Container;
* @property \Kanboard\Core\Security\AuthenticationManager $authenticationManager
* @property \Kanboard\Core\Security\AccessMap $applicationAccessMap
* @property \Kanboard\Core\Security\AccessMap $projectAccessMap
+ * @property \Kanboard\Core\Security\AccessMap $apiAccessMap
+ * @property \Kanboard\Core\Security\AccessMap $apiProjectAccessMap
* @property \Kanboard\Core\Security\Authorization $applicationAuthorization
* @property \Kanboard\Core\Security\Authorization $projectAuthorization
+ * @property \Kanboard\Core\Security\Authorization $apiAuthorization
+ * @property \Kanboard\Core\Security\Authorization $apiProjectAuthorization
* @property \Kanboard\Core\Security\Role $role
* @property \Kanboard\Core\Security\Token $token
* @property \Kanboard\Core\Session\FlashMessage $flash
diff --git a/app/Model/ActionModel.php b/app/Model/ActionModel.php
index 53393ed5..b5d2bd06 100644
--- a/app/Model/ActionModel.php
+++ b/app/Model/ActionModel.php
@@ -86,6 +86,18 @@ class ActionModel extends Base
}
/**
+ * Get the projectId by the actionId
+ *
+ * @access public
+ * @param integer $action_id
+ * @return integer
+ */
+ public function getProjectId($action_id)
+ {
+ return $this->db->table(self::TABLE)->eq('id', $action_id)->findOneColumn('project_id') ?: 0;
+ }
+
+ /**
* Attach parameters to actions
*
* @access private
diff --git a/app/Model/CategoryModel.php b/app/Model/CategoryModel.php
index 62fb5611..024d0026 100644
--- a/app/Model/CategoryModel.php
+++ b/app/Model/CategoryModel.php
@@ -56,6 +56,18 @@ class CategoryModel extends Base
}
/**
+ * Get the projectId by the category id
+ *
+ * @access public
+ * @param integer $category_id Category id
+ * @return integer
+ */
+ public function getProjectId($category_id)
+ {
+ return $this->db->table(self::TABLE)->eq('id', $category_id)->findOneColumn('project_id') ?: 0;
+ }
+
+ /**
* Get a category id by the category name and project id
*
* @access public
diff --git a/app/Model/ColumnModel.php b/app/Model/ColumnModel.php
index 1adac0f2..795fe692 100644
--- a/app/Model/ColumnModel.php
+++ b/app/Model/ColumnModel.php
@@ -32,6 +32,18 @@ class ColumnModel extends Base
}
/**
+ * Get projectId by the columnId
+ *
+ * @access public
+ * @param integer $column_id Column id
+ * @return integer
+ */
+ public function getProjectId($column_id)
+ {
+ return $this->db->table(self::TABLE)->eq('id', $column_id)->findOneColumn('project_id');
+ }
+
+ /**
* Get the first column id for a given project
*
* @access public
diff --git a/app/Model/CommentModel.php b/app/Model/CommentModel.php
index 36e1fc48..4231f29d 100644
--- a/app/Model/CommentModel.php
+++ b/app/Model/CommentModel.php
@@ -30,6 +30,22 @@ class CommentModel extends Base
const EVENT_USER_MENTION = 'comment.user.mention';
/**
+ * Get projectId from commentId
+ *
+ * @access public
+ * @param integer $comment_id
+ * @return integer
+ */
+ public function getProjectId($comment_id)
+ {
+ return $this->db
+ ->table(self::TABLE)
+ ->eq(self::TABLE.'.id', $comment_id)
+ ->join(TaskModel::TABLE, 'id', 'task_id')
+ ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0;
+ }
+
+ /**
* Get all comments for a given task
*
* @access public
diff --git a/app/Model/SubtaskModel.php b/app/Model/SubtaskModel.php
index 019064ad..a97bddbf 100644
--- a/app/Model/SubtaskModel.php
+++ b/app/Model/SubtaskModel.php
@@ -52,6 +52,22 @@ class SubtaskModel extends Base
const EVENT_DELETE = 'subtask.delete';
/**
+ * Get projectId from subtaskId
+ *
+ * @access public
+ * @param integer $subtask_id
+ * @return integer
+ */
+ public function getProjectId($subtask_id)
+ {
+ return $this->db
+ ->table(self::TABLE)
+ ->eq(self::TABLE.'.id', $subtask_id)
+ ->join(TaskModel::TABLE, 'id', 'task_id')
+ ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0;
+ }
+
+ /**
* Get available status
*
* @access public
diff --git a/app/Model/TaskFileModel.php b/app/Model/TaskFileModel.php
index 24c1ad4b..7603019a 100644
--- a/app/Model/TaskFileModel.php
+++ b/app/Model/TaskFileModel.php
@@ -73,6 +73,22 @@ class TaskFileModel extends FileModel
}
/**
+ * Get projectId from fileId
+ *
+ * @access public
+ * @param integer $file_id
+ * @return integer
+ */
+ public function getProjectId($file_id)
+ {
+ return $this->db
+ ->table(self::TABLE)
+ ->eq(self::TABLE.'.id', $file_id)
+ ->join(TaskModel::TABLE, 'id', 'task_id')
+ ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0;
+ }
+
+ /**
* Handle screenshot upload
*
* @access public
diff --git a/app/Model/TaskLinkModel.php b/app/Model/TaskLinkModel.php
index 45225e35..09978eae 100644
--- a/app/Model/TaskLinkModel.php
+++ b/app/Model/TaskLinkModel.php
@@ -29,6 +29,22 @@ class TaskLinkModel extends Base
const EVENT_CREATE_UPDATE = 'tasklink.create_update';
/**
+ * Get projectId from $task_link_id
+ *
+ * @access public
+ * @param integer $task_link_id
+ * @return integer
+ */
+ public function getProjectId($task_link_id)
+ {
+ return $this->db
+ ->table(self::TABLE)
+ ->eq(self::TABLE.'.id', $task_link_id)
+ ->join(TaskModel::TABLE, 'id', 'task_id')
+ ->findOneColumn(TaskModel::TABLE . '.project_id') ?: 0;
+ }
+
+ /**
* Get a task link
*
* @access public
diff --git a/app/ServiceProvider/ApiProvider.php b/app/ServiceProvider/ApiProvider.php
index 93b3c7f5..f88d9b4f 100644
--- a/app/ServiceProvider/ApiProvider.php
+++ b/app/ServiceProvider/ApiProvider.php
@@ -3,26 +3,26 @@
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\SubtaskTimeTrackingApi;
-use Kanboard\Api\SwimlaneApi;
-use Kanboard\Api\TaskApi;
-use Kanboard\Api\TaskLinkApi;
-use Kanboard\Api\UserApi;
+use Kanboard\Api\Procedure\ActionProcedure;
+use Kanboard\Api\Procedure\AppProcedure;
+use Kanboard\Api\Procedure\BoardProcedure;
+use Kanboard\Api\Procedure\CategoryProcedure;
+use Kanboard\Api\Procedure\ColumnProcedure;
+use Kanboard\Api\Procedure\CommentProcedure;
+use Kanboard\Api\Procedure\TaskFileProcedure;
+use Kanboard\Api\Procedure\GroupProcedure;
+use Kanboard\Api\Procedure\GroupMemberProcedure;
+use Kanboard\Api\Procedure\LinkProcedure;
+use Kanboard\Api\Procedure\MeProcedure;
+use Kanboard\Api\Middleware\AuthenticationMiddleware;
+use Kanboard\Api\Procedure\ProjectProcedure;
+use Kanboard\Api\Procedure\ProjectPermissionProcedure;
+use Kanboard\Api\Procedure\SubtaskProcedure;
+use Kanboard\Api\Procedure\SubtaskTimeTrackingProcedure;
+use Kanboard\Api\Procedure\SwimlaneProcedure;
+use Kanboard\Api\Procedure\TaskProcedure;
+use Kanboard\Api\Procedure\TaskLinkProcedure;
+use Kanboard\Api\Procedure\UserProcedure;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
@@ -45,31 +45,32 @@ class ApiProvider implements ServiceProviderInterface
$server = new Server();
$server->setAuthenticationHeader(API_AUTHENTICATION_HEADER);
$server->getMiddlewareHandler()
- ->withMiddleware(new AuthenticationApiMiddleware($container))
+ ->withMiddleware(new AuthenticationMiddleware($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 SubtaskTimeTrackingApi($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))
+ ->withObject(new MeProcedure($container))
+ ->withObject(new ActionProcedure($container))
+ ->withObject(new AppProcedure($container))
+ ->withObject(new BoardProcedure($container))
+ ->withObject(new ColumnProcedure($container))
+ ->withObject(new CategoryProcedure($container))
+ ->withObject(new CommentProcedure($container))
+ ->withObject(new TaskFileProcedure($container))
+ ->withObject(new LinkProcedure($container))
+ ->withObject(new ProjectProcedure($container))
+ ->withObject(new ProjectPermissionProcedure($container))
+ ->withObject(new SubtaskProcedure($container))
+ ->withObject(new SubtaskTimeTrackingProcedure($container))
+ ->withObject(new SwimlaneProcedure($container))
+ ->withObject(new TaskProcedure($container))
+ ->withObject(new TaskLinkProcedure($container))
+ ->withObject(new UserProcedure($container))
+ ->withObject(new GroupProcedure($container))
+ ->withObject(new GroupMemberProcedure($container))
+ ->withBeforeMethod('beforeProcedure')
;
-
+
$container['api'] = $server;
return $container;
}
diff --git a/app/ServiceProvider/AuthenticationProvider.php b/app/ServiceProvider/AuthenticationProvider.php
index 84e4354d..751fe514 100644
--- a/app/ServiceProvider/AuthenticationProvider.php
+++ b/app/ServiceProvider/AuthenticationProvider.php
@@ -46,9 +46,13 @@ class AuthenticationProvider implements ServiceProviderInterface
$container['projectAccessMap'] = $this->getProjectAccessMap();
$container['applicationAccessMap'] = $this->getApplicationAccessMap();
+ $container['apiAccessMap'] = $this->getApiAccessMap();
+ $container['apiProjectAccessMap'] = $this->getApiProjectAccessMap();
$container['projectAuthorization'] = new Authorization($container['projectAccessMap']);
$container['applicationAuthorization'] = new Authorization($container['applicationAccessMap']);
+ $container['apiAuthorization'] = new Authorization($container['apiAccessMap']);
+ $container['apiProjectAuthorization'] = new Authorization($container['apiProjectAccessMap']);
return $container;
}
@@ -151,4 +155,57 @@ class AuthenticationProvider implements ServiceProviderInterface
return $acl;
}
+
+ /**
+ * Get ACL for the API
+ *
+ * @access public
+ * @return AccessMap
+ */
+ public function getApiAccessMap()
+ {
+ $acl = new AccessMap;
+ $acl->setDefaultRole(Role::APP_USER);
+ $acl->setRoleHierarchy(Role::APP_ADMIN, array(Role::APP_MANAGER, Role::APP_USER, Role::APP_PUBLIC));
+ $acl->setRoleHierarchy(Role::APP_MANAGER, array(Role::APP_USER, Role::APP_PUBLIC));
+
+ $acl->add('UserProcedure', '*', Role::APP_ADMIN);
+ $acl->add('GroupMemberProcedure', '*', Role::APP_ADMIN);
+ $acl->add('GroupProcedure', '*', Role::APP_ADMIN);
+ $acl->add('LinkProcedure', '*', Role::APP_ADMIN);
+ $acl->add('TaskProcedure', array('getOverdueTasks'), Role::APP_ADMIN);
+ $acl->add('ProjectProcedure', array('getAllProjects'), Role::APP_ADMIN);
+ $acl->add('ProjectProcedure', array('createProject'), Role::APP_MANAGER);
+
+ return $acl;
+ }
+
+ /**
+ * Get ACL for the API
+ *
+ * @access public
+ * @return AccessMap
+ */
+ public function getApiProjectAccessMap()
+ {
+ $acl = new AccessMap;
+ $acl->setDefaultRole(Role::PROJECT_VIEWER);
+ $acl->setRoleHierarchy(Role::PROJECT_MANAGER, array(Role::PROJECT_MEMBER, Role::PROJECT_VIEWER));
+ $acl->setRoleHierarchy(Role::PROJECT_MEMBER, array(Role::PROJECT_VIEWER));
+
+ $acl->add('ActionProcedure', array('removeAction', 'getActions', 'createAction'), Role::PROJECT_MANAGER);
+ $acl->add('CategoryProcedure', '*', Role::PROJECT_MANAGER);
+ $acl->add('ColumnProcedure', '*', Role::PROJECT_MANAGER);
+ $acl->add('CommentProcedure', array('removeComment', 'createComment', 'updateComment'), Role::PROJECT_MEMBER);
+ $acl->add('ProjectPermissionProcedure', '*', Role::PROJECT_MANAGER);
+ $acl->add('ProjectProcedure', array('updateProject', 'removeProject', 'enableProject', 'disableProject', 'enableProjectPublicAccess', 'disableProjectPublicAccess'), Role::PROJECT_MANAGER);
+ $acl->add('SubtaskProcedure', '*', Role::PROJECT_MEMBER);
+ $acl->add('SubtaskTimeTrackingProcedure', '*', Role::PROJECT_MEMBER);
+ $acl->add('SwimlaneProcedure', '*', Role::PROJECT_MANAGER);
+ $acl->add('TaskFileProcedure', '*', Role::PROJECT_MEMBER);
+ $acl->add('TaskLinkProcedure', '*', Role::PROJECT_MEMBER);
+ $acl->add('TaskProcedure', '*', Role::PROJECT_MEMBER);
+
+ return $acl;
+ }
}
diff --git a/app/Validator/ProjectValidator.php b/app/Validator/ProjectValidator.php
index 9ef59111..8c6117a4 100644
--- a/app/Validator/ProjectValidator.php
+++ b/app/Validator/ProjectValidator.php
@@ -28,7 +28,7 @@ class ProjectValidator extends BaseValidator
new Validators\Integer('priority_start', t('This value must be an integer')),
new Validators\Integer('priority_end', t('This value must be an integer')),
new Validators\Integer('is_active', t('This value must be an integer')),
- new Validators\Required('name', t('The project name is required')),
+ new Validators\NotEmpty('name', t('This field cannot be empty')),
new Validators\MaxLength('name', t('The maximum length is %d characters', 50), 50),
new Validators\MaxLength('identifier', t('The maximum length is %d characters', 50), 50),
new Validators\MaxLength('start_date', t('The maximum length is %d characters', 10), 10),
@@ -47,11 +47,15 @@ class ProjectValidator extends BaseValidator
*/
public function validateCreation(array $values)
{
+ $rules = array(
+ new Validators\Required('name', t('The project name is required')),
+ );
+
if (! empty($values['identifier'])) {
$values['identifier'] = strtoupper($values['identifier']);
}
- $v = new Validator($values, $this->commonValidationRules());
+ $v = new Validator($values, array_merge($this->commonValidationRules(), $rules));
return array(
$v->execute(),
diff --git a/composer.json b/composer.json
index 85fdb5ad..d82f3f0c 100644
--- a/composer.json
+++ b/composer.json
@@ -14,7 +14,7 @@
"discard-changes": true
},
"require" : {
- "php" : ">=5.3.3",
+ "php" : ">=5.3.9",
"ext-gd" : "*",
"ext-mbstring" : "*",
"ext-hash" : "*",
@@ -23,21 +23,21 @@
"ext-ctype" : "*",
"ext-filter" : "*",
"ext-session" : "*",
- "christian-riesen/otp" : "1.4",
- "eluceo/ical": "0.8.0",
+ "christian-riesen/otp" : "1.4.3",
+ "eluceo/ical": "0.10.1",
"erusev/parsedown" : "1.6.0",
- "fguillot/json-rpc" : "1.2.0",
+ "fguillot/json-rpc" : "1.2.1",
"fguillot/picodb" : "1.0.12",
"fguillot/simpleLogger" : "1.0.1",
- "fguillot/simple-validator" : "1.0.0",
+ "fguillot/simple-validator" : "1.0.1",
"fguillot/simple-queue" : "1.0.1",
- "paragonie/random_compat": "@stable",
- "pimple/pimple" : "~3.0",
- "ramsey/array_column": "@stable",
- "swiftmailer/swiftmailer" : "~5.4",
- "symfony/console" : "~2.7",
- "symfony/event-dispatcher" : "~2.7",
- "gregwar/captcha": "1.*"
+ "paragonie/random_compat": "2.0.2",
+ "pimple/pimple" : "3.0.2",
+ "ramsey/array_column": "1.1.3",
+ "swiftmailer/swiftmailer" : "5.4.2",
+ "symfony/console" : "2.8.7",
+ "symfony/event-dispatcher" : "2.7.14",
+ "gregwar/captcha": "1.1.1"
},
"autoload" : {
"classmap" : ["app/"],
@@ -50,9 +50,10 @@
]
},
"require-dev" : {
- "symfony/yaml" : "2.1",
- "symfony/stopwatch" : "~2.6",
- "phpunit/phpunit" : "4.8.*",
- "phpunit/phpunit-selenium": "^2.0"
+ "phpdocumentor/reflection-docblock": "2.0.4",
+ "symfony/yaml": "2.8.7",
+ "symfony/stopwatch" : "2.6.13",
+ "phpunit/phpunit" : "4.8.26",
+ "phpunit/phpunit-selenium": "2.0.2"
}
}
diff --git a/composer.lock b/composer.lock
index e0177ed5..03c5e523 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": "2de2026649db7bc41653bef80f974c6a",
- "content-hash": "ea8ef74f1f1cf53b9f96b7609d756873",
+ "hash": "ab5b2c960b3a6d9f93883606269085e0",
+ "content-hash": "bd5f17c3382d7f85e33a68023927704c",
"packages": [
{
"name": "christian-riesen/base32",
@@ -63,22 +63,25 @@
},
{
"name": "christian-riesen/otp",
- "version": "1.4",
+ "version": "1.4.3",
"source": {
"type": "git",
"url": "https://github.com/ChristianRiesen/otp.git",
- "reference": "a209b8bbd975d96d6b5287f8658562061adef1f8"
+ "reference": "20a539ce6280eb029030f4e7caefd5709a75e1ad"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ChristianRiesen/otp/zipball/a209b8bbd975d96d6b5287f8658562061adef1f8",
- "reference": "a209b8bbd975d96d6b5287f8658562061adef1f8",
+ "url": "https://api.github.com/repos/ChristianRiesen/otp/zipball/20a539ce6280eb029030f4e7caefd5709a75e1ad",
+ "reference": "20a539ce6280eb029030f4e7caefd5709a75e1ad",
"shasum": ""
},
"require": {
"christian-riesen/base32": ">=1.0",
"php": ">=5.3.0"
},
+ "suggest": {
+ "paragonie/random_compat": "Optional polyfill for a more secure random generator for pre PHP7 versions"
+ },
"type": "library",
"autoload": {
"psr-0": {
@@ -107,20 +110,20 @@
"rfc6238",
"totp"
],
- "time": "2015-02-12 09:11:49"
+ "time": "2015-10-08 08:17:59"
},
{
"name": "eluceo/ical",
- "version": "0.8.0",
+ "version": "0.10.1",
"source": {
"type": "git",
"url": "https://github.com/markuspoerschke/iCal.git",
- "reference": "a291711851d1538e2726ffe95862aa5e340ddb9a"
+ "reference": "2dd99c12c0aa961c541380ab0c113135e14af33e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/markuspoerschke/iCal/zipball/a291711851d1538e2726ffe95862aa5e340ddb9a",
- "reference": "a291711851d1538e2726ffe95862aa5e340ddb9a",
+ "url": "https://api.github.com/repos/markuspoerschke/iCal/zipball/2dd99c12c0aa961c541380ab0c113135e14af33e",
+ "reference": "2dd99c12c0aa961c541380ab0c113135e14af33e",
"shasum": ""
},
"require": {
@@ -160,7 +163,7 @@
"ics",
"php calendar"
],
- "time": "2015-07-12 18:19:30"
+ "time": "2016-06-09 09:08:55"
},
{
"name": "erusev/parsedown",
@@ -203,16 +206,16 @@
},
{
"name": "fguillot/json-rpc",
- "version": "v1.2.0",
+ "version": "v1.2.1",
"source": {
"type": "git",
"url": "https://github.com/fguillot/JsonRPC.git",
- "reference": "b002320b10aa1eeb7aee83f7b703cd6a6e99ff78"
+ "reference": "d491bb549bfa11aff4c37abcea2ffb28c9523f69"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/b002320b10aa1eeb7aee83f7b703cd6a6e99ff78",
- "reference": "b002320b10aa1eeb7aee83f7b703cd6a6e99ff78",
+ "url": "https://api.github.com/repos/fguillot/JsonRPC/zipball/d491bb549bfa11aff4c37abcea2ffb28c9523f69",
+ "reference": "d491bb549bfa11aff4c37abcea2ffb28c9523f69",
"shasum": ""
},
"require": {
@@ -238,7 +241,7 @@
],
"description": "Simple Json-RPC client/server library that just works",
"homepage": "https://github.com/fguillot/JsonRPC",
- "time": "2016-05-29 13:06:36"
+ "time": "2016-06-25 23:11:10"
},
{
"name": "fguillot/picodb",
@@ -331,16 +334,16 @@
},
{
"name": "fguillot/simple-validator",
- "version": "1.0.0",
+ "version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/fguillot/simpleValidator.git",
- "reference": "9579993f3dd0f03053b28fec1e7b9990edc3947b"
+ "reference": "23b0a99c5f11ad74d05f8845feaafbcfd9223eda"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/fguillot/simpleValidator/zipball/9579993f3dd0f03053b28fec1e7b9990edc3947b",
- "reference": "9579993f3dd0f03053b28fec1e7b9990edc3947b",
+ "url": "https://api.github.com/repos/fguillot/simpleValidator/zipball/23b0a99c5f11ad74d05f8845feaafbcfd9223eda",
+ "reference": "23b0a99c5f11ad74d05f8845feaafbcfd9223eda",
"shasum": ""
},
"require": {
@@ -363,7 +366,7 @@
],
"description": "Simple validator library",
"homepage": "https://github.com/fguillot/simpleValidator",
- "time": "2015-08-29 00:44:37"
+ "time": "2016-06-26 15:09:26"
},
{
"name": "fguillot/simpleLogger",
@@ -682,16 +685,16 @@
},
{
"name": "symfony/console",
- "version": "v2.8.6",
+ "version": "v2.8.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "48221d3de4dc22d2cd57c97e8b9361821da86609"
+ "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/48221d3de4dc22d2cd57c97e8b9361821da86609",
- "reference": "48221d3de4dc22d2cd57c97e8b9361821da86609",
+ "url": "https://api.github.com/repos/symfony/console/zipball/5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3",
+ "reference": "5ac8bc9aa77bb2edf06af3a1bb6bc1020d23acd3",
"shasum": ""
},
"require": {
@@ -738,20 +741,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2016-04-26 12:00:47"
+ "time": "2016-06-06 15:06:25"
},
{
"name": "symfony/event-dispatcher",
- "version": "v2.8.6",
+ "version": "v2.7.14",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "a158f13992a3147d466af7a23b564ac719a4ddd8"
+ "reference": "d3e09ed1224503791f31b913d22196f65f9afed5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a158f13992a3147d466af7a23b564ac719a4ddd8",
- "reference": "a158f13992a3147d466af7a23b564ac719a4ddd8",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d3e09ed1224503791f31b913d22196f65f9afed5",
+ "reference": "d3e09ed1224503791f31b913d22196f65f9afed5",
"shasum": ""
},
"require": {
@@ -759,10 +762,10 @@
},
"require-dev": {
"psr/log": "~1.0",
- "symfony/config": "~2.0,>=2.0.5|~3.0.0",
- "symfony/dependency-injection": "~2.6|~3.0.0",
- "symfony/expression-language": "~2.6|~3.0.0",
- "symfony/stopwatch": "~2.3|~3.0.0"
+ "symfony/config": "~2.0,>=2.0.5",
+ "symfony/dependency-injection": "~2.6",
+ "symfony/expression-language": "~2.6",
+ "symfony/stopwatch": "~2.3"
},
"suggest": {
"symfony/dependency-injection": "",
@@ -771,7 +774,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.8-dev"
+ "dev-master": "2.7-dev"
}
},
"autoload": {
@@ -798,7 +801,7 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "time": "2016-05-03 18:59:18"
+ "time": "2016-06-06 11:03:51"
},
{
"name": "symfony/polyfill-mbstring",
@@ -966,32 +969,32 @@
},
{
"name": "phpspec/prophecy",
- "version": "v1.6.0",
+ "version": "v1.6.1",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
- "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972"
+ "reference": "58a8137754bc24b25740d4281399a4a3596058e0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3c91bdf81797d725b14cb62906f9a4ce44235972",
- "reference": "3c91bdf81797d725b14cb62906f9a4ce44235972",
+ "url": "https://api.github.com/repos/phpspec/prophecy/zipball/58a8137754bc24b25740d4281399a4a3596058e0",
+ "reference": "58a8137754bc24b25740d4281399a4a3596058e0",
"shasum": ""
},
"require": {
"doctrine/instantiator": "^1.0.2",
"php": "^5.3|^7.0",
- "phpdocumentor/reflection-docblock": "~2.0",
- "sebastian/comparator": "~1.1",
- "sebastian/recursion-context": "~1.0"
+ "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
+ "sebastian/comparator": "^1.1",
+ "sebastian/recursion-context": "^1.0"
},
"require-dev": {
- "phpspec/phpspec": "~2.0"
+ "phpspec/phpspec": "^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.5.x-dev"
+ "dev-master": "1.6.x-dev"
}
},
"autoload": {
@@ -1024,7 +1027,7 @@
"spy",
"stub"
],
- "time": "2016-02-15 07:46:21"
+ "time": "2016-06-07 08:13:47"
},
{
"name": "phpunit/php-code-coverage",
@@ -1629,16 +1632,16 @@
},
{
"name": "sebastian/exporter",
- "version": "1.2.1",
+ "version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "7ae5513327cb536431847bcc0c10edba2701064e"
+ "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/7ae5513327cb536431847bcc0c10edba2701064e",
- "reference": "7ae5513327cb536431847bcc0c10edba2701064e",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
+ "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
"shasum": ""
},
"require": {
@@ -1646,12 +1649,13 @@
"sebastian/recursion-context": "~1.0"
},
"require-dev": {
+ "ext-mbstring": "*",
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2.x-dev"
+ "dev-master": "1.3.x-dev"
}
},
"autoload": {
@@ -1691,7 +1695,7 @@
"export",
"exporter"
],
- "time": "2015-06-21 07:55:53"
+ "time": "2016-06-17 09:04:28"
},
{
"name": "sebastian/global-state",
@@ -1834,34 +1838,35 @@
},
{
"name": "symfony/stopwatch",
- "version": "v2.8.6",
+ "version": "v2.6.13",
+ "target-dir": "Symfony/Component/Stopwatch",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
- "reference": "9e24824b2a9a16e17ab997f61d70bc03948e434e"
+ "reference": "a0d91f2f4e2c60bd78f13388aa68f9d7cab8c987"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/stopwatch/zipball/9e24824b2a9a16e17ab997f61d70bc03948e434e",
- "reference": "9e24824b2a9a16e17ab997f61d70bc03948e434e",
+ "url": "https://api.github.com/repos/symfony/stopwatch/zipball/a0d91f2f4e2c60bd78f13388aa68f9d7cab8c987",
+ "reference": "a0d91f2f4e2c60bd78f13388aa68f9d7cab8c987",
"shasum": ""
},
"require": {
- "php": ">=5.3.9"
+ "php": ">=5.3.3"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "~2.7"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.8-dev"
+ "dev-master": "2.6-dev"
}
},
"autoload": {
- "psr-4": {
+ "psr-0": {
"Symfony\\Component\\Stopwatch\\": ""
- },
- "exclude-from-classmap": [
- "/Tests/"
- ]
+ }
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -1879,36 +1884,38 @@
],
"description": "Symfony Stopwatch Component",
"homepage": "https://symfony.com",
- "time": "2016-03-04 07:54:35"
+ "time": "2015-07-01 18:23:01"
},
{
"name": "symfony/yaml",
- "version": "v2.1.0",
- "target-dir": "Symfony/Component/Yaml",
+ "version": "v2.8.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
- "reference": "f18e004fc975707bb4695df1dbbe9b0d8c8b7715"
+ "reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/yaml/zipball/f18e004fc975707bb4695df1dbbe9b0d8c8b7715",
- "reference": "f18e004fc975707bb4695df1dbbe9b0d8c8b7715",
+ "url": "https://api.github.com/repos/symfony/yaml/zipball/815fabf3f48c7d1df345a69d1ad1a88f59757b34",
+ "reference": "815fabf3f48c7d1df345a69d1ad1a88f59757b34",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": ">=5.3.9"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.1-dev"
+ "dev-master": "2.8-dev"
}
},
"autoload": {
- "psr-0": {
- "Symfony\\Component\\Yaml": ""
- }
+ "psr-4": {
+ "Symfony\\Component\\Yaml\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
@@ -1916,29 +1923,26 @@
],
"authors": [
{
- "name": "Symfony Community",
- "homepage": "http://symfony.com/contributors"
- },
- {
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony Yaml Component",
- "homepage": "http://symfony.com",
- "time": "2012-08-22 13:48:41"
+ "homepage": "https://symfony.com",
+ "time": "2016-06-06 11:11:27"
}
],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": {
- "paragonie/random_compat": 0,
- "ramsey/array_column": 0
- },
+ "stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=5.3.3",
+ "php": ">=5.3.9",
"ext-gd": "*",
"ext-mbstring": "*",
"ext-hash": "*",
diff --git a/doc/api-authentication.markdown b/doc/api-authentication.markdown
index 962e5b1b..3ba1e8f5 100644
--- a/doc/api-authentication.markdown
+++ b/doc/api-authentication.markdown
@@ -1,48 +1,26 @@
API Authentication
==================
-Default method (HTTP Basic)
----------------------------
+API endpoint
+------------
+
+URL: `https://YOUR_SERVER/jsonrpc.php`
-The API credentials are available on the settings page.
-- API end-point: `https://YOUR_SERVER/jsonrpc.php`
+Default method (HTTP Basic)
+---------------------------
-If you want to use the "application api":
+### Application credentials
- Username: `jsonrpc`
- Password: API token on the settings page
-Otherwise for the "user api", just use the real username/passsword.
+### User credentials
+
+- Use the real username and password
The API use the [HTTP Basic Authentication Scheme described in the RFC2617](http://www.ietf.org/rfc/rfc2617.txt).
-If there is an authentication error, you will receive the HTTP status code `401 Not Authorized`.
-
-### Authorized User API procedures
-
-- getMe
-- getMyDashboard
-- getMyActivityStream
-- createMyPrivateProject
-- getMyProjectsList
-- getMyProjects
-- getTimezone
-- getVersion
-- getDefaultTaskColor
-- getDefaultTaskColors
-- getColorList
-- getProjectById
-- getTask
-- getTaskByReference
-- getAllTasks
-- openTask
-- closeTask
-- moveTaskPosition
-- createTask
-- updateTask
-- getBoard
-- getProjectActivity
-- getMyOverdueTasks
+
Custom HTTP header
------------------
@@ -64,3 +42,14 @@ curl \
-d '{"jsonrpc": "2.0", "method": "getAllProjects", "id": 1}' \
http://localhost/kanboard/jsonrpc.php
```
+
+Authentication error
+--------------------
+
+If the credentials are wrong, you will receive a `401 Not Authorized` and the corresponding JSON response.
+
+
+Authorization error
+-------------------
+
+If the connected user is not allowed to access to the resource, you will receive a `403 Forbidden`.
diff --git a/doc/api-json-rpc.markdown b/doc/api-json-rpc.markdown
index bb14b008..0f922a7c 100644
--- a/doc/api-json-rpc.markdown
+++ b/doc/api-json-rpc.markdown
@@ -8,25 +8,25 @@ There are two types of API access:
### Application API
-- Access to the API with the user "jsonrpc" and the token available in settings
+- Access to the API with the user "jsonrpc" and the token available on the settings page
- Access to all procedures
- No permission checked
- There is no user session on the server
+- No access to procedures that starts with "My..." (example: "getMe" or "getMyProjects")
- Example of possible clients: tools to migrate/import data, create tasks from another system, etc...
### User API
- Access to the API with the user credentials (username and password)
-- Access to a restricted set of procedures
-- The project permissions are checked
+- Application role and project permissions are checked for each procedure
- A user session is created on the server
-- Example of possible clients: mobile/desktop application, command line utility, etc...
+- Example of possible clients: native mobile/desktop application, command line utility, etc...
Security
--------
-- Always use HTTPS with a valid certificate
-- If you make a mobile application, it's your job to store securely the user credentials on the device
+- Always use HTTPS with a valid certificate (avoid clear text communication)
+- If you make a mobile application, it's your responsability to store securely the user credentials on the device
- After 3 authentication failure on the user api, the end-user have to unlock his account by using the login form
- Two factor authentication is not yet available through the API
diff --git a/doc/api-project-permission-procedures.markdown b/doc/api-project-permission-procedures.markdown
index 2844ae3c..d5e9b066 100644
--- a/doc/api-project-permission-procedures.markdown
+++ b/doc/api-project-permission-procedures.markdown
@@ -272,3 +272,36 @@ Response example:
"result": true
}
```
+
+## getProjectUserRole
+
+- Purpose: **Get the role of a user for a given project**
+- Parameters:
+ - **project_id** (integer, required)
+ - **user_id** (integer, required)
+- Result on success: **role name**
+- Result on failure: **false**
+
+Request example:
+
+```json
+{
+ "jsonrpc": "2.0",
+ "method": "getProjectUserRole",
+ "id": 2114673298,
+ "params": [
+ "2",
+ "3"
+ ]
+}
+```
+
+Response example:
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 2114673298,
+ "result": "project-viewer"
+}
+```
diff --git a/doc/api-project-procedures.markdown b/doc/api-project-procedures.markdown
index 6cc1b15b..d375852c 100644
--- a/doc/api-project-procedures.markdown
+++ b/doc/api-project-procedures.markdown
@@ -7,6 +7,8 @@ API Project Procedures
- Parameters:
- **name** (string, required)
- **description** (string, optional)
+ - **owner_id** (integer, optional)
+ - **identifier** (string, optional)
- Result on success: **project_id**
- Result on failure: **false**
@@ -183,9 +185,11 @@ Response example:
- Purpose: **Update a project**
- Parameters:
- - **id** (integer, required)
- - **name** (string, required)
+ - **project_id** (integer, required)
+ - **name** (string, optional)
- **description** (string, optional)
+ - **owner_id** (integer, optional)
+ - **identifier** (string, optional)
- Result on success: **true**
- Result on failure: **false**
@@ -197,7 +201,7 @@ Request example:
"method": "updateProject",
"id": 1853996288,
"params": {
- "id": 1,
+ "project_id": 1,
"name": "PHP client update"
}
}
diff --git a/doc/requirements.markdown b/doc/requirements.markdown
index 9943465a..f6c9b309 100644
--- a/doc/requirements.markdown
+++ b/doc/requirements.markdown
@@ -51,7 +51,7 @@ Kanboard is pre-configured to work with Apache (URL rewriting).
| PHP Version |
|----------------|
-| PHP >= 5.3.3 |
+| PHP >= 5.3.9 |
| PHP 5.4 |
| PHP 5.5 |
| PHP 5.6 |
diff --git a/doc/tests.markdown b/doc/tests.markdown
index 5e3d71d2..59177f87 100644
--- a/doc/tests.markdown
+++ b/doc/tests.markdown
@@ -9,7 +9,7 @@ Requirements
------------
- Linux/Unix machine
-- PHP cli
+- PHP
- PHPUnit installed
- Mysql and Postgresql (optional)
- Selenium (optional)
@@ -85,46 +85,37 @@ From your Kanboard directory, run the command `phpunit -c tests/units.postgres.x
Integration Tests
-----------------
-Acceptance tests (also known as end-to-end tests and sometimes functional tests) allow us to test the actual functionality of the browser using Selenium and PHPUnit.
+Integration tests are mainly used to test the API.
+The test suites are making real HTTP calls to the application that run inside a container.
-The PHPUnit config file is `tests/acceptance.xml`.
-From your Kanboard directory, run the command `phpunit -c tests/units.sqlite.xml`.
-
-Actually only the API calls are tested.
-
-Real HTTP calls are made with those tests.
-So a local instance of Kanboard is necessary and must listen on `http://localhost:8000/`.
-
-All data will be removed/altered by the test suite.
-Moreover the script will reset and set a new API key.
+### Requirements
-1. Start a local instance of Kanboard `php -S 127.0.0.1:8000`
-2. Run the test suite from another terminal
+- PHP
+- Composer
+- Unix operating system (Mac OS or Linux)
+- Docker
+- Docker Compose
-The same method as above is used to run tests across different databases:
+### Running integration tests
-- Sqlite: `phpunit -c tests/integration.sqlite.xml`
-- Mysql: `phpunit -c tests/integration.mysql.xml`
-- Postgresql: `phpunit -c tests/integration.postgres.xml`
+Integration tests are using Docker containers.
+There are 3 different environment available to run tests against each supported database.
-Example:
+You can use these commands to run each test suite:
```bash
-phpunit -c tests/integration.sqlite.xml
-
-PHPUnit 5.0.0 by Sebastian Bergmann and contributors.
+# Run tests with Sqlite
+make integration-test-sqlite
-............................................................... 63 / 135 ( 46%)
-............................................................... 126 / 135 ( 93%)
-......... 135 / 135 (100%)
+# Run tests with Mysql
+make integration-test-mysql
-Time: 1.18 minutes, Memory: 14.75Mb
-
-OK (135 tests, 526 assertions)
+# Run tests with Postgres
+make integration-test-postgres
```
Acceptance Tests
------------------
+----------------
Acceptance tests (also sometimes known as end-to-end tests, and functional tests) test the actual functionality of the UI in a browser using Selenium.
diff --git a/tests/configs/config.mysql.php b/tests/configs/config.mysql.php
new file mode 100644
index 00000000..27e32744
--- /dev/null
+++ b/tests/configs/config.mysql.php
@@ -0,0 +1,12 @@
+<?php
+
+define('DB_DRIVER', 'mysql');
+define('DB_USERNAME', 'root');
+define('DB_PASSWORD', 'kanboard');
+define('DB_HOSTNAME', 'mysql');
+define('DB_NAME', 'kanboard');
+
+define('DEBUG', true);
+define('LOG_DRIVER', 'stderr');
+
+define('API_AUTHENTICATION_TOKEN', 'test');
diff --git a/tests/configs/config.postgres.php b/tests/configs/config.postgres.php
new file mode 100644
index 00000000..161a2349
--- /dev/null
+++ b/tests/configs/config.postgres.php
@@ -0,0 +1,12 @@
+<?php
+
+define('DB_DRIVER', 'postgres');
+define('DB_USERNAME', 'postgres');
+define('DB_PASSWORD', 'postgres');
+define('DB_HOSTNAME', 'postgres');
+define('DB_NAME', 'kanboard');
+
+define('DEBUG', true);
+define('LOG_DRIVER', 'stderr');
+
+define('API_AUTHENTICATION_TOKEN', 'test');
diff --git a/tests/configs/config.sqlite.php b/tests/configs/config.sqlite.php
new file mode 100644
index 00000000..e969c17c
--- /dev/null
+++ b/tests/configs/config.sqlite.php
@@ -0,0 +1,8 @@
+<?php
+
+define('DB_DRIVER', 'sqlite');
+
+define('DEBUG', true);
+define('LOG_DRIVER', 'file');
+
+define('API_AUTHENTICATION_TOKEN', 'test');
diff --git a/tests/docker/Dockerfile.xenial b/tests/docker/Dockerfile.xenial
new file mode 100644
index 00000000..a48d0525
--- /dev/null
+++ b/tests/docker/Dockerfile.xenial
@@ -0,0 +1,24 @@
+FROM ubuntu:16.04
+
+RUN mkdir -p /var/lock/apache2 /var/run/apache2 /var/log/supervisor
+
+RUN apt-get update -qq && \
+ apt-get install -y apache2 supervisor cron curl unzip \
+ libapache2-mod-php7.0 php7.0-cli php7.0-mbstring php7.0-xml php7.0-mysql php7.0-sqlite3 \
+ php7.0-opcache php7.0-json php7.0-pgsql php7.0-ldap php7.0-gd php7.0-zip && \
+ apt clean && \
+ echo "ServerName localhost" >> /etc/apache2/apache2.conf && \
+ sed -ri 's/AllowOverride None/AllowOverride All/g' /etc/apache2/apache2.conf && \
+ a2enmod rewrite && \
+ curl -sS https://getcomposer.org/installer | php -- --filename=/usr/local/bin/composer
+
+COPY . /var/www/html
+
+RUN chown -R www-data:www-data /var/www/html/data /var/www/html/plugins
+
+COPY tests/docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
+COPY tests/configs /configs/
+
+EXPOSE 80
+
+ENTRYPOINT ["/var/www/html/tests/docker/entrypoint.sh"]
diff --git a/tests/docker/compose.integration.mysql.yaml b/tests/docker/compose.integration.mysql.yaml
new file mode 100644
index 00000000..6eda5eec
--- /dev/null
+++ b/tests/docker/compose.integration.mysql.yaml
@@ -0,0 +1,27 @@
+version: '2'
+services:
+ mysql:
+ image: mysql:5.7
+ environment:
+ MYSQL_ROOT_PASSWORD: "kanboard"
+ MYSQL_DATABASE: "kanboard"
+ MYSQL_USER: "kanboard"
+ MYSQL_PASSWORD: "kanboard"
+ ports:
+ - "3306:3306"
+ app:
+ build:
+ context: ../..
+ dockerfile: tests/docker/Dockerfile.xenial
+ ports:
+ - "8000:80"
+ depends_on:
+ - mysql
+ command: config-mysql
+ tests:
+ build:
+ context: ../..
+ dockerfile: tests/docker/Dockerfile.xenial
+ depends_on:
+ - app
+ command: integration-test-mysql
diff --git a/tests/docker/compose.integration.postgres.yaml b/tests/docker/compose.integration.postgres.yaml
new file mode 100644
index 00000000..ed095248
--- /dev/null
+++ b/tests/docker/compose.integration.postgres.yaml
@@ -0,0 +1,26 @@
+version: '2'
+services:
+ postgres:
+ image: postgres:9.5
+ environment:
+ POSTGRES_USER: postgres
+ POSTGRES_PASSWORD: postgres
+ POSTGRES_DB: kanboard
+ ports:
+ - "5432:5432"
+ app:
+ build:
+ context: ../..
+ dockerfile: tests/docker/Dockerfile.xenial
+ ports:
+ - "8000:80"
+ depends_on:
+ - postgres
+ command: config-postgres
+ tests:
+ build:
+ context: ../..
+ dockerfile: tests/docker/Dockerfile.xenial
+ depends_on:
+ - app
+ command: integration-test-postgres
diff --git a/tests/docker/compose.integration.sqlite.yaml b/tests/docker/compose.integration.sqlite.yaml
new file mode 100644
index 00000000..6431484e
--- /dev/null
+++ b/tests/docker/compose.integration.sqlite.yaml
@@ -0,0 +1,16 @@
+version: '2'
+services:
+ app:
+ build:
+ context: ../..
+ dockerfile: tests/docker/Dockerfile.xenial
+ ports:
+ - "8000:80"
+ command: config-sqlite
+ tests:
+ build:
+ context: ../..
+ dockerfile: tests/docker/Dockerfile.xenial
+ depends_on:
+ - app
+ command: integration-test-sqlite
diff --git a/tests/docker/entrypoint.sh b/tests/docker/entrypoint.sh
new file mode 100755
index 00000000..a88c7ed8
--- /dev/null
+++ b/tests/docker/entrypoint.sh
@@ -0,0 +1,33 @@
+#!/usr/bin/env bash
+
+function wait_schema_creation() {
+ curl -s http://app/login > /dev/null
+ sleep $1
+}
+
+case "$1" in
+"config-sqlite")
+ cp /configs/config.sqlite.php /var/www/html/config.php
+ /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
+ ;;
+"config-postgres")
+ cp /configs/config.postgres.php /var/www/html/config.php
+ /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
+ ;;
+"config-mysql")
+ cp /configs/config.mysql.php /var/www/html/config.php
+ /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
+ ;;
+"integration-test-sqlite")
+ wait_schema_creation 1
+ /var/www/html/vendor/phpunit/phpunit/phpunit -c /var/www/html/tests/integration.sqlite.xml
+ ;;
+"integration-test-postgres")
+ wait_schema_creation 5
+ /var/www/html/vendor/phpunit/phpunit/phpunit -c /var/www/html/tests/integration.postgres.xml
+ ;;
+"integration-test-mysql")
+ wait_schema_creation 15
+ /var/www/html/vendor/phpunit/phpunit/phpunit -c /var/www/html/tests/integration.mysql.xml
+ ;;
+esac
diff --git a/tests/docker/supervisord.conf b/tests/docker/supervisord.conf
new file mode 100644
index 00000000..4d5ee621
--- /dev/null
+++ b/tests/docker/supervisord.conf
@@ -0,0 +1,6 @@
+[supervisord]
+nodaemon=true
+
+[program:apache2]
+command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND"
+autorestart=true
diff --git a/tests/integration.mysql.xml b/tests/integration.mysql.xml
index 9d87f77e..33813187 100644
--- a/tests/integration.mysql.xml
+++ b/tests/integration.mysql.xml
@@ -5,16 +5,8 @@
</testsuite>
</testsuites>
<php>
- <const name="API_URL" value="http://localhost:8000/jsonrpc.php" />
- <const name="API_KEY" value="19ffd9709d03ce50675c3a43d1c49c1ac207f4bc45f06c5b2701fbdf8929" />
- <const name="DB_DRIVER" value="mysql" />
- <const name="DB_NAME" value="kanboard" />
- <const name="DB_HOSTNAME" value="localhost" />
- <const name="DB_USERNAME" value="root" />
- <const name="DB_PASSWORD" value="" />
- <const name="DB_PORT" value="" />
- <const name="DB_SSL_KEY" value="" />
- <const name="DB_SSL_CA" value="" />
- <const name="DB_SSL_CERT" value="" />
+ <const name="BASE_URL" value="http://app/" />
+ <const name="API_URL" value="http://app/jsonrpc.php" />
+ <const name="API_KEY" value="test" />
</php>
</phpunit>
diff --git a/tests/integration.postgres.xml b/tests/integration.postgres.xml
index ed8a3de3..33813187 100644
--- a/tests/integration.postgres.xml
+++ b/tests/integration.postgres.xml
@@ -5,13 +5,8 @@
</testsuite>
</testsuites>
<php>
- <const name="API_URL" value="http://localhost:8000/jsonrpc.php" />
- <const name="API_KEY" value="19ffd9709d03ce50675c3a43d1c49c1ac207f4bc45f06c5b2701fbdf8929" />
- <const name="DB_DRIVER" value="postgres" />
- <const name="DB_NAME" value="kanboard" />
- <const name="DB_HOSTNAME" value="localhost" />
- <const name="DB_USERNAME" value="postgres" />
- <const name="DB_PASSWORD" value="postgres" />
- <const name="DB_PORT" value="" />
+ <const name="BASE_URL" value="http://app/" />
+ <const name="API_URL" value="http://app/jsonrpc.php" />
+ <const name="API_KEY" value="test" />
</php>
-</phpunit> \ No newline at end of file
+</phpunit>
diff --git a/tests/integration.sqlite.xml b/tests/integration.sqlite.xml
index 1964f822..33813187 100644
--- a/tests/integration.sqlite.xml
+++ b/tests/integration.sqlite.xml
@@ -5,9 +5,8 @@
</testsuite>
</testsuites>
<php>
- <const name="API_URL" value="http://127.0.0.1:8000/jsonrpc.php" />
- <const name="API_KEY" value="19ffd9709d03ce50675c3a43d1c49c1ac207f4bc45f06c5b2701fbdf8929" />
- <const name="DB_DRIVER" value="sqlite" />
- <const name="DB_FILENAME" value="data/db.sqlite" />
+ <const name="BASE_URL" value="http://app/" />
+ <const name="API_URL" value="http://app/jsonrpc.php" />
+ <const name="API_KEY" value="test" />
</php>
-</phpunit> \ No newline at end of file
+</phpunit>
diff --git a/tests/integration/ActionProcedureTest.php b/tests/integration/ActionProcedureTest.php
new file mode 100644
index 00000000..432de3d3
--- /dev/null
+++ b/tests/integration/ActionProcedureTest.php
@@ -0,0 +1,66 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class ActionProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test actions';
+
+ public function testGetAvailableActions()
+ {
+ $actions = $this->app->getAvailableActions();
+ $this->assertNotEmpty($actions);
+ $this->assertInternalType('array', $actions);
+ $this->assertArrayHasKey('\Kanboard\Action\TaskCloseColumn', $actions);
+ }
+
+ public function testGetAvailableActionEvents()
+ {
+ $events = $this->app->getAvailableActionEvents();
+ $this->assertNotEmpty($events);
+ $this->assertInternalType('array', $events);
+ $this->assertArrayHasKey('task.move.column', $events);
+ }
+
+ public function testGetCompatibleActionEvents()
+ {
+ $events = $this->app->getCompatibleActionEvents('\Kanboard\Action\TaskCloseColumn');
+ $this->assertNotEmpty($events);
+ $this->assertInternalType('array', $events);
+ $this->assertArrayHasKey('task.move.column', $events);
+ }
+
+ public function testCRUD()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertCreateAction();
+ $this->assertGetActions();
+ $this->assertRemoveAction();
+ }
+
+ public function assertCreateAction()
+ {
+ $actionId = $this->app->createAction($this->projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1));
+ $this->assertNotFalse($actionId);
+ $this->assertTrue($actionId > 0);
+ }
+
+ public function assertGetActions()
+ {
+ $actions = $this->app->getActions($this->projectId);
+ $this->assertNotEmpty($actions);
+ $this->assertInternalType('array', $actions);
+ $this->assertArrayHasKey('id', $actions[0]);
+ $this->assertArrayHasKey('project_id', $actions[0]);
+ $this->assertArrayHasKey('event_name', $actions[0]);
+ $this->assertArrayHasKey('action_name', $actions[0]);
+ $this->assertArrayHasKey('params', $actions[0]);
+ $this->assertArrayHasKey('column_id', $actions[0]['params']);
+ }
+
+ public function assertRemoveAction()
+ {
+ $actionId = $this->app->createAction($this->projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1));
+ $this->assertTrue($this->app->removeAction($actionId));
+ }
+}
diff --git a/tests/integration/ApiTest.php b/tests/integration/ApiTest.php
deleted file mode 100644
index f552bea9..00000000
--- a/tests/integration/ApiTest.php
+++ /dev/null
@@ -1,928 +0,0 @@
-<?php
-
-require_once __DIR__.'/../../vendor/autoload.php';
-
-class Api extends PHPUnit_Framework_TestCase
-{
- private $client = null;
-
- public static function setUpBeforeClass()
- {
- if (DB_DRIVER === 'sqlite') {
- @unlink(DB_FILENAME);
- } elseif (DB_DRIVER === 'mysql') {
- $pdo = new PDO('mysql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
- $pdo->exec('DROP DATABASE '.DB_NAME);
- $pdo->exec('CREATE DATABASE '.DB_NAME);
- $pdo = null;
- } elseif (DB_DRIVER === 'postgres') {
- $pdo = new PDO('pgsql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
- $pdo->exec('DROP DATABASE '.DB_NAME);
- $pdo->exec('CREATE DATABASE '.DB_NAME.' WITH OWNER '.DB_USERNAME);
- $pdo = null;
- }
-
- $service = new Kanboard\ServiceProvider\DatabaseProvider;
-
- $db = $service->getInstance();
- $db->table('settings')->eq('option', 'api_token')->update(array('value' => API_KEY));
- $db->table('settings')->eq('option', 'application_timezone')->update(array('value' => 'Europe/Paris'));
- $db->closeConnection();
- }
-
- public function setUp()
- {
- $this->client = new JsonRPC\Client(API_URL);
- $this->client->authentication('jsonrpc', API_KEY);
- // $this->client->debug = true;
- }
-
- private function getTaskId()
- {
- $tasks = $this->client->getAllTasks(1, 1);
- $this->assertNotEmpty($tasks);
-
- return $tasks[0]['id'];
- }
-
- public function testRemoveAll()
- {
- $projects = $this->client->getAllProjects();
-
- if ($projects) {
- foreach ($projects as $project) {
- $this->assertEquals('http://127.0.0.1:8000/?controller=BoardViewController&action=show&project_id='.$project['id'], $project['url']['board']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=CalendarController&action=show&project_id='.$project['id'], $project['url']['calendar']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=TaskListController&action=show&project_id='.$project['id'], $project['url']['list']);
- $this->assertTrue($this->client->removeProject($project['id']));
- }
- }
- }
-
- public function testCreateProject()
- {
- $project_id = $this->client->createProject('API test');
- $this->assertNotFalse($project_id);
- $this->assertInternalType('int', $project_id);
- }
-
- public function testGetProjectById()
- {
- $project = $this->client->getProjectById(1);
- $this->assertNotEmpty($project);
- $this->assertEquals(1, $project['id']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=BoardViewController&action=show&project_id='.$project['id'], $project['url']['board']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=CalendarController&action=show&project_id='.$project['id'], $project['url']['calendar']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=TaskListController&action=show&project_id='.$project['id'], $project['url']['list']);
- }
-
- public function testGetProjectByName()
- {
- $project = $this->client->getProjectByName('API test');
- $this->assertNotEmpty($project);
- $this->assertEquals(1, $project['id']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=BoardViewController&action=show&project_id='.$project['id'], $project['url']['board']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=CalendarController&action=show&project_id='.$project['id'], $project['url']['calendar']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=TaskListController&action=show&project_id='.$project['id'], $project['url']['list']);
-
- $project = $this->client->getProjectByName(array('name' => 'API test'));
- $this->assertNotEmpty($project);
- $this->assertEquals(1, $project['id']);
-
- $project = $this->client->getProjectByName('None');
- $this->assertEmpty($project);
- $this->assertNull($project);
- }
-
- public function testGetAllProjects()
- {
- $projects = $this->client->getAllProjects();
- $this->assertNotEmpty($projects);
-
- foreach ($projects as $project) {
- $this->assertEquals('http://127.0.0.1:8000/?controller=BoardViewController&action=show&project_id='.$project['id'], $project['url']['board']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=CalendarController&action=show&project_id='.$project['id'], $project['url']['calendar']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=TaskListController&action=show&project_id='.$project['id'], $project['url']['list']);
- }
- }
-
- public function testUpdateProject()
- {
- $project = $this->client->getProjectById(1);
- $this->assertNotEmpty($project);
- $this->assertTrue($this->client->execute('updateProject', array('id' => 1, 'name' => 'API test 2')));
-
- $project = $this->client->getProjectById(1);
- $this->assertEquals('API test 2', $project['name']);
-
- $this->assertTrue($this->client->execute('updateProject', array('id' => 1, 'name' => 'API test', 'description' => 'test')));
-
- $project = $this->client->getProjectById(1);
- $this->assertEquals('API test', $project['name']);
- $this->assertEquals('test', $project['description']);
- }
-
- public function testDisableProject()
- {
- $this->assertTrue($this->client->disableProject(1));
- $project = $this->client->getProjectById(1);
- $this->assertNotEmpty($project);
- $this->assertEquals(0, $project['is_active']);
- }
-
- public function testEnableProject()
- {
- $this->assertTrue($this->client->enableProject(1));
- $project = $this->client->getProjectById(1);
- $this->assertNotEmpty($project);
- $this->assertEquals(1, $project['is_active']);
- }
-
- public function testEnableProjectPublicAccess()
- {
- $this->assertTrue($this->client->enableProjectPublicAccess(1));
- $project = $this->client->getProjectById(1);
- $this->assertNotEmpty($project);
- $this->assertEquals(1, $project['is_public']);
- $this->assertNotEmpty($project['token']);
- }
-
- public function testDisableProjectPublicAccess()
- {
- $this->assertTrue($this->client->disableProjectPublicAccess(1));
- $project = $this->client->getProjectById(1);
- $this->assertNotEmpty($project);
- $this->assertEquals(0, $project['is_public']);
- $this->assertEmpty($project['token']);
- }
-
- public function testgetProjectActivities()
- {
- $activities = $this->client->getProjectActivities(array('project_ids' => array(1)));
- $this->assertInternalType('array', $activities);
- $this->assertCount(0, $activities);
- }
-
- public function testgetProjectActivity()
- {
- $activities = $this->client->getProjectActivity(1);
- $this->assertInternalType('array', $activities);
- $this->assertCount(0, $activities);
- }
-
- public function testCreateTaskWithWrongMember()
- {
- $task = array(
- 'title' => 'Task #1',
- 'color_id' => 'blue',
- 'owner_id' => 1,
- 'project_id' => 1,
- 'column_id' => 2,
- );
-
- $task_id = $this->client->createTask($task);
-
- $this->assertFalse($task_id);
- }
-
- public function testGetAllowedUsers()
- {
- $users = $this->client->getMembers(1);
- $this->assertNotFalse($users);
- $this->assertEquals(array(), $users);
- }
-
- public function testAddMember()
- {
- $this->assertTrue($this->client->allowUser(1, 1));
- }
-
- public function testCreateTask()
- {
- $task = array(
- 'title' => 'Task #1',
- 'color_id' => 'blue',
- 'owner_id' => 1,
- 'project_id' => 1,
- 'column_id' => 2,
- );
-
- $task_id = $this->client->createTask($task);
-
- $this->assertNotFalse($task_id);
- $this->assertInternalType('int', $task_id);
- $this->assertTrue($task_id > 0);
- }
-
- /**
- * @expectedException InvalidArgumentException
- */
- public function testCreateTaskWithBadParams()
- {
- $task = array(
- 'title' => 'Task #1',
- 'color_id' => 'blue',
- 'owner_id' => 1,
- );
-
- $this->client->createTask($task);
- }
-
- public function testGetTask()
- {
- $task = $this->client->getTask(1);
-
- $this->assertNotFalse($task);
- $this->assertTrue(is_array($task));
- $this->assertEquals('Task #1', $task['title']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=TaskViewController&action=show&task_id='.$task['id'].'&project_id='.$task['project_id'], $task['url']);
- }
-
- public function testGetAllTasks()
- {
- $tasks = $this->client->getAllTasks(1, 1);
-
- $this->assertNotFalse($tasks);
- $this->assertTrue(is_array($tasks));
- $this->assertEquals('Task #1', $tasks[0]['title']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=TaskViewController&action=show&task_id='.$tasks[0]['id'].'&project_id='.$tasks[0]['project_id'], $tasks[0]['url']);
-
- $tasks = $this->client->getAllTasks(2, 0);
-
- $this->assertNotFalse($tasks);
- $this->assertTrue(is_array($tasks));
- $this->assertEmpty($tasks);
- }
-
- public function testMoveTaskSwimlane()
- {
- $task_id = $this->getTaskId();
-
- $task = $this->client->getTask($task_id);
- $this->assertNotFalse($task);
- $this->assertTrue(is_array($task));
- $this->assertEquals(1, $task['position']);
- $this->assertEquals(2, $task['column_id']);
- $this->assertEquals(0, $task['swimlane_id']);
-
- $moved_timestamp = $task['date_moved'];
- sleep(1);
- $this->assertTrue($this->client->moveTaskPosition(1, $task_id, 4, 1, 2));
-
- $task = $this->client->getTask($task_id);
- $this->assertNotFalse($task);
- $this->assertTrue(is_array($task));
- $this->assertEquals(1, $task['position']);
- $this->assertEquals(4, $task['column_id']);
- $this->assertEquals(2, $task['swimlane_id']);
- $this->assertNotEquals($moved_timestamp, $task['date_moved']);
- }
-
- public function testUpdateTask()
- {
- $task = $this->client->getTask(1);
-
- $values = array();
- $values['id'] = $task['id'];
- $values['color_id'] = 'green';
- $values['description'] = 'test';
- $values['date_due'] = '';
-
- $this->assertTrue($this->client->execute('updateTask', $values));
- }
-
- public function testRemoveTask()
- {
- $this->assertTrue($this->client->removeTask(1));
- }
-
- public function testRemoveUsers()
- {
- $users = $this->client->getAllUsers();
- $this->assertNotFalse($users);
- $this->assertNotEmpty($users);
-
- foreach ($users as $user) {
- if ($user['id'] > 1) {
- $this->assertTrue($this->client->removeUser($user['id']));
- }
- }
- }
-
- public function testCreateUser()
- {
- $user = array(
- 'username' => 'toto',
- 'name' => 'Toto',
- 'password' => '123456',
- );
-
- $user_id = $this->client->execute('createUser', $user);
- $this->assertNotFalse($user_id);
- $this->assertInternalType('int', $user_id);
- $this->assertTrue($user_id > 0);
- }
-
- public function testCreateManagerUser()
- {
- $user = array(
- 'username' => 'manager',
- 'name' => 'Manager',
- 'password' => '123456',
- 'role' => 'app-manager'
- );
-
- $user_id = $this->client->execute('createUser', $user);
- $this->assertNotFalse($user_id);
- $this->assertInternalType('int', $user_id);
- $this->assertTrue($user_id > 0);
- }
-
- /**
- * @expectedException InvalidArgumentException
- */
- public function testCreateUserWithBadParams()
- {
- $user = array(
- 'name' => 'Titi',
- 'password' => '123456',
- );
-
- $this->assertNull($this->client->execute('createUser', $user));
- }
-
- public function testGetUser()
- {
- $user = $this->client->getUser(2);
- $this->assertNotFalse($user);
- $this->assertTrue(is_array($user));
- $this->assertEquals('toto', $user['username']);
-
- $user = $this->client->getUser(3);
- $this->assertNotEmpty($user);
- $this->assertEquals('app-manager', $user['role']);
-
- $this->assertNull($this->client->getUser(2222));
- }
-
- public function testGetUserByName()
- {
- $user = $this->client->getUserByName('toto');
- $this->assertNotFalse($user);
- $this->assertTrue(is_array($user));
- $this->assertEquals(2, $user['id']);
-
- $user = $this->client->getUserByName('manager');
- $this->assertNotEmpty($user);
- $this->assertEquals('app-manager', $user['role']);
-
- $this->assertNull($this->client->getUserByName('nonexistantusername'));
- }
-
- public function testUpdateUser()
- {
- $user = array();
- $user['id'] = 2;
- $user['username'] = 'titi';
- $user['name'] = 'Titi';
-
- $this->assertTrue($this->client->execute('updateUser', $user));
-
- $user = $this->client->getUser(2);
- $this->assertNotFalse($user);
- $this->assertTrue(is_array($user));
- $this->assertEquals('titi', $user['username']);
- $this->assertEquals('Titi', $user['name']);
-
- $user = array();
- $user['id'] = 2;
- $user['email'] = 'titi@localhost';
-
- $this->assertTrue($this->client->execute('updateUser', $user));
-
- $user = $this->client->getUser(2);
- $this->assertNotFalse($user);
- $this->assertTrue(is_array($user));
- $this->assertEquals('titi@localhost', $user['email']);
- }
-
- public function testAllowedUser()
- {
- $this->assertTrue($this->client->allowUser(1, 2));
-
- $users = $this->client->getMembers(1);
- $this->assertNotFalse($users);
- $this->assertEquals(array(1 => 'admin', 2 => 'Titi'), $users);
- }
-
- public function testRevokeUser()
- {
- $this->assertTrue($this->client->revokeUser(1, 2));
-
- $users = $this->client->getMembers(1);
- $this->assertNotFalse($users);
- $this->assertEquals(array(1 => 'admin'), $users);
- }
-
- public function testCreateComment()
- {
- $task = array(
- 'title' => 'Task with comment',
- 'color_id' => 'red',
- 'owner_id' => 1,
- 'project_id' => 1,
- 'column_id' => 1,
- );
-
- $this->assertNotFalse($this->client->execute('createTask', $task));
-
- $tasks = $this->client->getAllTasks(1, 1);
- $this->assertNotEmpty($tasks);
- $this->assertEquals(1, count($tasks));
-
- $comment = array(
- 'task_id' => $tasks[0]['id'],
- 'user_id' => 2,
- 'content' => 'boo',
- );
-
- $comment_id = $this->client->execute('createComment', $comment);
-
- $this->assertNotFalse($comment_id);
- $this->assertInternalType('int', $comment_id);
- $this->assertTrue($comment_id > 0);
- }
-
- public function testGetComment()
- {
- $comment = $this->client->getComment(1);
- $this->assertNotFalse($comment);
- $this->assertNotEmpty($comment);
- $this->assertEquals(2, $comment['user_id']);
- $this->assertEquals('boo', $comment['comment']);
- }
-
- public function testUpdateComment()
- {
- $comment = array();
- $comment['id'] = 1;
- $comment['content'] = 'test';
-
- $this->assertTrue($this->client->execute('updateComment', $comment));
-
- $comment = $this->client->getComment(1);
- $this->assertEquals('test', $comment['comment']);
- }
-
- public function testGetAllComments()
- {
- $task_id = $this->getTaskId();
-
- $comment = array(
- 'task_id' => $task_id,
- 'user_id' => 1,
- 'content' => 'blabla',
- );
-
- $comment_id = $this->client->createComment($comment);
-
- $this->assertNotFalse($comment_id);
- $this->assertInternalType('int', $comment_id);
- $this->assertTrue($comment_id > 0);
-
- $comments = $this->client->getAllComments($task_id);
- $this->assertNotFalse($comments);
- $this->assertNotEmpty($comments);
- $this->assertTrue(is_array($comments));
- $this->assertEquals(2, count($comments));
- }
-
- public function testRemoveComment()
- {
- $task_id = $this->getTaskId();
-
- $comments = $this->client->getAllComments($task_id);
- $this->assertNotFalse($comments);
- $this->assertNotEmpty($comments);
- $this->assertTrue(is_array($comments));
-
- foreach ($comments as $comment) {
- $this->assertTrue($this->client->removeComment($comment['id']));
- }
-
- $comments = $this->client->getAllComments($task_id);
- $this->assertNotFalse($comments);
- $this->assertEmpty($comments);
- $this->assertTrue(is_array($comments));
- }
-
- public function testCreateSubtask()
- {
- $subtask = array(
- 'task_id' => $this->getTaskId(),
- 'title' => 'subtask #1',
- );
-
- $subtask_id = $this->client->createSubtask($subtask);
-
- $this->assertNotFalse($subtask_id);
- $this->assertInternalType('int', $subtask_id);
- $this->assertTrue($subtask_id > 0);
- }
-
- public function testGetSubtask()
- {
- $subtask = $this->client->getSubtask(1);
- $this->assertNotFalse($subtask);
- $this->assertNotEmpty($subtask);
- $this->assertEquals($this->getTaskId(), $subtask['task_id']);
- $this->assertEquals(0, $subtask['user_id']);
- $this->assertEquals('subtask #1', $subtask['title']);
- }
-
- public function testUpdateSubtask()
- {
- $subtask = array();
- $subtask['id'] = 1;
- $subtask['task_id'] = $this->getTaskId();
- $subtask['title'] = 'test';
-
- $this->assertTrue($this->client->execute('updateSubtask', $subtask));
-
- $subtask = $this->client->getSubtask(1);
- $this->assertEquals('test', $subtask['title']);
- }
-
- public function testGetAllSubtasks()
- {
- $subtask = array(
- 'task_id' => $this->getTaskId(),
- 'user_id' => 2,
- 'title' => 'Subtask #2',
- );
-
- $this->assertNotFalse($this->client->execute('createSubtask', $subtask));
-
- $subtasks = $this->client->getAllSubtasks($this->getTaskId());
- $this->assertNotFalse($subtasks);
- $this->assertNotEmpty($subtasks);
- $this->assertTrue(is_array($subtasks));
- $this->assertEquals(2, count($subtasks));
- }
-
- public function testRemoveSubtask()
- {
- $this->assertTrue($this->client->removeSubtask(1));
-
- $subtasks = $this->client->getAllSubtasks($this->getTaskId());
- $this->assertNotFalse($subtasks);
- $this->assertNotEmpty($subtasks);
- $this->assertTrue(is_array($subtasks));
- $this->assertEquals(1, count($subtasks));
- }
-
- public function testMoveTaskPosition()
- {
- $task_id = $this->getTaskId();
- $this->assertTrue($this->client->moveTaskPosition(1, $task_id, 3, 1));
-
- $task = $this->client->getTask($task_id);
- $this->assertNotFalse($task);
- $this->assertTrue(is_array($task));
- $this->assertEquals(1, $task['position']);
- $this->assertEquals(3, $task['column_id']);
- }
-
- public function testCategoryCreation()
- {
- $category = array(
- 'name' => 'Category',
- 'project_id' => 1,
- );
-
- $cat_id = $this->client->execute('createCategory', $category);
- $this->assertNotFalse($cat_id);
- $this->assertInternalType('int', $cat_id);
- $this->assertTrue($cat_id > 0);
-
- // Duplicate
-
- $category = array(
- 'name' => 'Category',
- 'project_id' => 1,
- );
-
- $this->assertFalse($this->client->execute('createCategory', $category));
- }
-
- /**
- * @expectedException InvalidArgumentException
- */
- public function testCategoryCreationWithBadParams()
- {
- // Missing project id
- $category = array(
- 'name' => 'Category',
- );
-
- $this->assertNull($this->client->execute('createCategory', $category));
- }
-
- public function testCategoryRead()
- {
- $category = $this->client->getCategory(1);
-
- $this->assertTrue(is_array($category));
- $this->assertNotEmpty($category);
- $this->assertEquals(1, $category['id']);
- $this->assertEquals('Category', $category['name']);
- $this->assertEquals(1, $category['project_id']);
- }
-
- public function testGetAllCategories()
- {
- $categories = $this->client->getAllCategories(1);
-
- $this->assertNotEmpty($categories);
- $this->assertNotFalse($categories);
- $this->assertTrue(is_array($categories));
- $this->assertEquals(1, count($categories));
- $this->assertEquals(1, $categories[0]['id']);
- $this->assertEquals('Category', $categories[0]['name']);
- $this->assertEquals(1, $categories[0]['project_id']);
- }
-
- public function testCategoryUpdate()
- {
- $category = array(
- 'id' => 1,
- 'name' => 'Renamed category',
- );
-
- $this->assertTrue($this->client->execute('updateCategory', $category));
-
- $category = $this->client->getCategory(1);
- $this->assertTrue(is_array($category));
- $this->assertNotEmpty($category);
- $this->assertEquals(1, $category['id']);
- $this->assertEquals('Renamed category', $category['name']);
- $this->assertEquals(1, $category['project_id']);
- }
-
- public function testCategoryRemove()
- {
- $this->assertTrue($this->client->removeCategory(1));
- $this->assertFalse($this->client->removeCategory(1));
- $this->assertFalse($this->client->removeCategory(1111));
- }
-
- public function testGetAvailableActions()
- {
- $actions = $this->client->getAvailableActions();
- $this->assertNotEmpty($actions);
- $this->assertInternalType('array', $actions);
- $this->assertArrayHasKey('\Kanboard\Action\TaskCloseColumn', $actions);
- }
-
- public function testGetAvailableActionEvents()
- {
- $events = $this->client->getAvailableActionEvents();
- $this->assertNotEmpty($events);
- $this->assertInternalType('array', $events);
- $this->assertArrayHasKey('task.move.column', $events);
- }
-
- public function testGetCompatibleActionEvents()
- {
- $events = $this->client->getCompatibleActionEvents('\Kanboard\Action\TaskCloseColumn');
- $this->assertNotEmpty($events);
- $this->assertInternalType('array', $events);
- $this->assertArrayHasKey('task.move.column', $events);
- }
-
- public function testCreateAction()
- {
- $action_id = $this->client->createAction(1, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1));
- $this->assertNotFalse($action_id);
- $this->assertEquals(1, $action_id);
- }
-
- public function testGetActions()
- {
- $actions = $this->client->getActions(1);
- $this->assertNotEmpty($actions);
- $this->assertInternalType('array', $actions);
- $this->assertCount(1, $actions);
- $this->assertArrayHasKey('id', $actions[0]);
- $this->assertArrayHasKey('project_id', $actions[0]);
- $this->assertArrayHasKey('event_name', $actions[0]);
- $this->assertArrayHasKey('action_name', $actions[0]);
- $this->assertArrayHasKey('params', $actions[0]);
- $this->assertArrayHasKey('column_id', $actions[0]['params']);
- }
-
- public function testRemoveAction()
- {
- $this->assertTrue($this->client->removeAction(1));
-
- $actions = $this->client->getActions(1);
- $this->assertEmpty($actions);
- $this->assertCount(0, $actions);
- }
-
- public function testGetAllLinks()
- {
- $links = $this->client->getAllLinks();
- $this->assertNotEmpty($links);
- $this->assertArrayHasKey('id', $links[0]);
- $this->assertArrayHasKey('label', $links[0]);
- $this->assertArrayHasKey('opposite_id', $links[0]);
- }
-
- public function testGetOppositeLink()
- {
- $link = $this->client->getOppositeLinkId(1);
- $this->assertEquals(1, $link);
-
- $link = $this->client->getOppositeLinkId(2);
- $this->assertEquals(3, $link);
- }
-
- public function testGetLinkByLabel()
- {
- $link = $this->client->getLinkByLabel('blocks');
- $this->assertNotEmpty($link);
- $this->assertEquals(2, $link['id']);
- $this->assertEquals(3, $link['opposite_id']);
- }
-
- public function testGetLinkById()
- {
- $link = $this->client->getLinkById(4);
- $this->assertNotEmpty($link);
- $this->assertEquals(4, $link['id']);
- $this->assertEquals(5, $link['opposite_id']);
- $this->assertEquals('duplicates', $link['label']);
- }
-
- public function testCreateLink()
- {
- $link_id = $this->client->createLink(array('label' => 'test'));
- $this->assertNotFalse($link_id);
- $this->assertInternalType('int', $link_id);
-
- $link_id = $this->client->createLink(array('label' => 'foo', 'opposite_label' => 'bar'));
- $this->assertNotFalse($link_id);
- $this->assertInternalType('int', $link_id);
- }
-
- public function testUpdateLink()
- {
- $link1 = $this->client->getLinkByLabel('bar');
- $this->assertNotEmpty($link1);
-
- $link2 = $this->client->getLinkByLabel('test');
- $this->assertNotEmpty($link2);
-
- $this->assertNotFalse($this->client->updateLink($link1['id'], $link2['id'], 'boo'));
-
- $link = $this->client->getLinkById($link1['id']);
- $this->assertNotEmpty($link);
- $this->assertEquals($link2['id'], $link['opposite_id']);
- $this->assertEquals('boo', $link['label']);
-
- $this->assertTrue($this->client->removeLink($link1['id']));
- }
-
- public function testCreateTaskLink()
- {
- $task_id1 = $this->client->createTask(array('project_id' => 1, 'title' => 'A'));
- $this->assertNotFalse($task_id1);
-
- $task_id2 = $this->client->createTask(array('project_id' => 1, 'title' => 'B'));
- $this->assertNotFalse($task_id2);
-
- $task_id3 = $this->client->createTask(array('project_id' => 1, 'title' => 'C'));
- $this->assertNotFalse($task_id3);
-
- $task_link_id = $this->client->createTaskLink($task_id1, $task_id2, 1);
- $this->assertNotFalse($task_link_id);
-
- $task_link = $this->client->getTaskLinkById($task_link_id);
- $this->assertNotEmpty($task_link);
- $this->assertEquals($task_id1, $task_link['task_id']);
- $this->assertEquals($task_id2, $task_link['opposite_task_id']);
- $this->assertEquals(1, $task_link['link_id']);
-
- $task_links = $this->client->getAllTaskLinks($task_id1);
- $this->assertNotEmpty($task_links);
- $this->assertCount(1, $task_links);
-
- $this->assertTrue($this->client->updateTaskLink($task_link_id, $task_id1, $task_id3, 2));
-
- $task_link = $this->client->getTaskLinkById($task_link_id);
- $this->assertNotEmpty($task_link);
- $this->assertEquals($task_id1, $task_link['task_id']);
- $this->assertEquals($task_id3, $task_link['opposite_task_id']);
- $this->assertEquals(2, $task_link['link_id']);
-
- $this->assertTrue($this->client->removeTaskLink($task_link_id));
- $this->assertEmpty($this->client->getAllTaskLinks($task_id1));
- }
-
- public function testCreateFile()
- {
- $this->assertNotFalse($this->client->createFile(1, $this->getTaskId(), 'My file', base64_encode('plain text file')));
- }
-
- public function testGetAllFiles()
- {
- $files = $this->client->getAllFiles(array('task_id' => $this->getTaskId()));
-
- $this->assertNotEmpty($files);
- $this->assertCount(1, $files);
- $this->assertEquals('My file', $files[0]['name']);
-
- $file = $this->client->getFile($files[0]['id']);
- $this->assertNotEmpty($file);
- $this->assertEquals('My file', $file['name']);
-
- $content = $this->client->downloadFile($file['id']);
- $this->assertNotEmpty($content);
- $this->assertEquals('plain text file', base64_decode($content));
-
- $content = $this->client->downloadFile(1234567);
- $this->assertEmpty($content);
-
- $this->assertTrue($this->client->removeFile($file['id']));
- $this->assertEmpty($this->client->getAllFiles(1));
- }
-
- public function testRemoveAllFiles()
- {
- $this->assertNotFalse($this->client->createFile(1, $this->getTaskId(), 'My file 1', base64_encode('plain text file')));
- $this->assertNotFalse($this->client->createFile(1, $this->getTaskId(), 'My file 2', base64_encode('plain text file')));
-
- $files = $this->client->getAllFiles(array('task_id' => $this->getTaskId()));
- $this->assertNotEmpty($files);
- $this->assertCount(2, $files);
-
- $this->assertTrue($this->client->removeAllFiles(array('task_id' => $this->getTaskId())));
-
- $files = $this->client->getAllFiles(array('task_id' => $this->getTaskId()));
- $this->assertEmpty($files);
- }
-
- public function testCreateTaskWithReference()
- {
- $task = array(
- 'title' => 'Task with external ticket number',
- 'reference' => 'TICKET-1234',
- 'project_id' => 1,
- 'description' => '[Link to my ticket](http://my-ticketing-system/1234)',
- );
-
- $task_id = $this->client->createTask($task);
-
- $this->assertNotFalse($task_id);
- $this->assertInternalType('int', $task_id);
- $this->assertTrue($task_id > 0);
- }
-
- public function testGetTaskByReference()
- {
- $task = $this->client->getTaskByReference(array('project_id' => 1, 'reference' => 'TICKET-1234'));
-
- $this->assertNotEmpty($task);
- $this->assertEquals('Task with external ticket number', $task['title']);
- $this->assertEquals('TICKET-1234', $task['reference']);
- $this->assertEquals('http://127.0.0.1:8000/?controller=TaskViewController&action=show&task_id='.$task['id'].'&project_id='.$task['project_id'], $task['url']);
- }
-
- public function testCreateOverdueTask()
- {
- $this->assertNotFalse($this->client->createTask(array(
- 'title' => 'overdue task',
- 'project_id' => 1,
- 'date_due' => date('Y-m-d', strtotime('-2days')),
- )));
- }
-
- public function testGetOverdueTasksByProject()
- {
- $tasks = $this->client->getOverdueTasksByProject(1);
- $this->assertNotEmpty($tasks);
- $this->assertCount(1, $tasks);
- $this->assertEquals('overdue task', $tasks[0]['title']);
- $this->assertEquals('API test', $tasks[0]['project_name']);
- }
-
- public function testGetOverdueTasks()
- {
- $tasks = $this->client->getOverdueTasks();
- $this->assertNotEmpty($tasks);
- $this->assertCount(1, $tasks);
- $this->assertEquals('overdue task', $tasks[0]['title']);
- $this->assertEquals('API test', $tasks[0]['project_name']);
- }
-}
diff --git a/tests/integration/AppTest.php b/tests/integration/AppProcedureTest.php
index 6575fbb8..06135dac 100644
--- a/tests/integration/AppTest.php
+++ b/tests/integration/AppProcedureTest.php
@@ -1,8 +1,8 @@
<?php
-require_once __DIR__.'/Base.php';
+require_once __DIR__.'/BaseProcedureTest.php';
-class AppTest extends Base
+class AppProcedureTest extends BaseProcedureTest
{
public function testGetTimezone()
{
@@ -31,4 +31,24 @@ class AppTest extends Base
$this->assertEquals('Project Member', $roles['project-member']);
$this->assertEquals('Project Viewer', $roles['project-viewer']);
}
+
+ public function testGetDefaultColor()
+ {
+ $this->assertEquals('yellow', $this->user->getDefaultTaskColor());
+ }
+
+ public function testGetDefaultColors()
+ {
+ $colors = $this->user->getDefaultTaskColors();
+ $this->assertNotEmpty($colors);
+ $this->assertArrayHasKey('red', $colors);
+ }
+
+ public function testGetColorList()
+ {
+ $colors = $this->user->getColorList();
+ $this->assertNotEmpty($colors);
+ $this->assertArrayHasKey('red', $colors);
+ $this->assertEquals('Red', $colors['red']);
+ }
}
diff --git a/tests/integration/Base.php b/tests/integration/Base.php
deleted file mode 100644
index 6f3ae076..00000000
--- a/tests/integration/Base.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-require_once __DIR__.'/../../vendor/autoload.php';
-
-abstract class Base extends PHPUnit_Framework_TestCase
-{
- protected $app = null;
- protected $admin = null;
- protected $user = null;
-
- public static function setUpBeforeClass()
- {
- if (DB_DRIVER === 'sqlite') {
- @unlink(DB_FILENAME);
- } elseif (DB_DRIVER === 'mysql') {
- $pdo = new PDO('mysql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
- $pdo->exec('DROP DATABASE '.DB_NAME);
- $pdo->exec('CREATE DATABASE '.DB_NAME);
- $pdo = null;
- } elseif (DB_DRIVER === 'postgres') {
- $pdo = new PDO('pgsql:host='.DB_HOSTNAME, DB_USERNAME, DB_PASSWORD);
- $pdo->exec('DROP DATABASE '.DB_NAME);
- $pdo->exec('CREATE DATABASE '.DB_NAME.' WITH OWNER '.DB_USERNAME);
- $pdo = null;
- }
-
- $service = new Kanboard\ServiceProvider\DatabaseProvider;
-
- $db = $service->getInstance();
- $db->table('settings')->eq('option', 'api_token')->update(array('value' => API_KEY));
- $db->closeConnection();
- }
-
- public function setUp()
- {
- $this->app = new JsonRPC\Client(API_URL);
- $this->app->authentication('jsonrpc', API_KEY);
- $this->app->getHttpClient()->withDebug();
-
- $this->admin = new JsonRPC\Client(API_URL);
- $this->admin->authentication('admin', 'admin');
- $this->admin->getHttpClient()->withDebug();
-
- $this->user = new JsonRPC\Client(API_URL);
- $this->user->authentication('user', 'password');
- $this->user->getHttpClient()->withDebug();
- }
-
- protected function getProjectId()
- {
- $projects = $this->app->getAllProjects();
- $this->assertNotEmpty($projects);
- return $projects[0]['id'];
- }
-
- protected function getGroupId()
- {
- $groups = $this->app->getAllGroups();
- $this->assertNotEmpty($groups);
- return $groups[0]['id'];
- }
-}
diff --git a/tests/integration/BaseProcedureTest.php b/tests/integration/BaseProcedureTest.php
new file mode 100644
index 00000000..e3382e82
--- /dev/null
+++ b/tests/integration/BaseProcedureTest.php
@@ -0,0 +1,122 @@
+<?php
+
+require_once __DIR__.'/../../vendor/autoload.php';
+
+abstract class BaseProcedureTest extends PHPUnit_Framework_TestCase
+{
+ protected $app = null;
+ protected $admin = null;
+ protected $manager = null;
+ protected $user = null;
+
+ protected $adminUserId = 0;
+ protected $managerUserId = 0;
+ protected $userUserId = 0;
+
+ protected $projectName = '';
+ protected $projectId = 0;
+ protected $taskTitle = 'My task';
+ protected $taskId = 0;
+
+ protected $groupName1 = 'My Group A';
+ protected $groupName2 = 'My Group B';
+ protected $groupId1;
+ protected $groupId2;
+
+ protected $username = 'test-user';
+ protected $userId;
+
+ public function setUp()
+ {
+ $this->setUpAppClient();
+ $this->setUpAdminUser();
+ $this->setUpManagerUser();
+ $this->setUpStandardUser();
+ }
+
+ public function setUpAppClient()
+ {
+ $this->app = new JsonRPC\Client(API_URL);
+ $this->app->authentication('jsonrpc', API_KEY);
+ $this->app->getHttpClient()->withDebug()->withTimeout(10);
+ }
+
+ public function setUpAdminUser()
+ {
+ $this->adminUserId = $this->getUserId('superuser');
+
+ if (! $this->adminUserId) {
+ $this->adminUserId = $this->app->createUser('superuser', 'password', 'Admin User', 'user@localhost', 'app-admin');
+ $this->assertNotFalse($this->adminUserId);
+ }
+
+ $this->admin = new JsonRPC\Client(API_URL);
+ $this->admin->authentication('superuser', 'password');
+ $this->admin->getHttpClient()->withDebug();
+ }
+
+ public function setUpManagerUser()
+ {
+ $this->managerUserId = $this->getUserId('manager');
+
+ if (! $this->managerUserId) {
+ $this->managerUserId = $this->app->createUser('manager', 'password', 'Manager User', 'user@localhost', 'app-manager');
+ $this->assertNotFalse($this->managerUserId);
+ }
+
+ $this->manager = new JsonRPC\Client(API_URL);
+ $this->manager->authentication('manager', 'password');
+ $this->manager->getHttpClient()->withDebug();
+ }
+
+ public function setUpStandardUser()
+ {
+ $this->userUserId = $this->getUserId('user');
+
+ if (! $this->userUserId) {
+ $this->userUserId = $this->app->createUser('user', 'password', 'Standard User', 'user@localhost', 'app-user');
+ $this->assertNotFalse($this->userUserId);
+ }
+
+ $this->user = new JsonRPC\Client(API_URL);
+ $this->user->authentication('user', 'password');
+ $this->user->getHttpClient()->withDebug();
+ }
+
+ public function getUserId($username)
+ {
+ $user = $this->app->getUserByName($username);
+
+ if (! empty($user)) {
+ return $user['id'];
+ }
+
+ return 0;
+ }
+
+ public function assertCreateTeamProject()
+ {
+ $this->projectId = $this->app->createProject($this->projectName, 'Description');
+ $this->assertNotFalse($this->projectId);
+ }
+
+ public function assertCreateUser()
+ {
+ $this->userId = $this->app->createUser($this->username, 'password');
+ $this->assertNotFalse($this->userId);
+ }
+
+ public function assertCreateGroups()
+ {
+ $this->groupId1 = $this->app->createGroup($this->groupName1);
+ $this->groupId2 = $this->app->createGroup($this->groupName2, 'External ID');
+ $this->assertNotFalse($this->groupId1);
+ $this->assertNotFalse($this->groupId2);
+ }
+
+ public function assertCreateTask()
+ {
+ $this->taskId = $this->app->createTask(array('title' => $this->taskTitle, 'project_id' => $this->projectId));
+ $this->assertNotFalse($this->taskId);
+ }
+}
diff --git a/tests/integration/BoardProcedureTest.php b/tests/integration/BoardProcedureTest.php
new file mode 100644
index 00000000..273e93c7
--- /dev/null
+++ b/tests/integration/BoardProcedureTest.php
@@ -0,0 +1,25 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class BoardProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test board';
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertGetBoard();
+ }
+
+ public function assertGetBoard()
+ {
+ $board = $this->app->getBoard($this->projectId);
+ $this->assertNotNull($board);
+ $this->assertCount(1, $board);
+ $this->assertEquals('Default swimlane', $board[0]['name']);
+
+ $this->assertCount(4, $board[0]['columns']);
+ $this->assertEquals('Ready', $board[0]['columns'][1]['title']);
+ }
+}
diff --git a/tests/integration/BoardTest.php b/tests/integration/BoardTest.php
deleted file mode 100644
index bf8d50b9..00000000
--- a/tests/integration/BoardTest.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-class BoardTest extends Base
-{
- public function testCreateProject()
- {
- $this->assertEquals(1, $this->app->createProject('A project'));
- }
-
- public function testGetBoard()
- {
- $board = $this->app->getBoard(1);
- $this->assertCount(1, $board);
- $this->assertEquals('Default swimlane', $board[0]['name']);
-
- $this->assertCount(4, $board[0]['columns']);
- $this->assertEquals('Ready', $board[0]['columns'][1]['title']);
- }
-}
diff --git a/tests/integration/CategoryProcedureTest.php b/tests/integration/CategoryProcedureTest.php
new file mode 100644
index 00000000..2f5294ba
--- /dev/null
+++ b/tests/integration/CategoryProcedureTest.php
@@ -0,0 +1,76 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class CategoryProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test categories';
+ private $categoryId = 0;
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertCreateCategory();
+ $this->assertThatCategoriesAreUnique();
+ $this->assertGetCategory();
+ $this->assertGetAllCategories();
+ $this->assertCategoryUpdate();
+ $this->assertRemoveCategory();
+ }
+
+ public function assertCreateCategory()
+ {
+ $this->categoryId = $this->app->createCategory(array(
+ 'name' => 'Category',
+ 'project_id' => $this->projectId,
+ ));
+
+ $this->assertNotFalse($this->categoryId);
+ }
+
+ public function assertThatCategoriesAreUnique()
+ {
+ $this->assertFalse($this->app->execute('createCategory', array(
+ 'name' => 'Category',
+ 'project_id' => $this->projectId,
+ )));
+ }
+
+ public function assertGetCategory()
+ {
+ $category = $this->app->getCategory($this->categoryId);
+
+ $this->assertInternalType('array', $category);
+ $this->assertEquals($this->categoryId, $category['id']);
+ $this->assertEquals('Category', $category['name']);
+ $this->assertEquals($this->projectId, $category['project_id']);
+ }
+
+ public function assertGetAllCategories()
+ {
+ $categories = $this->app->getAllCategories($this->projectId);
+
+ $this->assertCount(1, $categories);
+ $this->assertEquals($this->categoryId, $categories[0]['id']);
+ $this->assertEquals('Category', $categories[0]['name']);
+ $this->assertEquals($this->projectId, $categories[0]['project_id']);
+ }
+
+ public function assertCategoryUpdate()
+ {
+ $this->assertTrue($this->app->execute('updateCategory', array(
+ 'id' => $this->categoryId,
+ 'name' => 'Renamed category',
+ )));
+
+ $category = $this->app->getCategory($this->categoryId);
+ $this->assertEquals('Renamed category', $category['name']);
+ }
+
+ public function assertRemoveCategory()
+ {
+ $this->assertTrue($this->app->removeCategory($this->categoryId));
+ $this->assertFalse($this->app->removeCategory($this->categoryId));
+ $this->assertFalse($this->app->removeCategory(1111));
+ }
+}
diff --git a/tests/integration/ColumnProcedureTest.php b/tests/integration/ColumnProcedureTest.php
new file mode 100644
index 00000000..fb6a27c3
--- /dev/null
+++ b/tests/integration/ColumnProcedureTest.php
@@ -0,0 +1,69 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class ColumnProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test columns';
+ private $columns = array();
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertGetColumns();
+ $this->assertUpdateColumn();
+ $this->assertAddColumn();
+ $this->assertRemoveColumn();
+ $this->assertChangeColumnPosition();
+ }
+
+ public function assertGetColumns()
+ {
+ $this->columns = $this->app->getColumns($this->projectId);
+ $this->assertCount(4, $this->columns);
+ $this->assertEquals('Done', $this->columns[3]['title']);
+ }
+
+ public function assertUpdateColumn()
+ {
+ $this->assertTrue($this->app->updateColumn($this->columns[3]['id'], 'Another column', 2));
+
+ $this->columns = $this->app->getColumns($this->projectId);
+ $this->assertEquals('Another column', $this->columns[3]['title']);
+ $this->assertEquals(2, $this->columns[3]['task_limit']);
+ }
+
+ public function assertAddColumn()
+ {
+ $column_id = $this->app->addColumn($this->projectId, 'New column');
+ $this->assertNotFalse($column_id);
+ $this->assertTrue($column_id > 0);
+
+ $this->columns = $this->app->getColumns($this->projectId);
+ $this->assertCount(5, $this->columns);
+ $this->assertEquals('New column', $this->columns[4]['title']);
+ }
+
+ public function assertRemoveColumn()
+ {
+ $this->assertTrue($this->app->removeColumn($this->columns[3]['id']));
+
+ $this->columns = $this->app->getColumns($this->projectId);
+ $this->assertCount(4, $this->columns);
+ }
+
+ public function assertChangeColumnPosition()
+ {
+ $this->assertTrue($this->app->changeColumnPosition($this->projectId, $this->columns[0]['id'], 3));
+
+ $this->columns = $this->app->getColumns($this->projectId);
+ $this->assertEquals('Ready', $this->columns[0]['title']);
+ $this->assertEquals(1, $this->columns[0]['position']);
+ $this->assertEquals('Work in progress', $this->columns[1]['title']);
+ $this->assertEquals(2, $this->columns[1]['position']);
+ $this->assertEquals('Backlog', $this->columns[2]['title']);
+ $this->assertEquals(3, $this->columns[2]['position']);
+ $this->assertEquals('New column', $this->columns[3]['title']);
+ $this->assertEquals(4, $this->columns[3]['position']);
+ }
+}
diff --git a/tests/integration/ColumnTest.php b/tests/integration/ColumnTest.php
deleted file mode 100644
index 6d02afc0..00000000
--- a/tests/integration/ColumnTest.php
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-class ColumnTest extends Base
-{
- public function testCreateProject()
- {
- $this->assertEquals(1, $this->app->createProject('A project'));
- }
-
- public function testGetColumns()
- {
- $columns = $this->app->getColumns($this->getProjectId());
- $this->assertCount(4, $columns);
- $this->assertEquals('Done', $columns[3]['title']);
- }
-
- public function testUpdateColumn()
- {
- $this->assertTrue($this->app->updateColumn(4, 'Boo', 2));
-
- $columns = $this->app->getColumns($this->getProjectId());
- $this->assertEquals('Boo', $columns[3]['title']);
- $this->assertEquals(2, $columns[3]['task_limit']);
- }
-
- public function testAddColumn()
- {
- $column_id = $this->app->addColumn($this->getProjectId(), 'New column');
-
- $this->assertNotFalse($column_id);
- $this->assertInternalType('int', $column_id);
- $this->assertTrue($column_id > 0);
-
- $columns = $this->app->getColumns($this->getProjectId());
- $this->assertCount(5, $columns);
- $this->assertEquals('New column', $columns[4]['title']);
- }
-
- public function testRemoveColumn()
- {
- $this->assertTrue($this->app->removeColumn(5));
-
- $columns = $this->app->getColumns($this->getProjectId());
- $this->assertCount(4, $columns);
- }
-
- public function testChangeColumnPosition()
- {
- $this->assertTrue($this->app->changeColumnPosition($this->getProjectId(), 1, 3));
-
- $columns = $this->app->getColumns($this->getProjectId());
- $this->assertCount(4, $columns);
-
- $this->assertEquals('Ready', $columns[0]['title']);
- $this->assertEquals(1, $columns[0]['position']);
- $this->assertEquals('Work in progress', $columns[1]['title']);
- $this->assertEquals(2, $columns[1]['position']);
- $this->assertEquals('Backlog', $columns[2]['title']);
- $this->assertEquals(3, $columns[2]['position']);
- $this->assertEquals('Boo', $columns[3]['title']);
- $this->assertEquals(4, $columns[3]['position']);
- }
-}
diff --git a/tests/integration/CommentProcedureTest.php b/tests/integration/CommentProcedureTest.php
new file mode 100644
index 00000000..881d938c
--- /dev/null
+++ b/tests/integration/CommentProcedureTest.php
@@ -0,0 +1,63 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class CommentProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test comments';
+ private $commentId = 0;
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertCreateTask();
+ $this->assertCreateComment();
+ $this->assertUpdateComment();
+ $this->assertGetAllComments();
+ $this->assertRemoveComment();
+ }
+
+ public function assertCreateComment()
+ {
+ $this->commentId = $this->app->execute('createComment', array(
+ 'task_id' => $this->taskId,
+ 'user_id' => 1,
+ 'content' => 'foobar',
+ ));
+
+ $this->assertNotFalse($this->commentId);
+ }
+
+ public function assertGetComment()
+ {
+ $comment = $this->app->getComment($this->commentId);
+ $this->assertNotFalse($comment);
+ $this->assertNotEmpty($comment);
+ $this->assertEquals(1, $comment['user_id']);
+ $this->assertEquals('foobar', $comment['comment']);
+ }
+
+ public function assertUpdateComment()
+ {
+ $this->assertTrue($this->app->execute('updateComment', array(
+ 'id' => $this->commentId,
+ 'content' => 'test',
+ )));
+
+ $comment = $this->app->getComment($this->commentId);
+ $this->assertEquals('test', $comment['comment']);
+ }
+
+ public function assertGetAllComments()
+ {
+ $comments = $this->app->getAllComments($this->taskId);
+ $this->assertCount(1, $comments);
+ $this->assertEquals('test', $comments[0]['comment']);
+ }
+
+ public function assertRemoveComment()
+ {
+ $this->assertTrue($this->app->removeComment($this->commentId));
+ $this->assertFalse($this->app->removeComment($this->commentId));
+ }
+}
diff --git a/tests/integration/GroupMemberProcedureTest.php b/tests/integration/GroupMemberProcedureTest.php
new file mode 100644
index 00000000..fe243533
--- /dev/null
+++ b/tests/integration/GroupMemberProcedureTest.php
@@ -0,0 +1,53 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class GroupMemberProcedureTest extends BaseProcedureTest
+{
+ protected $username = 'user-group-member';
+ protected $groupName1 = 'My group member A';
+ protected $groupName2 = 'My group member B';
+
+ public function testAll()
+ {
+ $this->assertCreateGroups();
+ $this->assertCreateUser();
+ $this->assertAddMember();
+ $this->assertGetMembers();
+ $this->assertIsGroupMember();
+ $this->assertGetGroups();
+ $this->assertRemove();
+ }
+
+ public function assertAddMember()
+ {
+ $this->assertTrue($this->app->addGroupMember($this->groupId1, $this->userId));
+ }
+
+ public function assertGetMembers()
+ {
+ $members = $this->app->getGroupMembers($this->groupId1);
+ $this->assertCount(1, $members);
+ $this->assertEquals($this->username, $members[0]['username']);
+ }
+
+ public function assertIsGroupMember()
+ {
+ $this->assertTrue($this->app->isGroupMember($this->groupId1, $this->userId));
+ $this->assertFalse($this->app->isGroupMember($this->groupId1, $this->adminUserId));
+ }
+
+ public function assertGetGroups()
+ {
+ $groups = $this->app->getMemberGroups($this->userId);
+ $this->assertCount(1, $groups);
+ $this->assertEquals($this->groupId1, $groups[0]['id']);
+ $this->assertEquals($this->groupName1, $groups[0]['name']);
+ }
+
+ public function assertRemove()
+ {
+ $this->assertTrue($this->app->removeGroupMember($this->groupId1, $this->userId));
+ $this->assertFalse($this->app->isGroupMember($this->groupId1, $this->userId));
+ }
+}
diff --git a/tests/integration/GroupMemberTest.php b/tests/integration/GroupMemberTest.php
deleted file mode 100644
index d49945b5..00000000
--- a/tests/integration/GroupMemberTest.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-class GroupMemberTest extends Base
-{
- public function testAddMember()
- {
- $this->assertNotFalse($this->app->createGroup('My Group A'));
- $this->assertNotFalse($this->app->createGroup('My Group B'));
-
- $groupId = $this->getGroupId();
- $this->assertTrue($this->app->addGroupMember($groupId, 1));
- }
-
- public function testGetMembers()
- {
- $groups = $this->app->getAllGroups();
- $members = $this->app->getGroupMembers($groups[0]['id']);
- $this->assertCount(1, $members);
- $this->assertEquals('admin', $members[0]['username']);
-
- $this->assertSame(array(), $this->app->getGroupMembers($groups[1]['id']));
- }
-
- public function testIsGroupMember()
- {
- $groupId = $this->getGroupId();
- $this->assertTrue($this->app->isGroupMember($groupId, 1));
- $this->assertFalse($this->app->isGroupMember($groupId, 2));
- }
-
- public function testGetGroups()
- {
- $groups = $this->app->getMemberGroups(1);
- $this->assertCount(1, $groups);
- $this->assertEquals(1, $groups[0]['id']);
- $this->assertEquals('My Group A', $groups[0]['name']);
- }
-
- public function testRemove()
- {
- $groupId = $this->getGroupId();
- $this->assertTrue($this->app->removeGroupMember($groupId, 1));
- $this->assertFalse($this->app->isGroupMember($groupId, 1));
- }
-}
diff --git a/tests/integration/GroupProcedureTest.php b/tests/integration/GroupProcedureTest.php
new file mode 100644
index 00000000..610c121d
--- /dev/null
+++ b/tests/integration/GroupProcedureTest.php
@@ -0,0 +1,50 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class GroupProcedureTest extends BaseProcedureTest
+{
+ public function testAll()
+ {
+ $this->assertCreateGroups();
+ $this->assertGetAllGroups();
+ $this->assertGetGroup();
+ $this->assertUpdateGroup();
+ $this->assertRemove();
+ }
+
+ public function assertGetAllGroups()
+ {
+ $groups = $this->app->getAllGroups();
+ $this->assertNotEmpty($groups);
+ $this->assertArrayHasKey('name', $groups[0]);
+ $this->assertArrayHasKey('external_id', $groups[0]);
+ }
+
+ public function assertGetGroup()
+ {
+ $group = $this->app->getGroup($this->groupId1);
+ $this->assertNotEmpty($group);
+ $this->assertEquals($this->groupName1, $group['name']);
+ $this->assertEquals('', $group['external_id']);
+ }
+
+ public function assertUpdateGroup()
+ {
+ $this->assertTrue($this->app->updateGroup(array(
+ 'group_id' => $this->groupId2,
+ 'name' => 'My Group C',
+ 'external_id' => 'something else',
+ )));
+
+ $group = $this->app->getGroup($this->groupId2);
+ $this->assertNotEmpty($group);
+ $this->assertEquals('My Group C', $group['name']);
+ $this->assertEquals('something else', $group['external_id']);
+ }
+
+ public function assertRemove()
+ {
+ $this->assertTrue($this->app->removeGroup($this->groupId1));
+ }
+}
diff --git a/tests/integration/GroupTest.php b/tests/integration/GroupTest.php
deleted file mode 100644
index 7a5bccc9..00000000
--- a/tests/integration/GroupTest.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-class GroupTest extends Base
-{
- public function testCreateGroup()
- {
- $this->assertNotFalse($this->app->createGroup('My Group A'));
- $this->assertNotFalse($this->app->createGroup('My Group B', '1234'));
- }
-
- public function testGetter()
- {
- $groups = $this->app->getAllGroups();
- $this->assertCount(2, $groups);
- $this->assertEquals('My Group A', $groups[0]['name']);
- $this->assertEquals('', $groups[0]['external_id']);
- $this->assertEquals('My Group B', $groups[1]['name']);
- $this->assertEquals('1234', $groups[1]['external_id']);
-
- $group = $this->app->getGroup($groups[0]['id']);
- $this->assertNotEmpty($group);
- $this->assertEquals('My Group A', $group['name']);
- $this->assertEquals('', $group['external_id']);
- }
-
- public function testUpdate()
- {
- $groups = $this->app->getAllGroups();
-
- $this->assertTrue($this->app->updateGroup(array('group_id' => $groups[0]['id'], 'name' => 'ABC', 'external_id' => 'something')));
- $this->assertTrue($this->app->updateGroup(array('group_id' => $groups[1]['id'], 'external_id' => '')));
-
- $groups = $this->app->getAllGroups();
- $this->assertEquals('ABC', $groups[0]['name']);
- $this->assertEquals('something', $groups[0]['external_id']);
- $this->assertEquals('', $groups[1]['external_id']);
- }
-
- public function testRemove()
- {
- $groups = $this->app->getAllGroups();
- $this->assertTrue($this->app->removeGroup($groups[0]['id']));
- $this->assertTrue($this->app->removeGroup($groups[1]['id']));
- $this->assertSame(array(), $this->app->getAllGroups());
- }
-}
diff --git a/tests/integration/LinkProcedureTest.php b/tests/integration/LinkProcedureTest.php
new file mode 100644
index 00000000..fb07e694
--- /dev/null
+++ b/tests/integration/LinkProcedureTest.php
@@ -0,0 +1,70 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class LinkProcedureTest extends BaseProcedureTest
+{
+ public function testGetAllLinks()
+ {
+ $links = $this->app->getAllLinks();
+ $this->assertNotEmpty($links);
+ $this->assertArrayHasKey('id', $links[0]);
+ $this->assertArrayHasKey('label', $links[0]);
+ $this->assertArrayHasKey('opposite_id', $links[0]);
+ }
+
+ public function testGetOppositeLink()
+ {
+ $link = $this->app->getOppositeLinkId(1);
+ $this->assertEquals(1, $link);
+
+ $link = $this->app->getOppositeLinkId(2);
+ $this->assertEquals(3, $link);
+ }
+
+ public function testGetLinkByLabel()
+ {
+ $link = $this->app->getLinkByLabel('blocks');
+ $this->assertNotEmpty($link);
+ $this->assertEquals(2, $link['id']);
+ $this->assertEquals(3, $link['opposite_id']);
+ }
+
+ public function testGetLinkById()
+ {
+ $link = $this->app->getLinkById(4);
+ $this->assertNotEmpty($link);
+ $this->assertEquals(4, $link['id']);
+ $this->assertEquals(5, $link['opposite_id']);
+ $this->assertEquals('duplicates', $link['label']);
+ }
+
+ public function testCreateLink()
+ {
+ $link_id = $this->app->createLink(array('label' => 'test'));
+ $this->assertNotFalse($link_id);
+ $this->assertInternalType('int', $link_id);
+
+ $link_id = $this->app->createLink(array('label' => 'foo', 'opposite_label' => 'bar'));
+ $this->assertNotFalse($link_id);
+ $this->assertInternalType('int', $link_id);
+ }
+
+ public function testUpdateLink()
+ {
+ $link1 = $this->app->getLinkByLabel('bar');
+ $this->assertNotEmpty($link1);
+
+ $link2 = $this->app->getLinkByLabel('test');
+ $this->assertNotEmpty($link2);
+
+ $this->assertNotFalse($this->app->updateLink($link1['id'], $link2['id'], 'my link'));
+
+ $link = $this->app->getLinkById($link1['id']);
+ $this->assertNotEmpty($link);
+ $this->assertEquals($link2['id'], $link['opposite_id']);
+ $this->assertEquals('my link', $link['label']);
+
+ $this->assertTrue($this->app->removeLink($link1['id']));
+ }
+}
diff --git a/tests/integration/MeProcedureTest.php b/tests/integration/MeProcedureTest.php
new file mode 100644
index 00000000..2106419c
--- /dev/null
+++ b/tests/integration/MeProcedureTest.php
@@ -0,0 +1,68 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class MeProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My private project';
+
+ public function testAll()
+ {
+ $this->assertGetMe();
+ $this->assertCreateMyPrivateProject();
+ $this->assertGetMyProjectsList();
+ $this->assertGetMyProjects();
+ $this->assertCreateTask();
+ $this->assertGetMyDashboard();
+ $this->assertGetMyActivityStream();
+ }
+
+ public function assertGetMe()
+ {
+ $profile = $this->user->getMe();
+ $this->assertEquals('user', $profile['username']);
+ $this->assertEquals('app-user', $profile['role']);
+ }
+
+ public function assertCreateMyPrivateProject()
+ {
+ $this->projectId = $this->user->createMyPrivateProject($this->projectName);
+ $this->assertNotFalse($this->projectId);
+ }
+
+ public function assertGetMyProjectsList()
+ {
+ $projects = $this->user->getMyProjectsList();
+ $this->assertNotEmpty($projects);
+ $this->assertEquals($this->projectName, $projects[$this->projectId]);
+ }
+
+ public function assertGetMyProjects()
+ {
+ $projects = $this->user->getMyProjects();
+ $this->assertNotEmpty($projects);
+ }
+
+ public function assertCreateTask()
+ {
+ $taskId = $this->user->createTask(array('title' => 'My task', 'project_id' => $this->projectId, 'owner_id' => $this->userUserId));
+ $this->assertNotFalse($taskId);
+ }
+
+ public function assertGetMyDashboard()
+ {
+ $dashboard = $this->user->getMyDashboard();
+ $this->assertNotEmpty($dashboard);
+ $this->assertArrayHasKey('projects', $dashboard);
+ $this->assertArrayHasKey('tasks', $dashboard);
+ $this->assertArrayHasKey('subtasks', $dashboard);
+ $this->assertNotEmpty($dashboard['projects']);
+ $this->assertNotEmpty($dashboard['tasks']);
+ }
+
+ public function assertGetMyActivityStream()
+ {
+ $activity = $this->user->getMyActivityStream();
+ $this->assertNotEmpty($activity);
+ }
+}
diff --git a/tests/integration/MeTest.php b/tests/integration/MeTest.php
deleted file mode 100644
index 1b028b84..00000000
--- a/tests/integration/MeTest.php
+++ /dev/null
@@ -1,247 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-class MeTest extends Base
-{
- public function testCreateProject()
- {
- $this->assertEquals(1, $this->app->createProject('team project'));
- }
-
- public function testCreateUser()
- {
- $this->assertEquals(2, $this->app->createUser('user', 'password'));
- }
-
- /**
- * @expectedException JsonRPC\Exception\AccessDeniedException
- */
- public function testNotAllowedAppProcedure()
- {
- $this->app->getMe();
- }
-
- /**
- * @expectedException JsonRPC\Exception\AccessDeniedException
- */
- public function testNotAllowedUserProcedure()
- {
- $this->user->getAllProjects();
- }
-
- /**
- * @expectedException JsonRPC\Exception\AccessDeniedException
- */
- public function testNotAllowedProjectForUser()
- {
- $this->user->getProjectById(1);
- }
-
- public function testAllowedProjectForAdmin()
- {
- $this->assertNotEmpty($this->admin->getProjectById(1));
- }
-
- public function testGetTimezone()
- {
- $this->assertEquals('UTC', $this->user->getTimezone());
- }
-
- public function testGetVersion()
- {
- $this->assertEquals('master', $this->user->getVersion());
- }
-
- public function testGetDefaultColor()
- {
- $this->assertEquals('yellow', $this->user->getDefaultTaskColor());
- }
-
- public function testGetDefaultColors()
- {
- $colors = $this->user->getDefaultTaskColors();
- $this->assertNotEmpty($colors);
- $this->assertArrayHasKey('red', $colors);
- }
-
- public function testGetColorList()
- {
- $colors = $this->user->getColorList();
- $this->assertNotEmpty($colors);
- $this->assertArrayHasKey('red', $colors);
- $this->assertEquals('Red', $colors['red']);
- }
-
- public function testGetMe()
- {
- $profile = $this->user->getMe();
- $this->assertNotEmpty($profile);
- $this->assertEquals(2, $profile['id']);
- $this->assertEquals('user', $profile['username']);
- }
-
- public function testCreateMyPrivateProject()
- {
- $this->assertEquals(2, $this->user->createMyPrivateProject('my project'));
- }
-
- public function testGetMyProjectsList()
- {
- $projects = $this->user->getMyProjectsList();
- $this->assertNotEmpty($projects);
- $this->assertArrayNotHasKey(1, $projects);
- $this->assertArrayHasKey(2, $projects);
- $this->assertEquals('my project', $projects[2]);
- }
-
- public function testGetMyProjects()
- {
- $projects = $this->user->getMyProjects();
- $this->assertNotEmpty($projects);
- $this->assertCount(1, $projects);
- $this->assertEquals(2, $projects[0]['id']);
- $this->assertEquals('my project', $projects[0]['name']);
- $this->assertNotEmpty($projects[0]['url']['calendar']);
- $this->assertNotEmpty($projects[0]['url']['board']);
- $this->assertNotEmpty($projects[0]['url']['list']);
- }
-
- public function testGetProjectById()
- {
- $project = $this->user->getProjectById(2);
- $this->assertNotEmpty($project);
- $this->assertEquals('my project', $project['name']);
- $this->assertEquals(1, $project['is_private']);
- }
-
- public function testCreateTask()
- {
- $this->assertEquals(1, $this->user->createTask('my user title', 2));
- $this->assertEquals(2, $this->admin->createTask('my admin title', 1));
- }
-
- public function testCreateTaskWithWrongMember()
- {
- $this->assertFalse($this->user->createTask(array('title' => 'something', 'project_id' => 2, 'owner_id' => 1)));
- $this->assertFalse($this->app->createTask(array('title' => 'something', 'project_id' => 1, 'owner_id' => 2)));
- }
-
- public function testGetTask()
- {
- $task = $this->user->getTask(1);
- $this->assertNotEmpty($task);
- $this->assertEquals('my user title', $task['title']);
- $this->assertEquals('yellow', $task['color_id']);
- $this->assertArrayHasKey('color', $task);
- $this->assertArrayHasKey('name', $task['color']);
- $this->assertArrayHasKey('border', $task['color']);
- $this->assertArrayHasKey('background', $task['color']);
- }
-
- /**
- * @expectedException JsonRPC\Exception\AccessDeniedException
- */
- public function testGetAdminTask()
- {
- $this->user->getTask(2);
- }
-
- /**
- * @expectedException JsonRPC\Exception\AccessDeniedException
- */
- public function testGetProjectActivityDenied()
- {
- $this->user->getProjectActivity(1);
- }
-
- public function testGetProjectActivityAllowed()
- {
- $activity = $this->user->getProjectActivity(2);
- $this->assertNotEmpty($activity);
- }
-
- public function testGetMyActivityStream()
- {
- $activity = $this->user->getMyActivityStream();
- $this->assertNotEmpty($activity);
- }
-
- public function testCloseTask()
- {
- $this->assertTrue($this->user->closeTask(1));
- }
-
- public function testOpenTask()
- {
- $this->assertTrue($this->user->openTask(1));
- }
-
- public function testMoveTaskPosition()
- {
- $this->assertTrue($this->user->moveTaskPosition(2, 1, 2, 1));
- }
-
- public function testUpdateTaskWithWrongMember()
- {
- $this->assertFalse($this->user->updateTask(array('id' => 1, 'title' => 'new title', 'reference' => 'test', 'owner_id' => 1)));
- }
-
- public function testUpdateTask()
- {
- $this->assertTrue($this->user->updateTask(array('id' => 1, 'title' => 'new title', 'reference' => 'test', 'owner_id' => 2)));
- }
-
- public function testGetbyReference()
- {
- $task = $this->user->getTaskByReference(2, 'test');
- $this->assertNotEmpty($task);
- $this->assertEquals('new title', $task['title']);
- $this->assertEquals(2, $task['column_id']);
- $this->assertEquals(1, $task['position']);
- }
-
- public function testGetMyDashboard()
- {
- $dashboard = $this->user->getMyDashboard();
- $this->assertNotEmpty($dashboard);
- $this->assertArrayHasKey('projects', $dashboard);
- $this->assertArrayHasKey('tasks', $dashboard);
- $this->assertArrayHasKey('subtasks', $dashboard);
- $this->assertNotEmpty($dashboard['projects']);
- $this->assertNotEmpty($dashboard['tasks']);
- }
-
- public function testGetBoard()
- {
- $this->assertNotEmpty($this->user->getBoard(2));
- }
-
- public function testCreateOverdueTask()
- {
- $this->assertNotFalse($this->user->createTask(array(
- 'title' => 'overdue task',
- 'project_id' => 2,
- 'date_due' => date('Y-m-d', strtotime('-2days')),
- 'owner_id' => 2,
- )));
- }
-
- public function testGetMyOverdueTasks()
- {
- $tasks = $this->user->getMyOverdueTasks();
- $this->assertNotEmpty($tasks);
- $this->assertCount(1, $tasks);
- $this->assertEquals('overdue task', $tasks[0]['title']);
- $this->assertEquals('my project', $tasks[0]['project_name']);
- }
-
- public function testGetOverdueTasksByProject()
- {
- $tasks = $this->user->getOverdueTasksByProject(2);
- $this->assertNotEmpty($tasks);
- $this->assertCount(1, $tasks);
- $this->assertEquals('overdue task', $tasks[0]['title']);
- $this->assertEquals('my project', $tasks[0]['project_name']);
- }
-}
diff --git a/tests/integration/OverdueTaskProcedureTest.php b/tests/integration/OverdueTaskProcedureTest.php
new file mode 100644
index 00000000..65f52301
--- /dev/null
+++ b/tests/integration/OverdueTaskProcedureTest.php
@@ -0,0 +1,43 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class OverdueTaskProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test overdue tasks';
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertCreateOverdueTask();
+ $this->assertGetOverdueTasksByProject();
+ $this->assertGetOverdueTasks();
+ }
+
+ public function assertCreateOverdueTask()
+ {
+ $this->assertNotFalse($this->app->createTask(array(
+ 'title' => 'overdue task',
+ 'project_id' => $this->projectId,
+ 'date_due' => date('Y-m-d', strtotime('-2days')),
+ )));
+ }
+
+ public function assertGetOverdueTasksByProject()
+ {
+ $tasks = $this->app->getOverdueTasksByProject($this->projectId);
+ $this->assertNotEmpty($tasks);
+ $this->assertCount(1, $tasks);
+ $this->assertEquals('overdue task', $tasks[0]['title']);
+ $this->assertEquals($this->projectName, $tasks[0]['project_name']);
+ }
+
+ public function assertGetOverdueTasks()
+ {
+ $tasks = $this->app->getOverdueTasks();
+ $this->assertNotEmpty($tasks);
+ $this->assertCount(1, $tasks);
+ $this->assertEquals('overdue task', $tasks[0]['title']);
+ $this->assertEquals($this->projectName, $tasks[0]['project_name']);
+ }
+}
diff --git a/tests/integration/ProcedureAuthorizationTest.php b/tests/integration/ProcedureAuthorizationTest.php
new file mode 100644
index 00000000..a63e9d8c
--- /dev/null
+++ b/tests/integration/ProcedureAuthorizationTest.php
@@ -0,0 +1,306 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class ProcedureAuthorizationTest extends BaseProcedureTest
+{
+ public function testApiCredentialDoNotHaveAccessToUserCredentialProcedure()
+ {
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->app->getMe();
+ }
+
+ public function testUserCredentialDoNotHaveAccessToAdminProcedures()
+ {
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->getUser(1);
+ }
+
+ public function testManagerCredentialDoNotHaveAccessToAdminProcedures()
+ {
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->getAllProjects();
+ }
+
+ public function testUserCredentialDoNotHaveAccessToManagerProcedures()
+ {
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->createProject('Team project creation are only for app managers');
+ }
+
+ public function testAppManagerCanCreateTeamProject()
+ {
+ $this->assertNotFalse($this->manager->createProject('Team project created by app manager'));
+ }
+
+ public function testAdminManagerCanCreateTeamProject()
+ {
+ $projectId = $this->admin->createProject('Team project created by admin');
+ $this->assertNotFalse($projectId);
+
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->assertNotNull($this->manager->getProjectById($projectId));
+ }
+
+ public function testProjectManagerCanUpdateHisProject()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Team project can be updated',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+ $this->assertEquals('project-manager', $this->app->getProjectUserRole($projectId, $this->managerUserId));
+ $this->assertNotNull($this->manager->getProjectById($projectId));
+
+ $this->assertTrue($this->manager->updateProject($projectId, 'My team project have been updated'));
+ }
+
+ public function testProjectAuthorizationForbidden()
+ {
+ $projectId = $this->manager->createProject('A team project without members');
+ $this->assertNotFalse($projectId);
+
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->getProjectById($projectId);
+ }
+
+ public function testProjectAuthorizationGranted()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'A team project with members',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId));
+ $this->assertNotNull($this->user->getProjectById($projectId));
+ }
+
+ public function testActionAuthorizationForbidden()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $actionId = $this->manager->createAction($projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1));
+ $this->assertNotFalse($actionId);
+
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->removeAction($projectId);
+ }
+
+ public function testActionAuthorizationForbiddenBecauseNotProjectManager()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $actionId = $this->manager->createAction($projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1));
+ $this->assertNotFalse($actionId);
+
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member'));
+
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->removeAction($actionId);
+ }
+
+ public function testActionAuthorizationGranted()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $actionId = $this->manager->createAction($projectId, 'task.move.column', '\Kanboard\Action\TaskCloseColumn', array('column_id' => 1));
+ $this->assertNotFalse($actionId);
+
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-manager'));
+ $this->assertTrue($this->user->removeAction($actionId));
+ }
+
+ public function testCategoryAuthorizationForbidden()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $categoryId = $this->manager->createCategory($projectId, 'Test');
+ $this->assertNotFalse($categoryId);
+
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->removeCategory($categoryId);
+ }
+
+ public function testCategoryAuthorizationForbiddenBecauseNotProjectManager()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $categoryId = $this->manager->createCategory($projectId, 'Test');
+ $this->assertNotFalse($categoryId);
+
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member'));
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->removeCategory($categoryId);
+ }
+
+ public function testCategoryAuthorizationGranted()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $categoryId = $this->manager->createCategory($projectId, 'Test');
+ $this->assertNotFalse($categoryId);
+
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-manager'));
+ $this->assertTrue($this->user->removeCategory($categoryId));
+ }
+
+ public function testColumnAuthorizationForbidden()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $columnId = $this->manager->addColumn($projectId, 'Test');
+ $this->assertNotFalse($columnId);
+
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->removeColumn($columnId);
+ }
+
+ public function testColumnAuthorizationForbiddenBecauseNotProjectManager()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $columnId = $this->manager->addColumn($projectId, 'Test');
+ $this->assertNotFalse($columnId);
+
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member'));
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->removeColumn($columnId);
+ }
+
+ public function testColumnAuthorizationGranted()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $columnId = $this->manager->addColumn($projectId, 'Test');
+ $this->assertNotFalse($columnId);
+
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-manager'));
+ $this->assertTrue($this->user->removeColumn($columnId));
+ }
+
+ public function testCommentAuthorizationForbidden()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-viewer'));
+
+ $taskId = $this->manager->createTask('My Task', $projectId);
+ $this->assertNotFalse($taskId);
+
+ $commentId = $this->manager->createComment($taskId, $this->userUserId, 'My comment');
+ $this->assertNotFalse($commentId);
+
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->updateComment($commentId, 'something else');
+ }
+
+ public function testCommentAuthorizationGranted()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member'));
+
+ $taskId = $this->user->createTask('My Task', $projectId);
+ $this->assertNotFalse($taskId);
+
+ $commentId = $this->user->createComment($taskId, $this->userUserId, 'My comment');
+ $this->assertNotFalse($commentId);
+
+ $this->assertTrue($this->user->updateComment($commentId, 'something else'));
+ }
+
+ public function testSubtaskAuthorizationForbidden()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-viewer'));
+
+ $taskId = $this->manager->createTask('My Task', $projectId);
+ $this->assertNotFalse($taskId);
+
+ $subtaskId = $this->manager->createSubtask($taskId, 'My subtask');
+ $this->assertNotFalse($subtaskId);
+
+ $this->setExpectedException('JsonRPC\Exception\AccessDeniedException');
+ $this->user->removeSubtask($subtaskId);
+ }
+
+ public function testSubtaskAuthorizationGranted()
+ {
+ $projectId = $this->manager->createProject(array(
+ 'name' => 'Test Project',
+ 'owner_id' => $this->managerUserId,
+ ));
+
+ $this->assertNotFalse($projectId);
+ $this->assertTrue($this->manager->addProjectUser($projectId, $this->userUserId, 'project-member'));
+
+ $taskId = $this->user->createTask('My Task', $projectId);
+ $this->assertNotFalse($taskId);
+
+ $subtaskId = $this->manager->createSubtask($taskId, 'My subtask');
+ $this->assertNotFalse($subtaskId);
+
+ $this->assertTrue($this->user->removeSubtask($subtaskId));
+ }
+}
diff --git a/tests/integration/ProjectPermissionProcedureTest.php b/tests/integration/ProjectPermissionProcedureTest.php
new file mode 100644
index 00000000..74313dc4
--- /dev/null
+++ b/tests/integration/ProjectPermissionProcedureTest.php
@@ -0,0 +1,89 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class ProjectPermissionProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'Project with permission';
+ protected $username = 'user-project-permission';
+ protected $groupName1 = 'My group A for project permission';
+ protected $groupName2 = 'My group B for project permission';
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertCreateGroups();
+ $this->assertCreateUser();
+
+ $this->assertAddProjectUser();
+ $this->assertGetProjectUsers();
+ $this->assertGetAssignableUsers();
+ $this->assertChangeProjectUserRole();
+ $this->assertRemoveProjectUser();
+
+ $this->assertAddProjectGroup();
+ $this->assertGetProjectUsers();
+ $this->assertGetAssignableUsers();
+ $this->assertChangeProjectGroupRole();
+ $this->assertRemoveProjectGroup();
+ }
+
+ public function assertAddProjectUser()
+ {
+ $this->assertTrue($this->app->addProjectUser($this->projectId, $this->userId));
+ }
+
+ public function assertGetProjectUsers()
+ {
+ $members = $this->app->getProjectUsers($this->projectId);
+ $this->assertCount(1, $members);
+ $this->assertArrayHasKey($this->userId, $members);
+ $this->assertEquals($this->username, $members[$this->userId]);
+ }
+
+ public function assertGetAssignableUsers()
+ {
+ $members = $this->app->getAssignableUsers($this->projectId);
+ $this->assertCount(1, $members);
+ $this->assertArrayHasKey($this->userId, $members);
+ $this->assertEquals($this->username, $members[$this->userId]);
+ }
+
+ public function assertChangeProjectUserRole()
+ {
+ $this->assertTrue($this->app->changeProjectUserRole($this->projectId, $this->userId, 'project-viewer'));
+
+ $members = $this->app->getAssignableUsers($this->projectId);
+ $this->assertCount(0, $members);
+ }
+
+ public function assertRemoveProjectUser()
+ {
+ $this->assertTrue($this->app->removeProjectUser($this->projectId, $this->userId));
+
+ $members = $this->app->getProjectUsers($this->projectId);
+ $this->assertCount(0, $members);
+ }
+
+ public function assertAddProjectGroup()
+ {
+ $this->assertTrue($this->app->addGroupMember($this->groupId1, $this->userId));
+ $this->assertTrue($this->app->addProjectGroup($this->projectId, $this->groupId1));
+ }
+
+ public function assertChangeProjectGroupRole()
+ {
+ $this->assertTrue($this->app->changeProjectGroupRole($this->projectId, $this->groupId1, 'project-viewer'));
+
+ $members = $this->app->getAssignableUsers($this->projectId);
+ $this->assertCount(0, $members);
+ }
+
+ public function assertRemoveProjectGroup()
+ {
+ $this->assertTrue($this->app->removeProjectGroup($this->projectId, $this->groupId1));
+
+ $members = $this->app->getProjectUsers($this->projectId);
+ $this->assertCount(0, $members);
+ }
+}
diff --git a/tests/integration/ProjectPermissionTest.php b/tests/integration/ProjectPermissionTest.php
deleted file mode 100644
index b06ad4ad..00000000
--- a/tests/integration/ProjectPermissionTest.php
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-class ProjectPermissionTest extends Base
-{
- public function testGetProjectUsers()
- {
- $this->assertNotFalse($this->app->createProject('Test'));
- $this->assertNotFalse($this->app->createGroup('Test'));
-
- $projectId = $this->getProjectId();
- $groupId = $this->getGroupId();
-
- $this->assertTrue($this->app->addGroupMember($projectId, $groupId));
- $this->assertSame(array(), $this->app->getProjectUsers($projectId));
- }
-
- public function testProjectUser()
- {
- $projectId = $this->getProjectId();
- $this->assertTrue($this->app->addProjectUser($projectId, 1));
-
- $users = $this->app->getProjectUsers($projectId);
- $this->assertCount(1, $users);
- $this->assertEquals('admin', $users[1]);
-
- $users = $this->app->getAssignableUsers($projectId);
- $this->assertCount(1, $users);
- $this->assertEquals('admin', $users[1]);
-
- $this->assertTrue($this->app->changeProjectUserRole($projectId, 1, 'project-viewer'));
-
- $users = $this->app->getAssignableUsers($projectId);
- $this->assertCount(0, $users);
-
- $this->assertTrue($this->app->removeProjectUser($projectId, 1));
- $this->assertSame(array(), $this->app->getProjectUsers($projectId));
- }
-
- public function testProjectGroup()
- {
- $projectId = $this->getProjectId();
- $groupId = $this->getGroupId();
-
- $this->assertTrue($this->app->addProjectGroup($projectId, $groupId));
-
- $users = $this->app->getProjectUsers($projectId);
- $this->assertCount(1, $users);
- $this->assertEquals('admin', $users[1]);
-
- $users = $this->app->getAssignableUsers($projectId);
- $this->assertCount(1, $users);
- $this->assertEquals('admin', $users[1]);
-
- $this->assertTrue($this->app->changeProjectGroupRole($projectId, $groupId, 'project-viewer'));
-
- $users = $this->app->getAssignableUsers($projectId);
- $this->assertCount(0, $users);
-
- $this->assertTrue($this->app->removeProjectGroup($projectId, 1));
- $this->assertSame(array(), $this->app->getProjectUsers($projectId));
- }
-}
diff --git a/tests/integration/ProjectProcedureTest.php b/tests/integration/ProjectProcedureTest.php
new file mode 100644
index 00000000..69c2464f
--- /dev/null
+++ b/tests/integration/ProjectProcedureTest.php
@@ -0,0 +1,119 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class ProjectProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My team project';
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertGetProjectById();
+ $this->assertGetProjectByName();
+ $this->assertGetAllProjects();
+ $this->assertUpdateProject();
+ $this->assertUpdateProjectIdentifier();
+ $this->assertCreateProjectWithIdentifier();
+ $this->assertGetProjectActivity();
+ $this->assertGetProjectsActivity();
+ $this->assertEnableDisableProject();
+ $this->assertEnableDisablePublicAccess();
+ $this->assertRemoveProject();
+ }
+
+ public function assertGetProjectById()
+ {
+ $project = $this->app->getProjectById($this->projectId);
+ $this->assertNotNull($project);
+ $this->assertEquals($this->projectName, $project['name']);
+ $this->assertEquals('Description', $project['description']);
+ }
+
+ public function assertGetProjectByName()
+ {
+ $project = $this->app->getProjectByName($this->projectName);
+ $this->assertNotNull($project);
+ $this->assertEquals($this->projectId, $project['id']);
+ $this->assertEquals($this->projectName, $project['name']);
+ $this->assertEquals('Description', $project['description']);
+ }
+
+ public function assertGetAllProjects()
+ {
+ $projects = $this->app->getAllProjects();
+ $this->assertNotEmpty($projects);
+ }
+
+ public function assertGetProjectActivity()
+ {
+ $activities = $this->app->getProjectActivity($this->projectId);
+ $this->assertInternalType('array', $activities);
+ $this->assertCount(0, $activities);
+ }
+
+ public function assertGetProjectsActivity()
+ {
+ $activities = $this->app->getProjectActivities(array('project_ids' => array($this->projectId)));
+ $this->assertInternalType('array', $activities);
+ $this->assertCount(0, $activities);
+ }
+
+ public function assertUpdateProject()
+ {
+ $this->assertTrue($this->app->updateProject(array('project_id' => $this->projectId, 'name' => 'test', 'description' => 'test')));
+
+ $project = $this->app->getProjectById($this->projectId);
+ $this->assertNotNull($project);
+ $this->assertEquals('test', $project['name']);
+ $this->assertEquals('test', $project['description']);
+
+ $this->assertTrue($this->app->updateProject(array('project_id' => $this->projectId, 'name' => $this->projectName)));
+ }
+
+ public function assertUpdateProjectIdentifier()
+ {
+ $this->assertTrue($this->app->updateProject(array(
+ 'project_id' => $this->projectId,
+ 'identifier' => 'MYPROJECT',
+ )));
+
+ $project = $this->app->getProjectById($this->projectId);
+ $this->assertNotNull($project);
+ $this->assertEquals($this->projectName, $project['name']);
+ $this->assertEquals('MYPROJECT', $project['identifier']);
+ }
+
+ public function assertCreateProjectWithIdentifier()
+ {
+ $projectId = $this->app->createProject(array(
+ 'name' => 'My project with an identifier',
+ 'identifier' => 'MYPROJECTWITHIDENTIFIER',
+ ));
+
+ $this->assertNotFalse($projectId);
+
+ $project = $this->app->getProjectByIdentifier('MYPROJECTWITHIDENTIFIER');
+ $this->assertEquals($projectId, $project['id']);
+ $this->assertEquals('My project with an identifier', $project['name']);
+ $this->assertEquals('MYPROJECTWITHIDENTIFIER', $project['identifier']);
+ }
+
+ public function assertEnableDisableProject()
+ {
+ $this->assertTrue($this->app->disableProject($this->projectId));
+ $this->assertTrue($this->app->enableProject($this->projectId));
+ }
+
+ public function assertEnableDisablePublicAccess()
+ {
+ $this->assertTrue($this->app->disableProjectPublicAccess($this->projectId));
+ $this->assertTrue($this->app->enableProjectPublicAccess($this->projectId));
+ }
+
+ public function assertRemoveProject()
+ {
+ $this->assertTrue($this->app->removeProject($this->projectId));
+ $this->assertNull($this->app->getProjectById($this->projectId));
+ }
+}
diff --git a/tests/integration/SubtaskProcedureTest.php b/tests/integration/SubtaskProcedureTest.php
new file mode 100644
index 00000000..7ab4ef0b
--- /dev/null
+++ b/tests/integration/SubtaskProcedureTest.php
@@ -0,0 +1,64 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class SubtaskProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test subtasks';
+ private $subtaskId = 0;
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertCreateTask();
+ $this->assertCreateSubtask();
+ $this->assertGetSubtask();
+ $this->assertUpdateSubtask();
+ $this->assertGetAllSubtasks();
+ $this->assertRemoveSubtask();
+ }
+
+ public function assertCreateSubtask()
+ {
+ $this->subtaskId = $this->app->createSubtask(array(
+ 'task_id' => $this->taskId,
+ 'title' => 'subtask #1',
+ ));
+
+ $this->assertNotFalse($this->subtaskId);
+ }
+
+ public function assertGetSubtask()
+ {
+ $subtask = $this->app->getSubtask($this->subtaskId);
+ $this->assertEquals($this->taskId, $subtask['task_id']);
+ $this->assertEquals('subtask #1', $subtask['title']);
+ }
+
+ public function assertUpdateSubtask()
+ {
+ $this->assertTrue($this->app->execute('updateSubtask', array(
+ 'id' => $this->subtaskId,
+ 'task_id' => $this->taskId,
+ 'title' => 'test',
+ )));
+
+ $subtask = $this->app->getSubtask($this->subtaskId);
+ $this->assertEquals('test', $subtask['title']);
+ }
+
+ public function assertGetAllSubtasks()
+ {
+ $subtasks = $this->app->getAllSubtasks($this->taskId);
+ $this->assertCount(1, $subtasks);
+ $this->assertEquals('test', $subtasks[0]['title']);
+ }
+
+ public function assertRemoveSubtask()
+ {
+ $this->assertTrue($this->app->removeSubtask($this->subtaskId));
+
+ $subtasks = $this->app->getAllSubtasks($this->taskId);
+ $this->assertCount(0, $subtasks);
+ }
+}
diff --git a/tests/integration/SwimlaneProcedureTest.php b/tests/integration/SwimlaneProcedureTest.php
new file mode 100644
index 00000000..e64342b4
--- /dev/null
+++ b/tests/integration/SwimlaneProcedureTest.php
@@ -0,0 +1,93 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class SwimlaneProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test swimlanes';
+ private $swimlaneId = 0;
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ }
+
+ public function assertGetDefaultSwimlane()
+ {
+ $swimlane = $this->app->getDefaultSwimlane($this->projectId);
+ $this->assertNotEmpty($swimlane);
+ $this->assertEquals('Default swimlane', $swimlane['default_swimlane']);
+ }
+
+ public function assertAddSwimlane()
+ {
+ $this->swimlaneId = $this->app->addSwimlane($this->projectId, 'Swimlane 1');
+ $this->assertNotFalse($this->swimlaneId);
+ $this->assertNotFalse($this->app->addSwimlane($this->projectId, 'Swimlane 2'));
+ }
+
+ public function assertGetSwimlane()
+ {
+ $swimlane = $this->app->getSwimlane($this->swimlaneId);
+ $this->assertInternalType('array', $swimlane);
+ $this->assertEquals('Swimlane 1', $swimlane['name']);
+ }
+
+ public function assertUpdateSwimlane()
+ {
+ $this->assertTrue($this->app->updateSwimlane($this->swimlaneId, 'Another swimlane'));
+
+ $swimlane = $this->app->getSwimlaneById($this->swimlaneId);
+ $this->assertEquals('Another swimlane', $swimlane['name']);
+ }
+
+ public function assertDisableSwimlane()
+ {
+ $this->assertTrue($this->app->disableSwimlane($this->projectId, $this->swimlaneId));
+
+ $swimlane = $this->app->getSwimlaneById($this->swimlaneId);
+ $this->assertEquals(0, $swimlane['is_active']);
+ }
+
+ public function assertEnableSwimlane()
+ {
+ $this->assertTrue($this->app->enableSwimlane($this->projectId, $this->swimlaneId));
+
+ $swimlane = $this->app->getSwimlaneById($this->swimlaneId);
+ $this->assertEquals(1, $swimlane['is_active']);
+ }
+
+ public function assertGetAllSwimlanes()
+ {
+ $swimlanes = $this->app->getAllSwimlanes($this->projectId);
+ $this->assertCount(2, $swimlanes);
+ $this->assertEquals('Another swimlane', $swimlanes[0]['name']);
+ $this->assertEquals('Swimlane 2', $swimlanes[1]['name']);
+ }
+
+ public function assertGetActiveSwimlane()
+ {
+ $this->assertTrue($this->app->disableSwimlane($this->projectId, $this->swimlaneId));
+
+ $swimlanes = $this->app->getActiveSwimlanes($this->projectId);
+ $this->assertCount(2, $swimlanes);
+ $this->assertEquals('Default swimlane', $swimlanes[0]['name']);
+ $this->assertEquals('Swimlane 2', $swimlanes[1]['name']);
+ }
+
+ public function assertRemoveSwimlane()
+ {
+ $this->assertTrue($this->app->removeSwimlane($this->projectId, $this->swimlaneId));
+ }
+
+ public function assertChangePosition()
+ {
+ $swimlaneId1 = $this->app->addSwimlane($this->projectId, 'Swimlane A');
+ $this->assertNotFalse($this->app->addSwimlane($this->projectId, 'Swimlane B'));
+
+ $swimlanes = $this->app->getAllSwimlanes($this->projectId);
+ $this->assertCount(3, $swimlanes);
+
+ $this->assertTrue($this->app->changeSwimlanePosition($this->projectId, $swimlaneId1, 3));
+ }
+}
diff --git a/tests/integration/SwimlaneTest.php b/tests/integration/SwimlaneTest.php
deleted file mode 100644
index 88747204..00000000
--- a/tests/integration/SwimlaneTest.php
+++ /dev/null
@@ -1,103 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-class SwimlaneTest extends Base
-{
- public function testCreateProject()
- {
- $this->assertEquals(1, $this->app->createProject('A project'));
- }
-
- public function testGetDefaultSwimlane()
- {
- $swimlane = $this->app->getDefaultSwimlane(1);
- $this->assertNotEmpty($swimlane);
- $this->assertEquals('Default swimlane', $swimlane['default_swimlane']);
- }
-
- public function testAddSwimlane()
- {
- $swimlane_id = $this->app->addSwimlane(1, 'Swimlane 1');
- $this->assertNotFalse($swimlane_id);
- $this->assertInternalType('int', $swimlane_id);
-
- $swimlane = $this->app->getSwimlaneById($swimlane_id);
- $this->assertNotEmpty($swimlane);
- $this->assertInternalType('array', $swimlane);
- $this->assertEquals('Swimlane 1', $swimlane['name']);
- }
-
- public function testGetSwimlane()
- {
- $swimlane = $this->app->getSwimlane(1);
- $this->assertInternalType('array', $swimlane);
- $this->assertEquals('Swimlane 1', $swimlane['name']);
- }
-
- public function testUpdateSwimlane()
- {
- $swimlane = $this->app->getSwimlaneByName(1, 'Swimlane 1');
- $this->assertInternalType('array', $swimlane);
- $this->assertEquals(1, $swimlane['id']);
- $this->assertEquals('Swimlane 1', $swimlane['name']);
-
- $this->assertTrue($this->app->updateSwimlane($swimlane['id'], 'Another swimlane'));
-
- $swimlane = $this->app->getSwimlaneById($swimlane['id']);
- $this->assertEquals('Another swimlane', $swimlane['name']);
- }
-
- public function testDisableSwimlane()
- {
- $this->assertTrue($this->app->disableSwimlane(1, 1));
-
- $swimlane = $this->app->getSwimlaneById(1);
- $this->assertEquals(0, $swimlane['is_active']);
- }
-
- public function testEnableSwimlane()
- {
- $this->assertTrue($this->app->enableSwimlane(1, 1));
-
- $swimlane = $this->app->getSwimlaneById(1);
- $this->assertEquals(1, $swimlane['is_active']);
- }
-
- public function testGetAllSwimlanes()
- {
- $this->assertNotFalse($this->app->addSwimlane(1, 'Swimlane A'));
-
- $swimlanes = $this->app->getAllSwimlanes(1);
- $this->assertCount(2, $swimlanes);
- $this->assertEquals('Another swimlane', $swimlanes[0]['name']);
- $this->assertEquals('Swimlane A', $swimlanes[1]['name']);
- }
-
- public function testGetActiveSwimlane()
- {
- $this->assertTrue($this->app->disableSwimlane(1, 1));
-
- $swimlanes = $this->app->getActiveSwimlanes(1);
- $this->assertCount(2, $swimlanes);
- $this->assertEquals('Default swimlane', $swimlanes[0]['name']);
- $this->assertEquals('Swimlane A', $swimlanes[1]['name']);
- }
-
- public function testRemoveSwimlane()
- {
- $this->assertTrue($this->app->removeSwimlane(1, 2));
- }
-
- public function testChangePosition()
- {
- $this->assertNotFalse($this->app->addSwimlane(1, 'Swimlane 1'));
- $this->assertNotFalse($this->app->addSwimlane(1, 'Swimlane 2'));
-
- $swimlanes = $this->app->getAllSwimlanes(1);
- $this->assertCount(3, $swimlanes);
-
- $this->assertTrue($this->app->changeSwimlanePosition(1, 1, 3));
- $this->assertFalse($this->app->changeSwimlanePosition(1, 1, 6));
- }
-}
diff --git a/tests/integration/TaskFileProcedureTest.php b/tests/integration/TaskFileProcedureTest.php
new file mode 100644
index 00000000..61155555
--- /dev/null
+++ b/tests/integration/TaskFileProcedureTest.php
@@ -0,0 +1,67 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class TaskFileProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test task files';
+ protected $fileId;
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertCreateTask();
+ $this->assertCreateTaskFile();
+ $this->assertGetTaskFile();
+ $this->assertDownloadTaskFile();
+ $this->assertGetAllFiles();
+ $this->assertRemoveTaskFile();
+ $this->assertRemoveAllTaskFiles();
+ }
+
+ public function assertCreateTaskFile()
+ {
+ $this->fileId = $this->app->createTaskFile(1, $this->taskId, 'My file', base64_encode('plain text file'));
+ $this->assertNotFalse($this->fileId);
+ }
+
+ public function assertGetTaskFile()
+ {
+ $file = $this->app->getTaskFile($this->fileId);
+ $this->assertNotEmpty($file);
+ $this->assertEquals('My file', $file['name']);
+ }
+
+ public function assertDownloadTaskFile()
+ {
+ $content = $this->app->downloadTaskFile($this->fileId);
+ $this->assertNotEmpty($content);
+ $this->assertEquals('plain text file', base64_decode($content));
+ }
+
+ public function assertGetAllFiles()
+ {
+ $files = $this->app->getAllTaskFiles(array('task_id' => $this->taskId));
+ $this->assertCount(1, $files);
+ $this->assertEquals('My file', $files[0]['name']);
+ }
+
+ public function assertRemoveTaskFile()
+ {
+ $this->assertTrue($this->app->removeTaskFile($this->fileId));
+
+ $files = $this->app->getAllTaskFiles(array('task_id' => $this->taskId));
+ $this->assertEmpty($files);
+ }
+
+ public function assertRemoveAllTaskFiles()
+ {
+ $this->assertCreateTaskFile();
+ $this->assertCreateTaskFile();
+
+ $this->assertTrue($this->app->removeAllTaskFiles($this->taskId));
+
+ $files = $this->app->getAllTaskFiles(array('task_id' => $this->taskId));
+ $this->assertEmpty($files);
+ }
+}
diff --git a/tests/integration/TaskLinkProcedureTest.php b/tests/integration/TaskLinkProcedureTest.php
new file mode 100644
index 00000000..a25fced5
--- /dev/null
+++ b/tests/integration/TaskLinkProcedureTest.php
@@ -0,0 +1,68 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class TaskLinkProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test task links';
+ protected $taskLinkId;
+ protected $taskId1;
+ protected $taskId2;
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+
+ $this->taskId1 = $this->app->createTask(array('project_id' => $this->projectId, 'title' => 'Task 1'));
+ $this->taskId2 = $this->app->createTask(array('project_id' => $this->projectId, 'title' => 'Task 2'));
+
+ $this->assertNotFalse($this->taskId1);
+ $this->assertNotFalse($this->taskId2);
+
+ $this->assertCreateTaskLink();
+ $this->assertGetTaskLink();
+ $this->assertGetAllTaskLinks();
+ $this->assertUpdateTaskLink();
+ $this->assertRemoveTaskLink();
+ }
+
+ public function assertCreateTaskLink()
+ {
+ $this->taskLinkId = $this->app->createTaskLink($this->taskId1, $this->taskId2, 1);
+ $this->assertNotFalse($this->taskLinkId);
+ }
+
+ public function assertGetTaskLink()
+ {
+ $link = $this->app->getTaskLinkById($this->taskLinkId);
+ $this->assertNotNull($link);
+ $this->assertEquals($this->taskId1, $link['task_id']);
+ $this->assertEquals($this->taskId2, $link['opposite_task_id']);
+ $this->assertEquals(1, $link['link_id']);
+ }
+
+ public function assertGetAllTaskLinks()
+ {
+ $links = $this->app->getAllTaskLinks($this->taskId2);
+ $this->assertCount(1, $links);
+ }
+
+ public function assertUpdateTaskLink()
+ {
+ $this->assertTrue($this->app->updateTaskLink($this->taskLinkId, $this->taskId1, $this->taskId2, 3));
+
+ $link = $this->app->getTaskLinkById($this->taskLinkId);
+ $this->assertNotNull($link);
+ $this->assertEquals($this->taskId1, $link['task_id']);
+ $this->assertEquals($this->taskId2, $link['opposite_task_id']);
+ $this->assertEquals(3, $link['link_id']);
+ }
+
+ public function assertRemoveTaskLink()
+ {
+ $this->assertTrue($this->app->removeTaskLink($this->taskLinkId));
+
+ $links = $this->app->getAllTaskLinks($this->taskId2);
+ $this->assertCount(0, $links);
+ }
+}
diff --git a/tests/integration/TaskProcedureTest.php b/tests/integration/TaskProcedureTest.php
new file mode 100644
index 00000000..f456ae52
--- /dev/null
+++ b/tests/integration/TaskProcedureTest.php
@@ -0,0 +1,55 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class TaskProcedureTest extends BaseProcedureTest
+{
+ protected $projectName = 'My project to test tasks';
+
+ public function testAll()
+ {
+ $this->assertCreateTeamProject();
+ $this->assertCreateTask();
+ $this->assertUpdateTask();
+ $this->assertGetTaskById();
+ $this->assertGetTaskByReference();
+ $this->assertGetAllTasks();
+ $this->assertOpenCloseTask();
+ }
+
+ public function assertUpdateTask()
+ {
+ $this->assertTrue($this->app->updateTask(array('id' => $this->taskId, 'color_id' => 'red')));
+ }
+
+ public function assertGetTaskById()
+ {
+ $task = $this->app->getTask($this->taskId);
+ $this->assertNotNull($task);
+ $this->assertEquals('red', $task['color_id']);
+ $this->assertEquals($this->taskTitle, $task['title']);
+ }
+
+ public function assertGetTaskByReference()
+ {
+ $taskId = $this->app->createTask(array('title' => 'task with reference', 'project_id' => $this->projectId, 'reference' => 'test'));
+ $this->assertNotFalse($taskId);
+
+ $task = $this->app->getTaskByReference($this->projectId, 'test');
+ $this->assertNotNull($task);
+ $this->assertEquals($taskId, $task['id']);
+ }
+
+ public function assertGetAllTasks()
+ {
+ $tasks = $this->app->getAllTasks($this->projectId);
+ $this->assertInternalType('array', $tasks);
+ $this->assertNotEmpty($tasks);
+ }
+
+ public function assertOpenCloseTask()
+ {
+ $this->assertTrue($this->app->closeTask($this->taskId));
+ $this->assertTrue($this->app->openTask($this->taskId));
+ }
+}
diff --git a/tests/integration/TaskTest.php b/tests/integration/TaskTest.php
deleted file mode 100644
index 0c398761..00000000
--- a/tests/integration/TaskTest.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-class TaskTest extends Base
-{
- public function testSearchTasks()
- {
- $project_id1 = $this->app->createProject('My project');
- $project_id2 = $this->app->createProject('My project');
- $this->assertNotFalse($project_id1);
- $this->assertNotFalse($project_id2);
-
- $this->assertNotFalse($this->app->createTask(array('project_id' => $project_id1, 'title' => 'T1')));
- $this->assertNotFalse($this->app->createTask(array('project_id' => $project_id1, 'title' => 'T2')));
- $this->assertNotFalse($this->app->createTask(array('project_id' => $project_id2, 'title' => 'T3')));
-
- $tasks = $this->app->searchTasks($project_id1, 't2');
- $this->assertCount(1, $tasks);
- $this->assertEquals('T2', $tasks[0]['title']);
-
- $tasks = $this->app->searchTasks(array('project_id' => $project_id2, 'query' => 'assignee:nobody'));
- $this->assertCount(1, $tasks);
- $this->assertEquals('T3', $tasks[0]['title']);
- }
-
- public function testPriorityAttribute()
- {
- $project_id = $this->app->createProject('My project');
- $this->assertNotFalse($project_id);
-
- $task_id = $this->app->createTask(array('project_id' => $project_id, 'title' => 'My task', 'priority' => 2));
-
- $task = $this->app->getTask($task_id);
- $this->assertEquals(2, $task['priority']);
-
- $this->assertTrue($this->app->updateTask(array('id' => $task_id, 'project_id' => $project_id, 'priority' => 3)));
-
- $task = $this->app->getTask($task_id);
- $this->assertEquals(3, $task['priority']);
- }
-
- public function testChangeAssigneeToAssignableUser()
- {
- $project_id = $this->app->createProject('My project');
- $this->assertNotFalse($project_id);
-
- $user_id = $this->app->createUser('user0', 'password');
- $this->assertNotFalse($user_id);
-
- $this->assertTrue($this->app->addProjectUser($project_id, $user_id, 'project-member'));
-
- $task_id = $this->app->createTask(array('project_id' => $project_id, 'title' => 'My task'));
- $this->assertNotFalse($task_id);
-
- $this->assertTrue($this->app->updateTask(array('id' => $task_id, 'project_id' => $project_id, 'owner_id' => $user_id)));
-
- $task = $this->app->getTask($task_id);
- $this->assertEquals($user_id, $task['owner_id']);
- }
-
- public function testChangeAssigneeToNotAssignableUser()
- {
- $project_id = $this->app->createProject('My project');
- $this->assertNotFalse($project_id);
-
- $task_id = $this->app->createTask(array('project_id' => $project_id, 'title' => 'My task'));
- $this->assertNotFalse($task_id);
-
- $this->assertFalse($this->app->updateTask(array('id' => $task_id, 'project_id' => $project_id, 'owner_id' => 1)));
-
- $task = $this->app->getTask($task_id);
- $this->assertEquals(0, $task['owner_id']);
- }
-
- public function testChangeAssigneeToNobody()
- {
- $project_id = $this->app->createProject('My project');
- $this->assertNotFalse($project_id);
-
- $user_id = $this->app->createUser('user1', 'password');
- $this->assertNotFalse($user_id);
-
- $this->assertTrue($this->app->addProjectUser($project_id, $user_id, 'project-member'));
-
- $task_id = $this->app->createTask(array('project_id' => $project_id, 'title' => 'My task', 'owner_id' => $user_id));
- $this->assertNotFalse($task_id);
-
- $this->assertTrue($this->app->updateTask(array('id' => $task_id, 'project_id' => $project_id, 'owner_id' => 0)));
-
- $task = $this->app->getTask($task_id);
- $this->assertEquals(0, $task['owner_id']);
- }
-
- public function testMoveTaskToAnotherProject()
- {
- $project_id1 = $this->app->createProject('My project');
- $this->assertNotFalse($project_id1);
-
- $project_id2 = $this->app->createProject('My project');
- $this->assertNotFalse($project_id2);
-
- $task_id = $this->app->createTask(array('project_id' => $project_id1, 'title' => 'My task'));
- $this->assertNotFalse($task_id);
-
- $this->assertTrue($this->app->moveTaskToProject($task_id, $project_id2));
-
- $task = $this->app->getTask($task_id);
- $this->assertEquals($project_id2, $task['project_id']);
- }
-
- public function testMoveCopyToAnotherProject()
- {
- $project_id1 = $this->app->createProject('My project');
- $this->assertNotFalse($project_id1);
-
- $project_id2 = $this->app->createProject('My project');
- $this->assertNotFalse($project_id2);
-
- $task_id1 = $this->app->createTask(array('project_id' => $project_id1, 'title' => 'My task'));
- $this->assertNotFalse($task_id1);
-
- $task_id2 = $this->app->duplicateTaskToProject($task_id1, $project_id2);
- $this->assertNotFalse($task_id2);
-
- $task = $this->app->getTask($task_id1);
- $this->assertEquals($project_id1, $task['project_id']);
-
- $task = $this->app->getTask($task_id2);
- $this->assertEquals($project_id2, $task['project_id']);
- }
-}
diff --git a/tests/integration/UserProcedureTest.php b/tests/integration/UserProcedureTest.php
new file mode 100644
index 00000000..290f87fb
--- /dev/null
+++ b/tests/integration/UserProcedureTest.php
@@ -0,0 +1,63 @@
+<?php
+
+require_once __DIR__.'/BaseProcedureTest.php';
+
+class UserProcedureTest extends BaseProcedureTest
+{
+ public function testAll()
+ {
+ $this->assertCreateUser();
+ $this->assertGetUserById();
+ $this->assertGetUserByName();
+ $this->assertGetAllUsers();
+ $this->assertEnableDisableUser();
+ $this->assertUpdateUser();
+ $this->assertRemoveUser();
+ }
+
+ public function assertGetUserById()
+ {
+ $user = $this->app->getUser($this->userId);
+ $this->assertNotNull($user);
+ $this->assertEquals($this->username, $user['username']);
+ }
+
+ public function assertGetUserByName()
+ {
+ $user = $this->app->getUserByName($this->username);
+ $this->assertNotNull($user);
+ $this->assertEquals($this->username, $user['username']);
+ }
+
+ public function assertGetAllUsers()
+ {
+ $users = $this->app->getAllUsers();
+ $this->assertInternalType('array', $users);
+ $this->assertNotEmpty($users);
+ }
+
+ public function assertEnableDisableUser()
+ {
+ $this->assertTrue($this->app->disableUser($this->userId));
+ $this->assertFalse($this->app->isActiveUser($this->userId));
+ $this->assertTrue($this->app->enableUser($this->userId));
+ $this->assertTrue($this->app->isActiveUser($this->userId));
+ }
+
+ public function assertUpdateUser()
+ {
+ $this->assertTrue($this->app->updateUser(array(
+ 'id' => $this->userId,
+ 'name' => 'My user',
+ )));
+
+ $user = $this->app->getUser($this->userId);
+ $this->assertNotNull($user);
+ $this->assertEquals('My user', $user['name']);
+ }
+
+ public function assertRemoveUser()
+ {
+ $this->assertTrue($this->app->removeUser($this->userId));
+ }
+}
diff --git a/tests/integration/UserTest.php b/tests/integration/UserTest.php
deleted file mode 100644
index 10da051c..00000000
--- a/tests/integration/UserTest.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-require_once __DIR__.'/Base.php';
-
-class UserTest extends Base
-{
- public function testDisableUser()
- {
- $this->assertEquals(2, $this->app->createUser(array('username' => 'someone', 'password' => 'test123')));
- $this->assertTrue($this->app->isActiveUser(2));
-
- $this->assertTrue($this->app->disableUser(2));
- $this->assertFalse($this->app->isActiveUser(2));
-
- $this->assertTrue($this->app->enableUser(2));
- $this->assertTrue($this->app->isActiveUser(2));
- }
-}
diff --git a/tests/units/Model/ActionTest.php b/tests/units/Model/ActionModelTest.php
index 5db18983..4e21a999 100644
--- a/tests/units/Model/ActionTest.php
+++ b/tests/units/Model/ActionModelTest.php
@@ -11,7 +11,7 @@ use Kanboard\Model\CategoryModel;
use Kanboard\Model\ProjectUserRoleModel;
use Kanboard\Core\Security\Role;
-class ActionTest extends Base
+class ActionModelTest extends Base
{
public function testCreate()
{
@@ -69,6 +69,24 @@ class ActionTest extends Base
$this->assertEquals(array('column_id' => 1, 'color_id' => 'red'), $action['params']);
}
+ public function testGetProjectId()
+ {
+ $projectModel = new ProjectModel($this->container);
+ $actionModel = new ActionModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+
+ $this->assertEquals(1, $actionModel->create(array(
+ 'project_id' => 1,
+ 'event_name' => TaskModel::EVENT_CREATE,
+ 'action_name' => '\Kanboard\Action\TaskAssignColorColumn',
+ 'params' => array('column_id' => 1, 'color_id' => 'red'),
+ )));
+
+ $this->assertEquals(1, $actionModel->getProjectId(1));
+ $this->assertSame(0, $actionModel->getProjectId(42));
+ }
+
public function testGetAll()
{
$projectModel = new ProjectModel($this->container);
diff --git a/tests/units/Model/CategoryTest.php b/tests/units/Model/CategoryModelTest.php
index 1fdc51f6..80a20af6 100644
--- a/tests/units/Model/CategoryTest.php
+++ b/tests/units/Model/CategoryModelTest.php
@@ -8,7 +8,7 @@ use Kanboard\Model\TaskFinderModel;
use Kanboard\Model\ProjectModel;
use Kanboard\Model\CategoryModel;
-class CategoryTest extends Base
+class CategoryModelTest extends Base
{
public function testCreation()
{
@@ -81,6 +81,18 @@ class CategoryTest extends Base
$this->assertSame(0, $categoryModel->getIdByName(1, 'Category #2'));
}
+ public function testGetProjectId()
+ {
+ $projectModel = new ProjectModel($this->container);
+ $categoryModel = new CategoryModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'Project #1')));
+ $this->assertEquals(1, $categoryModel->create(array('name' => 'Category #1', 'project_id' => 1, 'description' => 'test')));
+
+ $this->assertEquals(1, $categoryModel->getProjectId(1));
+ $this->assertSame(0, $categoryModel->getProjectId(2));
+ }
+
public function testGetList()
{
$projectModel = new ProjectModel($this->container);
diff --git a/tests/units/Model/CommentTest.php b/tests/units/Model/CommentTest.php
index 7250ae0b..574b5a87 100644
--- a/tests/units/Model/CommentTest.php
+++ b/tests/units/Model/CommentTest.php
@@ -10,16 +10,16 @@ class CommentTest extends Base
{
public function testCreate()
{
- $c = new CommentModel($this->container);
- $tc = new TaskCreationModel($this->container);
- $p = new ProjectModel($this->container);
+ $commentModel = new CommentModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test1')));
- $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
- $this->assertEquals(1, $c->create(array('task_id' => 1, 'comment' => 'bla bla', 'user_id' => 1)));
- $this->assertEquals(2, $c->create(array('task_id' => 1, 'comment' => 'bla bla')));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
+ $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'bla bla', 'user_id' => 1)));
+ $this->assertEquals(2, $commentModel->create(array('task_id' => 1, 'comment' => 'bla bla')));
- $comment = $c->getById(1);
+ $comment = $commentModel->getById(1);
$this->assertNotEmpty($comment);
$this->assertEquals('bla bla', $comment['comment']);
$this->assertEquals(1, $comment['task_id']);
@@ -27,7 +27,7 @@ class CommentTest extends Base
$this->assertEquals('admin', $comment['username']);
$this->assertEquals(time(), $comment['date_creation'], '', 3);
- $comment = $c->getById(2);
+ $comment = $commentModel->getById(2);
$this->assertNotEmpty($comment);
$this->assertEquals('bla bla', $comment['comment']);
$this->assertEquals(1, $comment['task_id']);
@@ -38,17 +38,17 @@ class CommentTest extends Base
public function testGetAll()
{
- $c = new CommentModel($this->container);
- $tc = new TaskCreationModel($this->container);
- $p = new ProjectModel($this->container);
+ $commentModel = new CommentModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test1')));
- $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
- $this->assertNotFalse($c->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1)));
- $this->assertNotFalse($c->create(array('task_id' => 1, 'comment' => 'c2', 'user_id' => 1)));
- $this->assertNotFalse($c->create(array('task_id' => 1, 'comment' => 'c3', 'user_id' => 1)));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
+ $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1)));
+ $this->assertEquals(2, $commentModel->create(array('task_id' => 1, 'comment' => 'c2', 'user_id' => 1)));
+ $this->assertEquals(3, $commentModel->create(array('task_id' => 1, 'comment' => 'c3', 'user_id' => 1)));
- $comments = $c->getAll(1);
+ $comments = $commentModel->getAll(1);
$this->assertNotEmpty($comments);
$this->assertEquals(3, count($comments));
@@ -56,37 +56,51 @@ class CommentTest extends Base
$this->assertEquals(2, $comments[1]['id']);
$this->assertEquals(3, $comments[2]['id']);
- $this->assertEquals(3, $c->count(1));
+ $this->assertEquals(3, $commentModel->count(1));
}
public function testUpdate()
{
- $c = new CommentModel($this->container);
- $tc = new TaskCreationModel($this->container);
- $p = new ProjectModel($this->container);
+ $commentModel = new CommentModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test1')));
- $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
- $this->assertNotFalse($c->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1)));
- $this->assertTrue($c->update(array('id' => 1, 'comment' => 'bla')));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
+ $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1)));
+ $this->assertTrue($commentModel->update(array('id' => 1, 'comment' => 'bla')));
- $comment = $c->getById(1);
+ $comment = $commentModel->getById(1);
$this->assertNotEmpty($comment);
$this->assertEquals('bla', $comment['comment']);
}
public function validateRemove()
{
- $c = new CommentModel($this->container);
- $tc = new TaskCreationModel($this->container);
- $p = new ProjectModel($this->container);
+ $commentModel = new CommentModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test1')));
- $this->assertEquals(1, $tc->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
- $this->assertTrue($c->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1)));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
+ $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1)));
- $this->assertTrue($c->remove(1));
- $this->assertFalse($c->remove(1));
- $this->assertFalse($c->remove(1111));
+ $this->assertTrue($commentModel->remove(1));
+ $this->assertFalse($commentModel->remove(1));
+ $this->assertFalse($commentModel->remove(1111));
+ }
+
+ public function testGetProjectId()
+ {
+ $commentModel = new CommentModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $projectModel = new ProjectModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test', 'project_id' => 1, 'column_id' => 3, 'owner_id' => 1)));
+ $this->assertEquals(1, $commentModel->create(array('task_id' => 1, 'comment' => 'c1', 'user_id' => 1)));
+
+ $this->assertEquals(1, $commentModel->getProjectId(1));
+ $this->assertSame(0, $commentModel->getProjectId(2));
}
}
diff --git a/tests/units/Model/SubtaskTest.php b/tests/units/Model/SubtaskModelTest.php
index b65ee609..6451189d 100644
--- a/tests/units/Model/SubtaskTest.php
+++ b/tests/units/Model/SubtaskModelTest.php
@@ -5,10 +5,9 @@ require_once __DIR__.'/../Base.php';
use Kanboard\Model\TaskCreationModel;
use Kanboard\Model\SubtaskModel;
use Kanboard\Model\ProjectModel;
-use Kanboard\Core\User\UserSession;
use Kanboard\Model\TaskFinderModel;
-class SubtaskTest extends Base
+class SubtaskModelTest extends Base
{
public function onSubtaskCreated($event)
{
@@ -70,18 +69,18 @@ class SubtaskTest extends Base
public function testCreation()
{
- $tc = new TaskCreationModel($this->container);
- $s = new SubtaskModel($this->container);
- $p = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $subtaskModel = new SubtaskModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1)));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1)));
$this->container['dispatcher']->addListener(SubtaskModel::EVENT_CREATE, array($this, 'onSubtaskCreated'));
- $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1)));
+ $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1)));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(1, $subtask['id']);
$this->assertEquals(1, $subtask['task_id']);
@@ -95,19 +94,19 @@ class SubtaskTest extends Base
public function testModification()
{
- $tc = new TaskCreationModel($this->container);
- $s = new SubtaskModel($this->container);
- $p = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $subtaskModel = new SubtaskModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1)));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1)));
$this->container['dispatcher']->addListener(SubtaskModel::EVENT_UPDATE, array($this, 'onSubtaskUpdated'));
- $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1)));
- $this->assertTrue($s->update(array('id' => 1, 'user_id' => 1, 'status' => SubtaskModel::STATUS_INPROGRESS)));
+ $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1)));
+ $this->assertTrue($subtaskModel->update(array('id' => 1, 'user_id' => 1, 'status' => SubtaskModel::STATUS_INPROGRESS)));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(1, $subtask['id']);
$this->assertEquals(1, $subtask['task_id']);
@@ -121,61 +120,61 @@ class SubtaskTest extends Base
public function testRemove()
{
- $tc = new TaskCreationModel($this->container);
- $s = new SubtaskModel($this->container);
- $p = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $subtaskModel = new SubtaskModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1)));
- $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1)));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1)));
+ $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1)));
$this->container['dispatcher']->addListener(SubtaskModel::EVENT_DELETE, array($this, 'onSubtaskDeleted'));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
- $this->assertTrue($s->remove(1));
+ $this->assertTrue($subtaskModel->remove(1));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertEmpty($subtask);
}
public function testToggleStatusWithoutSession()
{
- $tc = new TaskCreationModel($this->container);
- $s = new SubtaskModel($this->container);
- $p = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $subtaskModel = new SubtaskModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test1')));
- $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1)));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1)));
- $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1)));
+ $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1)));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']);
$this->assertEquals(0, $subtask['user_id']);
$this->assertEquals(1, $subtask['task_id']);
- $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $s->toggleStatus(1));
+ $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskModel->toggleStatus(1));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']);
$this->assertEquals(0, $subtask['user_id']);
$this->assertEquals(1, $subtask['task_id']);
- $this->assertEquals(SubtaskModel::STATUS_DONE, $s->toggleStatus(1));
+ $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskModel->toggleStatus(1));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']);
$this->assertEquals(0, $subtask['user_id']);
$this->assertEquals(1, $subtask['task_id']);
- $this->assertEquals(SubtaskModel::STATUS_TODO, $s->toggleStatus(1));
+ $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskModel->toggleStatus(1));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']);
$this->assertEquals(0, $subtask['user_id']);
@@ -184,17 +183,16 @@ class SubtaskTest extends Base
public function testToggleStatusWithSession()
{
- $tc = new TaskCreationModel($this->container);
- $s = new SubtaskModel($this->container);
- $p = new ProjectModel($this->container);
- $us = new UserSession($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $subtaskModel = new SubtaskModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test1')));
- $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1)));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1)));
- $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1)));
+ $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1)));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']);
$this->assertEquals(0, $subtask['user_id']);
@@ -203,25 +201,25 @@ class SubtaskTest extends Base
// Set the current logged user
$this->container['sessionStorage']->user = array('id' => 1);
- $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $s->toggleStatus(1));
+ $this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtaskModel->toggleStatus(1));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(SubtaskModel::STATUS_INPROGRESS, $subtask['status']);
$this->assertEquals(1, $subtask['user_id']);
$this->assertEquals(1, $subtask['task_id']);
- $this->assertEquals(SubtaskModel::STATUS_DONE, $s->toggleStatus(1));
+ $this->assertEquals(SubtaskModel::STATUS_DONE, $subtaskModel->toggleStatus(1));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(SubtaskModel::STATUS_DONE, $subtask['status']);
$this->assertEquals(1, $subtask['user_id']);
$this->assertEquals(1, $subtask['task_id']);
- $this->assertEquals(SubtaskModel::STATUS_TODO, $s->toggleStatus(1));
+ $this->assertEquals(SubtaskModel::STATUS_TODO, $subtaskModel->toggleStatus(1));
- $subtask = $s->getById(1);
+ $subtask = $subtaskModel->getById(1);
$this->assertNotEmpty($subtask);
$this->assertEquals(SubtaskModel::STATUS_TODO, $subtask['status']);
$this->assertEquals(1, $subtask['user_id']);
@@ -230,19 +228,19 @@ class SubtaskTest extends Base
public function testCloseAll()
{
- $tc = new TaskCreationModel($this->container);
- $s = new SubtaskModel($this->container);
- $p = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $subtaskModel = new SubtaskModel($this->container);
+ $projectModel = new ProjectModel($this->container);
- $this->assertEquals(1, $p->create(array('name' => 'test1')));
- $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1)));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1)));
- $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1)));
- $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1)));
+ $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1)));
+ $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1)));
- $this->assertTrue($s->closeAll(1));
+ $this->assertTrue($subtaskModel->closeAll(1));
- $subtasks = $s->getAll(1);
+ $subtasks = $subtaskModel->getAll(1);
$this->assertNotEmpty($subtasks);
foreach ($subtasks as $subtask) {
@@ -252,24 +250,24 @@ class SubtaskTest extends Base
public function testDuplicate()
{
- $tc = new TaskCreationModel($this->container);
- $s = new SubtaskModel($this->container);
- $p = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $subtaskModel = new SubtaskModel($this->container);
+ $projectModel = new ProjectModel($this->container);
// We create a project
- $this->assertEquals(1, $p->create(array('name' => 'test1')));
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
// We create 2 tasks
- $this->assertEquals(1, $tc->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1)));
- $this->assertEquals(2, $tc->create(array('title' => 'test 2', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 0)));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 1)));
+ $this->assertEquals(2, $taskCreationModel->create(array('title' => 'test 2', 'project_id' => 1, 'column_id' => 1, 'owner_id' => 0)));
// We create many subtasks for the first task
- $this->assertEquals(1, $s->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_estimated' => 5, 'time_spent' => 3, 'status' => 1, 'another_subtask' => 'on')));
- $this->assertEquals(2, $s->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => '', 'time_spent' => '', 'status' => 2, 'user_id' => 1)));
+ $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1, 'time_estimated' => 5, 'time_spent' => 3, 'status' => 1, 'another_subtask' => 'on')));
+ $this->assertEquals(2, $subtaskModel->create(array('title' => 'subtask #2', 'task_id' => 1, 'time_estimated' => '', 'time_spent' => '', 'status' => 2, 'user_id' => 1)));
// We duplicate our subtasks
- $this->assertTrue($s->duplicate(1, 2));
- $subtasks = $s->getAll(2);
+ $this->assertTrue($subtaskModel->duplicate(1, 2));
+ $subtasks = $subtaskModel->getAll(2);
$this->assertNotFalse($subtasks);
$this->assertNotEmpty($subtasks);
@@ -385,4 +383,18 @@ class SubtaskTest extends Base
$this->assertEquals(2, $task['time_spent']);
$this->assertEquals(3, $task['time_estimated']);
}
+
+ public function testGetProjectId()
+ {
+ $taskCreationModel = new TaskCreationModel($this->container);
+ $subtaskModel = new SubtaskModel($this->container);
+ $projectModel = new ProjectModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(1, $taskCreationModel->create(array('title' => 'test 1', 'project_id' => 1)));
+ $this->assertEquals(1, $subtaskModel->create(array('title' => 'subtask #1', 'task_id' => 1)));
+
+ $this->assertEquals(1, $subtaskModel->getProjectId(1));
+ $this->assertEquals(0, $subtaskModel->getProjectId(2));
+ }
}
diff --git a/tests/units/Model/TaskFileTest.php b/tests/units/Model/TaskFileModelTest.php
index 2faee95c..de12553f 100644
--- a/tests/units/Model/TaskFileTest.php
+++ b/tests/units/Model/TaskFileModelTest.php
@@ -6,7 +6,7 @@ use Kanboard\Model\TaskFileModel;
use Kanboard\Model\TaskCreationModel;
use Kanboard\Model\ProjectModel;
-class TaskFileTest extends Base
+class TaskFileModelTest extends Base
{
public function testCreation()
{
@@ -442,4 +442,17 @@ class TaskFileTest extends Base
$this->assertTrue($fileModel->removeAll(1));
}
+
+ public function testGetProjectId()
+ {
+ $projectModel = new ProjectModel($this->container);
+ $fileModel = new TaskFileModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'test')));
+ $this->assertEquals(1, $fileModel->create(1, 'test', '/tmp/foobar', 10));
+ $this->assertEquals(1, $fileModel->getProjectId(1));
+ $this->assertEquals(0, $fileModel->getProjectId(2));
+ }
}
diff --git a/tests/units/Model/TaskLinkModelTest.php b/tests/units/Model/TaskLinkModelTest.php
new file mode 100644
index 00000000..78590891
--- /dev/null
+++ b/tests/units/Model/TaskLinkModelTest.php
@@ -0,0 +1,211 @@
+<?php
+
+require_once __DIR__.'/../Base.php';
+
+use Kanboard\Model\TaskFinderModel;
+use Kanboard\Model\TaskLinkModel;
+use Kanboard\Model\TaskCreationModel;
+use Kanboard\Model\ProjectModel;
+
+class TaskLinkModelTest extends Base
+{
+ // Check postgres issue: "Cardinality violation: 7 ERROR: more than one row returned by a subquery used as an expression"
+ public function testGetTaskWithMultipleMilestoneLink()
+ {
+ $taskFinderModel = new TaskFinderModel($this->container);
+ $taskLinkModel = new TaskLinkModel($this->container);
+ $projectModel = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A')));
+ $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B')));
+ $this->assertEquals(3, $taskCreationModel->create(array('project_id' => 1, 'title' => 'C')));
+
+ $this->assertNotFalse($taskLinkModel->create(1, 2, 9));
+ $this->assertNotFalse($taskLinkModel->create(1, 3, 9));
+
+ $task = $taskFinderModel->getExtendedQuery()->findOne();
+ $this->assertNotEmpty($task);
+ }
+
+ public function testCreateTaskLinkWithNoOpposite()
+ {
+ $taskLinkModel = new TaskLinkModel($this->container);
+ $projectModel = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A')));
+ $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B')));
+ $this->assertEquals(1, $taskLinkModel->create(1, 2, 1));
+
+ $links = $taskLinkModel->getAll(1);
+ $this->assertNotEmpty($links);
+ $this->assertCount(1, $links);
+ $this->assertEquals('relates to', $links[0]['label']);
+ $this->assertEquals('B', $links[0]['title']);
+ $this->assertEquals(2, $links[0]['task_id']);
+ $this->assertEquals(1, $links[0]['is_active']);
+
+ $links = $taskLinkModel->getAll(2);
+ $this->assertNotEmpty($links);
+ $this->assertCount(1, $links);
+ $this->assertEquals('relates to', $links[0]['label']);
+ $this->assertEquals('A', $links[0]['title']);
+ $this->assertEquals(1, $links[0]['task_id']);
+ $this->assertEquals(1, $links[0]['is_active']);
+
+ $task_link = $taskLinkModel->getById(1);
+ $this->assertNotEmpty($task_link);
+ $this->assertEquals(1, $task_link['id']);
+ $this->assertEquals(1, $task_link['task_id']);
+ $this->assertEquals(2, $task_link['opposite_task_id']);
+ $this->assertEquals(1, $task_link['link_id']);
+
+ $opposite_task_link = $taskLinkModel->getOppositeTaskLink($task_link);
+ $this->assertNotEmpty($opposite_task_link);
+ $this->assertEquals(2, $opposite_task_link['id']);
+ $this->assertEquals(2, $opposite_task_link['task_id']);
+ $this->assertEquals(1, $opposite_task_link['opposite_task_id']);
+ $this->assertEquals(1, $opposite_task_link['link_id']);
+ }
+
+ public function testCreateTaskLinkWithOpposite()
+ {
+ $taskLinkModel = new TaskLinkModel($this->container);
+ $projectModel = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A')));
+ $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B')));
+ $this->assertEquals(1, $taskLinkModel->create(1, 2, 2));
+
+ $links = $taskLinkModel->getAll(1);
+ $this->assertNotEmpty($links);
+ $this->assertCount(1, $links);
+ $this->assertEquals('blocks', $links[0]['label']);
+ $this->assertEquals('B', $links[0]['title']);
+ $this->assertEquals(2, $links[0]['task_id']);
+ $this->assertEquals(1, $links[0]['is_active']);
+
+ $links = $taskLinkModel->getAll(2);
+ $this->assertNotEmpty($links);
+ $this->assertCount(1, $links);
+ $this->assertEquals('is blocked by', $links[0]['label']);
+ $this->assertEquals('A', $links[0]['title']);
+ $this->assertEquals(1, $links[0]['task_id']);
+ $this->assertEquals(1, $links[0]['is_active']);
+
+ $task_link = $taskLinkModel->getById(1);
+ $this->assertNotEmpty($task_link);
+ $this->assertEquals(1, $task_link['id']);
+ $this->assertEquals(1, $task_link['task_id']);
+ $this->assertEquals(2, $task_link['opposite_task_id']);
+ $this->assertEquals(2, $task_link['link_id']);
+
+ $opposite_task_link = $taskLinkModel->getOppositeTaskLink($task_link);
+ $this->assertNotEmpty($opposite_task_link);
+ $this->assertEquals(2, $opposite_task_link['id']);
+ $this->assertEquals(2, $opposite_task_link['task_id']);
+ $this->assertEquals(1, $opposite_task_link['opposite_task_id']);
+ $this->assertEquals(3, $opposite_task_link['link_id']);
+ }
+
+ public function testGroupByLabel()
+ {
+ $taskLinkModel = new TaskLinkModel($this->container);
+ $projectModel = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A')));
+ $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B')));
+ $this->assertEquals(3, $taskCreationModel->create(array('project_id' => 1, 'title' => 'C')));
+
+ $this->assertNotFalse($taskLinkModel->create(1, 2, 2));
+ $this->assertNotFalse($taskLinkModel->create(1, 3, 2));
+
+ $links = $taskLinkModel->getAllGroupedByLabel(1);
+ $this->assertCount(1, $links);
+ $this->assertArrayHasKey('blocks', $links);
+ $this->assertCount(2, $links['blocks']);
+ $this->assertEquals('test', $links['blocks'][0]['project_name']);
+ $this->assertEquals('Backlog', $links['blocks'][0]['column_title']);
+ $this->assertEquals('blocks', $links['blocks'][0]['label']);
+ }
+
+ public function testUpdate()
+ {
+ $taskLinkModel = new TaskLinkModel($this->container);
+ $projectModel = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test1')));
+ $this->assertEquals(2, $projectModel->create(array('name' => 'test2')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A')));
+ $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 2, 'title' => 'B')));
+ $this->assertEquals(3, $taskCreationModel->create(array('project_id' => 1, 'title' => 'C')));
+
+ $this->assertEquals(1, $taskLinkModel->create(1, 2, 5));
+ $this->assertTrue($taskLinkModel->update(1, 1, 3, 11));
+
+ $links = $taskLinkModel->getAll(1);
+ $this->assertNotEmpty($links);
+ $this->assertCount(1, $links);
+ $this->assertEquals('is fixed by', $links[0]['label']);
+ $this->assertEquals('C', $links[0]['title']);
+ $this->assertEquals(3, $links[0]['task_id']);
+
+ $links = $taskLinkModel->getAll(2);
+ $this->assertEmpty($links);
+
+ $links = $taskLinkModel->getAll(3);
+ $this->assertNotEmpty($links);
+ $this->assertCount(1, $links);
+ $this->assertEquals('fixes', $links[0]['label']);
+ $this->assertEquals('A', $links[0]['title']);
+ $this->assertEquals(1, $links[0]['task_id']);
+ }
+
+ public function testRemove()
+ {
+ $taskLinkModel = new TaskLinkModel($this->container);
+ $projectModel = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A')));
+ $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B')));
+ $this->assertEquals(1, $taskLinkModel->create(1, 2, 2));
+
+ $links = $taskLinkModel->getAll(1);
+ $this->assertNotEmpty($links);
+ $links = $taskLinkModel->getAll(2);
+ $this->assertNotEmpty($links);
+
+ $this->assertTrue($taskLinkModel->remove($links[0]['id']));
+
+ $links = $taskLinkModel->getAll(1);
+ $this->assertEmpty($links);
+ $links = $taskLinkModel->getAll(2);
+ $this->assertEmpty($links);
+ }
+
+ public function testGetProjectId()
+ {
+ $taskLinkModel = new TaskLinkModel($this->container);
+ $projectModel = new ProjectModel($this->container);
+ $taskCreationModel = new TaskCreationModel($this->container);
+
+ $this->assertEquals(1, $projectModel->create(array('name' => 'test')));
+ $this->assertEquals(1, $taskCreationModel->create(array('project_id' => 1, 'title' => 'A')));
+ $this->assertEquals(2, $taskCreationModel->create(array('project_id' => 1, 'title' => 'B')));
+ $this->assertEquals(1, $taskLinkModel->create(1, 2, 2));
+
+ $this->assertEquals(1, $taskLinkModel->getProjectId(1));
+ $this->assertEquals(0, $taskLinkModel->getProjectId(42));
+ }
+}
diff --git a/tests/units/Model/TaskLinkTest.php b/tests/units/Model/TaskLinkTest.php
deleted file mode 100644
index bc574731..00000000
--- a/tests/units/Model/TaskLinkTest.php
+++ /dev/null
@@ -1,196 +0,0 @@
-<?php
-
-require_once __DIR__.'/../Base.php';
-
-use Kanboard\Model\TaskFinderModel;
-use Kanboard\Model\TaskLinkModel;
-use Kanboard\Model\TaskCreationModel;
-use Kanboard\Model\ProjectModel;
-
-class TaskLinkTest extends Base
-{
- // Check postgres issue: "Cardinality violation: 7 ERROR: more than one row returned by a subquery used as an expression"
- public function testGetTaskWithMultipleMilestoneLink()
- {
- $tf = new TaskFinderModel($this->container);
- $tl = new TaskLinkModel($this->container);
- $p = new ProjectModel($this->container);
- $tc = new TaskCreationModel($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A')));
- $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B')));
- $this->assertEquals(3, $tc->create(array('project_id' => 1, 'title' => 'C')));
-
- $this->assertNotFalse($tl->create(1, 2, 9));
- $this->assertNotFalse($tl->create(1, 3, 9));
-
- $task = $tf->getExtendedQuery()->findOne();
- $this->assertNotEmpty($task);
- }
-
- public function testCreateTaskLinkWithNoOpposite()
- {
- $tl = new TaskLinkModel($this->container);
- $p = new ProjectModel($this->container);
- $tc = new TaskCreationModel($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A')));
- $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B')));
- $this->assertEquals(1, $tl->create(1, 2, 1));
-
- $links = $tl->getAll(1);
- $this->assertNotEmpty($links);
- $this->assertCount(1, $links);
- $this->assertEquals('relates to', $links[0]['label']);
- $this->assertEquals('B', $links[0]['title']);
- $this->assertEquals(2, $links[0]['task_id']);
- $this->assertEquals(1, $links[0]['is_active']);
-
- $links = $tl->getAll(2);
- $this->assertNotEmpty($links);
- $this->assertCount(1, $links);
- $this->assertEquals('relates to', $links[0]['label']);
- $this->assertEquals('A', $links[0]['title']);
- $this->assertEquals(1, $links[0]['task_id']);
- $this->assertEquals(1, $links[0]['is_active']);
-
- $task_link = $tl->getById(1);
- $this->assertNotEmpty($task_link);
- $this->assertEquals(1, $task_link['id']);
- $this->assertEquals(1, $task_link['task_id']);
- $this->assertEquals(2, $task_link['opposite_task_id']);
- $this->assertEquals(1, $task_link['link_id']);
-
- $opposite_task_link = $tl->getOppositeTaskLink($task_link);
- $this->assertNotEmpty($opposite_task_link);
- $this->assertEquals(2, $opposite_task_link['id']);
- $this->assertEquals(2, $opposite_task_link['task_id']);
- $this->assertEquals(1, $opposite_task_link['opposite_task_id']);
- $this->assertEquals(1, $opposite_task_link['link_id']);
- }
-
- public function testCreateTaskLinkWithOpposite()
- {
- $tl = new TaskLinkModel($this->container);
- $p = new ProjectModel($this->container);
- $tc = new TaskCreationModel($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A')));
- $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B')));
- $this->assertEquals(1, $tl->create(1, 2, 2));
-
- $links = $tl->getAll(1);
- $this->assertNotEmpty($links);
- $this->assertCount(1, $links);
- $this->assertEquals('blocks', $links[0]['label']);
- $this->assertEquals('B', $links[0]['title']);
- $this->assertEquals(2, $links[0]['task_id']);
- $this->assertEquals(1, $links[0]['is_active']);
-
- $links = $tl->getAll(2);
- $this->assertNotEmpty($links);
- $this->assertCount(1, $links);
- $this->assertEquals('is blocked by', $links[0]['label']);
- $this->assertEquals('A', $links[0]['title']);
- $this->assertEquals(1, $links[0]['task_id']);
- $this->assertEquals(1, $links[0]['is_active']);
-
- $task_link = $tl->getById(1);
- $this->assertNotEmpty($task_link);
- $this->assertEquals(1, $task_link['id']);
- $this->assertEquals(1, $task_link['task_id']);
- $this->assertEquals(2, $task_link['opposite_task_id']);
- $this->assertEquals(2, $task_link['link_id']);
-
- $opposite_task_link = $tl->getOppositeTaskLink($task_link);
- $this->assertNotEmpty($opposite_task_link);
- $this->assertEquals(2, $opposite_task_link['id']);
- $this->assertEquals(2, $opposite_task_link['task_id']);
- $this->assertEquals(1, $opposite_task_link['opposite_task_id']);
- $this->assertEquals(3, $opposite_task_link['link_id']);
- }
-
- public function testGroupByLabel()
- {
- $tl = new TaskLinkModel($this->container);
- $p = new ProjectModel($this->container);
- $tc = new TaskCreationModel($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
-
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A')));
- $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B')));
- $this->assertEquals(3, $tc->create(array('project_id' => 1, 'title' => 'C')));
-
- $this->assertNotFalse($tl->create(1, 2, 2));
- $this->assertNotFalse($tl->create(1, 3, 2));
-
- $links = $tl->getAllGroupedByLabel(1);
- $this->assertCount(1, $links);
- $this->assertArrayHasKey('blocks', $links);
- $this->assertCount(2, $links['blocks']);
- $this->assertEquals('test', $links['blocks'][0]['project_name']);
- $this->assertEquals('Backlog', $links['blocks'][0]['column_title']);
- $this->assertEquals('blocks', $links['blocks'][0]['label']);
- }
-
- public function testUpdate()
- {
- $tl = new TaskLinkModel($this->container);
- $p = new ProjectModel($this->container);
- $tc = new TaskCreationModel($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test1')));
- $this->assertEquals(2, $p->create(array('name' => 'test2')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A')));
- $this->assertEquals(2, $tc->create(array('project_id' => 2, 'title' => 'B')));
- $this->assertEquals(3, $tc->create(array('project_id' => 1, 'title' => 'C')));
-
- $this->assertEquals(1, $tl->create(1, 2, 5));
- $this->assertTrue($tl->update(1, 1, 3, 11));
-
- $links = $tl->getAll(1);
- $this->assertNotEmpty($links);
- $this->assertCount(1, $links);
- $this->assertEquals('is fixed by', $links[0]['label']);
- $this->assertEquals('C', $links[0]['title']);
- $this->assertEquals(3, $links[0]['task_id']);
-
- $links = $tl->getAll(2);
- $this->assertEmpty($links);
-
- $links = $tl->getAll(3);
- $this->assertNotEmpty($links);
- $this->assertCount(1, $links);
- $this->assertEquals('fixes', $links[0]['label']);
- $this->assertEquals('A', $links[0]['title']);
- $this->assertEquals(1, $links[0]['task_id']);
- }
-
- public function testRemove()
- {
- $tl = new TaskLinkModel($this->container);
- $p = new ProjectModel($this->container);
- $tc = new TaskCreationModel($this->container);
-
- $this->assertEquals(1, $p->create(array('name' => 'test')));
- $this->assertEquals(1, $tc->create(array('project_id' => 1, 'title' => 'A')));
- $this->assertEquals(2, $tc->create(array('project_id' => 1, 'title' => 'B')));
- $this->assertEquals(1, $tl->create(1, 2, 2));
-
- $links = $tl->getAll(1);
- $this->assertNotEmpty($links);
- $links = $tl->getAll(2);
- $this->assertNotEmpty($links);
-
- $this->assertTrue($tl->remove($links[0]['id']));
-
- $links = $tl->getAll(1);
- $this->assertEmpty($links);
- $links = $tl->getAll(2);
- $this->assertEmpty($links);
- }
-}
diff --git a/tests/units/Validator/ProjectValidatorTest.php b/tests/units/Validator/ProjectValidatorTest.php
index 07de6c25..e1e2f077 100644
--- a/tests/units/Validator/ProjectValidatorTest.php
+++ b/tests/units/Validator/ProjectValidatorTest.php
@@ -55,13 +55,19 @@ class ProjectValidatorTest extends Base
$r = $validator->validateModification(array('id' => 1, 'name' => 'test', 'identifier' => 'TEST1'));
$this->assertTrue($r[0]);
- $r = $validator->validateModification(array('id' => 1, 'name' => 'test', 'identifier' => 'test3'));
+ $r = $validator->validateModification(array('id' => 1, 'identifier' => 'test3'));
$this->assertTrue($r[0]);
- $r = $validator->validateModification(array('id' => 1, 'name' => 'test', 'identifier' => ''));
+ $r = $validator->validateModification(array('id' => 1, 'identifier' => ''));
$this->assertTrue($r[0]);
- $r = $validator->validateModification(array('id' => 1, 'name' => 'test', 'identifier' => 'TEST2'));
+ $r = $validator->validateModification(array('id' => 1, 'identifier' => 'TEST2'));
+ $this->assertFalse($r[0]);
+
+ $r = $validator->validateModification(array('id' => 1, 'name' => ''));
+ $this->assertFalse($r[0]);
+
+ $r = $validator->validateModification(array('id' => 1, 'name' => null));
$this->assertFalse($r[0]);
}
}