Merge branch 'develop' into main
commit
e9f77aff51
|
@ -0,0 +1,52 @@
|
|||
name: test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 5
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04]
|
||||
php: ["7.4"]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Create config files
|
||||
run: |
|
||||
cp ./config/app_local.example.php ./config/app_local.php
|
||||
cp ./config/config.example.json ./config/config.json
|
||||
|
||||
- name: Setup MariaDB
|
||||
uses: getong/mariadb-action@v1.1
|
||||
with:
|
||||
host port: 3306
|
||||
container port: 3306
|
||||
mysql database: "cerebrate_test"
|
||||
mysql user: "cerebrate"
|
||||
mysql password: "cerebrate"
|
||||
|
||||
- name: Setup PHP
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: pdo, pdo_mysql, mysqli, simplexml
|
||||
|
||||
- name: Install dependencies
|
||||
env:
|
||||
php_version: ${{ matrix.php }}
|
||||
run: |
|
||||
sudo apt-get -y update
|
||||
sudo apt-get install -y --no-install-recommends curl git zip unzip libicu-dev libxml2-dev
|
||||
composer install --no-progress --no-interaction
|
||||
|
||||
- name: Run tests
|
||||
run: composer test
|
||||
env:
|
||||
DEBUG: true
|
|
@ -7,3 +7,6 @@ vendor
|
|||
webroot/theme/node_modules
|
||||
.vscode
|
||||
docker/run/
|
||||
.phpunit.result.cache
|
||||
config.json
|
||||
phpunit.xml
|
||||
|
|
|
@ -74,12 +74,6 @@ sudo mysql -e "GRANT ALL PRIVILEGES ON cerebrate.* to cerebrate@localhost;"
|
|||
sudo mysql -e "FLUSH PRIVILEGES;"
|
||||
```
|
||||
|
||||
Load the default table structure into the database
|
||||
|
||||
```bash
|
||||
sudo mysql -u cerebrate -p cerebrate < /var/www/cerebrate/INSTALL/mysql.sql
|
||||
```
|
||||
|
||||
create your local configuration and set the db credentials
|
||||
|
||||
```bash
|
||||
|
|
|
@ -1,408 +0,0 @@
|
|||
-- MySQL dump 10.16 Distrib 10.1.44-MariaDB, for debian-linux-gnu (x86_64)
|
||||
--
|
||||
-- Host: localhost Database: cerebrate
|
||||
-- ------------------------------------------------------
|
||||
-- Server version 10.1.44-MariaDB-0ubuntu0.18.04.1
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
--
|
||||
-- Table structure for table `alignment_tags`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `alignment_tags` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`alignment_id` int(10) unsigned NOT NULL,
|
||||
`tag_id` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `alignment_id` (`alignment_id`),
|
||||
KEY `tag_id` (`tag_id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_1` FOREIGN KEY (`alignment_id`) REFERENCES `alignments` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_10` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_11` FOREIGN KEY (`alignment_id`) REFERENCES `alignments` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_12` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_3` FOREIGN KEY (`alignment_id`) REFERENCES `alignments` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_4` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_5` FOREIGN KEY (`alignment_id`) REFERENCES `alignments` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_6` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_7` FOREIGN KEY (`alignment_id`) REFERENCES `alignments` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_8` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`),
|
||||
CONSTRAINT `alignment_tags_ibfk_9` FOREIGN KEY (`alignment_id`) REFERENCES `alignments` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `alignments`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `alignments` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`individual_id` int(10) unsigned NOT NULL,
|
||||
`organisation_id` int(10) unsigned NOT NULL,
|
||||
`type` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT 'member',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `individual_id` (`individual_id`),
|
||||
KEY `organisation_id` (`organisation_id`),
|
||||
CONSTRAINT `alignments_ibfk_1` FOREIGN KEY (`individual_id`) REFERENCES `individuals` (`id`),
|
||||
CONSTRAINT `alignments_ibfk_2` FOREIGN KEY (`organisation_id`) REFERENCES `organisations` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `auth_keys`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `auth_keys` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`uuid` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`authkey` varchar(72) CHARACTER SET ascii DEFAULT NULL,
|
||||
`authkey_start` varchar(4) CHARACTER SET ascii DEFAULT NULL,
|
||||
`authkey_end` varchar(4) CHARACTER SET ascii DEFAULT NULL,
|
||||
`created` int(10) unsigned NOT NULL,
|
||||
`expiration` int(10) unsigned NOT NULL,
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`comment` text COLLATE utf8mb4_unicode_ci,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `authkey_start` (`authkey_start`),
|
||||
KEY `authkey_end` (`authkey_end`),
|
||||
KEY `created` (`created`),
|
||||
KEY `expiration` (`expiration`),
|
||||
KEY `user_id` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `broods`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `broods` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`uuid` varchar(40) CHARACTER SET ascii DEFAULT NULL,
|
||||
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`url` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`description` text COLLATE utf8mb4_unicode_ci,
|
||||
`organisation_id` int(10) unsigned NOT NULL,
|
||||
`trusted` tinyint(1) DEFAULT NULL,
|
||||
`pull` tinyint(1) DEFAULT NULL,
|
||||
`skip_proxy` tinyint(1) DEFAULT NULL,
|
||||
`authkey` varchar(40) CHARACTER SET ascii DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `uuid` (`uuid`),
|
||||
KEY `name` (`name`),
|
||||
KEY `url` (`url`),
|
||||
KEY `authkey` (`authkey`),
|
||||
KEY `organisation_id` (`organisation_id`),
|
||||
FOREIGN KEY (`organisation_id`) REFERENCES `organisations` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `encryption_keys`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `encryption_keys` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`uuid` varchar(40) CHARACTER SET ascii DEFAULT NULL,
|
||||
`type` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`encryption_key` text COLLATE utf8mb4_unicode_ci,
|
||||
`revoked` tinyint(1) DEFAULT NULL,
|
||||
`expires` int(10) unsigned DEFAULT NULL,
|
||||
`owner_id` int(10) unsigned DEFAULT NULL,
|
||||
`owner_type` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `uuid` (`uuid`),
|
||||
KEY `type` (`type`),
|
||||
KEY `expires` (`expires`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `individual_encryption_keys`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `individual_encryption_keys` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`individual_id` int(10) unsigned NOT NULL,
|
||||
`encryption_key_id` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `individual_id` (`individual_id`),
|
||||
KEY `encryption_key_id` (`encryption_key_id`),
|
||||
CONSTRAINT `individual_encryption_keys_ibfk_1` FOREIGN KEY (`individual_id`) REFERENCES `individuals` (`id`),
|
||||
CONSTRAINT `individual_encryption_keys_ibfk_2` FOREIGN KEY (`encryption_key_id`) REFERENCES `encryption_keys` (`id`),
|
||||
CONSTRAINT `individual_encryption_keys_ibfk_3` FOREIGN KEY (`individual_id`) REFERENCES `individuals` (`id`),
|
||||
CONSTRAINT `individual_encryption_keys_ibfk_4` FOREIGN KEY (`encryption_key_id`) REFERENCES `encryption_keys` (`id`),
|
||||
CONSTRAINT `individual_encryption_keys_ibfk_5` FOREIGN KEY (`individual_id`) REFERENCES `individuals` (`id`),
|
||||
CONSTRAINT `individual_encryption_keys_ibfk_6` FOREIGN KEY (`encryption_key_id`) REFERENCES `encryption_keys` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `individuals`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `individuals` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`uuid` varchar(40) CHARACTER SET ascii DEFAULT NULL,
|
||||
`email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`first_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`last_name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`position` text COLLATE utf8mb4_unicode_ci,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `uuid` (`uuid`),
|
||||
KEY `email` (`email`),
|
||||
KEY `first_name` (`first_name`),
|
||||
KEY `last_name` (`last_name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `local_tools`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `local_tools` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`connector` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`settings` text COLLATE utf8mb4_unicode_ci,
|
||||
`exposed` tinyint(1) NOT NULL,
|
||||
`description` text COLLATE utf8mb4_unicode_ci,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `name` (`name`),
|
||||
KEY `connector` (`connector`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
--
|
||||
-- Table structure for table `organisation_encryption_keys`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `organisation_encryption_keys` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`organisation_id` int(10) unsigned NOT NULL,
|
||||
`encryption_key_id` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `organisation_id` (`organisation_id`),
|
||||
KEY `encryption_key_id` (`encryption_key_id`),
|
||||
CONSTRAINT `organisation_encryption_keys_ibfk_1` FOREIGN KEY (`organisation_id`) REFERENCES `organisations` (`id`),
|
||||
CONSTRAINT `organisation_encryption_keys_ibfk_2` FOREIGN KEY (`encryption_key_id`) REFERENCES `encryption_keys` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `organisations`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `organisations` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`uuid` varchar(40) CHARACTER SET ascii DEFAULT NULL,
|
||||
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`url` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`nationality` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`sector` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`type` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`contacts` text COLLATE utf8mb4_unicode_ci,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `uuid` (`uuid`),
|
||||
KEY `name` (`name`),
|
||||
KEY `url` (`url`),
|
||||
KEY `nationality` (`nationality`),
|
||||
KEY `sector` (`sector`),
|
||||
KEY `type` (`type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `roles`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `roles` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`uuid` varchar(40) CHARACTER SET ascii DEFAULT NULL,
|
||||
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`is_default` tinyint(1) DEFAULT NULL,
|
||||
`perm_admin` tinyint(1) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `name` (`name`),
|
||||
KEY `uuid` (`uuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `tags`
|
||||
--
|
||||
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE IF NOT EXISTS `tags` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`description` text COLLATE utf8mb4_unicode_ci,
|
||||
`colour` varchar(6) CHARACTER SET ascii NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `name` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `users`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`uuid` varchar(40) CHARACTER SET ascii DEFAULT NULL,
|
||||
`username` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`password` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||
`role_id` int(11) unsigned NOT NULL,
|
||||
`individual_id` int(11) unsigned NOT NULL,
|
||||
`disabled` tinyint(1) DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `uuid` (`uuid`),
|
||||
KEY `role_id` (`role_id`),
|
||||
KEY `individual_id` (`individual_id`),
|
||||
CONSTRAINT `users_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`),
|
||||
CONSTRAINT `users_ibfk_2` FOREIGN KEY (`individual_id`) REFERENCES `individuals` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sharing_groups` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`uuid` varchar(40) CHARACTER SET ascii DEFAULT NULL,
|
||||
`name` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||
`releasability` text DEFAULT NULL,
|
||||
`description` text DEFAULT NULL,
|
||||
`organisation_id` int(10) unsigned NOT NULL,
|
||||
`user_id` int(10) unsigned NOT NULL,
|
||||
`active` tinyint(1) DEFAULT '1',
|
||||
`local` tinyint(1) DEFAULT '1',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `uuid` (`uuid`),
|
||||
KEY `user_id` (`user_id`),
|
||||
KEY `organisation_id` (`organisation_id`),
|
||||
KEY `name` (`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `sgo` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`sharing_group_id` int(10) unsigned NOT NULL,
|
||||
`organisation_id` int(10) unsigned NOT NULL,
|
||||
`deleted` tinyint(1) DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `sharing_group_id` (`sharing_group_id`),
|
||||
KEY `organisation_id` (`organisation_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `meta_fields` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`scope` varchar(191) NOT NULL,
|
||||
`parent_id` int(10) unsigned NOT NULL,
|
||||
`field` varchar(191) NOT NULL,
|
||||
`value` varchar(191) NOT NULL,
|
||||
`uuid` varchar(40) CHARACTER SET ascii DEFAULT NULL,
|
||||
`meta_template_id` int(10) unsigned NOT NULL,
|
||||
`meta_template_field_id` int(10) unsigned NOT NULL,
|
||||
`is_default` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `scope` (`scope`),
|
||||
KEY `uuid` (`uuid`),
|
||||
KEY `parent_id` (`parent_id`),
|
||||
KEY `field` (`field`),
|
||||
KEY `value` (`value`),
|
||||
KEY `meta_template_id` (`meta_template_id`),
|
||||
KEY `meta_template_field_id` (`meta_template_field_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `meta_templates` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`scope` varchar(191) NOT NULL,
|
||||
`name` varchar(191) NOT NULL,
|
||||
`namespace` varchar(191) NOT NULL,
|
||||
`description` text,
|
||||
`version` varchar(191) NOT NULL,
|
||||
`uuid` varchar(40) CHARACTER SET ascii,
|
||||
`source` varchar(191),
|
||||
`enabled` tinyint(1) DEFAULT 0,
|
||||
`is_default` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `scope` (`scope`),
|
||||
KEY `source` (`source`),
|
||||
KEY `name` (`name`),
|
||||
KEY `namespace` (`namespace`),
|
||||
KEY `version` (`version`),
|
||||
KEY `uuid` (`uuid`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `meta_template_fields` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`field` varchar(191) NOT NULL,
|
||||
`type` varchar(191) NOT NULL,
|
||||
`meta_template_id` int(10) unsigned NOT NULL,
|
||||
`regex` text,
|
||||
`multiple` tinyint(1) DEFAULT 0,
|
||||
`enabled` tinyint(1) DEFAULT 0,
|
||||
PRIMARY KEY (`id`),
|
||||
CONSTRAINT `meta_template_id` FOREIGN KEY (`meta_template_id`) REFERENCES `meta_templates` (`id`),
|
||||
KEY `field` (`field`),
|
||||
KEY `type` (`type`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `audit_logs` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`created` datetime NOT NULL,
|
||||
`user_id` int(10) unsigned DEFAULT NULL,
|
||||
`authkey_id` int(10) unsigned DEFAULT NULL,
|
||||
`request_ip` varbinary(16) DEFAULT NULL,
|
||||
`request_type` tinyint NOT NULL,
|
||||
`request_id` varchar(191) DEFAULT NULL,
|
||||
`request_action` varchar(20) NOT NULL,
|
||||
`model` varchar(80) NOT NULL,
|
||||
`model_id` int(10) unsigned DEFAULT NULL,
|
||||
`model_title` text DEFAULT NULL,
|
||||
`change` blob,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `user_id` (`user_id`),
|
||||
KEY `request_ip` (`request_ip`),
|
||||
KEY `model` (`model`),
|
||||
KEY `request_action` (`request_action`),
|
||||
KEY `model_id` (`model_id`),
|
||||
KEY `created` (`created`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2020-06-22 14:30:02
|
|
@ -19,9 +19,12 @@
|
|||
"cakephp/bake": "^2.0.3",
|
||||
"cakephp/cakephp-codesniffer": "~4.0.0",
|
||||
"cakephp/debug_kit": "^4.0",
|
||||
"fzaninotto/faker": "^1.9",
|
||||
"josegonzalez/dotenv": "^3.2",
|
||||
"league/openapi-psr7-validator": "^0.16.4",
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"psy/psysh": "@stable"
|
||||
"psy/psysh": "@stable",
|
||||
"wiremock-php/wiremock-php": "^2.32"
|
||||
},
|
||||
"suggest": {
|
||||
"markstory/asset_compress": "An asset compression plugin which provides file concatenation and a flexible filter system for preprocessing and minification.",
|
||||
|
@ -44,7 +47,6 @@
|
|||
"scripts": {
|
||||
"post-install-cmd": "App\\Console\\Installer::postInstall",
|
||||
"post-create-project-cmd": "App\\Console\\Installer::postInstall",
|
||||
"post-autoload-dump": "Cake\\Composer\\Installer\\PluginInstaller::postAutoloadDump",
|
||||
"check": [
|
||||
"@test",
|
||||
"@cs-check"
|
||||
|
@ -52,7 +54,11 @@
|
|||
"cs-check": "phpcs --colors -p --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/",
|
||||
"cs-fix": "phpcbf --colors --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/",
|
||||
"stan": "phpstan analyse src/",
|
||||
"test": "phpunit --colors=always"
|
||||
"test": [
|
||||
"nohup sh ./tests/Helper/wiremock/start.sh >/dev/null 2>&1 &",
|
||||
"phpunit",
|
||||
"sh ./tests/Helper/wiremock/stop.sh"
|
||||
]
|
||||
},
|
||||
"prefer-stable": true,
|
||||
"config": {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -73,12 +73,10 @@ return [
|
|||
* The test connection is used during the test suite.
|
||||
*/
|
||||
'test' => [
|
||||
'host' => 'localhost',
|
||||
//'port' => 'non_standard_port_number',
|
||||
'username' => 'my_app',
|
||||
'password' => 'secret',
|
||||
'database' => 'test_myapp',
|
||||
//'schema' => 'myapp',
|
||||
'host' => '127.0.0.1',
|
||||
'username' => 'cerebrate',
|
||||
'password' => 'cerebrate',
|
||||
'database' => 'cerebrate_test',
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
@ -7,4 +7,3 @@ webroot /usr/share/php-cerebrate
|
|||
config /usr/share/php-cerebrate
|
||||
debian/cerebrate.local.conf /etc/apache2/sites-available/
|
||||
debian/config.php /etc/cerebrate/
|
||||
INSTALL/mysql.sql => /usr/share/dbconfig-common/data/php-cerebrate/install/mysql
|
||||
|
|
|
@ -1,20 +1,3 @@
|
|||
# Database init
|
||||
|
||||
For the `docker-compose` setup to work you must initialize database with
|
||||
what is in `../INSTALL/mysql.sql`
|
||||
|
||||
```
|
||||
mkdir -p run/dbinit/
|
||||
cp ../INSTALL/mysql.sql run/dbinit/
|
||||
```
|
||||
|
||||
The MariaDB container has a volume mounted as follow
|
||||
`- ./run/dbinit:/docker-entrypoint-initdb.d/:ro`
|
||||
|
||||
So that on startup the container will source files in this directory to seed
|
||||
the database. Once it's done the container will run normally and Cerebrate will
|
||||
be able to roll its database migration scripts
|
||||
|
||||
# Actual data and volumes
|
||||
|
||||
The actual database will be located in `./run/database` exposed with the
|
||||
|
|
|
@ -5,7 +5,6 @@ services:
|
|||
restart: always
|
||||
volumes:
|
||||
- ./run/database:/var/lib/mysql
|
||||
- ./run/dbinit:/docker-entrypoint-initdb.d/:ro
|
||||
environment:
|
||||
MARIADB_RANDOM_ROOT_PASSWORD: "yes"
|
||||
MYSQL_DATABASE: "cerebrate"
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
# Prerequisites based on usecases
|
||||
|
||||
This document list the requirements that have to be met in order to perform the desired usecase.
|
||||
|
||||
## Connect a local tool to cerebrate
|
||||
- **Networking**: The *cerebrate* application must be able to contact the local tool service. That means the address and the port of the local tool must be reachable by *cerebrate*.
|
||||
- **User permissions**: Depends on the actions performed by Cerebrate on the local tool.
|
||||
- Example: For a standard MISP configuration, a simple user with the `user` role is enough for Cerebrate to pass the health check.
|
||||
|
||||
## Conect two cerebrate instances together
|
||||
- **Networking**: The two *cerebrate* applications must be able to contact each others. That means the address and the port of both tools must be reachable by the other one.
|
||||
- **User permissions**: No specific role or set of permission is required. Any user role can be used.
|
||||
|
||||
## Connect two local tools through cerebrate
|
||||
- **Networking**: The two *cerebrate* applications must be able to contact each others. That means the address and the port of both tools must be reachable by the other one. This also applies to both the local tools.
|
||||
- **User permissions**: Depends on the actions performed by Cerebrate on the local tool.
|
||||
- Example: For a standard MISP configuration, in order to have two instance connected, the API key used by *cebrate* to orchestrate the inter-connection must belong to a user having the `site-admin` permission flag. This is essential as only the `site-admin` permission allows to create synchronisation links between MISP instances.
|
|
@ -1,13 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit
|
||||
colors="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
bootstrap="tests/bootstrap.php"
|
||||
>
|
||||
<phpunit colors="true" processIsolation="false" stopOnFailure="false" bootstrap="tests/bootstrap.php">
|
||||
<php>
|
||||
<ini name="memory_limit" value="-1" />
|
||||
<ini name="apc.enable_cli" value="1" />
|
||||
<env name="WIREMOCK_HOST" value="localhost" />
|
||||
<env name="WIREMOCK_PORT" value="8080" />
|
||||
<env name="OPENAPI_SPEC" value="webroot/docs/openapi.yaml" />
|
||||
<env name="SKIP_DB_MIGRATIONS" value="0" />
|
||||
</php>
|
||||
|
||||
<!-- Add any additional test suites you want to run here -->
|
||||
|
@ -15,17 +14,17 @@
|
|||
<testsuite name="app">
|
||||
<directory>tests/TestCase/</directory>
|
||||
</testsuite>
|
||||
<!-- Add plugin test suites here. -->
|
||||
<testsuite name="controller">
|
||||
<directory>./tests/TestCase/Controller</directory>
|
||||
</testsuite>
|
||||
<testsuite name="api">
|
||||
<directory>./tests/TestCase/Api</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<!-- Setup a listener for fixtures -->
|
||||
<listeners>
|
||||
<listener class="Cake\TestSuite\Fixture\FixtureInjector">
|
||||
<arguments>
|
||||
<object class="Cake\TestSuite\Fixture\FixtureManager"/>
|
||||
</arguments>
|
||||
</listener>
|
||||
</listeners>
|
||||
<extensions>
|
||||
<extension class="\Cake\TestSuite\Fixture\PHPUnitExtension" />
|
||||
</extensions>
|
||||
|
||||
<!-- Ignore vendor tests in code coverage reports -->
|
||||
<filter>
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Controller\AppController;
|
||||
|
||||
class ApiController extends AppController
|
||||
{
|
||||
/**
|
||||
* Controller action for displaying built-in Redoc UI
|
||||
*
|
||||
* @return \Cake\Http\Response|null|void Renders view
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$url = '/docs/openapi.yaml';
|
||||
$this->set('url', $url);
|
||||
}
|
||||
}
|
|
@ -194,6 +194,9 @@ class ACLComponent extends Component
|
|||
'getBookmarks' => ['*'],
|
||||
'saveBookmark' => ['*'],
|
||||
'deleteBookmark' => ['*']
|
||||
],
|
||||
'Api' => [
|
||||
'index' => ['*']
|
||||
]
|
||||
);
|
||||
|
||||
|
|
|
@ -45,7 +45,12 @@ class Sidemenu {
|
|||
'label' => __('Broods'),
|
||||
'icon' => $this->iconTable['Broods'],
|
||||
'url' => '/broods/index',
|
||||
]
|
||||
],
|
||||
'API' => [
|
||||
'label' => __('API'),
|
||||
'icon' => $this->iconTable['API'],
|
||||
'url' => '/api/index',
|
||||
],
|
||||
],
|
||||
__('Administration') => [
|
||||
'Roles' => [
|
||||
|
|
|
@ -34,6 +34,7 @@ class NavigationComponent extends Component
|
|||
'LocalTools' => 'tools',
|
||||
'Instance' => 'server',
|
||||
'Tags' => 'tags',
|
||||
'API' => 'code',
|
||||
];
|
||||
|
||||
public function initialize(array $config): void
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Controller\Component;
|
|||
|
||||
use Cake\Controller\Component;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Http\Exception\MethodNotAllowedException;
|
||||
|
||||
class ParamHandlerComponent extends Component
|
||||
{
|
||||
|
@ -47,7 +48,7 @@ class ParamHandlerComponent extends Component
|
|||
return $this->isRest;
|
||||
}
|
||||
if ($this->request->is('json')) {
|
||||
if (!empty($this->request->input()) && empty($this->request->input('json_decode'))) {
|
||||
if (!empty((string)$this->request->getBody()) && empty($this->request->getParsedBody())) {
|
||||
throw new MethodNotAllowedException('Invalid JSON input. Make sure that the JSON input is a correctly formatted JSON string. This request has been blocked to avoid an unfiltered request.');
|
||||
}
|
||||
$this->isRest = true;
|
||||
|
|
|
@ -24,21 +24,24 @@ class CommonConnectorTools
|
|||
|
||||
public function __construct()
|
||||
{
|
||||
Log::setConfig("LocalToolDebug", [
|
||||
if (empty(Log::getConfig("LocalToolDebug{$this->connectorName}"))) {
|
||||
Log::setConfig("LocalToolDebug{$this->connectorName}", [
|
||||
'className' => FileLog::class,
|
||||
'path' => LOGS,
|
||||
'file' => "{$this->connectorName}-debug",
|
||||
'scopes' => [$this->connectorName],
|
||||
'levels' => ['notice', 'info', 'debug'],
|
||||
]);
|
||||
Log::setConfig("LocalToolError", [
|
||||
}
|
||||
if (empty(Log::getConfig("LocalToolError{$this->connectorName}"))) {
|
||||
Log::setConfig("LocalToolError{$this->connectorName}", [
|
||||
'className' => FileLog::class,
|
||||
'path' => LOGS,
|
||||
'file' => "{$this->connectorName}-error",
|
||||
'scopes' => [$this->connectorName],
|
||||
'levels' => ['warning', 'error', 'critical', 'alert', 'emergency'],
|
||||
]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected function logDebug($message)
|
||||
|
|
|
@ -164,7 +164,7 @@ class AuditLogsTable extends AppTable
|
|||
return $this->user;
|
||||
}
|
||||
|
||||
$this->user = ['id' => 0, /*'org_id' => 0, */'authkey_id' => 0, 'request_type' => self::REQUEST_TYPE_DEFAULT];
|
||||
$this->user = ['id' => 0, /*'org_id' => 0, */'authkey_id' => 0, 'request_type' => self::REQUEST_TYPE_DEFAULT, 'name' => ''];
|
||||
|
||||
$isShell = (php_sapi_name() === 'cli');
|
||||
if ($isShell) {
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<redoc spec-url='<?php echo $url ?>'></redoc>
|
||||
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
|
@ -11,7 +11,10 @@ use Cake\Routing\Router;
|
|||
<div class="fw-light"><?= __('Logged in as') ?></div>
|
||||
<div>
|
||||
<?= $this->SocialProvider->getIcon($this->request->getAttribute('identity')) ?>
|
||||
[<?= h($loggedUser['organisation']['name']) ?>] <strong><?= h($this->request->getAttribute('identity')['username']) ?></strong>
|
||||
<span class="ms-1 me-3">
|
||||
[<?= h($loggedUser['organisation']['name']) ?>]
|
||||
<strong><?= h($this->request->getAttribute('identity')['username']) ?></strong>
|
||||
</span>
|
||||
</div>
|
||||
</h6>
|
||||
<div class="dropdown-divider"></div>
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
use Authentication\PasswordHasher\DefaultPasswordHasher;
|
||||
|
||||
class AuthKeysFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
public const ADMIN_API_ID = 1;
|
||||
public const ADMIN_API_KEY = 'd033e22ae348aeb5660fc2140aec35850c4da997';
|
||||
|
||||
|
||||
public const SYNC_API_ID = 2;
|
||||
public const SYNC_API_KEY = '6b387ced110858dcbcda36edb044dc18f91a0894';
|
||||
|
||||
|
||||
public const ORG_ADMIN_API_ID = 3;
|
||||
public const ORG_ADMIN_API_KEY = '1c4685d281d478dbcebd494158024bc3539004d0';
|
||||
|
||||
public const REGULAR_USER_API_ID = 4;
|
||||
public const REGULAR_USER_API_KEY = '12dea96fec20593566ab75692c9949596833adc9';
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$hasher = new DefaultPasswordHasher();
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::ADMIN_API_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'authkey' => $hasher->hash(self::ADMIN_API_KEY),
|
||||
'authkey_start' => substr(self::ADMIN_API_KEY, 0, 4),
|
||||
'authkey_end' => substr(self::ADMIN_API_KEY, -4),
|
||||
'expiration' => 0,
|
||||
'user_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'comment' => '',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::SYNC_API_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'authkey' => $hasher->hash(self::SYNC_API_KEY),
|
||||
'authkey_start' => substr(self::SYNC_API_KEY, 0, 4),
|
||||
'authkey_end' => substr(self::SYNC_API_KEY, -4),
|
||||
'expiration' => 0,
|
||||
'user_id' => UsersFixture::USER_SYNC_ID,
|
||||
'comment' => '',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::ORG_ADMIN_API_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'authkey' => $hasher->hash(self::ORG_ADMIN_API_KEY),
|
||||
'authkey_start' => substr(self::ORG_ADMIN_API_KEY, 0, 4),
|
||||
'authkey_end' => substr(self::ORG_ADMIN_API_KEY, -4),
|
||||
'expiration' => 0,
|
||||
'user_id' => UsersFixture::USER_ORG_ADMIN_ID,
|
||||
'comment' => '',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::REGULAR_USER_API_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'authkey' => $hasher->hash(self::REGULAR_USER_API_KEY),
|
||||
'authkey_start' => substr(self::REGULAR_USER_API_KEY, 0, 4),
|
||||
'authkey_end' => substr(self::REGULAR_USER_API_KEY, -4),
|
||||
'expiration' => 0,
|
||||
'user_id' => UsersFixture::USER_REGULAR_USER_ID,
|
||||
'comment' => '',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
]
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class BroodsFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
public const BROOD_A_ID = 1;
|
||||
public const BROOD_A_API_KEY = '6dcd4ce23d88e2ee9568ba546c007c63d9131c1b';
|
||||
|
||||
public const BROOD_B_ID = 2;
|
||||
public const BROOD_B_API_KEY = 'ae4f281df5a5d0ff3cad6371f76d5c29b6d953ec';
|
||||
|
||||
public const BROOD_WIREMOCK_ID = 3;
|
||||
public const BROOD_WIREMOCK_API_KEY = 'bfc63c07f74fa18b52d3cced97072cad00e51346';
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::BROOD_A_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'Brood A',
|
||||
'url' => $faker->url,
|
||||
'description' => $faker->text,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'trusted' => true,
|
||||
'pull' => true,
|
||||
'skip_proxy' => true,
|
||||
'authkey' => self::BROOD_A_API_KEY,
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::BROOD_B_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'Brood A',
|
||||
'url' => $faker->url,
|
||||
'description' => $faker->text,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_B_ID,
|
||||
'trusted' => true,
|
||||
'pull' => true,
|
||||
'skip_proxy' => true,
|
||||
'authkey' => self::BROOD_B_API_KEY,
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::BROOD_WIREMOCK_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'wiremock',
|
||||
'url' => 'http://localhost:8080',
|
||||
'description' => $faker->text,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_B_ID,
|
||||
'trusted' => true,
|
||||
'pull' => true,
|
||||
'skip_proxy' => true,
|
||||
'authkey' => self::BROOD_WIREMOCK_API_KEY,
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
]
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\Http\Exception\NotImplementedException;
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class EncryptionKeysFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
public const ENCRYPTION_KEY_ORG_A_ID = 1;
|
||||
public const ENCRYPTION_KEY_ORG_B_ID = 2;
|
||||
|
||||
public const TYPE_PGP = 'pgp';
|
||||
public const TYPE_SMIME = 'smime';
|
||||
|
||||
public const KEY_TYPE_EDCH = 'EDCH';
|
||||
public const KEY_TYPE_RSA = 'RSA';
|
||||
public const KEY_TYPE_SMIME = 'S/MIME';
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::ENCRYPTION_KEY_ORG_A_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'type' => self::TYPE_PGP,
|
||||
'encryption_key' => $this->getPublicKey(self::KEY_TYPE_EDCH),
|
||||
'revoked' => false,
|
||||
'expires' => null,
|
||||
'owner_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'owner_model' => 'Organisation',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::ENCRYPTION_KEY_ORG_B_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'type' => self::TYPE_PGP,
|
||||
'encryption_key' => $this->getPublicKey(self::KEY_TYPE_EDCH),
|
||||
'revoked' => false,
|
||||
'expires' => null,
|
||||
'owner_id' => OrganisationsFixture::ORGANISATION_B_ID,
|
||||
'owner_model' => 'Organisation',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
|
||||
public static function getPublicKey(string $type): string
|
||||
{
|
||||
switch ($type) {
|
||||
case self::KEY_TYPE_EDCH:
|
||||
return <<<EOD
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: OpenPGP v1.0.0
|
||||
|
||||
xm8EYeaEmhMFK4EEACIDAwTS1DNpEsyLo6ynsxJhe1J1k75OYGjkiYgj+4157e06
|
||||
m8uNX9TRI3XKAKUs2ecG6Iv6beXpvLHcBu/GqwYnpLigpABkhLbUob5spIg+OqNA
|
||||
l0U75pLyshmQ8DOWupjq2ZTNG2Zvb2JhciA8Zm9vYmFyQGV4YW1wbGUuY29tPsKP
|
||||
BBMTCgAXBQJh5oSaAhsvAwsJBwMVCggCHgECF4AACgkQfYJ4NsWgZlqadgF6Apv0
|
||||
S3JrJgmUejRVaMBoAlGlME6OibfAo/faYyOhO/tb0Kw8MYfrF27D+N3/TR8BAX0e
|
||||
KhJvhcoHZlcb6E+xUvAT9zYyCpX6g1s2rU9qeLJEbWeEiz7/e1diYgQ2TuuJTr/O
|
||||
UgRh5oSaEwgqhkjOPQMBBwIDBHTGkUJ9McCAGMB9/jhzJJ9arYLIdMUwHbxf68K3
|
||||
yQaiQf2F0BUciz37I2pFPBV17CJzsHdoIG4rhrU4PI+srzvCwCcEGBMKAA8FAmHm
|
||||
hJoFCQ8JnAACGy4AagkQfYJ4NsWgZlpfIAQZEwoABgUCYeaEmgAKCRC+TAWGbVzh
|
||||
xvHIAP9C6iogC55FEE8XuQ2g6dPyIyou940sLQIYKdFpG2CTnwEAvosKiPEC+bwC
|
||||
b75QibMSCGlYPOIO5WW9OqJyT4I59bwH4QF+KRv6b3wOoFz8/ptDyIbFpNSoBrDT
|
||||
9D35Gk9oVSZg9FDeQunGRt2qkvfDxBMecPWXAYDlNTFtdBUWeXeMLJlEr5YyC3SA
|
||||
RIbej4EnbpXmhdODjKLv1p5tAOw/lgEfQKzBEwbOUgRh5oSaEwgqhkjOPQMBBwID
|
||||
BO9vsx/0+act9x1hNk0LHxE/PELjL2Abn/JBjAIvGgTmiZc5Vkb2XrUYAoOhKI4G
|
||||
ab9UTnlGznER74SWWLELUt7CwCcEGBMKAA8FAmHmhJoFCQ8JnAACGy4AagkQfYJ4
|
||||
NsWgZlpfIAQZEwoABgUCYeaEmgAKCRC5+NJ8Prn4UPSRAQCH7Ek29Z9ivuvIaj6n
|
||||
2AYdgHZHBEYAg5uwSBchPRXBHwD/QxRRAyKnwdmTLJzaB7M82bHLRU5WXbEgqucv
|
||||
9HuQpkiv6wGA2NVSulEz7VxxKIcaU8xQRrStIBXqMvNo/13kdlq2YWQ6EZnG7EU7
|
||||
ExIU8Y2OkuFWAX9gLoJCjxfMuH5u27nNkztxL4SgORfCxWRg6VaVAFXX21dlQwIf
|
||||
XUzE5dzw+nOspVE=
|
||||
=WnCK
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
EOD;
|
||||
default:
|
||||
throw new NotImplementedException('Unknown key type');
|
||||
}
|
||||
}
|
||||
|
||||
private static function getPrivateKey(string $type): string
|
||||
{
|
||||
switch ($type) {
|
||||
case self::KEY_TYPE_EDCH:
|
||||
return <<<EOD
|
||||
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
Version: OpenPGP v1.0.0
|
||||
|
||||
xcASBGHmhJoTBSuBBAAiAwME0tQzaRLMi6Osp7MSYXtSdZO+TmBo5ImII/uNee3t
|
||||
OpvLjV/U0SN1ygClLNnnBuiL+m3l6byx3AbvxqsGJ6S4oKQAZIS21KG+bKSIPjqj
|
||||
QJdFO+aS8rIZkPAzlrqY6tmU/gkDCCcuNcl1iEuoYIjwDlg5yqzxdXu9Q7V+WvBf
|
||||
OflkWwIGYLjrqcDWNZqz9v4alO8/uKPZoRyYmQx3yBxjgrNs4bjibFxc43oTlHtD
|
||||
JA7m+Ba4cWyMVFJ96TPXAvI5fAJszRtmb29iYXIgPGZvb2JhckBleGFtcGxlLmNv
|
||||
bT7CjwQTEwoAFwUCYeaEmgIbLwMLCQcDFQoIAh4BAheAAAoJEH2CeDbFoGZamnYB
|
||||
egKb9EtyayYJlHo0VWjAaAJRpTBOjom3wKP32mMjoTv7W9CsPDGH6xduw/jd/00f
|
||||
AQF9HioSb4XKB2ZXG+hPsVLwE/c2MgqV+oNbNq1PaniyRG1nhIs+/3tXYmIENk7r
|
||||
iU6/x6UEYeaEmhMIKoZIzj0DAQcCAwR0xpFCfTHAgBjAff44cySfWq2CyHTFMB28
|
||||
X+vCt8kGokH9hdAVHIs9+yNqRTwVdewic7B3aCBuK4a1ODyPrK87/gkDCCiGr5A8
|
||||
Yq+pYCpNvctmdVC3wwN+LNpiXHtkYWD37TdpwrdR0h8H/PSZFdHgkyK3tqmxPApC
|
||||
S3+s+cBzza5mTPqaq/7Cc6ck40juXNBIC8rCwCcEGBMKAA8FAmHmhJoFCQ8JnAAC
|
||||
Gy4AagkQfYJ4NsWgZlpfIAQZEwoABgUCYeaEmgAKCRC+TAWGbVzhxvHIAP9C6iog
|
||||
C55FEE8XuQ2g6dPyIyou940sLQIYKdFpG2CTnwEAvosKiPEC+bwCb75QibMSCGlY
|
||||
POIO5WW9OqJyT4I59bwH4QF+KRv6b3wOoFz8/ptDyIbFpNSoBrDT9D35Gk9oVSZg
|
||||
9FDeQunGRt2qkvfDxBMecPWXAYDlNTFtdBUWeXeMLJlEr5YyC3SARIbej4EnbpXm
|
||||
hdODjKLv1p5tAOw/lgEfQKzBEwbHpQRh5oSaEwgqhkjOPQMBBwIDBO9vsx/0+act
|
||||
9x1hNk0LHxE/PELjL2Abn/JBjAIvGgTmiZc5Vkb2XrUYAoOhKI4Gab9UTnlGznER
|
||||
74SWWLELUt7+CQMI0o+tsXn5S31gHyPTI5yRG0I7dZg4OrU+tCu11AYzC4y3aO0M
|
||||
E2tixY7BDHIgtiWkeDWo8j4f8zYhBL9x/M3mpinZ6vQEhOdED+8shBmPNMLAJwQY
|
||||
EwoADwUCYeaEmgUJDwmcAAIbLgBqCRB9gng2xaBmWl8gBBkTCgAGBQJh5oSaAAoJ
|
||||
ELn40nw+ufhQ9JEBAIfsSTb1n2K+68hqPqfYBh2AdkcERgCDm7BIFyE9FcEfAP9D
|
||||
FFEDIqfB2ZMsnNoHszzZsctFTlZdsSCq5y/0e5CmSK/rAYDY1VK6UTPtXHEohxpT
|
||||
zFBGtK0gFeoy82j/XeR2WrZhZDoRmcbsRTsTEhTxjY6S4VYBf2AugkKPF8y4fm7b
|
||||
uc2TO3EvhKA5F8LFZGDpVpUAVdfbV2VDAh9dTMTl3PD6c6ylUQ==
|
||||
=96JC
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
||||
EOD;
|
||||
default:
|
||||
throw new NotImplementedException('Unknown key type');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class InboxFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
public $table = 'inbox';
|
||||
|
||||
public const INBOX_USER_REGISTRATION_ID = 1;
|
||||
public const INBOX_INCOMING_CONNECTION_REQUEST_ID = 2;
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::INBOX_USER_REGISTRATION_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'scope' => 'User',
|
||||
'action' => 'Registration',
|
||||
'title' => 'User account creation requested for foo@bar.com',
|
||||
'origin' => '::1',
|
||||
'comment' => null,
|
||||
'description' => 'Handle user account for this cerebrate instance',
|
||||
'user_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'data' => [
|
||||
'email' => 'foo@bar.com',
|
||||
'password' => '$2y$10$dr5C0MWgBx1723yyws0HPudTqHz4k8wJ1PQ1ApVkNuH64LuZAr\/ve',
|
||||
],
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::INBOX_INCOMING_CONNECTION_REQUEST_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'scope' => 'LocalTool',
|
||||
'action' => 'IncomingConnectionRequest',
|
||||
'title' => 'Request for MISP Inter-connection',
|
||||
'origin' => 'http://127.0.0.1',
|
||||
'comment' => null,
|
||||
'description' => 'Handle Phase I of inter-connection when another cerebrate instance performs the request.',
|
||||
'user_id' => UsersFixture::USER_ORG_ADMIN_ID,
|
||||
'data' => [
|
||||
'connectorName' => 'MispConnector',
|
||||
'cerebrateURL' => 'http://127.0.0.1',
|
||||
'local_tool_id' => 1,
|
||||
'remote_tool_id' => 1,
|
||||
],
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class IndividualsFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
public const INDIVIDUAL_ADMIN_ID = 1;
|
||||
public const INDIVIDUAL_SYNC_ID = 2;
|
||||
public const INDIVIDUAL_ORG_ADMIN_ID = 3;
|
||||
public const INDIVIDUAL_REGULAR_USER_ID = 4;
|
||||
public const INDIVIDUAL_A_ID = 5;
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::INDIVIDUAL_ADMIN_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'email' => $faker->email(),
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'position' => 'admin',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::INDIVIDUAL_SYNC_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'email' => $faker->email(),
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'position' => 'sync',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::INDIVIDUAL_ORG_ADMIN_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'email' => $faker->email(),
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'position' => 'org_admin',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::INDIVIDUAL_REGULAR_USER_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'email' => $faker->email(),
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'position' => 'user',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::INDIVIDUAL_A_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'email' => $faker->email(),
|
||||
'first_name' => $faker->firstName,
|
||||
'last_name' => $faker->lastName,
|
||||
'position' => 'user',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
]
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class OrganisationsFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
public const ORGANISATION_A_ID = 1;
|
||||
public const ORGANISATION_B_ID = 2;
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::ORGANISATION_A_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'Organisation A',
|
||||
'url' => $faker->url,
|
||||
'nationality' => $faker->countryCode,
|
||||
'sector' => 'IT',
|
||||
'type' => '',
|
||||
'contacts' => '',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::ORGANISATION_B_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'Organisation B',
|
||||
'url' => $faker->url,
|
||||
'nationality' => $faker->countryCode,
|
||||
'sector' => 'IT',
|
||||
'type' => '',
|
||||
'contacts' => '',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
]
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class RolesFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
public const ROLE_ADMIN_ID = 1;
|
||||
public const ROLE_SYNC_ID = 2;
|
||||
public const ROLE_ORG_ADMIN_ID = 3;
|
||||
public const ROLE_REGULAR_USER_ID = 4;
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::ROLE_ADMIN_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'admin',
|
||||
'is_default' => false,
|
||||
'perm_admin' => true,
|
||||
'perm_sync' => false,
|
||||
'perm_org_admin' => false
|
||||
],
|
||||
[
|
||||
'id' => self::ROLE_SYNC_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'sync',
|
||||
'is_default' => false,
|
||||
'perm_admin' => false,
|
||||
'perm_sync' => true,
|
||||
'perm_org_admin' => false
|
||||
],
|
||||
[
|
||||
'id' => self::ROLE_ORG_ADMIN_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'org_admin',
|
||||
'is_default' => false,
|
||||
'perm_admin' => false,
|
||||
'perm_sync' => false,
|
||||
'perm_org_admin' => true
|
||||
],
|
||||
[
|
||||
'id' => self::ROLE_REGULAR_USER_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'user',
|
||||
'is_default' => true,
|
||||
'perm_admin' => false,
|
||||
'perm_sync' => false,
|
||||
'perm_org_admin' => false
|
||||
]
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class SharingGroupsFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
public const SHARING_GROUP_A_ID = 1;
|
||||
public const SHARING_GROUP_B_ID = 2;
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::SHARING_GROUP_A_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'Sharing Group A',
|
||||
'releasability' => 'Sharing Group A releasability',
|
||||
'description' => 'Sharing Group A description',
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'user_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'active' => true,
|
||||
'local' => true,
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::SHARING_GROUP_B_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'name' => 'Sharing Group B',
|
||||
'releasability' => 'Sharing Group B releasability',
|
||||
'description' => 'Sharing Group B description',
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_B_ID,
|
||||
'user_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'active' => true,
|
||||
'local' => true,
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class TagsTaggedsFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
public $table = 'tags_tagged';
|
||||
|
||||
public const TAG_RED_ID = 1;
|
||||
public const TAG_GREEN_ID = 2;
|
||||
public const TAG_BLUE_ID = 3;
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'tag_id' => TagsTagsFixture::TAG_ORG_A_ID,
|
||||
'fk_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'fk_model' => 'Organisations',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'tag_id' => TagsTagsFixture::TAG_ORG_B_ID,
|
||||
'fk_id' => OrganisationsFixture::ORGANISATION_B_ID,
|
||||
'fk_model' => 'Organisations',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
|
||||
class TagsTagsFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
public const TAG_RED_ID = 1;
|
||||
public const TAG_GREEN_ID = 2;
|
||||
public const TAG_BLUE_ID = 3;
|
||||
public const TAG_ORG_A_ID = 4;
|
||||
public const TAG_ORG_B_ID = 5;
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::TAG_RED_ID,
|
||||
'name' => 'red',
|
||||
'namespace' => null,
|
||||
'predicate' => null,
|
||||
'value' => null,
|
||||
'colour' => 'FF0000',
|
||||
'counter' => 0,
|
||||
'text_colour' => 'red',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::TAG_GREEN_ID,
|
||||
'name' => 'green',
|
||||
'namespace' => null,
|
||||
'predicate' => null,
|
||||
'value' => null,
|
||||
'colour' => '00FF00',
|
||||
'counter' => 0,
|
||||
'text_colour' => 'green',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::TAG_BLUE_ID,
|
||||
'name' => 'blue',
|
||||
'namespace' => null,
|
||||
'predicate' => null,
|
||||
'value' => null,
|
||||
'colour' => '0000FF',
|
||||
'counter' => 0,
|
||||
'text_colour' => 'blue',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::TAG_ORG_A_ID,
|
||||
'name' => 'org-a',
|
||||
'namespace' => null,
|
||||
'predicate' => null,
|
||||
'value' => null,
|
||||
'colour' => '000000',
|
||||
'counter' => 0,
|
||||
'text_colour' => 'black',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::TAG_ORG_B_ID,
|
||||
'name' => 'org-b',
|
||||
'namespace' => null,
|
||||
'predicate' => null,
|
||||
'value' => null,
|
||||
'colour' => '000000',
|
||||
'counter' => 0,
|
||||
'text_colour' => 'black',
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
]
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Fixture;
|
||||
|
||||
use Cake\TestSuite\Fixture\TestFixture;
|
||||
use Authentication\PasswordHasher\DefaultPasswordHasher;
|
||||
|
||||
class UsersFixture extends TestFixture
|
||||
{
|
||||
public $connection = 'test';
|
||||
|
||||
// Admin user
|
||||
public const USER_ADMIN_ID = 1;
|
||||
public const USER_ADMIN_USERNAME = 'admin';
|
||||
public const USER_ADMIN_PASSWORD = 'AdminPassword';
|
||||
|
||||
// Sync user
|
||||
public const USER_SYNC_ID = 2;
|
||||
public const USER_SYNC_USERNAME = 'sync';
|
||||
public const USER_SYNC_PASSWORD = 'SyncPassword';
|
||||
|
||||
// Org Admin user
|
||||
public const USER_ORG_ADMIN_ID = 3;
|
||||
public const USER_ORG_ADMIN_USERNAME = 'org_admin';
|
||||
public const USER_ORG_ADMIN_PASSWORD = 'OrgAdminPassword';
|
||||
|
||||
// Regular User user
|
||||
public const USER_REGULAR_USER_ID = 4;
|
||||
public const USER_REGULAR_USER_USERNAME = 'user';
|
||||
public const USER_REGULAR_USER_PASSWORD = 'UserPassword';
|
||||
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$hasher = new DefaultPasswordHasher();
|
||||
$faker = \Faker\Factory::create();
|
||||
|
||||
$this->records = [
|
||||
[
|
||||
'id' => self::USER_ADMIN_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'username' => self::USER_ADMIN_USERNAME,
|
||||
'password' => $hasher->hash(self::USER_ADMIN_PASSWORD),
|
||||
'role_id' => RolesFixture::ROLE_ADMIN_ID,
|
||||
'individual_id' => IndividualsFixture::INDIVIDUAL_ADMIN_ID,
|
||||
'disabled' => 0,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::USER_SYNC_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'username' => self::USER_SYNC_USERNAME,
|
||||
'password' => $hasher->hash(self::USER_SYNC_PASSWORD),
|
||||
'role_id' => RolesFixture::ROLE_SYNC_ID,
|
||||
'individual_id' => IndividualsFixture::INDIVIDUAL_SYNC_ID,
|
||||
'disabled' => 0,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::USER_ORG_ADMIN_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'username' => self::USER_ORG_ADMIN_USERNAME,
|
||||
'password' => $hasher->hash(self::USER_ORG_ADMIN_PASSWORD),
|
||||
'role_id' => RolesFixture::ROLE_ORG_ADMIN_ID,
|
||||
'individual_id' => IndividualsFixture::INDIVIDUAL_ORG_ADMIN_ID,
|
||||
'disabled' => 0,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
],
|
||||
[
|
||||
'id' => self::USER_REGULAR_USER_ID,
|
||||
'uuid' => $faker->uuid(),
|
||||
'username' => self::USER_REGULAR_USER_USERNAME,
|
||||
'password' => $hasher->hash(self::USER_REGULAR_USER_PASSWORD),
|
||||
'role_id' => RolesFixture::ROLE_REGULAR_USER_ID,
|
||||
'individual_id' => IndividualsFixture::INDIVIDUAL_REGULAR_USER_ID,
|
||||
'disabled' => 0,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'created' => $faker->dateTime()->getTimestamp(),
|
||||
'modified' => $faker->dateTime()->getTimestamp()
|
||||
]
|
||||
];
|
||||
parent::init();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,294 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Helper;
|
||||
|
||||
use Cake\TestSuite\IntegrationTestTrait;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Http\ServerRequestFactory;
|
||||
use Cake\Http\ServerRequest;
|
||||
use Cake\Http\Exception\NotImplementedException;
|
||||
use \League\OpenAPIValidation\PSR7\ValidatorBuilder;
|
||||
use \League\OpenAPIValidation\PSR7\RequestValidator;
|
||||
use \League\OpenAPIValidation\PSR7\ResponseValidator;
|
||||
use \League\OpenAPIValidation\PSR7\OperationAddress;
|
||||
|
||||
/**
|
||||
* Trait ApiTestTrait
|
||||
*
|
||||
* @package App\Test\TestCase\Helper
|
||||
*/
|
||||
trait ApiTestTrait
|
||||
{
|
||||
use IntegrationTestTrait {
|
||||
IntegrationTestTrait::_buildRequest as _buildRequestOriginal;
|
||||
IntegrationTestTrait::_sendRequest as _sendRequestOriginal;
|
||||
}
|
||||
|
||||
/** @var string */
|
||||
protected $_authToken = '';
|
||||
|
||||
/** @var ValidatorBuilder */
|
||||
private $_validator;
|
||||
|
||||
/** @var RequestValidator */
|
||||
private $_requestValidator;
|
||||
|
||||
/** @var ResponseValidator */
|
||||
private $_responseValidator;
|
||||
|
||||
/** @var ServerRequest */
|
||||
protected $_psrRequest;
|
||||
|
||||
/* @var boolean */
|
||||
protected $_skipOpenApiValidations = false;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->initializeOpenApiValidator();
|
||||
}
|
||||
|
||||
public function setAuthToken(string $authToken): void
|
||||
{
|
||||
$this->_authToken = $authToken;
|
||||
|
||||
// somehow this is not set automatically in test environment
|
||||
$_SERVER['HTTP_AUTHORIZATION'] = $authToken;
|
||||
|
||||
$this->configRequest([
|
||||
'headers' => [
|
||||
'Accept' => 'application/json',
|
||||
'Authorization' => $this->_authToken,
|
||||
'Content-Type' => 'application/json'
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip OpenAPI validations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function skipOpenApiValidations(): void
|
||||
{
|
||||
$this->_skipOpenApiValidations = true;
|
||||
}
|
||||
|
||||
public function assertResponseContainsArray(array $expected): void
|
||||
{
|
||||
$responseArray = json_decode((string)$this->_response->getBody(), true);
|
||||
throw new NotImplementedException('TODO: see codeception seeResponseContainsJson()');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load OpenAPI specification validator
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function initializeOpenApiValidator(): void
|
||||
{
|
||||
if (!$this->_skipOpenApiValidations) {
|
||||
$this->_validator = Configure::read('App.OpenAPIValidator');
|
||||
if ($this->_validator === null) {
|
||||
throw new \Exception('OpenAPI validator is not configured');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the API request against the OpenAPI spec
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function assertRequestMatchesOpenApiSpec(): void
|
||||
{
|
||||
$this->_validator->getRequestValidator()->validate($this->_psrRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the API response against the OpenAPI spec
|
||||
*
|
||||
* @param string $path The path to the API endpoint
|
||||
* @param string $method The HTTP method used to call the endpoint
|
||||
* @return void
|
||||
*/
|
||||
public function assertResponseMatchesOpenApiSpec(string $endpoint, string $method = 'get'): void
|
||||
{
|
||||
$address = new OperationAddress($endpoint, $method);
|
||||
$this->_validator->getResponseValidator()->validate($address, $this->_response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a record exists in the database
|
||||
*
|
||||
* @param string $table The table name
|
||||
* @param array $conditions The conditions to check
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException
|
||||
*
|
||||
* @see https://book.cakephp.org/4/en/orm-query-builder.html
|
||||
*/
|
||||
public function assertDbRecordExists(string $table, array $conditions): void
|
||||
{
|
||||
$record = $this->getTableLocator()->get($table)->find()->where($conditions)->first();
|
||||
if (!$record) {
|
||||
throw new \PHPUnit\Framework\AssertionFailedError("Record not found in table '$table' with conditions: " . json_encode($conditions));
|
||||
}
|
||||
$this->assertNotEmpty($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a record do not exists in the database
|
||||
*
|
||||
* @param string $table The table name
|
||||
* @param array $conditions The conditions to check
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException
|
||||
*
|
||||
* @see https://book.cakephp.org/4/en/orm-query-builder.html
|
||||
*/
|
||||
public function assertDbRecordNotExists(string $table, array $conditions): void
|
||||
{
|
||||
$record = $this->getTableLocator()->get($table)->find()->where($conditions)->first();
|
||||
if ($record) {
|
||||
throw new \PHPUnit\Framework\AssertionFailedError("Record found in table '$table' with conditions: " . json_encode($conditions));
|
||||
}
|
||||
$this->assertEmpty($record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the response body and returns the decoded JSON
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getJsonResponseAsArray(): array
|
||||
{
|
||||
if ($this->_response->getHeaders()['Content-Type'][0] !== 'application/json') {
|
||||
throw new \Exception('The response is not a JSON response');
|
||||
}
|
||||
|
||||
return json_decode((string)$this->_response->getBody(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a database records as an array
|
||||
*
|
||||
* @param string $table The table name
|
||||
* @param array $conditions The conditions to check
|
||||
* @return array
|
||||
* @throws \Cake\Datasource\Exception\RecordNotFoundException
|
||||
*/
|
||||
public function getRecordFromDb(string $table, array $conditions): array
|
||||
{
|
||||
return $this->getTableLocator()->get($table)->find()->where($conditions)->first()->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method intercepts IntegrationTestTrait::_buildRequest()
|
||||
* in the quest to get a PSR-7 request object and saves it for
|
||||
* later inspection, also validates it against the OpenAPI spec.
|
||||
* @see \Cake\TestSuite\IntegrationTestTrait::_buildRequest()
|
||||
*
|
||||
* @param string $url The URL
|
||||
* @param string $method The HTTP method
|
||||
* @param array|string $data The request data.
|
||||
* @return array The request context
|
||||
*/
|
||||
protected function _buildRequest(string $url, $method, $data = []): array
|
||||
{
|
||||
$spec = $this->_buildRequestOriginal($url, $method, $data);
|
||||
|
||||
$this->_psrRequest = $this->_createPsr7RequestFromSpec($spec);
|
||||
|
||||
// Validate request against OpenAPI spec
|
||||
if (!$this->_skipOpenApiValidations) {
|
||||
try {
|
||||
$this->assertRequestMatchesOpenApiSpec();
|
||||
} catch (\Exception $exception) {
|
||||
$this->fail($exception->getMessage());
|
||||
}
|
||||
} else {
|
||||
$this->addWarning(
|
||||
sprintf(
|
||||
'OpenAPI spec validations skipped for request [%s]%s.',
|
||||
$this->_psrRequest->getMethod(),
|
||||
$this->_psrRequest->getPath()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return $spec;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method intercepts IntegrationTestTrait::_buildRequest()
|
||||
* and validates the response against the OpenAPI spec.
|
||||
*
|
||||
* @see \Cake\TestSuite\IntegrationTestTrait::_sendRequest()
|
||||
*
|
||||
* @param array|string $url The URL
|
||||
* @param string $method The HTTP method
|
||||
* @param array|string $data The request data.
|
||||
* @return void
|
||||
* @throws \PHPUnit\Exception|\Throwable
|
||||
*/
|
||||
protected function _sendRequest($url, $method, $data = []): void
|
||||
{
|
||||
// Adding Content-Type: application/json $this->configRequest() prevents this from happening somehow
|
||||
if (in_array($method, ['POST', 'PATCH', 'PUT']) && $this->_request['headers']['Content-Type'] === 'application/json') {
|
||||
$data = json_encode($data);
|
||||
}
|
||||
|
||||
$this->_sendRequestOriginal($url, $method, $data);
|
||||
|
||||
// Validate response against OpenAPI spec
|
||||
if (!$this->_skipOpenApiValidations) {
|
||||
$this->assertResponseMatchesOpenApiSpec(
|
||||
$this->_psrRequest->getPath(),
|
||||
strtolower($this->_psrRequest->getMethod())
|
||||
);
|
||||
} else {
|
||||
$this->addWarning(
|
||||
sprintf(
|
||||
'OpenAPI spec validations skipped for response of [%s]%s.',
|
||||
$this->_psrRequest->getMethod(),
|
||||
$this->_psrRequest->getPath()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a PSR-7 request from the request spec.
|
||||
* @see \Cake\TestSuite\MiddlewareDispatcher::_createRequest()
|
||||
*
|
||||
* @param array<string, mixed> $spec The request spec.
|
||||
* @return \Cake\Http\ServerRequest
|
||||
*/
|
||||
private function _createPsr7RequestFromSpec(array $spec): ServerRequest
|
||||
{
|
||||
if (isset($spec['input'])) {
|
||||
$spec['post'] = [];
|
||||
$spec['environment']['CAKEPHP_INPUT'] = $spec['input'];
|
||||
}
|
||||
$environment = array_merge(
|
||||
array_merge($_SERVER, ['REQUEST_URI' => $spec['url']]),
|
||||
$spec['environment']
|
||||
);
|
||||
if (strpos($environment['PHP_SELF'], 'phpunit') !== false) {
|
||||
$environment['PHP_SELF'] = '/';
|
||||
}
|
||||
return ServerRequestFactory::fromGlobals(
|
||||
$environment,
|
||||
$spec['query'],
|
||||
$spec['post'],
|
||||
$spec['cookies'],
|
||||
$spec['files']
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\Helper;
|
||||
|
||||
use \WireMock\Client\WireMock;
|
||||
use Exception;
|
||||
|
||||
trait WireMockTestTrait
|
||||
{
|
||||
/** @var WireMock */
|
||||
private $wiremock;
|
||||
|
||||
/** @var array<mixed> */
|
||||
private $config = [
|
||||
'hostname' => 'localhost',
|
||||
'port' => 8080
|
||||
];
|
||||
|
||||
public function initializeWireMock(): void
|
||||
{
|
||||
$this->wiremock = WireMock::create(
|
||||
$_ENV['WIREMOCK_HOST'] ?? $this->config['hostname'],
|
||||
$_ENV['WIREMOCK_PORT'] ?? $this->config['port']
|
||||
);
|
||||
|
||||
if (!$this->wiremock->isAlive()) {
|
||||
throw new Exception('Failed to connect to WireMock server.');
|
||||
}
|
||||
|
||||
$this->clearWireMockStubs();
|
||||
}
|
||||
|
||||
public function clearWireMockStubs(): void
|
||||
{
|
||||
$this->wiremock->resetToDefault();
|
||||
}
|
||||
|
||||
public function getWireMock(): WireMock
|
||||
{
|
||||
return $this->wiremock;
|
||||
}
|
||||
|
||||
public function getWireMockBaseUrl(): string
|
||||
{
|
||||
return sprintf('http://%s:%s', $this->config['hostname'], $this->config['port']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Adapted from @rowanhill wiremock start.sh script
|
||||
# https://github.com/rowanhill/wiremock-php/blob/master/wiremock/start.sh
|
||||
|
||||
cd ./tmp/
|
||||
|
||||
instance=1
|
||||
port=8080
|
||||
if [ $# -gt 0 ]; then
|
||||
instance=$1
|
||||
port=$2
|
||||
fi
|
||||
pidFile=wiremock.$instance.pid
|
||||
logFile=wiremock.$instance.log
|
||||
|
||||
# Ensure WireMock isn't already running
|
||||
if [ -e $pidFile ]; then
|
||||
echo WireMock is already started: see process `cat $pidFile` 1>&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Download the wiremock jar if we need it
|
||||
if ! [ -e wiremock-standalone.jar ]; then
|
||||
echo WireMock standalone JAR missing. Downloading.
|
||||
curl https://repo1.maven.org/maven2/com/github/tomakehurst/wiremock-jre8-standalone/2.32.0/wiremock-jre8-standalone-2.32.0.jar -o wiremock-standalone.jar
|
||||
status=$?
|
||||
if [ ${status} -ne 0 ]; then
|
||||
echo curl could not download WireMock JAR 1>&2
|
||||
exit ${status}
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start WireMock in standalone mode (in a background process) and save its output to a log
|
||||
java -jar wiremock-standalone.jar --port $port --root-dir $instance --disable-banner &> $logFile 2>&1 &
|
||||
pgrep -f wiremock-standalone.jar > $pidFile
|
||||
|
||||
echo WireMock $instance started on port $port
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Adapted from @rowanhill wiremock stop.sh script
|
||||
# https://github.com/rowanhill/wiremock-php/blob/master/wiremock/stop.sh
|
||||
|
||||
cd ./tmp/
|
||||
|
||||
instance=1
|
||||
if [ $# -gt 0 ]; then
|
||||
instance=$1
|
||||
fi
|
||||
pidFile=wiremock.$instance.pid
|
||||
|
||||
|
||||
if [ -e $pidFile ]; then
|
||||
kill -9 `cat $pidFile`
|
||||
rm $pidFile
|
||||
else
|
||||
echo WireMock is not started 2>&1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo WireMock $instance stopped
|
|
@ -0,0 +1,123 @@
|
|||
# Testing
|
||||
1. Add a `cerebrate_test` database to the database:
|
||||
```mysql
|
||||
CREATE DATABASE cerebrate_test;
|
||||
GRANT ALL PRIVILEGES ON cerebrate_test.* to cerebrate@localhost;
|
||||
FLUSH PRIVILEGES;
|
||||
QUIT;
|
||||
```
|
||||
|
||||
2. Add a the test database to your `config/app_local.php` config file and set `debug` mode to `true`.
|
||||
```php
|
||||
'debug' => true,
|
||||
'Datasources' => [
|
||||
'default' => [
|
||||
...
|
||||
],
|
||||
/*
|
||||
* The test connection is used during the test suite.
|
||||
*/
|
||||
'test' => [
|
||||
'host' => 'localhost',
|
||||
'username' => 'cerebrate',
|
||||
'password' => 'cerebrate',
|
||||
'database' => 'cerebrate_test',
|
||||
],
|
||||
],
|
||||
```
|
||||
|
||||
## Runing the tests
|
||||
```
|
||||
$ composer install
|
||||
$ composer test
|
||||
> sh ./tests/Helper/wiremock/start.sh
|
||||
WireMock 1 started on port 8080
|
||||
> phpunit
|
||||
[ * ] Running DB migrations, it may take some time ...
|
||||
|
||||
The WireMock server is started .....
|
||||
port: 8080
|
||||
enable-browser-proxying: false
|
||||
disable-banner: true
|
||||
no-request-journal: false
|
||||
verbose: false
|
||||
|
||||
PHPUnit 8.5.22 by Sebastian Bergmann and contributors.
|
||||
|
||||
|
||||
..... 5 / 5 (100%)
|
||||
|
||||
Time: 11.61 seconds, Memory: 26.00 MB
|
||||
|
||||
OK (5 tests, 15 assertions)
|
||||
```
|
||||
|
||||
Running a specific suite:
|
||||
```
|
||||
$ vendor/bin/phpunit --testsuite=api --testdox
|
||||
```
|
||||
Available suites:
|
||||
* `app`: runs all test suites
|
||||
* `api`: runs only api tests
|
||||
* `controller`: runs only controller tests
|
||||
* _to be continued ..._
|
||||
|
||||
By default the database is re-generated before running the test suite, to skip this step and speed up the test run set the following env variable in `phpunit.xml`:
|
||||
```xml
|
||||
<php>
|
||||
...
|
||||
<env name="SKIP_DB_MIGRATIONS" value="1" />
|
||||
</php>
|
||||
```
|
||||
## Extras
|
||||
### WireMock
|
||||
Some integration tests perform calls to external APIs, we use WireMock to mock the response of these API calls.
|
||||
|
||||
To download and run WireMock run the following script in a separate terminal:
|
||||
```
|
||||
sh ./tests/Helper/wiremock/start.sh
|
||||
```
|
||||
|
||||
You can also run WireMock with docker, check the official docs: http://wiremock.org/docs/docker/
|
||||
|
||||
> NOTE: When running the tests with `composer test` WireMock is automatically started and stoped after the tests finish.
|
||||
|
||||
The default `hostname` and `port` for WireMock are set in `phpunit.xml` as environment variables:
|
||||
```xml
|
||||
<php>
|
||||
...
|
||||
<env name="WIREMOCK_HOST" value="localhost" />
|
||||
<env name="WIREMOCK_PORT" value="8080" />
|
||||
</php>
|
||||
```
|
||||
### Coverage
|
||||
HTML:
|
||||
```
|
||||
$ vendor/bin/phpunit --coverage-html tmp/coverage
|
||||
```
|
||||
|
||||
XML:
|
||||
```
|
||||
$ vendor/bin/phpunit --verbose --coverage-clover=coverage.xml
|
||||
```
|
||||
|
||||
### OpenAPI validation
|
||||
API tests can assert the API response matches the OpenAPI specification, after the request add this line:
|
||||
|
||||
```php
|
||||
$this->assertResponseMatchesOpenApiSpec(self::ENDPOINT);
|
||||
```
|
||||
|
||||
The default OpenAPI spec path is set in `phpunit.xml` as a environment variablea:
|
||||
```xml
|
||||
<php>
|
||||
...
|
||||
<env name="OPENAPI_SPEC" value="webroot/docs/openapi.yaml" />
|
||||
</php>
|
||||
```
|
||||
|
||||
### Debugging tests
|
||||
```
|
||||
$ export XDEBUG_CONFIG="idekey=IDEKEY"
|
||||
$ phpunit
|
||||
```
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class AddAuthKeyApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/authKeys/add';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testAddAdminAuthKey(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'uuid' => $uuid,
|
||||
'authkey' => $faker->sha1,
|
||||
'expiration' => 0,
|
||||
'user_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'comment' => $faker->text
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"uuid": "%s"', $uuid));
|
||||
$this->assertDbRecordExists('AuthKeys', ['uuid' => $uuid]);
|
||||
}
|
||||
|
||||
public function testAddAdminAuthKeyNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'uuid' => $uuid,
|
||||
'authkey' => $faker->sha1,
|
||||
'expiration' => 0,
|
||||
'user_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'comment' => $faker->text
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(404);
|
||||
$this->addWarning('Should return 405 Method Not Allowed instead of 404 Not Found');
|
||||
$this->assertDbRecordNotExists('AuthKeys', ['uuid' => $uuid]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class DeleteAuthKeyApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/authKeys/delete';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
];
|
||||
|
||||
public function testDeleteAdminAuthKey(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, AuthKeysFixture::ADMIN_API_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordNotExists('AuthKeys', ['id' => AuthKeysFixture::ADMIN_API_ID]);
|
||||
}
|
||||
|
||||
public function testDeleteOrgAdminAuthKeyNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, AuthKeysFixture::ORG_ADMIN_API_ID);
|
||||
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordExists('AuthKeys', ['id' => AuthKeysFixture::ORG_ADMIN_API_ID]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class IndexAuthKeysApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/authKeys/index';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testIndexAuthKeys(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', AuthKeysFixture::ADMIN_API_ID));
|
||||
}
|
||||
|
||||
public function testIndexDoesNotShowAdminAuthKeysAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseNotContains(sprintf('"id": %d', AuthKeysFixture::REGULAR_USER_API_KEY));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class AddBroodApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/broods/add';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.Broods'
|
||||
];
|
||||
|
||||
public function testAddBrood(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'uuid' => $uuid,
|
||||
'name' => 'Brood A',
|
||||
'url' => $faker->url,
|
||||
'description' => $faker->text,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'trusted' => true,
|
||||
'pull' => true,
|
||||
'skip_proxy' => true,
|
||||
'authkey' => $faker->sha1,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"uuid": "%s"', $uuid));
|
||||
$this->assertDbRecordExists('Broods', ['uuid' => $uuid]);
|
||||
}
|
||||
|
||||
public function testAddBroodNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'uuid' => $uuid,
|
||||
'name' => 'Brood A',
|
||||
'url' => $faker->url,
|
||||
'description' => $faker->text,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'trusted' => true,
|
||||
'pull' => true,
|
||||
'skip_proxy' => true,
|
||||
'authkey' => $faker->sha1,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists('Broods', ['uuid' => $uuid]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\BroodsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class DeleteBroodApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/broods/delete';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.Broods'
|
||||
];
|
||||
|
||||
public function testDeleteBrood(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, BroodsFixture::BROOD_A_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordNotExists('Broods', ['id' => BroodsFixture::BROOD_A_ID]);
|
||||
}
|
||||
|
||||
public function testDeleteBroodNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, BroodsFixture::BROOD_A_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordExists('Broods', ['id' => BroodsFixture::BROOD_A_ID]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\IntegrationTestTrait;
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\BroodsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class EditBroodApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/broods/edit';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.Broods'
|
||||
];
|
||||
|
||||
public function testEditBrood(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, BroodsFixture::BROOD_A_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'name' => 'Test Brood 4321',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists(
|
||||
'Broods',
|
||||
[
|
||||
'id' => BroodsFixture::BROOD_A_ID,
|
||||
'name' => 'Test Brood 4321',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testEditBroodNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, BroodsFixture::BROOD_B_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'name' => 'Test Brood 1234'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists(
|
||||
'Broods',
|
||||
[
|
||||
'id' => BroodsFixture::BROOD_B_ID,
|
||||
'name' => 'Test Brood 1234'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\BroodsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class IndexBroodsApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/users/index';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.Broods'
|
||||
];
|
||||
|
||||
public function testIndexBroods(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', BroodsFixture::BROOD_A_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\BroodsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
use App\Test\Helper\WireMockTestTrait;
|
||||
use \WireMock\Client\WireMock;
|
||||
|
||||
class TestBroodConnectionApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
use WireMockTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/broods/testConnection';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.Broods'
|
||||
];
|
||||
|
||||
public function testTestBroodConnection(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->initializeWireMock();
|
||||
$this->mockCerebrateStatusResponse();
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, BroodsFixture::BROOD_WIREMOCK_ID);
|
||||
$this->get($url);
|
||||
|
||||
$this->getWireMock()->verify(
|
||||
WireMock::getRequestedFor(WireMock::urlEqualTo('/instance/status.json'))
|
||||
->withHeader('Content-Type', WireMock::equalTo('application/json'))
|
||||
->withHeader('Authorization', WireMock::equalTo(BroodsFixture::BROOD_WIREMOCK_API_KEY))
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('"user": "wiremock"');
|
||||
}
|
||||
|
||||
private function mockCerebrateStatusResponse(): \WireMock\Stubbing\StubMapping
|
||||
{
|
||||
return $this->getWireMock()->stubFor(
|
||||
WireMock::get(WireMock::urlEqualTo('/instance/status.json'))
|
||||
->willReturn(WireMock::aResponse()
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withBody((string)json_encode([
|
||||
"version" => "0.1",
|
||||
"application" => "Cerebrate",
|
||||
"user" => [
|
||||
"id" => 1,
|
||||
"username" => "wiremock",
|
||||
"role" => [
|
||||
"id" => 1
|
||||
]
|
||||
]
|
||||
])))
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\BroodsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class ViewBroodApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/broods/view';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.Broods'
|
||||
];
|
||||
|
||||
public function testViewBroodGroupById(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, BroodsFixture::BROOD_A_ID);
|
||||
$this->get($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', BroodsFixture::BROOD_A_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\EncryptionKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class AddEncryptionKeyApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/encryptionKeys/add';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.EncryptionKeys'
|
||||
];
|
||||
|
||||
public function testAddUserEncryptionKey(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'uuid' => $uuid,
|
||||
'type' => EncryptionKeysFixture::TYPE_PGP,
|
||||
'encryption_key' => EncryptionKeysFixture::getPublicKey(EncryptionKeysFixture::KEY_TYPE_EDCH),
|
||||
'revoked' => false,
|
||||
'expires' => null,
|
||||
'owner_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'owner_model' => 'User'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"uuid": "%s"', $uuid));
|
||||
$this->assertDbRecordExists('EncryptionKeys', ['uuid' => $uuid]);
|
||||
}
|
||||
|
||||
public function testAddAdminUserEncryptionKeyNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'uuid' => $uuid,
|
||||
'type' => EncryptionKeysFixture::TYPE_PGP,
|
||||
'encryption_key' => EncryptionKeysFixture::getPublicKey(EncryptionKeysFixture::KEY_TYPE_EDCH),
|
||||
'revoked' => false,
|
||||
'expires' => null,
|
||||
'owner_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'owner_model' => 'User'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists('EncryptionKeys', ['uuid' => $uuid]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\EncryptionKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class DeleteEncryptionKeyApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/encryptionKeys/delete';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.EncryptionKeys'
|
||||
];
|
||||
|
||||
public function testDeleteEncryptionKey(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, EncryptionKeysFixture::ENCRYPTION_KEY_ORG_A_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordNotExists('EncryptionKeys', ['id' => EncryptionKeysFixture::ENCRYPTION_KEY_ORG_A_ID]);
|
||||
}
|
||||
|
||||
public function testDeleteEncryptionKeyNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, EncryptionKeysFixture::ENCRYPTION_KEY_ORG_B_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordExists('EncryptionKeys', ['id' => EncryptionKeysFixture::ENCRYPTION_KEY_ORG_B_ID]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\EncryptionKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class EditEncryptionKeyApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/encryptionKeys/edit';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.EncryptionKeys'
|
||||
];
|
||||
|
||||
public function testRevokeEncryptionKey(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, EncryptionKeysFixture::ENCRYPTION_KEY_ORG_A_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'revoked' => true,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists(
|
||||
'EncryptionKeys',
|
||||
[
|
||||
'id' => EncryptionKeysFixture::ENCRYPTION_KEY_ORG_A_ID,
|
||||
'revoked' => true,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testRevokeAdminEncryptionKeyNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, EncryptionKeysFixture::ENCRYPTION_KEY_ORG_B_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'revoked' => true
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists(
|
||||
'EncryptionKeys',
|
||||
[
|
||||
'id' => EncryptionKeysFixture::ENCRYPTION_KEY_ORG_B_ID,
|
||||
'revoked' => true
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\EncryptionKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class IndexEncryptionKeysApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/encryptionKeys/index';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.EncryptionKeys'
|
||||
|
||||
];
|
||||
|
||||
public function testIndexEncryptionKeys(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', EncryptionKeysFixture::ENCRYPTION_KEY_ORG_A_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\EncryptionKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class ViewEncryptionKeyApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/encryptionKeys/view';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.EncryptionKeys'
|
||||
];
|
||||
|
||||
public function testViewEncryptionKeyById(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, EncryptionKeysFixture::ENCRYPTION_KEY_ORG_A_ID);
|
||||
$this->get($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', EncryptionKeysFixture::ENCRYPTION_KEY_ORG_A_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class CreateInboxEntryApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/inbox/createEntry';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Inbox',
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testAddUserRegistrationInbox(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
// to avoid $this->request->clientIp() to return null
|
||||
$_SERVER['REMOTE_ADDR'] = '::1';
|
||||
|
||||
$url = sprintf("%s/%s/%s", self::ENDPOINT, 'User', 'Registration');
|
||||
$this->post(
|
||||
$url,
|
||||
[
|
||||
'email' => 'john@example.com',
|
||||
'password' => 'Password12345!'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('"email": "john@example.com"');
|
||||
$this->assertDbRecordExists(
|
||||
'Inbox',
|
||||
[
|
||||
'id' => 3, // hacky, but `data` is json string cannot verify the value because of the hashed password
|
||||
'scope' => 'User',
|
||||
'action' => 'Registration',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testAddUserRegistrationInboxNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$url = sprintf("%s/%s/%s", self::ENDPOINT, 'User', 'Registration');
|
||||
$this->post(
|
||||
$url,
|
||||
[
|
||||
'email' => 'john@example.com',
|
||||
'password' => 'Password12345!'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists('Inbox', ['id' => 3]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\InboxFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class IndexInboxApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/inbox/index';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Inbox',
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testIndexInbox(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', InboxFixture::INBOX_USER_REGISTRATION_ID));
|
||||
$this->assertResponseContains(sprintf('"id": %d', InboxFixture::INBOX_INCOMING_CONNECTION_REQUEST_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class AddIndividualApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/individuals/add';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testAddIndividual(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'email' => 'john@example.com',
|
||||
'first_name' => 'John',
|
||||
'last_name' => 'Doe',
|
||||
'position' => 'Security Analyst'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('"email": "john@example.com"');
|
||||
$this->assertDbRecordExists('Individuals', ['email' => 'john@example.com']);
|
||||
}
|
||||
|
||||
// public function testAddUserNotAllowedAsRegularUser(): void
|
||||
// {
|
||||
// $this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
// $this->post(
|
||||
// self::ENDPOINT,
|
||||
// [
|
||||
// 'email' => 'john@example.com',
|
||||
// 'first_name' => 'John',
|
||||
// 'last_name' => 'Doe',
|
||||
// 'position' => 'Security Analyst'
|
||||
// ]
|
||||
// );
|
||||
|
||||
// $this->assertResponseCode(405);
|
||||
// $this->assertDbRecordNotExists('Individuals', ['email' => 'john@example.com']);
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\IndividualsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class DeleteIndividualApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/individuals/delete';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testDeleteIndividual(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, IndividualsFixture::INDIVIDUAL_A_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordNotExists('Individuals', ['id' => IndividualsFixture::INDIVIDUAL_A_ID]);
|
||||
}
|
||||
|
||||
public function testDeleteIndividualNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, IndividualsFixture::INDIVIDUAL_ADMIN_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordExists('Individuals', ['id' => IndividualsFixture::INDIVIDUAL_ADMIN_ID]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\IndividualsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class EditIndividualApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/individuals/edit';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testEditIndividualAsAdmin(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, IndividualsFixture::INDIVIDUAL_REGULAR_USER_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'email' => 'foo@bar.com',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists('Individuals', [
|
||||
'id' => IndividualsFixture::INDIVIDUAL_REGULAR_USER_ID,
|
||||
'email' => 'foo@bar.com'
|
||||
]);
|
||||
}
|
||||
|
||||
public function testEditAnyIndividualNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, IndividualsFixture::INDIVIDUAL_ADMIN_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'email' => 'foo@bar.com',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists('Individuals', [
|
||||
'id' => IndividualsFixture::INDIVIDUAL_ADMIN_ID,
|
||||
'email' => 'foo@bar.com'
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\IndividualsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class IndexIndividualsApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/individuals/index';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testIndexIndividuals(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', IndividualsFixture::INDIVIDUAL_ADMIN_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\IndividualsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class ViewIndividualApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/individuals/view';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testViewIndividualById(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, IndividualsFixture::INDIVIDUAL_ADMIN_ID);
|
||||
$this->get($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', IndividualsFixture::INDIVIDUAL_ADMIN_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class AddOrganisationApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/organisations/add';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testAddOrganisation(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'name' => 'Test Organisation',
|
||||
'description' => $faker->text,
|
||||
'uuid' => $uuid,
|
||||
'url' => 'http://example.com',
|
||||
'nationality' => 'US',
|
||||
'sector' => 'sector',
|
||||
'type' => 'type',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"uuid": "%s"', $uuid));
|
||||
$this->assertDbRecordExists('Organisations', ['uuid' => $uuid]);
|
||||
}
|
||||
|
||||
public function testAddOrganisationNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'name' => 'Test Organisation',
|
||||
'description' => $faker->text,
|
||||
'uuid' => $uuid,
|
||||
'url' => 'http://example.com',
|
||||
'nationality' => 'US',
|
||||
'sector' => 'sector',
|
||||
'type' => 'type',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists('Organisations', ['uuid' => $uuid]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\IntegrationTestTrait;
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class DeleteOrganisationApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/organisations/delete';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testDeleteOrganisation(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_B_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordNotExists('Organisations', ['id' => OrganisationsFixture::ORGANISATION_B_ID]);
|
||||
}
|
||||
|
||||
public function testDeleteOrganisationNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_B_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordExists('Organisations', ['id' => OrganisationsFixture::ORGANISATION_B_ID]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class EditOrganisationApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/organisations/edit';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testEditOrganisation(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'name' => 'Test Organisation 4321',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists(
|
||||
'Organisations',
|
||||
[
|
||||
'id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'name' => 'Test Organisation 4321',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testEditOrganisationNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_B_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'name' => 'Test Organisation 1234'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists(
|
||||
'Organisations',
|
||||
[
|
||||
'id' => OrganisationsFixture::ORGANISATION_B_ID,
|
||||
'name' => 'Test Organisation 1234'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class IndexOrganisationApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/organisations/index';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testIndexOrganisations(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', OrganisationsFixture::ORGANISATION_A_ID));
|
||||
$this->assertResponseContains(sprintf('"id": %d', OrganisationsFixture::ORGANISATION_B_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Fixture\TagsTagsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class TagOrganisationApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/organisations/tag';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.TagsTags',
|
||||
'app.Organisations',
|
||||
'app.TagsTaggeds',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testTagOrganisation(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||
$this->post(
|
||||
$url,
|
||||
[
|
||||
'tag_list' => "[\"red\"]"
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists(
|
||||
'TagsTagged',
|
||||
[
|
||||
'tag_id' => TagsTagsFixture::TAG_RED_ID,
|
||||
'fk_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'fk_model' => 'Organisations'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testTagOrganisationNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||
$this->post(
|
||||
$url,
|
||||
[
|
||||
'tag_list' => "[\"green\"]"
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists(
|
||||
'TagsTagged',
|
||||
[
|
||||
'tag_id' => TagsTagsFixture::TAG_GREEN_ID,
|
||||
'fk_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'fk_model' => 'Organisations'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Fixture\TagsTagsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class UntagOrganisationApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/organisations/untag';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.TagsTags',
|
||||
'app.Organisations',
|
||||
'app.TagsTaggeds',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testUntagOrganisation(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||
$this->post(
|
||||
$url,
|
||||
[
|
||||
'tag_list' => "[\"org-a\"]"
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordNotExists(
|
||||
'TagsTagged',
|
||||
[
|
||||
'tag_id' => TagsTagsFixture::TAG_ORG_A_ID,
|
||||
'fk_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'fk_model' => 'Organisations'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testUntagOrganisationNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||
$this->post(
|
||||
$url,
|
||||
[
|
||||
'tag_list' => "[\"org-a\"]"
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordExists(
|
||||
'TagsTagged',
|
||||
[
|
||||
'tag_id' => TagsTagsFixture::TAG_ORG_A_ID,
|
||||
'fk_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'fk_model' => 'Organisations'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class ViewOrganisationApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/organisations/view';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.TagsTags',
|
||||
'app.Organisations',
|
||||
'app.TagsTaggeds',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testViewOrganisationById(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, OrganisationsFixture::ORGANISATION_A_ID);
|
||||
$this->get($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('"name": "Organisation A"');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class AddSharingGroupApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/sharingGroups/add';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.SharingGroups'
|
||||
];
|
||||
|
||||
public function testAddSharingGroup(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'uuid' => $uuid,
|
||||
'name' => 'Test Sharing Group',
|
||||
'releasability' => 'Test Sharing Group releasability',
|
||||
'description' => 'Test Sharing Group description',
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'user_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'active' => true,
|
||||
'local' => true
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"uuid": "%s"', $uuid));
|
||||
$this->assertDbRecordExists('SharingGroups', ['uuid' => $uuid]);
|
||||
}
|
||||
|
||||
public function testAddSharingGroupNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$faker = \Faker\Factory::create();
|
||||
$uuid = $faker->uuid;
|
||||
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'uuid' => $uuid,
|
||||
'name' => 'Test Sharing Group',
|
||||
'releasability' => 'Sharing Group A',
|
||||
'description' => 'Sharing Group A description',
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'user_id' => UsersFixture::USER_ADMIN_ID,
|
||||
'active' => true,
|
||||
'local' => true
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists('SharingGroups', ['uuid' => $uuid]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\SharingGroupsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class DeleteSharingGroupApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/sharingGroups/delete';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.SharingGroups'
|
||||
];
|
||||
|
||||
public function testDeleteSharingGroup(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, SharingGroupsFixture::SHARING_GROUP_A_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordNotExists('SharingGroups', ['id' => SharingGroupsFixture::SHARING_GROUP_A_ID]);
|
||||
}
|
||||
|
||||
public function testDeleteSharingGroupNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, SharingGroupsFixture::SHARING_GROUP_A_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordExists('SharingGroups', ['id' => SharingGroupsFixture::SHARING_GROUP_A_ID]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\SharingGroupsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class EditSharingGroupApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/sharingGroups/edit';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.SharingGroups'
|
||||
];
|
||||
|
||||
public function testEditSharingGroup(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, SharingGroupsFixture::SHARING_GROUP_A_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'name' => 'Test Sharing Group 4321',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists(
|
||||
'SharingGroups',
|
||||
[
|
||||
'id' => SharingGroupsFixture::SHARING_GROUP_A_ID,
|
||||
'name' => 'Test Sharing Group 4321',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testEditSharingGroupNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, SharingGroupsFixture::SHARING_GROUP_B_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'name' => 'Test Sharing Group 1234'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists(
|
||||
'SharingGroups',
|
||||
[
|
||||
'id' => SharingGroupsFixture::SHARING_GROUP_B_ID,
|
||||
'name' => 'Test Sharing Group 1234'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\SharingGroupsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class IndexSharingGroupsApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/sharingGroups/index';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.SharingGroups'
|
||||
];
|
||||
|
||||
public function testIndexSharingGroups(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', SharingGroupsFixture::SHARING_GROUP_A_ID));
|
||||
$this->assertResponseContains(sprintf('"id": %d', SharingGroupsFixture::SHARING_GROUP_B_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\SharingGroupsFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class ViewSharingGroupApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/sharingGroups/view';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys',
|
||||
'app.SharingGroups'
|
||||
];
|
||||
|
||||
public function testViewSharingGroupById(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, SharingGroupsFixture::SHARING_GROUP_A_ID);
|
||||
$this->get($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"id": %d', SharingGroupsFixture::SHARING_GROUP_A_ID));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class IndexTagsApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/tags/index';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.TagsTags',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testIndexTags(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('"name": "red"');
|
||||
$this->assertResponseContains('"name": "green"');
|
||||
$this->assertResponseContains('"name": "blue"');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Fixture\OrganisationsFixture;
|
||||
use App\Test\Fixture\RolesFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class AddUserApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/users/add';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testAddUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'individual_id' => UsersFixture::USER_REGULAR_USER_ID,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'role_id' => RolesFixture::ROLE_REGULAR_USER_ID,
|
||||
'disabled' => false,
|
||||
'username' => 'test',
|
||||
'password' => 'Password123456!',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('"username": "test"');
|
||||
$this->assertDbRecordExists('Users', ['username' => 'test']);
|
||||
}
|
||||
|
||||
public function testAddUserNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$this->post(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'individual_id' => UsersFixture::USER_REGULAR_USER_ID,
|
||||
'organisation_id' => OrganisationsFixture::ORGANISATION_A_ID,
|
||||
'role_id' => RolesFixture::ROLE_REGULAR_USER_ID,
|
||||
'disabled' => false,
|
||||
'username' => 'test',
|
||||
'password' => 'Password123456!'
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordNotExists('Users', ['username' => 'test']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
use Cake\Auth\FormAuthenticate;
|
||||
use Cake\Http\ServerRequest;
|
||||
use Cake\Http\Response;
|
||||
use Cake\Controller\ComponentRegistry;
|
||||
|
||||
class ChangePasswordApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/users/edit';
|
||||
|
||||
/** @var \Cake\Auth\FormAuthenticate */
|
||||
protected $auth;
|
||||
|
||||
/** @var \Cake\Controller\ComponentRegistry */
|
||||
protected $collection;
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->initializeOpenApiValidator();
|
||||
|
||||
$this->collection = new ComponentRegistry();
|
||||
$this->auth = new FormAuthenticate($this->collection, [
|
||||
'userModel' => 'Users',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testChangePasswordOwnUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$newPassword = 'Test12345678!';
|
||||
|
||||
$this->put(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'password' => $newPassword,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
|
||||
// Test new password with form login
|
||||
$request = new ServerRequest([
|
||||
'url' => 'users/login',
|
||||
'post' => [
|
||||
'username' => UsersFixture::USER_REGULAR_USER_USERNAME,
|
||||
'password' => $newPassword
|
||||
],
|
||||
]);
|
||||
$result = $this->auth->authenticate($request, new Response());
|
||||
|
||||
$this->assertEquals(UsersFixture::USER_REGULAR_USER_ID, $result['id']);
|
||||
$this->assertEquals(UsersFixture::USER_REGULAR_USER_USERNAME, $result['username']);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class DeleteUserApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/users/delete';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testDeleteUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_REGULAR_USER_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordNotExists('Users', ['id' => UsersFixture::USER_REGULAR_USER_ID]);
|
||||
}
|
||||
|
||||
public function testDeleteUserNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_ORG_ADMIN_ID);
|
||||
$this->delete($url);
|
||||
|
||||
$this->assertResponseCode(405);
|
||||
$this->assertDbRecordExists('Users', ['id' => UsersFixture::USER_ORG_ADMIN_ID]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Fixture\RolesFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class EditUserApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/users/edit';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testEditUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_REGULAR_USER_ID);
|
||||
$this->put(
|
||||
$url,
|
||||
[
|
||||
'id' => UsersFixture::USER_REGULAR_USER_ID,
|
||||
'role_id' => RolesFixture::ROLE_ORG_ADMIN_ID,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordExists('Users', [
|
||||
'id' => UsersFixture::USER_REGULAR_USER_ID,
|
||||
'role_id' => RolesFixture::ROLE_ORG_ADMIN_ID
|
||||
]);
|
||||
}
|
||||
|
||||
public function testEditRoleNotAllowedAsRegularUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::REGULAR_USER_API_KEY);
|
||||
$this->put(
|
||||
self::ENDPOINT,
|
||||
[
|
||||
'role_id' => RolesFixture::ROLE_ADMIN_ID,
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertDbRecordNotExists('Users', [
|
||||
'id' => UsersFixture::USER_REGULAR_USER_ID,
|
||||
'role_id' => RolesFixture::ROLE_ADMIN_ID
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class IndexUsersApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/users/index';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testIndexUsers(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"username": "%s"', UsersFixture::USER_ADMIN_USERNAME));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Api\Users;
|
||||
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\AuthKeysFixture;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
use App\Test\Helper\ApiTestTrait;
|
||||
|
||||
class ViewUserApiTest extends TestCase
|
||||
{
|
||||
use ApiTestTrait;
|
||||
|
||||
protected const ENDPOINT = '/users/view';
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Organisations',
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users',
|
||||
'app.AuthKeys'
|
||||
];
|
||||
|
||||
public function testViewMyUser(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$this->get(self::ENDPOINT);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"username": "%s"', UsersFixture::USER_ADMIN_USERNAME));
|
||||
}
|
||||
|
||||
public function testViewUserById(): void
|
||||
{
|
||||
$this->setAuthToken(AuthKeysFixture::ADMIN_API_KEY);
|
||||
$url = sprintf('%s/%d', self::ENDPOINT, UsersFixture::USER_REGULAR_USER_ID);
|
||||
$this->get($url);
|
||||
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains(sprintf('"username": "%s"', UsersFixture::USER_REGULAR_USER_USERNAME));
|
||||
}
|
||||
}
|
|
@ -40,10 +40,14 @@ class ApplicationTest extends IntegrationTestCase
|
|||
$app->bootstrap();
|
||||
$plugins = $app->getPlugins();
|
||||
|
||||
$this->assertCount(3, $plugins);
|
||||
$this->assertCount(7, $plugins);
|
||||
$this->assertSame('Bake', $plugins->get('Bake')->getName());
|
||||
$this->assertSame('DebugKit', $plugins->get('DebugKit')->getName());
|
||||
$this->assertSame('Migrations', $plugins->get('Migrations')->getName());
|
||||
$this->assertSame('Authentication', $plugins->get('Authentication')->getName());
|
||||
$this->assertSame('ADmad/SocialAuth', $plugins->get('ADmad/SocialAuth')->getName());
|
||||
$this->assertSame('Tags', $plugins->get('Tags')->getName());
|
||||
$this->assertSame('Cake/TwigView', $plugins->get('Cake/TwigView')->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
|
||||
* Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice
|
||||
*
|
||||
* @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
|
||||
* @link https://cakephp.org CakePHP(tm) Project
|
||||
* @since 1.2.0
|
||||
* @license https://opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace App\Test\TestCase\Controller;
|
||||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\TestSuite\IntegrationTestTrait;
|
||||
use Cake\TestSuite\TestCase;
|
||||
|
||||
/**
|
||||
* PagesControllerTest class
|
||||
*
|
||||
* @uses \App\Controller\PagesController
|
||||
*/
|
||||
class PagesControllerTest extends TestCase
|
||||
{
|
||||
use IntegrationTestTrait;
|
||||
|
||||
/**
|
||||
* testMultipleGet method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMultipleGet()
|
||||
{
|
||||
$this->get('/');
|
||||
$this->assertResponseOk();
|
||||
$this->get('/');
|
||||
$this->assertResponseOk();
|
||||
}
|
||||
|
||||
/**
|
||||
* testDisplay method
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDisplay()
|
||||
{
|
||||
$this->get('/pages/home');
|
||||
$this->assertResponseOk();
|
||||
$this->assertResponseContains('CakePHP');
|
||||
$this->assertResponseContains('<html>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that missing template renders 404 page in production
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMissingTemplate()
|
||||
{
|
||||
Configure::write('debug', false);
|
||||
$this->get('/pages/not_existing');
|
||||
|
||||
$this->assertResponseError();
|
||||
$this->assertResponseContains('Error');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that missing template in debug mode renders missing_template error page
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testMissingTemplateInDebug()
|
||||
{
|
||||
Configure::write('debug', true);
|
||||
$this->get('/pages/not_existing');
|
||||
|
||||
$this->assertResponseFailure();
|
||||
$this->assertResponseContains('Missing Template');
|
||||
$this->assertResponseContains('Stacktrace');
|
||||
$this->assertResponseContains('not_existing.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test directory traversal protection
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testDirectoryTraversalProtection()
|
||||
{
|
||||
$this->get('/pages/../Layout/ajax');
|
||||
$this->assertResponseCode(403);
|
||||
$this->assertResponseContains('Forbidden');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that CSRF protection is applied to page rendering.
|
||||
*
|
||||
* @reutrn void
|
||||
*/
|
||||
public function testCsrfAppliedError()
|
||||
{
|
||||
$this->post('/pages/home', ['hello' => 'world']);
|
||||
|
||||
$this->assertResponseCode(403);
|
||||
$this->assertResponseContains('CSRF');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that CSRF protection is applied to page rendering.
|
||||
*
|
||||
* @reutrn void
|
||||
*/
|
||||
public function testCsrfAppliedOk()
|
||||
{
|
||||
$this->enableCsrfToken();
|
||||
$this->post('/pages/home', ['hello' => 'world']);
|
||||
|
||||
$this->assertResponseCode(200);
|
||||
$this->assertResponseContains('CakePHP');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Test\TestCase\Controller\Users;
|
||||
|
||||
use Cake\TestSuite\IntegrationTestTrait;
|
||||
use Cake\TestSuite\TestCase;
|
||||
use App\Test\Fixture\UsersFixture;
|
||||
|
||||
class UsersControllerTest extends TestCase
|
||||
{
|
||||
use IntegrationTestTrait;
|
||||
|
||||
protected $fixtures = [
|
||||
'app.Individuals',
|
||||
'app.Roles',
|
||||
'app.Users'
|
||||
];
|
||||
public function testLogin(): void
|
||||
{
|
||||
$this->enableCsrfToken();
|
||||
$this->enableSecurityToken();
|
||||
|
||||
$this->post('/users/login', [
|
||||
'username' => UsersFixture::USER_ADMIN_USERNAME,
|
||||
'password' => UsersFixture::USER_ADMIN_PASSWORD,
|
||||
]);
|
||||
|
||||
$this->assertSessionHasKey('authUser.uuid');
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
|
@ -17,6 +18,11 @@ declare(strict_types=1);
|
|||
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Datasource\ConnectionManager;
|
||||
use Migrations\TestSuite\Migrator;
|
||||
use \League\OpenAPIValidation\PSR7\ValidatorBuilder;
|
||||
use \League\OpenAPIValidation\PSR7\RequestValidator;
|
||||
use \League\OpenAPIValidation\PSR7\ResponseValidator;
|
||||
use \League\OpenAPIValidation\PSR7\OperationAddress;
|
||||
|
||||
/**
|
||||
* Test runner bootstrap.
|
||||
|
@ -50,3 +56,19 @@ ConnectionManager::alias('test_debug_kit', 'debug_kit');
|
|||
// does not allow the sessionid to be set after stdout
|
||||
// has been written to.
|
||||
session_id('cli');
|
||||
|
||||
if (!$_ENV['SKIP_DB_MIGRATIONS']) {
|
||||
echo "[ * ] Running DB migrations, it may take some time ...\n";
|
||||
$migrator = new Migrator();
|
||||
$migrator->runMany([
|
||||
['connection' => 'test'],
|
||||
['plugin' => 'Tags', 'connection' => 'test'],
|
||||
['plugin' => 'ADmad/SocialAuth', 'connection' => 'test']
|
||||
]);
|
||||
} else {
|
||||
echo "[ * ] Skipping DB migrations ...\n";
|
||||
}
|
||||
|
||||
$specFile = $_ENV['OPENAPI_SPEC'] ?? APP . '../webroot/docs/openapi.yaml';
|
||||
// Initialize OpenAPI spec validator
|
||||
Configure::write('App.OpenAPIValidator', (new ValidatorBuilder)->fromYamlFile($specFile));
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue