new: add api tests for MetaTemplates and openapi spec, fix minor issues.

pull/93/head
Luciano Righetti 2022-03-08 15:51:07 +01:00
parent ce4448f4e7
commit 9a2c6a4c4b
10 changed files with 543 additions and 3 deletions

View File

@ -59,6 +59,11 @@
"nohup sh ./tests/Helper/wiremock/start.sh >/dev/null 2>&1 &",
"phpunit",
"sh ./tests/Helper/wiremock/stop.sh"
],
"migrate": [
"./bin/cake migrations migrate",
"./bin/cake migrations migrate -p tags",
"./bin/cake migrations migrate -p ADmad/SocialAuth"
]
},
"prefer-stable": true,
@ -66,4 +71,4 @@
"sort-packages": true
},
"minimum-stability": "dev"
}
}

View File

@ -60,7 +60,12 @@ class MetaTemplatesController extends AppController
if (!is_numeric($template_id)) {
throw new NotFoundException(__('Invalid {0} for provided ID.', $this->MetaTemplates->getAlias(), $template_id));
}
$metaTemplate = $this->MetaTemplates->get($template_id);
// $metaTemplate = $this->MetaTemplates->get($template_id);
$metaTemplate = $this->MetaTemplates->find()->where([
'id' => $template_id,
'enabled' => 1
])->contain(['MetaTemplateFields'])->first();
if (empty($metaTemplate)) {
throw new NotFoundException(__('Invalid {0} {1}.', $this->MetaTemplates->getAlias(), $template_id));
}

View File

@ -114,7 +114,7 @@ class MetaTemplatesTable extends AppTable
if ($updateStatus['up-to-date']) {
$errors['message'] = __('Meta-template already up-to-date');
$success = true;
} else if ($this->isStrategyAllowed(MetaTemplatesTable::UPDATE_STRATEGY_CREATE_NEW) && $updateStatus['new']) {
} else if ($this->isStrategyAllowed(MetaTemplatesTable::UPDATE_STRATEGY_CREATE_NEW) && $updateStatus['is-new']) {
$success = $this->saveNewMetaTemplate($templateOnDisk, $errors);
} else if ($this->isStrategyAllowed(MetaTemplatesTable::UPDATE_STRATEGY_UPDATE_EXISTING) && $updateStatus['automatically-updateable']) {
$success = $this->updateMetaTemplate($metaTemplate, $templateOnDisk, $errors);

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace App\Test\Fixture;
use Cake\TestSuite\Fixture\TestFixture;
class MetaTemplateFieldsFixture extends TestFixture
{
public $connection = 'test';
public function init(): void
{
$this->records = [
[
'field' => 'test_field_1',
'type' => 'text',
'meta_template_id' => MetaTemplatesFixture::ENABLED_TEST_ORG_META_TEMPLATE_ID,
'regex' => null,
'multiple' => 1,
'enabled' => 1,
'counter' => 0
]
];
parent::init();
}
}

View File

@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
namespace App\Test\Fixture;
use Cake\TestSuite\Fixture\TestFixture;
class MetaTemplatesFixture extends TestFixture
{
public $connection = 'test';
public const ENABLED_TEST_ORG_META_TEMPLATE_ID = 1;
public const ENABLED_TEST_ORG_META_TEMPLATE_UUID = 'ee26022a-69e2-4451-bfda-f2ca9f3dd2e5';
public const DISABLED_TEST_ORG_META_TEMPLATE_ID = 2;
public const DISABLED_TEST_ORG_META_TEMPLATE_UUID = '698c616d-49f3-4c51-9364-6e223ff4bbc2';
public const ENABLED_TEST_ORG_META_TEMPLATE_SPEC = [
'uuid' => self::ENABLED_TEST_ORG_META_TEMPLATE_UUID,
'name' => 'Test Org Meta Template (enabled)',
'description' => 'Test Org Meta Template Description (enabled)',
'version' => 2,
'scope' => 'organisation',
'namespace' => 'test',
'source' => 'Cerebrate',
'metaFields' => [
[
"field" => "test_field_1",
"type" => "text",
"multiple" => true
],
[
"field" => "test_field_2",
"type" => "text",
"multiple" => true
]
],
];
public function init(): void
{
$faker = \Faker\Factory::create();
$this->records = [
[
'id' => self::ENABLED_TEST_ORG_META_TEMPLATE_ID,
'scope' => 'organisation',
'name' => 'Test Meta Template (enabled)',
'namespace' => 'cerebrate',
'description' => 'Test Meta Template Description (enabled)',
'version' => '1',
'uuid' => self::ENABLED_TEST_ORG_META_TEMPLATE_UUID,
'source' => 'Cerebrate',
'enabled' => true,
'is_default' => false,
'created' => $faker->dateTime()->getTimestamp(),
'modified' => $faker->dateTime()->getTimestamp()
],
[
'id' => self::DISABLED_TEST_ORG_META_TEMPLATE_ID,
'scope' => 'organisation',
'name' => 'Test Meta Template (disabled)',
'namespace' => 'cerebrate',
'description' => 'Test Meta Template Description (disabled)',
'version' => '1',
'uuid' => self::DISABLED_TEST_ORG_META_TEMPLATE_UUID,
'source' => 'Cerebrate',
'enabled' => false,
'is_default' => false,
'created' => $faker->dateTime()->getTimestamp(),
'modified' => $faker->dateTime()->getTimestamp()
]
];
parent::init();
}
}

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Api\MetaTemplates;
use Cake\TestSuite\TestCase;
use App\Test\Fixture\AuthKeysFixture;
use App\Test\Helper\ApiTestTrait;
class CreateMetaTemplateApiTest extends TestCase
{
use ApiTestTrait;
protected const ENDPOINT = '/metaTemplates/createNewTemplate';
public const CSIRT_META_TEMPLATE_UUID = 'faca6acc-23e0-4585-8fd8-4379e3a6250d';
protected $fixtures = [
'app.Organisations',
'app.Individuals',
'app.Roles',
'app.Users',
'app.AuthKeys',
'app.MetaTemplates'
];
public function testLoadMetaTemplate(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$url = sprintf('%s/%s', self::ENDPOINT, self::CSIRT_META_TEMPLATE_UUID);
$this->post($url);
$this->assertResponseOk();
$this->assertDbRecordExists('MetaTemplates', [
'uuid' => self::CSIRT_META_TEMPLATE_UUID,
]);
}
public function testLoadMetaTemplateNotAllowedAsRegularUser(): void
{
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
$url = sprintf('%s/%s', self::ENDPOINT, self::CSIRT_META_TEMPLATE_UUID);
$this->post($url);
$this->assertResponseCode(405);
$this->assertDbRecordNotExists('MetaTemplates', [
'uuid' => self::CSIRT_META_TEMPLATE_UUID,
]);
}
}

View File

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Api\MetaTemplates;
use Cake\TestSuite\TestCase;
use App\Test\Fixture\AuthKeysFixture;
use App\Test\Fixture\MetaTemplatesFixture;
use App\Test\Helper\ApiTestTrait;
class ToggleEnableMetaTemplateApiTest extends TestCase
{
use ApiTestTrait;
protected const ENDPOINT = '/metaTemplates/toggle/%d/enabled';
protected $fixtures = [
'app.Organisations',
'app.Individuals',
'app.Roles',
'app.Users',
'app.AuthKeys',
'app.MetaTemplates'
];
public function testToggleEnabledMetaTemplate(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$url = sprintf(self::ENDPOINT, MetaTemplatesFixture::DISABLED_TEST_ORG_META_TEMPLATE_ID);
$this->post($url);
$this->assertResponseOk();
$this->assertDbRecordExists('MetaTemplates', [
'id' => MetaTemplatesFixture::DISABLED_TEST_ORG_META_TEMPLATE_ID,
'enabled' => true
]);
}
public function testToggleDisabledMetaTemplate(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$url = sprintf(self::ENDPOINT, MetaTemplatesFixture::ENABLED_TEST_ORG_META_TEMPLATE_ID);
$this->post($url);
$this->assertResponseOk();
$this->assertDbRecordExists('MetaTemplates', [
'id' => MetaTemplatesFixture::ENABLED_TEST_ORG_META_TEMPLATE_ID,
'enabled' => false
]);
}
public function testEnableMetaTemplateNotAllowedAsRegularUser(): void
{
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
$url = sprintf(self::ENDPOINT, MetaTemplatesFixture::DISABLED_TEST_ORG_META_TEMPLATE_ID);
$this->post($url);
$this->assertResponseCode(405);
$this->assertDbRecordExists('MetaTemplates', [
'id' => MetaTemplatesFixture::DISABLED_TEST_ORG_META_TEMPLATE_ID,
'enabled' => false
]);
}
}

View File

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Api\MetaTemplates;
use Cake\TestSuite\TestCase;
use App\Test\Fixture\AuthKeysFixture;
use App\Test\Fixture\MetaTemplatesFixture;
use App\Test\Helper\ApiTestTrait;
use App\Model\Table\MetaTemplatesTable;
class UpdateAllMetaTemplatesApiTest extends TestCase
{
use ApiTestTrait;
protected const ENDPOINT = '/metaTemplates/updateAllTemplates';
protected $fixtures = [
'app.Organisations',
'app.Individuals',
'app.Roles',
'app.Users',
'app.AuthKeys',
'app.MetaTemplates',
'app.MetaTemplateFields'
];
public function testUpdateAllMetaTemplates(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
$this->post(self::ENDPOINT);
$this->assertResponseOk();
$response = $this->getJsonResponseAsArray();
$this->assertEmpty($response['update_errors']);
$this->assertNotEmpty($response['files_processed']);
$this->assertTrue($response['success']);
$this->assertDbRecordExists('MetaTemplates', [
'id' => 3 // id 1 and 2 are loaded via MetaTemplatesFixture
]);
}
}

View File

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace App\Test\TestCase\Api\MetaTemplates;
use Cake\TestSuite\TestCase;
use App\Test\Fixture\AuthKeysFixture;
use App\Test\Fixture\MetaTemplatesFixture;
use App\Test\Helper\ApiTestTrait;
use App\Model\Table\MetaTemplatesTable;
class UpdateMetaTemplateByIdApiTest extends TestCase
{
use ApiTestTrait;
protected const ENDPOINT = '/metaTemplates/update/%d';
protected $fixtures = [
'app.Organisations',
'app.Individuals',
'app.Roles',
'app.Users',
'app.AuthKeys',
'app.MetaTemplates',
'app.MetaTemplateFields'
];
public function testUpdateMetaTemplateById(): void
{
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
// Dump MetaTemplate json file to disk
file_put_contents(
ROOT . '/libraries/default/meta_fields/test.json',
json_encode(MetaTemplatesFixture::ENABLED_TEST_ORG_META_TEMPLATE_SPEC)
);
$url = sprintf(self::ENDPOINT, MetaTemplatesFixture::ENABLED_TEST_ORG_META_TEMPLATE_ID);
$this->post($url, [
'update_strategy' => MetaTemplatesTable::UPDATE_STRATEGY_CREATE_NEW
]);
$this->assertResponseOk();
$response = $this->getJsonResponseAsArray();
$this->assertEmpty($response['update_errors']);
$this->assertNotEmpty($response['files_processed']);
$this->assertTrue($response['success']);
$this->assertDbRecordExists('MetaTemplateFields', [
'field' => 'test_field_2'
]);
// Delete MetaTemplate json file from disk
unlink(ROOT . '/libraries/default/meta_fields/test.json');
}
}

View File

@ -29,6 +29,8 @@ tags:
description: "Authkeys are used for API access. A user can have more than one authkey, so if you would like to use separate keys per tool that queries Cerebrate, add additional keys. Use the comment field to make identifying your keys easier."
- name: LocalTools
description: "Cerebrate can connect to local tools via individual connectors, built to expose the various functionalities of the given tool via Cerebrate. Simply view the connectors' details and the accompanying instance list to manage the connections using the given connector."
- name: MetaTemplates
description: ""
paths:
/individuals/index:
@ -878,6 +880,77 @@ paths:
default:
$ref: "#/components/responses/ApiErrorResponse"
# MetaTemplates
/metaTemplates/createNewTemplate/{metaTemplateUuid}:
post:
summary: "Load a MetaTemplate"
operationId: loadMetaTemplate
tags:
- MetaTemplates
parameters:
- $ref: "#/components/parameters/metaTemplateUuid"
responses:
"200":
$ref: "#/components/responses/LoadMetaTemplateResponse"
"403":
$ref: "#/components/responses/UnauthorizedApiErrorResponse"
"405":
$ref: "#/components/responses/MethodNotAllowedApiErrorResponse"
default:
$ref: "#/components/responses/ApiErrorResponse"
/metaTemplates/toggle/{metaTemplateId}/enabled:
post:
summary: "Toggle MetaTemplate enabled/disabled"
operationId: toggleEnableMetaTemplate
tags:
- MetaTemplates
parameters:
- $ref: "#/components/parameters/metaTemplateId"
responses:
"200":
$ref: "#/components/responses/MetaTemplateResponse"
"403":
$ref: "#/components/responses/UnauthorizedApiErrorResponse"
"405":
$ref: "#/components/responses/MethodNotAllowedApiErrorResponse"
default:
$ref: "#/components/responses/ApiErrorResponse"
/metaTemplates/update/{metaTemplateId}:
post:
summary: "Update MetaTemplate by ID"
operationId: updateMetaTemplateById
tags:
- MetaTemplates
parameters:
- $ref: "#/components/parameters/metaTemplateId"
responses:
"200":
$ref: "#/components/responses/UpdateMetaTemplateResponse"
"403":
$ref: "#/components/responses/UnauthorizedApiErrorResponse"
"405":
$ref: "#/components/responses/MethodNotAllowedApiErrorResponse"
default:
$ref: "#/components/responses/ApiErrorResponse"
/metaTemplates/updateAllTemplates:
post:
summary: "Update all MetaTemplates"
operationId: updateAllMetaTemplates
tags:
- MetaTemplates
responses:
"200":
$ref: "#/components/responses/UpdateMetaTemplateResponse"
"403":
$ref: "#/components/responses/UnauthorizedApiErrorResponse"
"405":
$ref: "#/components/responses/MethodNotAllowedApiErrorResponse"
default:
$ref: "#/components/responses/ApiErrorResponse"
components:
schemas:
# General
@ -1524,6 +1597,65 @@ components:
items:
$ref: "#/components/schemas/LocalTool"
# MetaTemplates
MetaTemplateScope:
type: string
enum:
- "organisation"
MetaTemplateName:
type: string
MetaTemplateNamespace:
type: string
example: "cerebrate"
MetaTemplateDescription:
type: string
MetaTemplateVersion:
type: string
example: "1.0"
MetaTemplateSource:
type: string
example: "Cerebrate"
MetaTemplateIsEnabled:
type: boolean
MetaTemplateIsDefault:
type: boolean
MetaTemplate:
type: object
properties:
id:
$ref: "#/components/schemas/ID"
scope:
$ref: "#/components/schemas/MetaTemplateScope"
name:
$ref: "#/components/schemas/MetaTemplateName"
namespace:
$ref: "#/components/schemas/MetaTemplateNamespace"
description:
$ref: "#/components/schemas/MetaTemplateDescription"
version:
$ref: "#/components/schemas/MetaTemplateVersion"
uuid:
$ref: "#/components/schemas/UUID"
source:
$ref: "#/components/schemas/MetaTemplateSource"
enabled:
$ref: "#/components/schemas/MetaTemplateIsEnabled"
is_default:
$ref: "#/components/schemas/MetaTemplateIsDefault"
created:
$ref: "#/components/schemas/DateTime"
modified:
$ref: "#/components/schemas/DateTime"
# Errors
ApiError:
type: object
@ -1673,6 +1805,22 @@ components:
type: string
example: "user@example.com"
metaTemplateUuid:
name: metaTemplateUuid
in: path
description: "UUID of the MetaTemplate"
required: true
schema:
$ref: "#/components/schemas/UUID"
metaTemplateId:
name: metaTemplateId
in: path
description: "Numeric ID of the MetaTemplate"
required: true
schema:
$ref: "#/components/schemas/ID"
securitySchemes:
ApiKeyAuth:
type: apiKey
@ -2329,6 +2477,57 @@ components:
schema:
$ref: "#/components/schemas/LocalToolList"
# MetaTemplates
MetaTemplateResponse:
description: "MetaTemplate response"
content:
application/json:
schema:
$ref: "#/components/schemas/MetaTemplate"
LoadMetaTemplateResponse:
description: "Load MetaTemplate response"
content:
application/json:
schema:
type: object
properties:
update_errors:
type: array
items:
type: object
properties:
message:
type: string
example: "Cannot update meta-template, update strategy not provided or not allowed"
files_processed:
type: array
items:
$ref: "#/components/schemas/UUID"
success:
type: boolean
UpdateMetaTemplateResponse:
description: "Update MetaTemplate response"
content:
application/json:
schema:
type: object
properties:
update_errors:
type: array
items:
type: object
properties:
message:
type: string
example: "Cannot update meta-template, update strategy not provided or not allowed"
files_processed:
type: array
items:
$ref: "#/components/schemas/UUID"
success:
type: boolean
# Errors
ApiErrorResponse:
description: "Unexpected API error"