diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..2317d521b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,23 @@ +; This file is for unifying the coding style for different editors and IDEs. +; More information at https://editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = false +trim_trailing_whitespace = false + +[*.bat] +end_of_line = crlf + +[*.yml] +indent_size = 2 + +[*.twig] +insert_final_newline = false + +[Makefile] +indent_style = tab diff --git a/app/src/Controller/AppController.php b/app/src/Controller/AppController.php index 340e090b3..ed331192f 100644 --- a/app/src/Controller/AppController.php +++ b/app/src/Controller/AppController.php @@ -135,6 +135,9 @@ public function beforeRender(EventInterface $event) { $this->set('vv_menu_permissions', $this->Authorization->menuPermissions($this->request->getSession()->read('Auth.User.username'), $mgid)); } + + // Generate a nonce for use in JavaScript tags with the Content-Security-Policy script-src directive + $this->set('vv_js_nonce', base64_encode(random_bytes(16))); } /** diff --git a/app/templates/ApiUsers/fields.inc b/app/templates/ApiUsers/fields.inc index e7cbe73c3..44a2dadb0 100644 --- a/app/templates/ApiUsers/fields.inc +++ b/app/templates/ApiUsers/fields.inc @@ -26,18 +26,22 @@ */ $def = ""; - if(!empty($vv_cur_mg->table_name)) { // This prefix requirement is enforced in ApiUsersTable $def = $vv_cur_mg->table_name . "."; } -// This view does not support read-only -if($action == 'add' || $action == 'edit') { - print $this->Field->control('username', ['default' => $def]); - print $this->Field->control('password'); - if(isset($vv_cur_mg)) { - // Don't require a system of record ID if we're not in a matchgrid context - print $this->Field->control('system_of_record_id', ['empty' => true], false); - } +$fields = [ + 'username' => [ + 'default' => $def + ], + 'password' +]; + +if(isset($vv_cur_mg)) { + // Only include a system of record ID in a matchgrid context + $fields['system_of_record_id'] = [ + 'empty' => true, + 'required' => false + ]; } diff --git a/app/templates/AttributeGroups/fields.inc b/app/templates/AttributeGroups/fields.inc index 1a9b7c5ee..683f1bfa4 100644 --- a/app/templates/AttributeGroups/fields.inc +++ b/app/templates/AttributeGroups/fields.inc @@ -24,8 +24,7 @@ * @since COmanage Match v1.0.0 * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ - -// This view does not support read-only -if($action == 'add' || $action == 'edit') { - print $this->Field->control('name'); -} \ No newline at end of file + +$fields = [ + 'name' +]; diff --git a/app/templates/AttributeMappings/fields-nav.inc b/app/templates/AttributeMappings/fields-nav.inc deleted file mode 100644 index 0010d4300..000000000 --- a/app/templates/AttributeMappings/fields-nav.inc +++ /dev/null @@ -1,34 +0,0 @@ - 'attribute_map', - 'active' => 'mappings' -]; \ No newline at end of file diff --git a/app/templates/AttributeMappings/fields.inc b/app/templates/AttributeMappings/fields.inc index f4743f025..ae3ff654a 100644 --- a/app/templates/AttributeMappings/fields.inc +++ b/app/templates/AttributeMappings/fields.inc @@ -24,9 +24,14 @@ * @since COmanage Match v1.0.0 * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ - -// This view does not support read-only -if($action == 'add' || $action == 'edit') { - print $this->Field->control('query'); - print $this->Field->control('value'); -} \ No newline at end of file + +$fields = [ + 'query', + 'value' +]; + +// Subnavigation tabs +$subnav = [ + 'name' => 'attribute_map', + 'active' => 'mappings' +]; \ No newline at end of file diff --git a/app/templates/AttributeMaps/fields-nav.inc b/app/templates/AttributeMaps/fields-nav.inc deleted file mode 100644 index 87743f4a3..000000000 --- a/app/templates/AttributeMaps/fields-nav.inc +++ /dev/null @@ -1,34 +0,0 @@ - 'attribute_map', - 'active' => 'properties' -]; \ No newline at end of file diff --git a/app/templates/AttributeMaps/fields.inc b/app/templates/AttributeMaps/fields.inc index 246363f0c..b16666438 100644 --- a/app/templates/AttributeMaps/fields.inc +++ b/app/templates/AttributeMaps/fields.inc @@ -24,9 +24,16 @@ * @since COmanage Match v1.0.0 * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ - -// This view does not support read-only -if($action == 'add' || $action == 'edit') { - print $this->Field->control('name'); - print $this->Field->control('description', [], false); -} \ No newline at end of file + +$fields = [ + 'name', + 'description' => [ + 'required' => false + ] +]; + +// Subnavigation tabs +$subnav = [ + 'name' => 'attribute_map', + 'active' => 'properties' +]; \ No newline at end of file diff --git a/app/templates/Attributes/fields.inc b/app/templates/Attributes/fields.inc index 9fb5c8f3f..18a3109f8 100644 --- a/app/templates/Attributes/fields.inc +++ b/app/templates/Attributes/fields.inc @@ -24,27 +24,45 @@ * @since COmanage Match v1.0.0 * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ - -// This view does not support read-only -if($action == 'add' || $action == 'edit') { - print $this->Field->control('name'); - - print $this->Field->control('description', [], false); - - print $this->Field->control('api_name'); - - print $this->Field->control('index_display', [], false); - - print $this->Field->control('alphanumeric', [], false); - print $this->Field->control('case_sensitive', [], false); - print $this->Field->control('null_equivalents', [], false); - - print $this->Field->control('search_distance', [], false); - print $this->Field->control('search_exact', [], false); - print $this->Field->control('search_substr_from', [], false); - print $this->Field->control('search_substr_for', [], false); - print $this->Field->control('attribute_map_id', ['empty' => true], false); - print $this->Field->control('attribute_group_id', ['empty' => true], false); -} +$fields = [ + 'name', + 'description' => [ + 'required' => false + ], + 'api_name', + 'index_display' => [ + 'required' => false + ], + 'alphanumeric' => [ + 'required' => false + ], + 'case_sensitive' => [ + 'required' => false + ], + 'null_equivalents' => [ + 'required' => false + ], + 'search_distance' => [ + 'required' => false + ], + 'search_exact' => [ + 'required' => false + ], + 'search_substr_from' => [ + 'required' => false + ], + 'search_substr_for' => [ + 'required' => false + ], + 'attribute_map_id' => [ + 'empty' => true, + 'required' => false + ], + 'attribute_group_id' => [ + 'empty' => true, + 'required' => false + ] +]; + \ No newline at end of file diff --git a/app/templates/Endpoints/fields.inc b/app/templates/Endpoints/fields.inc index 5d628cdf7..c56fa938f 100644 --- a/app/templates/Endpoints/fields.inc +++ b/app/templates/Endpoints/fields.inc @@ -25,13 +25,13 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not support read-only -if($action == 'add' || $action == 'edit') { - print $this->Field->control('description'); - - print $this->Field->control('url'); - - print $this->Field->control('username', [], false); - - print $this->Field->control('password', [], false); -} +$fields = [ + 'description', + 'url', + 'username' => [ + 'required' => false + ], + 'password' => [ + 'required' => false + ], +]; \ No newline at end of file diff --git a/app/templates/MatchgridHistoryRecords/fields.inc b/app/templates/MatchgridHistoryRecords/fields.inc index 03b8d9b9e..60eaf30d8 100644 --- a/app/templates/MatchgridHistoryRecords/fields.inc +++ b/app/templates/MatchgridHistoryRecords/fields.inc @@ -28,31 +28,42 @@ ?> \App\Lib\Enum\MatchgridActionEnum::CommentAdded, 'actor_identifier' => $vv_user['username'], 'remote_ip' => $this->request->getEnv('REMOTE_ADDR') ]; - print $this->Field->control('sor', ['readonly' => true, 'value' => $this->request->getQuery('sor')]); - - print $this->Field->control('sorid', ['readonly' => true, 'value' => $this->request->getQuery('sorid')]); - - print $this->Field->control('comment'); -} elseif($action == 'view') { - print $this->Field->control('comment'); + // Define interactive fields + $fields = [ + 'sor' => [ + 'readonly' => true, + 'value' => $this->request->getQuery('sor') + ], + 'sorid' => [ + 'readonly' => true, + 'value' => $this->request->getQuery('sorid') + ], + 'comment' + ]; - print $this->Field->control('action'); +} elseif($action == 'view') { - print $this->Field->control('sor'); - - print $this->Field->control('sorid'); - - print $this->Field->control('remote_ip'); - - print $this->Field->control('actor_identifier'); + // Define fields for read-only display + $fields = [ + 'comment', + 'action', + 'sor', + 'sorid', + 'remote_ip', + 'actor_identifier', + 'created' + ]; - print $this->Field->control('created'); } \ No newline at end of file diff --git a/app/templates/MatchgridRecords/fields.inc b/app/templates/MatchgridRecords/fields.inc index 204e9d4a8..e30eee2fb 100644 --- a/app/templates/MatchgridRecords/fields.inc +++ b/app/templates/MatchgridRecords/fields.inc @@ -25,36 +25,51 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -if($action == 'add' || $action == 'edit') { - print $this->Field->control('sor', ['type' => 'select', 'options' => $sor, 'empty' => __('match.fd.select'), 'required' => true]); - print $this->Field->control('sorid', ['required' => true]); +$fields = [ + 'sor' => [ + 'type' => 'select', + 'options' => $sor, + 'empty' => __('match.fd.select'), + 'required' => true + ], + 'sorid' => [ + 'required' => true + ] +]; + +foreach($attributes as $attr) { + // If there is an attribute grouping, we need to append it to the api name + // XXX There's similar logic in BulkLoad, maybe make this a call on Attributes? + // eg: Attributes->getInternalApiName() + $f = $attr->api_name; - foreach($attributes as $attr) { - $options = []; - - // If there is an attribute grouping, we need to append it to the api name - // XXX There's similar logic in BulkLoad, maybe make this a call on Attributes? - // eg: Attributes->getInternalApiName() - $f = $attr->api_name; - - if(!empty($attr->attribute_group->name)) { - $f .= "/" . $attr->attribute_group->name; - } - - // We have to manually set the current value since the control name doesn't - // map to the object name - if($action == 'edit') { - $options['default'] = $vv_obj->{$attr->name}; - } - - print $this->Field->control($f, $options, false, $attr->name); + if(!empty($attr->attribute_group->name)) { + $f .= "/" . $attr->attribute_group->name; + } + + $fields[$f] = [ + 'required' => false, + 'labelText' => $attr->name + ]; + + // We have to manually set the current value since the control name doesn't + // map to the object name + if($action == 'edit') { + $fields[$f]['default'] = $vv_obj->{$attr->name}; } - - print $this->Field->control('referenceid', [], false, __('match.fd.referenceid', [1])); } +$fields['referenceid'] = [ + 'required' => false, + 'labelText' => __('match.fd.referenceid', [1]) +]; + + if($action == 'edit') { - print $this->Field->control('request_time'); + $fields['request_time'] = []; + // Force resolution to read only since it might not be populated - print $this->Field->control('resolution_time', ['readonly' => true]); + $fields['resolution_time'] = [ + 'readonly' => true + ]; } \ No newline at end of file diff --git a/app/templates/MatchgridSettings/fields.inc b/app/templates/MatchgridSettings/fields.inc index 9ef13fa05..4988160ce 100644 --- a/app/templates/MatchgridSettings/fields.inc +++ b/app/templates/MatchgridSettings/fields.inc @@ -26,13 +26,35 @@ */ use \App\Lib\Enum\ReferenceIdEnum; + +$fields = [ + 'referenceid_method' => [ + 'empty' => true + ], + 'referenceid_start' => [ + 'default' => 1001 + ], + 'referenceid_prefix' => [ + 'required' => false + ], + 'notification_email' => [ + 'required' => false + ], + 'resolution_notification_endpoint_id' => [ + 'empty' => true, + 'required' => false, + 'labelText' => __('match.fd.resolution_notification_endpoint') + ] +]; + ?> - -Field->control('referenceid_method', - ['empty' => true, - 'onChange' => 'fields_update_gadgets();']); - print $this->Field->control('referenceid_start', - ['default' => 1001]); - - print $this->Field->control('referenceid_prefix', [], false); - - print $this->Field->control('notification_email', [], false); + $(function() { + fields_update_gadgets(); - print $this->Field->control('resolution_notification_endpoint_id', - ['empty' => true], - false, - __('match.fd.resolution_notification_endpoint')); -} + $('#referenceid-method').change(function() { + fields_update_gadgets(); + }); + }); + diff --git a/app/templates/Matchgrids/fields.inc b/app/templates/Matchgrids/fields.inc index e8e992c2a..53b2874d9 100644 --- a/app/templates/Matchgrids/fields.inc +++ b/app/templates/Matchgrids/fields.inc @@ -25,12 +25,12 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not support read-only -if($action == 'add' || $action == 'edit') { - print $this->Field->control('table_name'); - - print $this->Field->control('description', [], false); - - print $this->Field->control('status', - ['empty' => false]); -} +$fields = [ + 'table_name', + 'description' => [ + 'required' => false + ], + 'status' => [ + 'empty' => false + ] +]; diff --git a/app/templates/Matchgrids/reconcile.php b/app/templates/Matchgrids/reconcile.php index 03f09913f..75b6e3a3c 100644 --- a/app/templates/Matchgrids/reconcile.php +++ b/app/templates/Matchgrids/reconcile.php @@ -217,12 +217,12 @@ - \ No newline at end of file + }); + \ No newline at end of file diff --git a/app/templates/Permissions/fields.inc b/app/templates/Permissions/fields.inc index 04876de61..ae7abc8d9 100644 --- a/app/templates/Permissions/fields.inc +++ b/app/templates/Permissions/fields.inc @@ -26,15 +26,27 @@ */ use \App\Lib\Enum\PermissionEnum; + +$fields = [ + 'username', + 'permission' => [ + 'empty' => true + ], + 'matchgrid_id' => [ + 'empty' => true + ] +]; + ?> - -Field->control('username'); - - print $this->Field->control('permission', - ['empty' => true, - 'onChange' => 'fields_update_gadgets();']); - - print $this->Field->control('matchgrid_id', ['empty' => true]); -} \ No newline at end of file diff --git a/app/templates/RuleAttributes/fields-nav.inc b/app/templates/RuleAttributes/fields-nav.inc deleted file mode 100644 index 448d29bf6..000000000 --- a/app/templates/RuleAttributes/fields-nav.inc +++ /dev/null @@ -1,34 +0,0 @@ - 'rule', - 'active' => 'attributes' -]; \ No newline at end of file diff --git a/app/templates/RuleAttributes/fields.inc b/app/templates/RuleAttributes/fields.inc index 310dd9010..a6906f015 100644 --- a/app/templates/RuleAttributes/fields.inc +++ b/app/templates/RuleAttributes/fields.inc @@ -27,15 +27,43 @@ use \App\Lib\Enum\ConfidenceModeEnum; use \App\Lib\Enum\SearchTypeEnum; + +$fields = [ + 'attribute_id' => [ + 'empty' => true + ], + 'crosscheck_attribute_id' => [ + 'empty' => true, + 'required' => false, + 'labelText' => __('match.fd.RuleAttributes.crosscheck_attribute_id') + ], + 'search_type' => [ + 'empty' => true + ], + 'required' => [ + 'required' => false + ], + 'match_empty' => [ + 'required' => false + ] +]; + +// Subnavigation tabs +$subnav = [ + 'name' => 'rule', + 'active' => 'attributes' +]; + ?> - -Field->control('attribute_id', ['empty' => true]); - print $this->Field->control('crosscheck_attribute_id', ['empty' => true], false, __('match.fd.RuleAttributes.crosscheck_attribute_id')); - print $this->Field->control('search_type', ['empty' => true]); - print $this->Field->control('required', ['onChange'=>'fields_update_gadgets();'], false); - print $this->Field->control('match_empty', [], false); -} \ No newline at end of file diff --git a/app/templates/Rules/fields-nav.inc b/app/templates/Rules/fields-nav.inc deleted file mode 100644 index dc914bfec..000000000 --- a/app/templates/Rules/fields-nav.inc +++ /dev/null @@ -1,34 +0,0 @@ - 'rule', - 'active' => 'properties' -]; \ No newline at end of file diff --git a/app/templates/Rules/fields.inc b/app/templates/Rules/fields.inc index cc72f6a38..0c12d798c 100644 --- a/app/templates/Rules/fields.inc +++ b/app/templates/Rules/fields.inc @@ -25,10 +25,21 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ -// This view does not support read-only -if($action == 'add' || $action == 'edit') { - print $this->Field->control('name'); - print $this->Field->control('description', [], false); - print $this->Field->control('confidence_mode', ['empty' => true]); - print $this->Field->control('ordr', [], false); -} \ No newline at end of file +$fields = [ + 'name', + 'description' => [ + 'required' => false + ], + 'confidence_mode' => [ + 'empty' => true + ], + 'ordr' => [ + 'required' => false + ] +]; + +// Subnavigation tabs +$subnav = [ + 'name' => 'rule', + 'active' => 'properties' +]; diff --git a/app/templates/Standard/add-edit-view.php b/app/templates/Standard/add-edit-view.php index e0c8d235c..b3495a488 100644 --- a/app/templates/Standard/add-edit-view.php +++ b/app/templates/Standard/add-edit-view.php @@ -33,26 +33,29 @@ // $this->name = Models $modelsName = $this->name; -// Include subnavigation structures on add/edit/view pages -// XXX: if fields.inc is made configuration only, move the contents of fields-nav.inc into fields.inc -// Include subnav on all but the top-level object's Add view when subnav exists. -if((!empty($vv_primary_link_model) && $vv_primary_link_model != 'Matchgrids') || $action != 'add') { - if(file_exists(ROOT . DS . "templates" . DS . $modelsName . DS . "fields-nav.inc")) { - include(ROOT . DS . "templates" . DS . $modelsName . DS . "fields-nav.inc"); - } -} +// Include fields configuration for the form +include(TEMPLATES . $modelsName . DS . "fields.inc"); // $flashArgs pass banner messages to the flash element container $flashArgs = []; if(!empty($banners)) { - // XXX this doesn't work yet because we don't include fields.inc until later - // either create a second file to include earlier, or use a function to emit - // the fields (which would be more consistent with how Views render...) $flashArgs['vv_banners'] = $banners; } ?> - - + +
@@ -120,7 +125,7 @@ @@ -131,7 +136,7 @@ @@ -139,14 +144,14 @@ - = $this->fetch('content'); ?> + = $this->fetch('content') ?> @@ -155,21 +160,21 @@