Add new API procedures for groups, roles and project permissions

This commit is contained in:
Frederic Guillot 2016-01-22 21:23:12 -05:00
parent f27bcec2d9
commit ad8fcf035a
26 changed files with 1122 additions and 266 deletions

View File

@ -6,6 +6,7 @@ New features:
* Forgot Password
* Add dropdown menu on each board column title to close all tasks
* Add Malay language
* Add new API procedures for groups, roles and project permissions
Improvements:

View File

@ -34,4 +34,14 @@ class App extends \Kanboard\Core\Base
{
return $this->color->getList();
}
public function getApplicationRoles()
{
return $this->role->getApplicationRoles();
}
public function getProjectRoles()
{
return $this->role->getProjectRoles();
}
}

View File

@ -23,7 +23,7 @@ class Auth extends Base
*/
public function checkCredentials($username, $password, $class, $method)
{
$this->container['dispatcher']->dispatch('app.bootstrap');
$this->dispatcher->dispatch('app.bootstrap');
if ($this->isUserAuthenticated($username, $password)) {
$this->checkProcedurePermission(true, $method);

View File

@ -32,14 +32,18 @@ class File extends \Kanboard\Core\Base
}
} catch (ObjectStorageException $e) {
$this->logger->error($e->getMessage());
return '';
}
return '';
}
public function createFile($project_id, $task_id, $filename, $blob)
{
return $this->file->uploadContent($project_id, $task_id, $filename, $blob);
try {
return $this->file->uploadContent($project_id, $task_id, $filename, $blob);
} catch (ObjectStorageException $e) {
$this->logger->error($e->getMessage());
return false;
}
}
public function removeFile($file_id)

49
app/Api/Group.php Normal file
View File

@ -0,0 +1,49 @@
<?php
namespace Kanboard\Api;
/**
* Group API controller
*
* @package api
* @author Frederic Guillot
*/
class Group extends \Kanboard\Core\Base
{
public function createGroup($name, $external_id = '')
{
return $this->group->create($name, $external_id);
}
public function updateGroup($group_id, $name = null, $external_id = null)
{
$values = array(
'id' => $group_id,
'name' => $name,
'external_id' => $external_id,
);
foreach ($values as $key => $value) {
if (is_null($value)) {
unset($values[$key]);
}
}
return $this->group->update($values);
}
public function removeGroup($group_id)
{
return $this->group->remove($group_id);
}
public function getGroup($group_id)
{
return $this->group->getById($group_id);
}
public function getAllGroups()
{
return $this->group->getAll();
}
}

32
app/Api/GroupMember.php Normal file
View File

@ -0,0 +1,32 @@
<?php
namespace Kanboard\Api;
/**
* Group Member API controller
*
* @package api
* @author Frederic Guillot
*/
class GroupMember extends \Kanboard\Core\Base
{
public function getGroupMembers($group_id)
{
return $this->groupMember->getMembers($group_id);
}
public function addGroupMember($group_id, $user_id)
{
return $this->groupMember->addUser($group_id, $user_id);
}
public function removeGroupMember($group_id, $user_id)
{
return $this->groupMember->removeUser($group_id, $user_id);
}
public function isGroupMember($group_id, $user_id)
{
return $this->groupMember->isMember($group_id, $user_id);
}
}

View File

@ -5,25 +5,68 @@ namespace Kanboard\Api;
use Kanboard\Core\Security\Role;
/**
* ProjectPermission API controller
* Project Permission API controller
*
* @package api
* @author Frederic Guillot
*/
class ProjectPermission extends \Kanboard\Core\Base
{
public function getMembers($project_id)
public function getProjectUsers($project_id)
{
return $this->projectUserRole->getAllUsers($project_id);
}
public function revokeUser($project_id, $user_id)
public function getAssignableUsers($project_id, $prepend_unassigned = false)
{
return $this->projectUserRole->getAssignableUsersList($project_id, $prepend_unassigned);
}
public function addProjectUser($project_id, $user_id, $role = Role::PROJECT_MEMBER)
{
return $this->projectUserRole->addUser($project_id, $user_id, $role);
}
public function addProjectGroup($project_id, $group_id, $role = Role::PROJECT_MEMBER)
{
return $this->projectGroupRole->addGroup($project_id, $group_id, $role);
}
public function removeProjectUser($project_id, $user_id)
{
return $this->projectUserRole->removeUser($project_id, $user_id);
}
public function removeProjectGroup($project_id, $group_id)
{
return $this->projectGroupRole->removeGroup($project_id, $group_id);
}
public function changeProjectUserRole($project_id, $user_id, $role)
{
return $this->projectUserRole->changeUserRole($project_id, $user_id, $role);
}
public function changeProjectGroupRole($project_id, $group_id, $role)
{
return $this->projectGroupRole->changeGroupRole($project_id, $group_id, $role);
}
// Deprecated
public function getMembers($project_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->projectUserRole->addUser($project_id, $user_id, Role::PROJECT_MEMBER);
return $this->addProjectUser($project_id, $user_id);
}
}

View File

@ -50,7 +50,7 @@ class Role
}
/**
* Get application roles
* Get role name
*
* @access public
* @param string $role

View File

@ -229,3 +229,63 @@ Response example:
}
}
```
### getApplicationRoles
- Purpose: **Get the application roles**
- Parameters: none
- Result: **Dictionary of role => role_name**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getApplicationRoles",
"id": 317154243
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 317154243,
"result": {
"app-admin": "Administrator",
"app-manager": "Manager",
"app-user": "User"
}
}
```
### getProjectRoles
- Purpose: **Get the project roles**
- Parameters: none
- Result: **Dictionary of role => role_name**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getProjectRoles",
"id": 8981960
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 8981960,
"result": {
"project-manager": "Project Manager",
"project-member": "Project Member",
"project-viewer": "Project Viewer"
}
}
```

View File

@ -0,0 +1,152 @@
Group Member API Procedures
===========================
### getGroupMembers
- Purpose: **Get all members of a group**
- Parameters:
- **group_id** (integer, required)
- Result on success: **List of users**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getGroupMembers",
"id": 1987176726,
"params": [
"1"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1987176726,
"result": [
{
"group_id": "1",
"user_id": "1",
"id": "1",
"username": "admin",
"is_ldap_user": "0",
"name": null,
"email": null,
"notifications_enabled": "0",
"timezone": null,
"language": null,
"disable_login_form": "0",
"notifications_filter": "4",
"nb_failed_login": "0",
"lock_expiration_date": "0",
"is_project_admin": "0",
"gitlab_id": null,
"role": "app-admin"
}
]
}
```
### addGroupMember
- Purpose: **Add a user to a group**
- Parameters:
- **group_id** (integer, required)
- **user_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "addGroupMember",
"id": 1589058273,
"params": [
1,
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1589058273,
"result": true
}
```
### removeGroupMember
- Purpose: **Remove a user from a group**
- Parameters:
- **group_id** (integer, required)
- **user_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "removeGroupMember",
"id": 1730416406,
"params": [
1,
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1730416406,
"result": true
}
```
### isGroupMember
- Purpose: **Check if a user is member of a group**
- Parameters:
- **group_id** (integer, required)
- **user_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "isGroupMember",
"id": 1052800865,
"params": [
1,
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1052800865,
"result": false
}
```

View File

@ -0,0 +1,174 @@
Group API Procedures
====================
### createGroup
- Purpose: **Create a new group**
- Parameters:
- **name** (string, required)
- **external_id** (string, optional)
- Result on success: **link_id**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "createGroup",
"id": 1416806551,
"params": [
"My Group B",
"1234"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1416806551,
"result": 2
}
```
### updateGroup
- Purpose: **Update a group**
- Parameters:
- **group_id** (integer, required)
- **name** (string, optional)
- **external_id** (string, optional)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "updateGroup",
"id": 866078030,
"params": {
"group_id": "1",
"name": "ABC",
"external_id": "something"
}
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 866078030,
"result": true
}
```
### removeGroup
- Purpose: **Remove a group**
- Parameters:
- **group_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "removeGroup",
"id": 566000661,
"params": [
"1"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 566000661,
"result": true
}
```
### getGroup
- Purpose: **Get one group**
- Parameters:
- **group_id** (integer, required)
- Result on success: **Group dictionary**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getGroup",
"id": 1968647622,
"params": [
"1"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1968647622,
"result": {
"id": "1",
"external_id": "",
"name": "My Group A"
}
}
```
### getAllGroups
- Purpose: **Get all groups**
- Parameters: none
- Result on success: **list of groups**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getAllGroups",
"id": 546070742
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 546070742,
"result": [
{
"id": "1",
"external_id": "",
"name": "My Group A"
},
{
"id": "2",
"external_id": "1234",
"name": "My Group B"
}
]
}
```

View File

@ -48,16 +48,19 @@ Usage
- [Authentication](api-authentication.markdown)
- [Examples](api-examples.markdown)
- [Application Procedures](api-application-procedures.markdown)
- [Project Procedures](api-project-procedures.markdown)
- [Board Procedures](api-board-procedures.markdown)
- [Swimlane Procedures](api-swimlane-procedures.markdown)
- [Category Procedures](api-category-procedures.markdown)
- [Automatic Action Procedures](api-action-procedures.markdown)
- [Task Procedures](api-task-procedures.markdown)
- [Subtask Procedures](api-subtask-procedures.markdown)
- [File Procedures](api-file-procedures.markdown)
- [Link Procedures](api-link-procedures.markdown)
- [Comment Procedures](api-comment-procedures.markdown)
- [User Procedures](api-user-procedures.markdown)
- [User API Access Procedures](api-me-procedures.markdown)
- [Application](api-application-procedures.markdown)
- [Projects](api-project-procedures.markdown)
- [Project Permissions](api-project-permission-procedures.markdown)
- [Boards](api-board-procedures.markdown)
- [Swimlanes](api-swimlane-procedures.markdown)
- [Categories](api-category-procedures.markdown)
- [Automatic Actions](api-action-procedures.markdown)
- [Tasks](api-task-procedures.markdown)
- [Subtasks](api-subtask-procedures.markdown)
- [Files](api-file-procedures.markdown)
- [Links](api-link-procedures.markdown)
- [Comments](api-comment-procedures.markdown)
- [Users](api-user-procedures.markdown)
- [Groups](api-group-procedures.markdown)
- [Group Members](api-group-member-procedures.markdown)
- [Me](api-me-procedures.markdown)

View File

@ -0,0 +1,274 @@
Project Permission API Procedures
=================================
### getProjectUsers
- Purpose: **Get all members of a project**
- Parameters:
- **project_id** (integer, required)
- Result on success: **Dictionary of user_id => user name**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getProjectUsers",
"id": 1601016721,
"params": [
"1"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1601016721,
"result": {
"1": "admin"
}
}
```
### getAssignableUsers
- Purpose: **Get users that can be assigned to a task for a project** (all members except viewers)
- Parameters:
- **project_id** (integer, required)
- **prepend_unassigned** (boolean, optional, default is false)
- Result on success: **Dictionary of user_id => user name**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getAssignableUsers",
"id": 658294870,
"params": [
"1"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 658294870,
"result": {
"1": "admin"
}
}
```
### addProjectUser
- Purpose: **Grant access to a project for a user**
- Parameters:
- **project_id** (integer, required)
- **user_id** (integer, required)
- **role** (string, optional)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "addProjectUser",
"id": 1294688355,
"params": [
"1",
"1",
"project-viewer"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1294688355,
"result": true
}
```
### addProjectGroup
- Purpose: **Grant access to a project for a group**
- Parameters:
- **project_id** (integer, required)
- **group_id** (integer, required)
- **role** (string, optional)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "addProjectGroup",
"id": 1694959089,
"params": [
"1",
"1"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1694959089,
"result": true
}
```
### removeProjectUser
- Purpose: **Revoke user access to a project**
- Parameters:
- **project_id** (integer, required)
- **user_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "removeProjectUser",
"id": 645233805,
"params": [
1,
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 645233805,
"result": true
}
```
### removeProjectGroup
- Purpose: **Revoke group access to a project**
- Parameters:
- **project_id** (integer, required)
- **group_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "removeProjectGroup",
"id": 557146966,
"params": [
1,
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 557146966,
"result": true
}
```
### changeProjectUserRole
- Purpose: **Change role of a user for a project**
- Parameters:
- **project_id** (integer, required)
- **user_id** (integer, required)
- **role** (string, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "changeProjectUserRole",
"id": 193473170,
"params": [
"1",
"1",
"project-viewer"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 193473170,
"result": true
}
```
### changeProjectGroupRole
- Purpose: **Change role of a group for a project**
- Parameters:
- **project_id** (integer, required)
- **group_id** (integer, required)
- **role** (string, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "changeProjectGroupRole",
"id": 2114673298,
"params": [
"1",
"1",
"project-viewer"
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 2114673298,
"result": true
}
```

View File

@ -409,104 +409,3 @@ Request example:
]
}
```
### getMembers
- Purpose: **Get members of a project**
- Parameters:
- **project_id** (integer, required)
- Result on success: Key/value pair of user_id and username
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "getMembers",
"id": 1944388643,
"params": [
1
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 1944388643,
"result": {
"1": "user1",
"2": "user2",
"3": "user3"
}
}
```
### revokeUser
- Purpose: **Revoke user access for a given project**
- Parameters:
- **project_id** (integer, required)
- **user_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "revokeUser",
"id": 251218350,
"params": [
1,
2
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 251218350,
"result": true
}
```
### allowUser
- Purpose: **Grant user access for a given project**
- Parameters:
- **project_id** (integer, required)
- **user_id** (integer, required)
- Result on success: **true**
- Result on failure: **false**
Request example:
```json
{
"jsonrpc": "2.0",
"method": "allowUser",
"id": 2111451404,
"params": [
1,
2
]
}
```
Response example:
```json
{
"jsonrpc": "2.0",
"id": 2111451404,
"result": true
}
```

View File

@ -1,7 +1,7 @@
How to run units and functional tests?
======================================
Automated tests
===============
[PHPUnit](https://phpunit.de/) is used to run automatic tests on Kanboard.
[PHPUnit](https://phpunit.de/) is used to run automated tests on Kanboard.
You can run tests across different databases (Sqlite, Mysql and Postgresql) to be sure that the result is the same everywhere.
@ -9,31 +9,18 @@ Requirements
------------
- Linux/Unix machine
- PHP command line
- PHP cli
- PHPUnit installed
- Mysql and Postgresql (optional)
Install the latest version of PHPUnit
-------------------------------------
Unit Tests
----------
Simply download the PHPUnit PHAR et copy the file somewhere in your `$PATH`:
```bash
wget https://phar.phpunit.de/phpunit.phar
chmod +x phpunit.phar
sudo mv phpunit.phar /usr/local/bin/phpunit
phpunit --version
PHPUnit 4.2.6 by Sebastian Bergmann.
```
Running unit tests
------------------
### Testing with Sqlite
### Test with Sqlite
Sqlite tests use a in-memory database, nothing is written on the file system.
The config file is `tests/units.sqlite.xml`.
The PHPUnit config file is `tests/units.sqlite.xml`.
From your Kanboard directory, run the command `phpunit -c tests/units.sqlite.xml`.
Example:
@ -41,21 +28,26 @@ Example:
```bash
phpunit -c tests/units.sqlite.xml
PHPUnit 4.2.6 by Sebastian Bergmann.
PHPUnit 5.0.0 by Sebastian Bergmann and contributors.
Configuration read from /Volumes/Devel/apps/kanboard/tests/units.sqlite.xml
............................................................... 63 / 649 ( 9%)
............................................................... 126 / 649 ( 19%)
............................................................... 189 / 649 ( 29%)
............................................................... 252 / 649 ( 38%)
............................................................... 315 / 649 ( 48%)
............................................................... 378 / 649 ( 58%)
............................................................... 441 / 649 ( 67%)
............................................................... 504 / 649 ( 77%)
............................................................... 567 / 649 ( 87%)
............................................................... 630 / 649 ( 97%)
................... 649 / 649 (100%)
................................................................. 65 / 74 ( 87%)
.........
Time: 1.22 minutes, Memory: 151.25Mb
Time: 9.05 seconds, Memory: 17.75Mb
OK (74 tests, 6145 assertions)
OK (649 tests, 43595 assertions)
```
**NOTE:** PHPUnit is already included in the Vagrant environment
### Testing with Mysql
### Test with Mysql
You must have Mysql or MariaDb installed on localhost.
@ -68,27 +60,10 @@ By default, those credentials are used:
For each execution the database is dropped and created again.
The config file is `tests/units.mysql.xml`.
The PHPUnit config file is `tests/units.mysql.xml`.
From your Kanboard directory, run the command `phpunit -c tests/units.mysql.xml`.
Example:
```bash
phpunit -c tests/units.mysql.xml
PHPUnit 4.2.6 by Sebastian Bergmann.
Configuration read from /Volumes/Devel/apps/kanboard/tests/units.mysql.xml
................................................................. 65 / 74 ( 87%)
.........
Time: 49.77 seconds, Memory: 17.50Mb
OK (74 tests, 6145 assertions)
```
### Testing with Postgresql
### Test with Postgresql
You must have Postgresql installed on localhost.
@ -100,37 +75,20 @@ By default, those credentials are used:
- Database: **kanboard_unit_test**
Be sure to allow the user `postgres` to create and drop databases.
For each execution the database is dropped and created again.
The database is recreated for each execution.
The config file is `tests/units.postgres.xml`.
The PHPUnit config file is `tests/units.postgres.xml`.
From your Kanboard directory, run the command `phpunit -c tests/units.postgres.xml`.
Example:
```bash
phpunit -c tests/units.postgres.xml
PHPUnit 4.2.6 by Sebastian Bergmann.
Configuration read from /Volumes/Devel/apps/kanboard/tests/units.postgres.xml
................................................................. 65 / 74 ( 87%)
.........
Time: 52.66 seconds, Memory: 17.50Mb
OK (74 tests, 6145 assertions)
```
Running functionals tests
-------------------------
Integration Tests
-----------------
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`.
So a local instance of Kanboard is necessary and must listen on `http://localhost:8000/`.
Don't forget that all data will be removed/altered by the test suite.
All data will be removed/altered by the test suite.
Moreover the script will reset and set a new API key.
1. Start a local instance of Kanboard `php -S 127.0.0.1:8000`
@ -138,27 +96,27 @@ Moreover the script will reset and set a new API key.
The same method as above is used to run tests across different databases:
- Sqlite: `phpunit -c tests/functionals.sqlite.xml`
- Mysql: `phpunit -c tests/functionals.mysql.xml`
- Postgresql: `phpunit -c tests/functionals.postgres.xml`
- Sqlite: `phpunit -c tests/integration.sqlite.xml`
- Mysql: `phpunit -c tests/integration.mysql.xml`
- Postgresql: `phpunit -c tests/integration.postgres.xml`
Example:
```bash
phpunit -c tests/functionals.sqlite.xml
phpunit -c tests/integration.sqlite.xml
PHPUnit 4.2.6 by Sebastian Bergmann.
PHPUnit 5.0.0 by Sebastian Bergmann and contributors.
Configuration read from /Volumes/Devel/apps/kanboard/tests/functionals.sqlite.xml
............................................................... 63 / 135 ( 46%)
............................................................... 126 / 135 ( 93%)
......... 135 / 135 (100%)
..........................................
Time: 1.18 minutes, Memory: 14.75Mb
Time: 1.72 seconds, Memory: 4.25Mb
OK (42 tests, 160 assertions)
OK (135 tests, 526 assertions)
```
Continuous Integration with Travis-ci
Continuous Integration with Travis-CI
-------------------------------------
After each commit pushed on the main repository, unit tests are executed across 5 different versions of PHP:
@ -171,6 +129,4 @@ After each commit pushed on the main repository, unit tests are executed across
Each version of PHP is tested against the 3 supported database: Sqlite, Mysql and Postgresql.
That mean we run 15 jobs each time the repository is updated. The execution time is around 25 minutes.
The Travis config file `.travis.yml` is located on the root directory of Kanboard.

View File

@ -19,6 +19,8 @@ use Kanboard\Api\Swimlane;
use Kanboard\Api\Task;
use Kanboard\Api\TaskLink;
use Kanboard\Api\User;
use Kanboard\Api\Group;
use Kanboard\Api\GroupMember;
$server = new Server;
$server->setAuthenticationHeader(API_AUTHENTICATION_HEADER);
@ -39,5 +41,7 @@ $server->attach(new Swimlane($container));
$server->attach(new Task($container));
$server->attach(new TaskLink($container));
$server->attach(new User($container));
$server->attach(new Group($container));
$server->attach(new GroupMember($container));
echo $server->execute();

View File

@ -1,7 +1,7 @@
<phpunit stopOnError="true" stopOnFailure="true" colors="true">
<testsuites>
<testsuite name="Kanboard">
<directory>functionals</directory>
<directory>integration</directory>
</testsuite>
</testsuites>
<php>

View File

@ -1,7 +1,7 @@
<phpunit stopOnError="true" stopOnFailure="true" colors="true">
<testsuites>
<testsuite name="Kanboard">
<directory>functionals</directory>
<directory>integration</directory>
</testsuite>
</testsuites>
<php>

View File

@ -1,7 +1,7 @@
<phpunit stopOnError="true" stopOnFailure="true" colors="true">
<testsuites>
<testsuite name="Kanboard">
<directory>functionals</directory>
<directory>integration</directory>
</testsuite>
</testsuites>
<php>

View File

@ -45,16 +45,6 @@ class Api extends PHPUnit_Framework_TestCase
return $tasks[0]['id'];
}
public function testGetTimezone()
{
$this->assertEquals('Europe/Paris', $this->client->getTimezone());
}
public function testGetVersion()
{
$this->assertEquals('master', $this->client->getVersion());
}
public function testRemoveAll()
{
$projects = $this->client->getAllProjects();

View File

@ -0,0 +1,34 @@
<?php
require_once __DIR__.'/Base.php';
class AppTest extends Base
{
public function testGetTimezone()
{
$this->assertEquals('UTC', $this->app->getTimezone());
}
public function testGetVersion()
{
$this->assertEquals('master', $this->app->getVersion());
}
public function testGetApplicationRoles()
{
$roles = $this->app->getApplicationRoles();
$this->assertCount(3, $roles);
$this->assertEquals('Administrator', $roles['app-admin']);
$this->assertEquals('Manager', $roles['app-manager']);
$this->assertEquals('User', $roles['app-user']);
}
public function testGetProjectRoles()
{
$roles = $this->app->getProjectRoles();
$this->assertCount(3, $roles);
$this->assertEquals('Project Manager', $roles['project-manager']);
$this->assertEquals('Project Member', $roles['project-member']);
$this->assertEquals('Project Viewer', $roles['project-viewer']);
}
}

View File

@ -0,0 +1,62 @@
<?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->debug = true;
$this->admin = new JsonRPC\Client(API_URL);
$this->admin->authentication('admin', 'admin');
// $this->admin->debug = true;
$this->user = new JsonRPC\Client(API_URL);
$this->user->authentication('user', 'password');
// $this->user->debug = true;
}
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'];
}
}

View File

@ -0,0 +1,39 @@
<?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 testRemove()
{
$groupId = $this->getGroupId();
$this->assertTrue($this->app->removeGroupMember($groupId, 1));
$this->assertFalse($this->app->isGroupMember($groupId, 1));
}
}

View File

@ -0,0 +1,48 @@
<?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());
}
}

View File

@ -1,51 +1,9 @@
<?php
require_once __DIR__.'/../../vendor/autoload.php';
require_once __DIR__.'/Base.php';
class UserApi extends PHPUnit_Framework_TestCase
class MeTest extends Base
{
private $app = null;
private $admin = null;
private $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->debug = true;
$this->admin = new JsonRPC\Client(API_URL);
$this->admin->authentication('admin', 'admin');
// $this->admin->debug = true;
$this->user = new JsonRPC\Client(API_URL);
$this->user->authentication('user', 'password');
// $this->user->debug = true;
}
public function testCreateProject()
{
$this->assertEquals(1, $this->app->createProject('team project'));

View File

@ -0,0 +1,64 @@
<?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));
}
}