diff --git a/app/resources/locales/en_US/information.po b/app/resources/locales/en_US/information.po index 933cd91f0..85a1b293f 100644 --- a/app/resources/locales/en_US/information.po +++ b/app/resources/locales/en_US/information.po @@ -108,5 +108,11 @@ msgstr "Active, Cannot Be Disabled" msgid "plugin.inactive" msgstr "Inactive" +msgid "record" +msgstr "Record" + +msgid "report.for" +msgstr "Report for " + msgid "table.list" msgstr "{0} List" \ No newline at end of file diff --git a/app/resources/locales/en_US/operation.po b/app/resources/locales/en_US/operation.po index 473c81ebf..a80337754 100644 --- a/app/resources/locales/en_US/operation.po +++ b/app/resources/locales/en_US/operation.po @@ -36,12 +36,12 @@ msgstr "Add" msgid "add.a" msgstr "Add a New {0}" -msgid "add.bulk" -msgstr "Bulk add" - msgid "add.member" msgstr "Add member: " +msgid "apply" +msgstr "Apply" + msgid "autocomplete.pager.show.more" msgstr "show more" @@ -69,6 +69,12 @@ msgstr "Assign" msgid "any" msgstr "Any" +msgid "bulk.actions" +msgstr "Bulk Actions" + +msgid "bulk.add" +msgstr "Bulk add" + msgid "cancel" msgstr "Cancel" @@ -171,6 +177,9 @@ msgstr "Display records" msgid "page.goto" msgstr "Go to page" +msgid "pick" +msgstr "Pick" + msgid "previous" msgstr "Previous" @@ -210,6 +219,9 @@ msgstr "Search" msgid "search.global" msgstr "Global Search" +msgid "select.prompt" +msgstr "Please select..." + msgid "skip_to_content" msgstr "Skip to main content" diff --git a/app/resources/locales/en_US/result.po b/app/resources/locales/en_US/result.po index ec5506dec..fd77789d5 100644 --- a/app/resources/locales/en_US/result.po +++ b/app/resources/locales/en_US/result.po @@ -57,6 +57,9 @@ msgstr "External Identity status recalculated from {0} to {1}" msgid "ExternalIdentitySources.synced" msgstr "External Identity Source sync complete" +msgid "failed" +msgstr "failed" + msgid "Groups.added" msgstr "Group {0} created" @@ -154,6 +157,9 @@ msgstr "Created new External Identity via Pipeline {0} ({1}) using Source {2} ({ msgid "Pipelines.started" msgstr "Pipeline {0} ({1}) started for EIS {2} ({3}) source key {4}" +msgid "removed" +msgstr "removed" + msgid "saved" msgstr "Saved" @@ -190,3 +196,6 @@ msgstr "Database connection established" msgid "test.mail.ok" msgstr "Test message sent" + +msgid "updated" +msgstr "updated" diff --git a/app/src/Controller/Component/RegistryAuthComponent.php b/app/src/Controller/Component/RegistryAuthComponent.php index bc00de262..a1646e817 100644 --- a/app/src/Controller/Component/RegistryAuthComponent.php +++ b/app/src/Controller/Component/RegistryAuthComponent.php @@ -252,12 +252,21 @@ public function beforeFilter(EventInterface $event) { } if(Configure::read('debug')) { - // For testing purposes throw an error, but in production we want to + // For testing purposes, throw an error, but in production we want to // redirect to /login + if($request->is('ajax') || $request->is('restful')) { + // Permission denied + throw new ForbiddenException(__d('error', 'perm')); + } $controller->Flash->error("Authorization Failed (RegistryAuthComponent)"); return $controller->redirect("/"); } } + + if($request->is('ajax') || $request->is('restful')) { + // Permission denied + throw new ForbiddenException(__d('error', 'perm')); + } // No authentication, redirect to login diff --git a/app/src/Lib/Enum/BulkActionEnum.php b/app/src/Lib/Enum/BulkActionEnum.php new file mode 100644 index 000000000..d0169dde7 --- /dev/null +++ b/app/src/Lib/Enum/BulkActionEnum.php @@ -0,0 +1,76 @@ + 'delete', + 'owner' => 'post', + default => 'get' + }; + } + + /** + * Return actions to request http methods + * + * @param array $actions + * + * @return array + * @since COmanage Registry v5.0.0 + */ + + public static function actionsToMethods() : array + { + $ret = []; + foreach (self::getConstValues() as $act) { + $ret[$act] = match($act) { + 'delete' => 'delete', + 'owner' => 'post', + default => 'get' + }; + } + + return $ret; + } +} \ No newline at end of file diff --git a/app/src/Lib/Enum/StandardEnum.php b/app/src/Lib/Enum/StandardEnum.php index 80c20fb63..5cf23ea16 100644 --- a/app/src/Lib/Enum/StandardEnum.php +++ b/app/src/Lib/Enum/StandardEnum.php @@ -82,4 +82,43 @@ public static function getConstValues() : array { return array_values($consts); } + + /** + * Get the Keys for the constants in the Enumeration in Humanized form. + * + * @since COmanage Registry v5.0.0 + * @return array Array of enumeration keys + */ + + public static function getConstHumanized() : array { + // Get the keys for this enum + $reflect = new ReflectionClass(get_called_class()); + + $consts = $reflect->getConstants(); + + return collection(array_keys($consts))->map( + fn($key) => Inflector::humanize(Inflector::underscore($key)) + )->toList(); + } + + /** + * Reverse the Const. The key is now the value is the humanized form + * of the key. Ideal for Select elements + * + * @since COmanage Registry v5.0.0 + * @return array + */ + + public static function getHumanized() : array { + // Get the keys for this enum + $reflect = new ReflectionClass(get_called_class()); + + $consts = $reflect->getConstants(); + + $humanized = collection(array_keys($consts))->map( + fn($key) => Inflector::humanize(Inflector::underscore($key)) + )->toList(); + + return array_combine(array_values($consts), $humanized); + } } \ No newline at end of file diff --git a/app/src/View/Helper/VueHelper.php b/app/src/View/Helper/VueHelper.php index 54adaa1a3..3175e6732 100644 --- a/app/src/View/Helper/VueHelper.php +++ b/app/src/View/Helper/VueHelper.php @@ -51,11 +51,14 @@ class VueHelper extends Helper { 'login', 'primary', 'datepicker.hour', + 'status', 'unverified' ], 'information' => [ 'global.value.none', - 'datepicker.hour' + 'datepicker.hour', + 'record', + 'report.for' ], 'operation' => [ 'add', @@ -65,6 +68,11 @@ class VueHelper extends Helper { 'autocomplete.people.label', 'autocomplete.people.placeholder', 'close' + ], + 'result' => [ + 'failed', + 'removed', + 'updated' ] ]; diff --git a/app/templates/GroupMembers/columns.inc b/app/templates/GroupMembers/columns.inc index 3007190e8..8cef9bbc8 100644 --- a/app/templates/GroupMembers/columns.inc +++ b/app/templates/GroupMembers/columns.inc @@ -25,6 +25,8 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ +use App\Lib\Enum\BulkActionEnum; + $indexColumns = [ 'name' => [ 'type' => 'link', @@ -83,13 +85,11 @@ $topLinks = [ */ ]; -/* -// When the $bulkActions variable exists in a columns.inc config, the "Bulk edit" switch will appear in the index. -$bulkActions = [ - // TODO: develop bulk actions. For now, use a placeholder. - 'delete' => true -]; -*/ + +// When the $bulkActions variable exists in a columns.inc config, the "Bulk edit" switch will appear in the index. +// The array should contain a list of actions to be made available. +$bulkActions = [BulkActionEnum::Delete]; + $subnav = [ 'name' => 'group', diff --git a/app/templates/Groups/columns.inc b/app/templates/Groups/columns.inc index 2167470fd..75abf054e 100644 --- a/app/templates/Groups/columns.inc +++ b/app/templates/Groups/columns.inc @@ -25,6 +25,8 @@ * @license Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) */ +use App\Lib\Enum\BulkActionEnum; + $indexColumns = [ 'name' => [ 'type' => 'link' @@ -73,10 +75,7 @@ $rowActions = [ ] ]; -/* -// When the $bulkActions variable exists in a columns.inc config, the "Bulk edit" switch will appear in the index. -$bulkActions = [ - // TODO: develop bulk actions. For now, use a placeholder. - 'delete' => true -]; -*/ \ No newline at end of file + +// When the $bulkActions variable exists in a columns.inc config, the "Bulk edit" switch will appear in the index. +// The array should contain a list of actions to be made available. +$bulkActions = [BulkActionEnum::Delete]; diff --git a/app/templates/Notifications/fields.inc b/app/templates/Notifications/fields.inc index c6a5819bd..449c5da13 100644 --- a/app/templates/Notifications/fields.inc +++ b/app/templates/Notifications/fields.inc @@ -58,7 +58,10 @@ if($vv_action == 'view') { ] ]); } else { - print $this->Field->control('status'); + print $this->element('form/listItem', [ + 'arguments' => [ + 'fieldName' => 'status' + ]]); } print $this->element('form/listItem', [ diff --git a/app/templates/Standard/index.php b/app/templates/Standard/index.php index d29a64b71..1e12d4e9d 100644 --- a/app/templates/Standard/index.php +++ b/app/templates/Standard/index.php @@ -169,14 +169,21 @@ - + + = $this->element('flash', $flashArgs); ?> + + + + + = $this->element('bulk/bulk', ['bulkActions' => $bulkActions]); ?> + - + '; } ?> - -
` + info += ` ${this.action} ${resp.statusText} (Code: ${resp.status})
${this.jsn[idx].message}
` + info += `${this.jsn[idx].url}
` + } + return { + 'record': this.labels.filter((idx, lbl) => lbl.id == parseInt(id))[0].label, + 'status': info + } + }) + } + }, + mounted() { + this.body = this.parseRawData() + let parsed = JSON.parse(JSON.stringify(this.body)) + $("#error-datatable").DataTable({ + data: parsed, + columns: this.columns, + paging: false, + scrollCollapse: true, + scrollY: '250px', + }); + }, + inject: ['txt'], + components: { + DataTable + }, + template: ` +{{ this.txt['record'] }} | +{{ this.txt['status'] }} | +
---|