mirror of https://github.com/MISP/MISP
Merge branch '3.x' into feature/3.x_HttpTool
commit
3927609cb6
|
@ -158,15 +158,15 @@ class ACLComponent extends Component
|
||||||
'view' => ['perm_admin'],
|
'view' => ['perm_admin'],
|
||||||
],
|
],
|
||||||
'Organisations' => [
|
'Organisations' => [
|
||||||
'add' => ['perm_admin'],
|
'add' => ['perm_site_admin'],
|
||||||
'delete' => ['perm_admin'],
|
'delete' => ['perm_site_admin'],
|
||||||
'edit' => ['perm_admin'],
|
'edit' => ['perm_site_admin', 'perm_admin'],
|
||||||
'filtering' => ['*'],
|
'filtering' => ['*'],
|
||||||
'index' => ['*'],
|
'index' => ['*'],
|
||||||
'tag' => ['perm_tagger'],
|
'tag' => ['AND' => ['perm_tagger', 'OR' => ['perm_site_admin', 'perm_admin']]],
|
||||||
'untag' => ['perm_tagger'],
|
'untag' => ['AND' => ['perm_tagger', 'OR' => ['perm_site_admin', 'perm_admin']]],
|
||||||
'view' => ['*'],
|
'view' => ['*'],
|
||||||
'viewTags' => ['*']
|
'viewTags' => ['*'],
|
||||||
],
|
],
|
||||||
'Outbox' => [
|
'Outbox' => [
|
||||||
'createEntry' => ['perm_admin'],
|
'createEntry' => ['perm_admin'],
|
||||||
|
@ -506,7 +506,7 @@ class ACLComponent extends Component
|
||||||
// we have to be in a publically allowed scope otherwise the Auth component will kick us out anyway.
|
// we have to be in a publically allowed scope otherwise the Auth component will kick us out anyway.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!empty($this->user->Role->perm_admin)) {
|
if (!empty($this->user->Role->perm_site_admin)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//$this->__checkLoggedActions($user, $controller, $action);
|
//$this->__checkLoggedActions($user, $controller, $action);
|
||||||
|
@ -700,7 +700,7 @@ class ACLComponent extends Component
|
||||||
}
|
}
|
||||||
foreach ($this->aclList as $controller => $actions) {
|
foreach ($this->aclList as $controller => $actions) {
|
||||||
foreach ($actions as $action => $permissions) {
|
foreach ($actions as $action => $permissions) {
|
||||||
if ($role['perm_admin']) {
|
if ($role['perm_site_admin']) {
|
||||||
$results = $this->__formatControllerAction($results, $controller, $action, $url_mode);
|
$results = $this->__formatControllerAction($results, $controller, $action, $url_mode);
|
||||||
} elseif (in_array('*', $permissions)) {
|
} elseif (in_array('*', $permissions)) {
|
||||||
$results = $this->__formatControllerAction($results, $controller, $action, $url_mode);
|
$results = $this->__formatControllerAction($results, $controller, $action, $url_mode);
|
||||||
|
|
|
@ -424,7 +424,7 @@ class CRUDComponent extends Component
|
||||||
throw new NotFoundException(__('Could not save {0} due to the input failing to meet expectations. Your input is bad and you should feel bad.', $this->ObjectAlias));
|
throw new NotFoundException(__('Could not save {0} due to the input failing to meet expectations. Your input is bad and you should feel bad.', $this->ObjectAlias));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$savedData = $this->Table->save($data);
|
$savedData = $this->Table->save($data); // FIXME catch exceptions thrown by DB constraints, as otherwise we get 500 Internal Server Errors
|
||||||
if ($savedData !== false) {
|
if ($savedData !== false) {
|
||||||
if (isset($params['afterSave'])) {
|
if (isset($params['afterSave'])) {
|
||||||
$params['afterSave']($data);
|
$params['afterSave']($data);
|
||||||
|
@ -458,7 +458,7 @@ class CRUDComponent extends Component
|
||||||
);
|
);
|
||||||
if ($this->Controller->ParamHandler->isRest()) {
|
if ($this->Controller->ParamHandler->isRest()) {
|
||||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($message, 'json');
|
$this->Controller->restResponsePayload = $this->RestResponse->viewData($message, 'json');
|
||||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
} elseif ($this->Controller->ParamHandler->isAjax()) {
|
||||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'add', $data, $message, $validationErrors);
|
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'add', $data, $message, $validationErrors);
|
||||||
} else {
|
} else {
|
||||||
$this->Controller->Flash->error($message);
|
$this->Controller->Flash->error($message);
|
||||||
|
@ -715,32 +715,16 @@ class CRUDComponent extends Component
|
||||||
$params['afterSave']($data);
|
$params['afterSave']($data);
|
||||||
}
|
}
|
||||||
$message = __('{0} `{1}` updated.', $this->ObjectAlias, $savedData->{$this->Table->getDisplayField()});
|
$message = __('{0} `{1}` updated.', $this->ObjectAlias, $savedData->{$this->Table->getDisplayField()});
|
||||||
if ($this->Controller->ParamHandler->isRest()) {
|
$this->setResponseForController('edit', true, $message, $data, null, $params);
|
||||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($savedData, 'json');
|
|
||||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
|
||||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxSuccessResponse($this->ObjectAlias, 'edit', $savedData, $message);
|
|
||||||
} else {
|
|
||||||
$this->Controller->Flash->success($message);
|
|
||||||
if (empty($params['redirect'])) {
|
|
||||||
$this->Controller->redirect(['action' => 'view', $id]);
|
|
||||||
} else {
|
|
||||||
$this->Controller->redirect($params['redirect']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$validationErrors = $data->getErrors();
|
$validationErrors = $data->getErrors();
|
||||||
$validationMessage = $this->prepareValidationError($data);
|
$validationMessage = $this->prepareValidationMessage($validationErrors);
|
||||||
$message = __(
|
$message = __(
|
||||||
'{0} could not be modified.{1}',
|
'{0} could not be modified.{1}',
|
||||||
$this->ObjectAlias,
|
$this->ObjectAlias,
|
||||||
empty($validationMessage) ? '' : PHP_EOL . __('Reason: {0}', $validationMessage)
|
empty($validationMessage) ? '' : PHP_EOL . __('Reason: {0}', $validationMessage)
|
||||||
);
|
);
|
||||||
if ($this->Controller->ParamHandler->isRest()) {
|
$this->setResponseForController('edit', false, $message, $data, null, $params);
|
||||||
} else if ($this->Controller->ParamHandler->isAjax()) {
|
|
||||||
$this->Controller->ajaxResponsePayload = $this->RestResponse->ajaxFailResponse($this->ObjectAlias, 'edit', $data, $message, $validationErrors);
|
|
||||||
} else {
|
|
||||||
$this->Controller->Flash->error($message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!empty($params['fields'])) {
|
if (!empty($params['fields'])) {
|
||||||
|
@ -1187,6 +1171,7 @@ class CRUDComponent extends Component
|
||||||
} else {
|
} else {
|
||||||
if ($this->Controller->ParamHandler->isRest()) {
|
if ($this->Controller->ParamHandler->isRest()) {
|
||||||
$data = $data ?? $message;
|
$data = $data ?? $message;
|
||||||
|
// FIXME show error in the JSON response, and return with an HTTP error code
|
||||||
$this->Controller->restResponsePayload = $this->RestResponse->viewData($data, 'json');
|
$this->Controller->restResponsePayload = $this->RestResponse->viewData($data, 'json');
|
||||||
} elseif ($this->Controller->ParamHandler->isAjax()) {
|
} elseif ($this->Controller->ParamHandler->isAjax()) {
|
||||||
if (!empty($additionalData['redirect'])) { // If a redirection occurs, we need to make sure the flash message gets displayed
|
if (!empty($additionalData['redirect'])) { // If a redirection occurs, we need to make sure the flash message gets displayed
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
<?php
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Controller\AppController;
|
use App\Model\Entity\Organisation;
|
||||||
use Cake\Utility\Hash;
|
|
||||||
use Cake\Utility\Text;
|
|
||||||
use Cake\Database\Expression\QueryExpression;
|
|
||||||
use Cake\Http\Exception\NotFoundException;
|
|
||||||
use Cake\Http\Exception\MethodNotAllowedException;
|
use Cake\Http\Exception\MethodNotAllowedException;
|
||||||
use Cake\Http\Exception\ForbiddenException;
|
|
||||||
|
|
||||||
class OrganisationsController extends AppController
|
class OrganisationsController extends AppController
|
||||||
{
|
{
|
||||||
|
|
||||||
public $quickFilterFields = [['name' => true], 'uuid', 'nationality', 'sector', 'type', 'url', 'local'];
|
public $quickFilterFields = [['name' => true], 'uuid', 'nationality', 'sector', 'type', 'url', 'local'];
|
||||||
public $filterFields = [
|
public $filterFields = [
|
||||||
'name', 'uuid', 'nationality', 'sector', 'type', 'url', 'local'
|
'name', 'uuid', 'nationality', 'sector', 'type', 'url', 'local',
|
||||||
];
|
];
|
||||||
public $containFields = [];
|
public $containFields = [];
|
||||||
public $statisticsFields = ['nationality', 'sector'];
|
public $statisticsFields = ['nationality', 'sector'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the list of organizations.
|
||||||
|
*
|
||||||
|
* @return \Cake\Http\Response|null
|
||||||
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$customContextFilters = [
|
$customContextFilters = [
|
||||||
[
|
[
|
||||||
'label' => __('Local orgs'),
|
'label' => __('Local orgs'),
|
||||||
'filterCondition' => ['local' => 1]
|
'filterCondition' => ['local' => 1],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'label' => __('External orgs'),
|
'label' => __('External orgs'),
|
||||||
'filterCondition' => ['local' => 0]
|
'filterCondition' => ['local' => 0],
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
$loggedUserOrganisationNationality = $this->ACL->getUser()['Organisation']['nationality'];
|
$loggedUserOrganisationNationality = $this->ACL->getUser()['Organisation']['nationality'];
|
||||||
if (!empty($loggedUserOrganisationNationality)) {
|
if (!empty($loggedUserOrganisationNationality)) {
|
||||||
|
@ -38,54 +38,79 @@ class OrganisationsController extends AppController
|
||||||
'label' => __('Country: {0}', $loggedUserOrganisationNationality),
|
'label' => __('Country: {0}', $loggedUserOrganisationNationality),
|
||||||
'filterCondition' => [
|
'filterCondition' => [
|
||||||
'nationality' => $loggedUserOrganisationNationality,
|
'nationality' => $loggedUserOrganisationNationality,
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->CRUD->index([
|
$this->CRUD->index(
|
||||||
'filters' => $this->filterFields,
|
[
|
||||||
'quickFilters' => $this->quickFilterFields,
|
'filters' => $this->filterFields,
|
||||||
'quickFilterForMetaField' => ['enabled' => true, 'wildcard_search' => true],
|
'quickFilters' => $this->quickFilterFields,
|
||||||
'contextFilters' => [
|
'quickFilterForMetaField' => ['enabled' => true, 'wildcard_search' => true],
|
||||||
'custom' => $customContextFilters,
|
'contextFilters' => [
|
||||||
],
|
'custom' => $customContextFilters,
|
||||||
'afterFind' => function($entity) {
|
],
|
||||||
$entity->setVirtual(['user_count']);
|
'afterFind' => function ($entity) {
|
||||||
return $entity;
|
$entity->setVirtual(['user_count']);
|
||||||
},
|
|
||||||
'contain' => $this->containFields,
|
return $entity;
|
||||||
'statisticsFields' => $this->statisticsFields,
|
},
|
||||||
]);
|
'contain' => $this->containFields,
|
||||||
|
'statisticsFields' => $this->statisticsFields,
|
||||||
|
]
|
||||||
|
);
|
||||||
$responsePayload = $this->CRUD->getResponsePayload();
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
if (!empty($responsePayload)) {
|
if (!empty($responsePayload)) {
|
||||||
return $responsePayload;
|
return $responsePayload;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filtering function.
|
||||||
|
*/
|
||||||
public function filtering()
|
public function filtering()
|
||||||
{
|
{
|
||||||
$this->CRUD->filtering();
|
$this->CRUD->filtering();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new organization.
|
||||||
|
*
|
||||||
|
* @return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
|
||||||
|
*/
|
||||||
public function add()
|
public function add()
|
||||||
{
|
{
|
||||||
$this->CRUD->add();
|
$params = [
|
||||||
|
'beforeSave' => function (Organisation $org) {
|
||||||
|
$org['created_by'] = $this->ACL->getUser()['id'];
|
||||||
|
|
||||||
|
return $org;
|
||||||
|
},
|
||||||
|
];
|
||||||
|
$this->CRUD->add($params);
|
||||||
$responsePayload = $this->CRUD->getResponsePayload();
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
if (!empty($responsePayload)) {
|
if (!empty($responsePayload)) {
|
||||||
return $responsePayload;
|
return $responsePayload;
|
||||||
}
|
}
|
||||||
$this->set('countries',
|
$this->set(
|
||||||
|
'countries',
|
||||||
array_merge(
|
array_merge(
|
||||||
[
|
[
|
||||||
'' => __('Not specified')
|
'' => __('Not specified'),
|
||||||
],
|
],
|
||||||
//$this->_arrayToValuesIndexArray($this->Organisation->getCountries())
|
//$this->_arrayToValuesIndexArray($this->Organisation->getCountries())
|
||||||
)
|
),
|
||||||
);
|
);
|
||||||
$this->set('metaGroup', 'ContactDB');
|
$this->set('metaGroup', 'ContactDB');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function view($id)
|
/**
|
||||||
|
* View an organization.
|
||||||
|
*
|
||||||
|
* @param int $id The ID of the organization.
|
||||||
|
* @return \Cake\Http\Response|null The response payload.
|
||||||
|
*/
|
||||||
|
public function view(int $id)
|
||||||
{
|
{
|
||||||
$this->CRUD->view($id);
|
$this->CRUD->view($id);
|
||||||
$responsePayload = $this->CRUD->getResponsePayload();
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
|
@ -95,15 +120,24 @@ class OrganisationsController extends AppController
|
||||||
$this->set('metaGroup', 'ContactDB');
|
$this->set('metaGroup', 'ContactDB');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit($id)
|
/**
|
||||||
|
* Edit an organization.
|
||||||
|
*
|
||||||
|
* @param int $id The ID of the organization.
|
||||||
|
* @return \Cake\Http\Response|null The response payload.
|
||||||
|
*/
|
||||||
|
public function edit(int $id)
|
||||||
{
|
{
|
||||||
$currentUser = $this->ACL->getUser();
|
$currentUser = $this->ACL->getUser();
|
||||||
if (
|
if (
|
||||||
!($currentUser['Organisation']['id'] == $id && $currentUser['Role']['perm_org_admin']) &&
|
!(
|
||||||
!$currentUser['Role']['perm_admin']
|
$currentUser['Role']['perm_site_admin'] ||
|
||||||
|
($currentUser['Organisation']['id'] == $id && $currentUser['Role']['perm_admin'])
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
throw new MethodNotAllowedException(__('You cannot modify that organisation.'));
|
throw new MethodNotAllowedException(__('You cannot modify that organisation.'));
|
||||||
}
|
}
|
||||||
|
// FIXME prevent change of the created_by field
|
||||||
$this->CRUD->edit($id);
|
$this->CRUD->edit($id);
|
||||||
$responsePayload = $this->CRUD->getResponsePayload();
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
if (!empty($responsePayload)) {
|
if (!empty($responsePayload)) {
|
||||||
|
@ -113,7 +147,13 @@ class OrganisationsController extends AppController
|
||||||
$this->render('add');
|
$this->render('add');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function delete($id)
|
/**
|
||||||
|
* Delete an organization.
|
||||||
|
*
|
||||||
|
* @param int $id The ID of the organization.
|
||||||
|
* @return \Cake\Http\Response|null The response payload.
|
||||||
|
*/
|
||||||
|
public function delete(int $id)
|
||||||
{
|
{
|
||||||
$this->CRUD->delete($id);
|
$this->CRUD->delete($id);
|
||||||
$responsePayload = $this->CRUD->getResponsePayload();
|
$responsePayload = $this->CRUD->getResponsePayload();
|
||||||
|
@ -123,30 +163,48 @@ class OrganisationsController extends AppController
|
||||||
$this->set('metaGroup', 'ContactDB');
|
$this->set('metaGroup', 'ContactDB');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tag($id)
|
// /**
|
||||||
{
|
// * Tag an organization.
|
||||||
$this->CRUD->tag($id);
|
// *
|
||||||
$responsePayload = $this->CRUD->getResponsePayload();
|
// * @param int $id The ID of the organization.
|
||||||
if (!empty($responsePayload)) {
|
// * @return \Cake\Http\Response|null The response payload.
|
||||||
return $responsePayload;
|
// */
|
||||||
}
|
// public function tag(int $id)
|
||||||
}
|
// {
|
||||||
|
// $this->CRUD->tag($id);
|
||||||
|
// $responsePayload = $this->CRUD->getResponsePayload();
|
||||||
|
// if (!empty($responsePayload)) {
|
||||||
|
// return $responsePayload;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
public function untag($id)
|
// /**
|
||||||
{
|
// * Untag an organization.
|
||||||
$this->CRUD->untag($id);
|
// *
|
||||||
$responsePayload = $this->CRUD->getResponsePayload();
|
// * @param int $id The ID of the organization.
|
||||||
if (!empty($responsePayload)) {
|
// * @return \Cake\Http\Response|null The response payload.
|
||||||
return $responsePayload;
|
// */
|
||||||
}
|
// public function untag(int $id)
|
||||||
}
|
// {
|
||||||
|
// $this->CRUD->untag($id);
|
||||||
|
// $responsePayload = $this->CRUD->getResponsePayload();
|
||||||
|
// if (!empty($responsePayload)) {
|
||||||
|
// return $responsePayload;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
public function viewTags($id)
|
// /**
|
||||||
{
|
// * View tags for an organization.
|
||||||
$this->CRUD->viewTags($id);
|
// *
|
||||||
$responsePayload = $this->CRUD->getResponsePayload();
|
// * @param int $id The ID of the organization.
|
||||||
if (!empty($responsePayload)) {
|
// * @return \Cake\Http\Response|null The response payload.
|
||||||
return $responsePayload;
|
// */
|
||||||
}
|
// public function viewTags(int $id)
|
||||||
}
|
// {
|
||||||
|
// $this->CRUD->viewTags($id);
|
||||||
|
// $responsePayload = $this->CRUD->getResponsePayload();
|
||||||
|
// if (!empty($responsePayload)) {
|
||||||
|
// return $responsePayload;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -535,7 +535,7 @@ class SharingGroupsController extends AppController
|
||||||
return $sg;
|
return $sg;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function __initialiseSGQuickEditObject($id, $request, $type = 'org')
|
private function __initialiseSGQuickEditObject(int $id, $request, $type = 'org')
|
||||||
{
|
{
|
||||||
$params = [
|
$params = [
|
||||||
'org' => [
|
'org' => [
|
||||||
|
|
|
@ -1,18 +1,62 @@
|
||||||
<?php
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Model\Behavior;
|
namespace App\Model\Behavior;
|
||||||
|
|
||||||
use Cake\ORM\Behavior;
|
|
||||||
use Cake\Event\EventInterface;
|
|
||||||
use Cake\Datasource\EntityInterface;
|
|
||||||
use ArrayObject;
|
use ArrayObject;
|
||||||
|
use Cake\Datasource\EntityInterface;
|
||||||
|
use Cake\Event\EventInterface;
|
||||||
|
use Cake\ORM\Behavior;
|
||||||
use Cake\Utility\Text;
|
use Cake\Utility\Text;
|
||||||
|
use Cake\Validation\Validator;
|
||||||
|
|
||||||
class UUIDBehavior extends Behavior
|
class UUIDBehavior extends Behavior
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* beforeSave
|
||||||
|
*
|
||||||
|
* @param \Cake\Event\EventInterface $event the efent
|
||||||
|
* @param \Cake\Datasource\EntityInterface; $entity the entity
|
||||||
|
* @param array $options extra options
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
|
public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
|
||||||
{
|
{
|
||||||
if ($entity->isNew() && empty($entity['uuid'])) {
|
if ($entity->isNew() && empty($entity['uuid'])) {
|
||||||
$entity['uuid'] = Text::uuid();
|
$entity['uuid'] = Text::uuid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* buildValidator
|
||||||
|
*
|
||||||
|
* @param \Cake\Event\EventInterface $event the event
|
||||||
|
* @param \Cake\Validation\Validator $validator the validator
|
||||||
|
* @param string $name the string to validate
|
||||||
|
* @return \Cake\Validation\Validator
|
||||||
|
*/
|
||||||
|
public function buildValidator(EventInterface $event, Validator $validator, string $name)
|
||||||
|
{
|
||||||
|
$validator
|
||||||
|
->notEmptyString('uuid')
|
||||||
|
->add(
|
||||||
|
'uuid',
|
||||||
|
'valid',
|
||||||
|
[
|
||||||
|
'rule' => 'uuid',
|
||||||
|
'message' => 'The UUID is not valid',
|
||||||
|
]
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'uuid',
|
||||||
|
'unique',
|
||||||
|
[
|
||||||
|
'rule' => 'validateUnique',
|
||||||
|
'provider' => 'table',
|
||||||
|
'message' => 'The UUID name must be unique.',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return $validator;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Model\Table;
|
namespace App\Model\Table;
|
||||||
|
|
||||||
use App\Model\Table\AppTable;
|
|
||||||
use ArrayObject;
|
use ArrayObject;
|
||||||
use Cake\Datasource\EntityInterface;
|
use Cake\Datasource\EntityInterface;
|
||||||
use Cake\Event\EventInterface;
|
use Cake\Event\EventInterface;
|
||||||
|
@ -11,6 +11,12 @@ use Cake\Validation\Validator;
|
||||||
|
|
||||||
class OrganisationsTable extends AppTable
|
class OrganisationsTable extends AppTable
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Initialize method.
|
||||||
|
*
|
||||||
|
* @param array $config The configuration for the table.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function initialize(array $config): void
|
public function initialize(array $config): void
|
||||||
{
|
{
|
||||||
parent::initialize($config);
|
parent::initialize($config);
|
||||||
|
@ -23,42 +29,101 @@ class OrganisationsTable extends AppTable
|
||||||
$this->setDisplayField('name');
|
$this->setDisplayField('name');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback method called before saving an entity.
|
||||||
|
*
|
||||||
|
* @param \Cake\Event\EventInterface $event The event instance.
|
||||||
|
* @param \Cake\Datasource\EntityInterface $entity The entity being saved.
|
||||||
|
* @param \ArrayObject $options The options passed to the save method.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
|
public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
|
||||||
{
|
{
|
||||||
if ($entity->isNew()) {
|
if ($entity->isNew()) {
|
||||||
$entity->date_created = date('Y-m-d H:i:s');
|
$entity->date_created = date('Y-m-d H:i:s');
|
||||||
}
|
}
|
||||||
$entity->date_modified = date('Y-m-d H:i:s');
|
$entity->date_modified = date('Y-m-d H:i:s');
|
||||||
return;
|
// $entity->created_by = $this->ACL->getUser(); // FIXME force the value in the model, see also https://github.com/usemuffin/footprint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default validation rules for the table.
|
||||||
|
*
|
||||||
|
* @param \Cake\Validation\Validator $validator The validator instance.
|
||||||
|
* @return \Cake\Validation\Validator The updated validator instance.
|
||||||
|
*/
|
||||||
public function validationDefault(Validator $validator): Validator
|
public function validationDefault(Validator $validator): Validator
|
||||||
{
|
{
|
||||||
$validator
|
$validator
|
||||||
->notEmptyString('name')
|
->notEmptyString('name')
|
||||||
->notEmptyString('uuid')
|
->requirePresence(['name', 'uuid'], 'create')
|
||||||
->requirePresence(['name', 'uuid'], 'create');
|
->add(
|
||||||
|
'name',
|
||||||
|
[
|
||||||
|
'unique' => [
|
||||||
|
'rule' => 'validateUnique',
|
||||||
|
'provider' => 'table',
|
||||||
|
'message' => 'The organisation name must be unique.',
|
||||||
|
],
|
||||||
|
'maxLength' => [
|
||||||
|
'rule' => ['maxLength', 255],
|
||||||
|
'message' => 'Name cannot be more than 255 chars.',
|
||||||
|
],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'type',
|
||||||
|
'maxLength',
|
||||||
|
[
|
||||||
|
'rule' => ['maxLength', 255],
|
||||||
|
'message' => 'Type cannot be more than 255 chars.',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'nationality',
|
||||||
|
'maxLength',
|
||||||
|
[
|
||||||
|
'rule' => ['maxLength', 255],
|
||||||
|
'message' => 'Nationality cannot be more than 255 chars.',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
->add(
|
||||||
|
'sector',
|
||||||
|
'maxLength',
|
||||||
|
[
|
||||||
|
'rule' => ['maxLength', 255],
|
||||||
|
'message' => 'Sector cannot be more than 255 chars.',
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
return $validator;
|
return $validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Capture the organization.
|
||||||
|
*
|
||||||
|
* @param mixed $org The organization to capture.
|
||||||
|
* @return int|null The captured organization ID, or null if capture failed.
|
||||||
|
*/
|
||||||
public function captureOrg($org): ?int
|
public function captureOrg($org): ?int
|
||||||
{
|
{
|
||||||
if (!empty($org['uuid'])) {
|
if (!empty($org['uuid'])) {
|
||||||
$existingOrg = $this->find()->where(
|
$existingOrg = $this->find()->where(
|
||||||
[
|
[
|
||||||
'uuid' => $org['uuid']
|
'uuid' => $org['uuid'],
|
||||||
]
|
]
|
||||||
)->first();
|
)->first();
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (empty($existingOrg)) {
|
if (empty($existingOrg)) {
|
||||||
|
/** @var \App\Model\Entity\Organisation $entityToSave */
|
||||||
$entityToSave = $this->newEmptyEntity();
|
$entityToSave = $this->newEmptyEntity();
|
||||||
$this->patchEntity(
|
$this->patchEntity(
|
||||||
$entityToSave,
|
$entityToSave,
|
||||||
$org,
|
$org,
|
||||||
[
|
[
|
||||||
'accessibleFields' => $entityToSave->getAccessibleFieldForNew()
|
'accessibleFields' => $entityToSave->getAccessibleFieldForNew(),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,10 +135,17 @@ class OrganisationsTable extends AppTable
|
||||||
if (!$savedEntity) {
|
if (!$savedEntity) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $savedEntity->id;
|
return $savedEntity->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function fetchOrg($id)
|
/**
|
||||||
|
* Fetches an organization by its ID.
|
||||||
|
*
|
||||||
|
* @param int $id The ID of the organization to fetch.
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function fetchOrg(int $id)
|
||||||
{
|
{
|
||||||
if (empty($id)) {
|
if (empty($id)) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -87,10 +159,11 @@ class OrganisationsTable extends AppTable
|
||||||
$org = $this->find(
|
$org = $this->find(
|
||||||
'all',
|
'all',
|
||||||
[
|
[
|
||||||
'conditions' => $conditions,
|
'conditions' => $conditions,
|
||||||
'recursive' => -1
|
'recursive' => -1,
|
||||||
]
|
]
|
||||||
)->disableHydration()->first();
|
)->disableHydration()->first();
|
||||||
return (empty($org)) ? false : $org;
|
|
||||||
|
return empty($org) ? false : $org;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ class OrganisationsFixture extends TestFixture
|
||||||
'contacts' => '',
|
'contacts' => '',
|
||||||
'description' => 'ORGANISATION A',
|
'description' => 'ORGANISATION A',
|
||||||
'date_created' => $faker->dateTime()->getTimestamp(),
|
'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
'date_modified' => $faker->dateTime()->getTimestamp()
|
'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => self::ORGANISATION_B_ID,
|
'id' => self::ORGANISATION_B_ID,
|
||||||
|
@ -48,7 +48,7 @@ class OrganisationsFixture extends TestFixture
|
||||||
'contacts' => '',
|
'contacts' => '',
|
||||||
'description' => 'ORGANISATION B',
|
'description' => 'ORGANISATION B',
|
||||||
'date_created' => $faker->dateTime()->getTimestamp(),
|
'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
'date_modified' => $faker->dateTime()->getTimestamp()
|
'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => self::ORGANISATION_C_ID,
|
'id' => self::ORGANISATION_C_ID,
|
||||||
|
@ -61,8 +61,8 @@ class OrganisationsFixture extends TestFixture
|
||||||
'contacts' => '',
|
'contacts' => '',
|
||||||
'description' => 'ORGANISATION C',
|
'description' => 'ORGANISATION C',
|
||||||
'date_created' => $faker->dateTime()->getTimestamp(),
|
'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
'date_modified' => $faker->dateTime()->getTimestamp()
|
'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
parent::init();
|
parent::init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ class UsersFixture extends TestFixture
|
||||||
'disabled' => 0,
|
'disabled' => 0,
|
||||||
'org_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
'org_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||||
'date_created' => $faker->dateTime()->getTimestamp(),
|
'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
'date_modified' => $faker->dateTime()->getTimestamp()
|
'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => self::USER_SYNC_ID,
|
'id' => self::USER_SYNC_ID,
|
||||||
|
@ -57,7 +57,7 @@ class UsersFixture extends TestFixture
|
||||||
'disabled' => 0,
|
'disabled' => 0,
|
||||||
'org_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
'org_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||||
'date_created' => $faker->dateTime()->getTimestamp(),
|
'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
'date_modified' => $faker->dateTime()->getTimestamp()
|
'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => self::USER_ORG_ADMIN_ID,
|
'id' => self::USER_ORG_ADMIN_ID,
|
||||||
|
@ -68,7 +68,7 @@ class UsersFixture extends TestFixture
|
||||||
'disabled' => 0,
|
'disabled' => 0,
|
||||||
'org_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
'org_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||||
'date_created' => $faker->dateTime()->getTimestamp(),
|
'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
'date_modified' => $faker->dateTime()->getTimestamp()
|
'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => self::USER_REGULAR_USER_ID,
|
'id' => self::USER_REGULAR_USER_ID,
|
||||||
|
@ -79,8 +79,8 @@ class UsersFixture extends TestFixture
|
||||||
'disabled' => 0,
|
'disabled' => 0,
|
||||||
'org_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
'org_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||||
'date_created' => $faker->dateTime()->getTimestamp(),
|
'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
'date_modified' => $faker->dateTime()->getTimestamp()
|
'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
]
|
],
|
||||||
];
|
];
|
||||||
parent::init();
|
parent::init();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace App\Test\Helper;
|
namespace App\Test\Helper;
|
||||||
|
@ -23,28 +22,49 @@ trait ApiTestTrait
|
||||||
IntegrationTestTrait::_sendRequest as _sendRequestOriginal;
|
IntegrationTestTrait::_sendRequest as _sendRequestOriginal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var string */
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $_authToken = '';
|
protected $_authToken = '';
|
||||||
|
|
||||||
/** @var ValidatorBuilder */
|
/**
|
||||||
|
* @var ValidatorBuilder
|
||||||
|
*/
|
||||||
private $_validator;
|
private $_validator;
|
||||||
|
|
||||||
/** @var RequestValidator */
|
/**
|
||||||
|
* @var RequestValidator
|
||||||
|
*/
|
||||||
private $_requestValidator;
|
private $_requestValidator;
|
||||||
|
|
||||||
/** @var ResponseValidator */
|
/**
|
||||||
|
* @var ResponseValidator
|
||||||
|
*/
|
||||||
private $_responseValidator;
|
private $_responseValidator;
|
||||||
|
|
||||||
/** @var ServerRequest */
|
/**
|
||||||
|
* @var ServerRequest
|
||||||
|
*/
|
||||||
protected $_psrRequest;
|
protected $_psrRequest;
|
||||||
|
|
||||||
/** @var boolean */
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
protected $_skipOpenApiValidations = false;
|
protected $_skipOpenApiValidations = false;
|
||||||
|
|
||||||
public function setUp(): void
|
public function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
parent::setUp();
|
||||||
$this->initializeOpenApiValidator();
|
$this->initializeOpenApiValidator();
|
||||||
|
|
||||||
|
$this->configRequest(
|
||||||
|
[
|
||||||
|
'headers' => [
|
||||||
|
'Accept' => 'application/json',
|
||||||
|
'Content-Type' => 'application/json',
|
||||||
|
],
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setAuthToken(string $authToken): void
|
public function setAuthToken(string $authToken): void
|
||||||
|
@ -59,8 +79,8 @@ trait ApiTestTrait
|
||||||
'headers' => [
|
'headers' => [
|
||||||
'Accept' => 'application/json',
|
'Accept' => 'application/json',
|
||||||
'Authorization' => $this->_authToken,
|
'Authorization' => $this->_authToken,
|
||||||
'Content-Type' => 'application/json'
|
'Content-Type' => 'application/json',
|
||||||
]
|
],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +109,7 @@ trait ApiTestTrait
|
||||||
public function initializeOpenApiValidator(): void
|
public function initializeOpenApiValidator(): void
|
||||||
{
|
{
|
||||||
if (!$this->_skipOpenApiValidations) {
|
if (!$this->_skipOpenApiValidations) {
|
||||||
$this->_validator = Configure::read('App.OpenAPIValidator');
|
$this->_validator = Configure::read('App.OpenAPIValidator');
|
||||||
if ($this->_validator === null) {
|
if ($this->_validator === null) {
|
||||||
throw new \Exception('OpenAPI validator is not configured');
|
throw new \Exception('OpenAPI validator is not configured');
|
||||||
}
|
}
|
||||||
|
@ -127,7 +147,6 @@ trait ApiTestTrait
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException
|
* @throws \Cake\Datasource\Exception\RecordNotFoundException
|
||||||
*
|
|
||||||
* @see https://book.cakephp.org/4/en/orm-query-builder.html
|
* @see https://book.cakephp.org/4/en/orm-query-builder.html
|
||||||
*/
|
*/
|
||||||
public function assertDbRecordExists(string $table, array $conditions): void
|
public function assertDbRecordExists(string $table, array $conditions): void
|
||||||
|
@ -147,7 +166,6 @@ trait ApiTestTrait
|
||||||
* @return void
|
* @return void
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException
|
* @throws \Cake\Datasource\Exception\RecordNotFoundException
|
||||||
*
|
|
||||||
* @see https://book.cakephp.org/4/en/orm-query-builder.html
|
* @see https://book.cakephp.org/4/en/orm-query-builder.html
|
||||||
*/
|
*/
|
||||||
public function assertDbRecordNotExists(string $table, array $conditions): void
|
public function assertDbRecordNotExists(string $table, array $conditions): void
|
||||||
|
@ -191,8 +209,8 @@ trait ApiTestTrait
|
||||||
* This method intercepts IntegrationTestTrait::_buildRequest()
|
* This method intercepts IntegrationTestTrait::_buildRequest()
|
||||||
* in the quest to get a PSR-7 request object and saves it for
|
* in the quest to get a PSR-7 request object and saves it for
|
||||||
* later inspection, also validates it against the OpenAPI spec.
|
* later inspection, also validates it against the OpenAPI spec.
|
||||||
* @see \Cake\TestSuite\IntegrationTestTrait::_buildRequest()
|
|
||||||
*
|
*
|
||||||
|
* @see \Cake\TestSuite\IntegrationTestTrait::_buildRequest()
|
||||||
* @param string $url The URL
|
* @param string $url The URL
|
||||||
* @param string $method The HTTP method
|
* @param string $method The HTTP method
|
||||||
* @param array|string $data The request data.
|
* @param array|string $data The request data.
|
||||||
|
@ -229,7 +247,6 @@ trait ApiTestTrait
|
||||||
* and validates the response against the OpenAPI spec.
|
* and validates the response against the OpenAPI spec.
|
||||||
*
|
*
|
||||||
* @see \Cake\TestSuite\IntegrationTestTrait::_sendRequest()
|
* @see \Cake\TestSuite\IntegrationTestTrait::_sendRequest()
|
||||||
*
|
|
||||||
* @param array|string $url The URL
|
* @param array|string $url The URL
|
||||||
* @param string $method The HTTP method
|
* @param string $method The HTTP method
|
||||||
* @param array|string $data The request data.
|
* @param array|string $data The request data.
|
||||||
|
@ -274,8 +291,8 @@ trait ApiTestTrait
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a PSR-7 request from the request spec.
|
* Create a PSR-7 request from the request spec.
|
||||||
* @see \Cake\TestSuite\MiddlewareDispatcher::_createRequest()
|
|
||||||
*
|
*
|
||||||
|
* @see \Cake\TestSuite\MiddlewareDispatcher::_createRequest()
|
||||||
* @param array<string, mixed> $spec The request spec.
|
* @param array<string, mixed> $spec The request spec.
|
||||||
* @return \Cake\Http\ServerRequest
|
* @return \Cake\Http\ServerRequest
|
||||||
*/
|
*/
|
||||||
|
@ -292,6 +309,7 @@ trait ApiTestTrait
|
||||||
if (strpos($environment['PHP_SELF'], 'phpunit') !== false) {
|
if (strpos($environment['PHP_SELF'], 'phpunit') !== false) {
|
||||||
$environment['PHP_SELF'] = '/';
|
$environment['PHP_SELF'] = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
return ServerRequestFactory::fromGlobals(
|
return ServerRequestFactory::fromGlobals(
|
||||||
$environment,
|
$environment,
|
||||||
$spec['query'],
|
$spec['query'],
|
||||||
|
|
|
@ -43,4 +43,15 @@ class DeleteCerebrateApiTest extends TestCase
|
||||||
$this->assertResponseCode(405);
|
$this->assertResponseCode(405);
|
||||||
$this->assertDbRecordExists('Cerebrates', ['id' => CerebratesFixture::SERVER_A_ID]);
|
$this->assertDbRecordExists('Cerebrates', ['id' => CerebratesFixture::SERVER_A_ID]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDeleteCerebrateNotAllowedAsOrgAdmin(): void
|
||||||
|
{
|
||||||
|
$this->skipOpenApiValidations();
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ORG_ADMIN_API_KEY);
|
||||||
|
$url = sprintf('%s/%d', self::ENDPOINT, CerebratesFixture::SERVER_A_ID);
|
||||||
|
$this->delete($url);
|
||||||
|
|
||||||
|
$this->assertResponseCode(405);
|
||||||
|
$this->assertDbRecordExists('Cerebrates', ['id' => CerebratesFixture::SERVER_A_ID]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,287 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Test\TestCase\Api\Organisations;
|
||||||
|
|
||||||
|
use App\Test\Fixture\AuthKeysFixture;
|
||||||
|
use App\Test\Fixture\OrganisationsFixture;
|
||||||
|
use App\Test\Helper\ApiTestTrait;
|
||||||
|
use Cake\TestSuite\TestCase;
|
||||||
|
|
||||||
|
class AddOrganisationsApiTest extends TestCase
|
||||||
|
{
|
||||||
|
use ApiTestTrait;
|
||||||
|
|
||||||
|
protected const ENDPOINT = '/organisations/add';
|
||||||
|
|
||||||
|
protected $fixtures = [
|
||||||
|
'app.Organisations',
|
||||||
|
'app.Roles',
|
||||||
|
'app.Users',
|
||||||
|
'app.AuthKeys',
|
||||||
|
];
|
||||||
|
|
||||||
|
private function addOrganisation(array $org_data): void
|
||||||
|
{
|
||||||
|
$url = sprintf('%s', self::ENDPOINT);
|
||||||
|
$this->post(
|
||||||
|
$url,
|
||||||
|
$org_data
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertResponseOk();
|
||||||
|
$this->assertDbRecordExists(
|
||||||
|
'Organisations',
|
||||||
|
$org_data
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addNotAllowed(array $org_data): void
|
||||||
|
{
|
||||||
|
$url = sprintf('%s', self::ENDPOINT);
|
||||||
|
$this->post(
|
||||||
|
$url,
|
||||||
|
$org_data
|
||||||
|
);
|
||||||
|
$this->assertResponseCode(405);
|
||||||
|
$this->assertDbRecordNotExists(
|
||||||
|
'Organisations',
|
||||||
|
[
|
||||||
|
'name' => $org_data['name'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddOrganisationAsAdmin(): void
|
||||||
|
{
|
||||||
|
$faker = \Faker\Factory::create();
|
||||||
|
$org_data = [
|
||||||
|
'uuid' => $faker->uuid(),
|
||||||
|
'name' => $faker->text(10),
|
||||||
|
'description' => $faker->text(10),
|
||||||
|
'nationality' => $faker->countryCode,
|
||||||
|
'sector' => 'IT',
|
||||||
|
'type' => '',
|
||||||
|
'contacts' => '',
|
||||||
|
'local' => 1,
|
||||||
|
'restricted_to_domain' => '',
|
||||||
|
'landingpage' => '',
|
||||||
|
//'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'created_by' => 0,
|
||||||
|
];
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$this->addOrganisation($org_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddNotAllowedAsRegularUser(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||||
|
$faker = \Faker\Factory::create();
|
||||||
|
$org_data = [
|
||||||
|
'uuid' => $faker->uuid(),
|
||||||
|
'name' => $faker->text(10),
|
||||||
|
'description' => $faker->text(10),
|
||||||
|
'nationality' => $faker->countryCode,
|
||||||
|
'sector' => 'IT',
|
||||||
|
'type' => '',
|
||||||
|
'contacts' => '',
|
||||||
|
'local' => 1,
|
||||||
|
'restricted_to_domain' => '',
|
||||||
|
'landingpage' => '',
|
||||||
|
//'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'created_by' => 0,
|
||||||
|
];
|
||||||
|
$this->addNotAllowed($org_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddNotAllowedAsOrgAdmin(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ORG_ADMIN_API_KEY); // user from org A
|
||||||
|
$faker = \Faker\Factory::create();
|
||||||
|
$org_data = [
|
||||||
|
'uuid' => $faker->uuid(),
|
||||||
|
'name' => $faker->text(10),
|
||||||
|
'description' => $faker->text(10),
|
||||||
|
'nationality' => $faker->countryCode,
|
||||||
|
'sector' => 'IT',
|
||||||
|
'type' => '',
|
||||||
|
'contacts' => '',
|
||||||
|
'local' => 1,
|
||||||
|
'restricted_to_domain' => '',
|
||||||
|
'landingpage' => '',
|
||||||
|
//'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'created_by' => 0,
|
||||||
|
];
|
||||||
|
$this->addNotAllowed($org_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddNameAlreadyExists(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$faker = \Faker\Factory::create();
|
||||||
|
$org_data = [
|
||||||
|
'uuid' => $faker->uuid(),
|
||||||
|
'name' => 'Organisation A',
|
||||||
|
'description' => $faker->text(10),
|
||||||
|
'nationality' => $faker->countryCode,
|
||||||
|
'sector' => 'DUPLICATE ENTRY',
|
||||||
|
'type' => '',
|
||||||
|
'contacts' => '',
|
||||||
|
'local' => 1,
|
||||||
|
'restricted_to_domain' => '',
|
||||||
|
'landingpage' => '',
|
||||||
|
//'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'created_by' => 0,
|
||||||
|
];
|
||||||
|
$url = sprintf('%s', self::ENDPOINT);
|
||||||
|
$this->post(
|
||||||
|
$url,
|
||||||
|
$org_data
|
||||||
|
);
|
||||||
|
$this->assertResponseCode(200);
|
||||||
|
$this->assertDbRecordNotExists(
|
||||||
|
'Organisations',
|
||||||
|
[
|
||||||
|
'name' => 'Organisation A',
|
||||||
|
'sector' => 'DUPLICATE ENTRY',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddUuidAlreadyExists(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$faker = \Faker\Factory::create();
|
||||||
|
$org_data = [
|
||||||
|
'uuid' => OrganisationsFixture::ORGANISATION_A_UUID,
|
||||||
|
'name' => $faker->text(10),
|
||||||
|
'description' => $faker->text(10),
|
||||||
|
'nationality' => $faker->countryCode,
|
||||||
|
'sector' => 'DUPLICATE ENTRY',
|
||||||
|
'type' => '',
|
||||||
|
'contacts' => '',
|
||||||
|
'local' => 1,
|
||||||
|
'restricted_to_domain' => '',
|
||||||
|
'landingpage' => '',
|
||||||
|
//'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'created_by' => 0,
|
||||||
|
];
|
||||||
|
$url = sprintf('%s', self::ENDPOINT);
|
||||||
|
$this->post(
|
||||||
|
$url,
|
||||||
|
$org_data
|
||||||
|
);
|
||||||
|
$this->assertResponseCode(200);
|
||||||
|
$this->assertDbRecordNotExists(
|
||||||
|
'Organisations',
|
||||||
|
[
|
||||||
|
'name' => $org_data['name'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testBadUuid(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$faker = \Faker\Factory::create();
|
||||||
|
$org_data = [
|
||||||
|
'uuid' => '11111111-1111-1111-1111-111111111111',
|
||||||
|
'name' => $faker->text(10),
|
||||||
|
'description' => $faker->text(10),
|
||||||
|
'nationality' => $faker->countryCode,
|
||||||
|
'sector' => 'DUPLICATE ENTRY',
|
||||||
|
'type' => '',
|
||||||
|
'contacts' => '',
|
||||||
|
'local' => 1,
|
||||||
|
'restricted_to_domain' => '',
|
||||||
|
'landingpage' => '',
|
||||||
|
//'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'created_by' => 0,
|
||||||
|
];
|
||||||
|
$url = sprintf('%s', self::ENDPOINT);
|
||||||
|
$this->post(
|
||||||
|
$url,
|
||||||
|
$org_data
|
||||||
|
);
|
||||||
|
$this->assertResponseCode(200);
|
||||||
|
$this->assertDbRecordNotExists(
|
||||||
|
'Organisations',
|
||||||
|
[
|
||||||
|
'name' => $org_data['name'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddLongName(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$faker = \Faker\Factory::create();
|
||||||
|
$org_data = [
|
||||||
|
'uuid' => $faker->uuid(),
|
||||||
|
'name' => 'This is a very long name that is longer than 255 characters and should not be allowed. aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
|
||||||
|
'description' => $faker->text(10),
|
||||||
|
'nationality' => $faker->countryCode,
|
||||||
|
'sector' => 'IT',
|
||||||
|
'type' => '',
|
||||||
|
'contacts' => '',
|
||||||
|
'local' => 1,
|
||||||
|
'restricted_to_domain' => '',
|
||||||
|
'landingpage' => '',
|
||||||
|
//'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'created_by' => 0,
|
||||||
|
];
|
||||||
|
$url = sprintf('%s', self::ENDPOINT);
|
||||||
|
$this->post(
|
||||||
|
$url,
|
||||||
|
$org_data
|
||||||
|
);
|
||||||
|
$this->assertResponseCode(200);
|
||||||
|
$this->assertDbRecordNotExists(
|
||||||
|
'Organisations',
|
||||||
|
[
|
||||||
|
'name' => $org_data['name'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAddCreatedBy(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$faker = \Faker\Factory::create();
|
||||||
|
$org_data = [
|
||||||
|
'uuid' => $faker->uuid(),
|
||||||
|
'name' => $faker->text(10),
|
||||||
|
'description' => $faker->text(10),
|
||||||
|
'nationality' => $faker->countryCode,
|
||||||
|
'sector' => 'IT',
|
||||||
|
'type' => '',
|
||||||
|
'contacts' => '',
|
||||||
|
'local' => 1,
|
||||||
|
'restricted_to_domain' => '',
|
||||||
|
'landingpage' => '',
|
||||||
|
//'date_created' => $faker->dateTime()->getTimestamp(),
|
||||||
|
// 'date_modified' => $faker->dateTime()->getTimestamp(),
|
||||||
|
'created_by' => 1,
|
||||||
|
];
|
||||||
|
$url = sprintf('%s', self::ENDPOINT);
|
||||||
|
$this->post(
|
||||||
|
$url,
|
||||||
|
$org_data
|
||||||
|
);
|
||||||
|
$this->assertResponseCode(200);
|
||||||
|
$this->assertDbRecordExists(
|
||||||
|
'Organisations',
|
||||||
|
[
|
||||||
|
'uuid' => $org_data['uuid'],
|
||||||
|
'created_by' => AuthKeysFixture::ADMIN_API_ID,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Test\TestCase\Api\Organisations;
|
||||||
|
|
||||||
|
use App\Test\Fixture\AuthKeysFixture;
|
||||||
|
use App\Test\Fixture\OrganisationsFixture;
|
||||||
|
use App\Test\Helper\ApiTestTrait;
|
||||||
|
use Cake\TestSuite\TestCase;
|
||||||
|
|
||||||
|
class DeleteOrganisationsApiTest extends TestCase
|
||||||
|
{
|
||||||
|
use ApiTestTrait;
|
||||||
|
|
||||||
|
protected const ENDPOINT = '/organisations/delete';
|
||||||
|
|
||||||
|
protected $fixtures = [
|
||||||
|
'app.Organisations',
|
||||||
|
'app.Roles',
|
||||||
|
'app.Users',
|
||||||
|
'app.AuthKeys',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function testDeleteOrganisation(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||||
|
$this->delete($url);
|
||||||
|
|
||||||
|
$this->assertResponseOk();
|
||||||
|
$this->assertDbRecordNotExists('Organisations', ['id' => OrganisationsFixture::ORGANISATION_A_ID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDeleteOrganisationNotAllowedAsRegularUser(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||||
|
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||||
|
$this->delete($url);
|
||||||
|
|
||||||
|
$this->assertResponseCode(405);
|
||||||
|
$this->assertDbRecordExists('Organisations', ['id' => OrganisationsFixture::ORGANISATION_A_ID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDeleteOrganisationNotAllowedAsOrgAdmin(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ORG_ADMIN_API_KEY);
|
||||||
|
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||||
|
$this->delete($url);
|
||||||
|
|
||||||
|
$this->assertResponseCode(405);
|
||||||
|
$this->assertDbRecordExists('Organisations', ['id' => OrganisationsFixture::ORGANISATION_A_ID]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Test\TestCase\Api\Organisations;
|
||||||
|
|
||||||
|
use App\Test\Fixture\AuthKeysFixture;
|
||||||
|
use App\Test\Fixture\OrganisationsFixture;
|
||||||
|
use App\Test\Helper\ApiTestTrait;
|
||||||
|
use Cake\TestSuite\TestCase;
|
||||||
|
|
||||||
|
class EditOrganisationsApiTest extends TestCase
|
||||||
|
{
|
||||||
|
use ApiTestTrait;
|
||||||
|
|
||||||
|
protected const ENDPOINT = '/organisations/edit';
|
||||||
|
|
||||||
|
protected $fixtures = [
|
||||||
|
'app.Organisations',
|
||||||
|
'app.Roles',
|
||||||
|
'app.Users',
|
||||||
|
'app.AuthKeys',
|
||||||
|
];
|
||||||
|
|
||||||
|
private function editOrganisation(int $org_id): void
|
||||||
|
{
|
||||||
|
$url = sprintf('%s/%d', self::ENDPOINT, $org_id);
|
||||||
|
$this->put(
|
||||||
|
$url,
|
||||||
|
[
|
||||||
|
'id' => $org_id,
|
||||||
|
'description' => 'new description',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertResponseOk();
|
||||||
|
$this->assertDbRecordExists(
|
||||||
|
'Organisations',
|
||||||
|
[
|
||||||
|
'id' => $org_id,
|
||||||
|
'description' => 'new description',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function editNotAllowed(int $org_id): void
|
||||||
|
{
|
||||||
|
$url = sprintf('%s/%d', self::ENDPOINT, $org_id);
|
||||||
|
$this->put(
|
||||||
|
$url,
|
||||||
|
[
|
||||||
|
'id' => $org_id,
|
||||||
|
'description' => 'new description',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$this->assertResponseCode(405);
|
||||||
|
$this->assertDbRecordNotExists(
|
||||||
|
'Organisations',
|
||||||
|
[
|
||||||
|
'id' => $org_id,
|
||||||
|
'description' => 'new description',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEditOrganisationAsAdmin(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$this->editOrganisation(OrganisationsFixture::ORGANISATION_A_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEditOrganisationAsOrgAdmin(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ORG_ADMIN_API_KEY); // user from org A
|
||||||
|
$this->editOrganisation(OrganisationsFixture::ORGANISATION_A_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEditNotAllowedAsRegularUser(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||||
|
$this->editNotAllowed(OrganisationsFixture::ORGANISATION_A_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEditNotAllowedAsWrongOrgAdmin(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ORG_ADMIN_API_KEY); // user from org A
|
||||||
|
$this->editNotAllowed(OrganisationsFixture::ORGANISATION_B_ID); // edit org B not allowed
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testEditNameAlreadyExists(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||||
|
$this->put(
|
||||||
|
$url,
|
||||||
|
[
|
||||||
|
'id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||||
|
'name' => 'Organisation B',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$this->assertResponseCode(200);
|
||||||
|
$this->assertDbRecordNotExists(
|
||||||
|
'Organisations',
|
||||||
|
[
|
||||||
|
'id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||||
|
'description' => 'Organisation B',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Test\TestCase\Api\Organisations;
|
||||||
|
|
||||||
|
use App\Test\Fixture\AuthKeysFixture;
|
||||||
|
use App\Test\Fixture\OrganisationsFixture;
|
||||||
|
use App\Test\Helper\ApiTestTrait;
|
||||||
|
use Cake\TestSuite\TestCase;
|
||||||
|
|
||||||
|
class IndexOrganisationsApiTest extends TestCase
|
||||||
|
{
|
||||||
|
use ApiTestTrait;
|
||||||
|
|
||||||
|
protected const ENDPOINT = '/organisations/index';
|
||||||
|
|
||||||
|
protected $fixtures = [
|
||||||
|
'app.Organisations',
|
||||||
|
'app.Roles',
|
||||||
|
'app.Users',
|
||||||
|
'app.AuthKeys',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function testIndexOrganisationsAsUser(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||||
|
$this->get(self::ENDPOINT);
|
||||||
|
|
||||||
|
$this->assertResponseOk();
|
||||||
|
$this->assertResponseContains(sprintf('"uuid": "%s"', OrganisationsFixture::ORGANISATION_A_UUID));
|
||||||
|
$this->assertResponseContains(sprintf('"uuid": "%s"', OrganisationsFixture::ORGANISATION_B_UUID));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIndexOrganisationsAsAdmin(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||||
|
$this->get(self::ENDPOINT);
|
||||||
|
|
||||||
|
$this->assertResponseOk();
|
||||||
|
$this->assertResponseContains(sprintf('"uuid": "%s"', OrganisationsFixture::ORGANISATION_A_UUID));
|
||||||
|
$this->assertResponseContains(sprintf('"uuid": "%s"', OrganisationsFixture::ORGANISATION_B_UUID));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIndexOrganisationsWithInvalidAuthToken(): void
|
||||||
|
{
|
||||||
|
$this->setAuthToken('invalid_token');
|
||||||
|
$this->get(self::ENDPOINT);
|
||||||
|
$this->assertResponseCode(405);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIndexOrganisationsWithNoAuthToken(): void
|
||||||
|
{
|
||||||
|
$this->skipOpenApiValidations();
|
||||||
|
$this->get(self::ENDPOINT);
|
||||||
|
$this->assertResponseCode(405);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue