diff --git a/ProcessMaker/Console/Commands/RevokeOauthAccessTokens.php b/ProcessMaker/Console/Commands/RevokeOauthAccessTokens.php new file mode 100644 index 0000000000..c93a6a02fb --- /dev/null +++ b/ProcessMaker/Console/Commands/RevokeOauthAccessTokens.php @@ -0,0 +1,69 @@ +option('name'); + $after = $this->option('after'); + $clientId = $this->option('client_id'); + $noInteraction = $this->option('no-interaction'); + + if (!$name && !$after && !$clientId) { + $this->error('At least one of --name, --after, or --client_id must be specified.'); + return; + } + + if (!$noInteraction && !$this->confirm('Are you sure you want to revoke this certificate?')) { + $this->info('Certificate revocation cancelled.'); + return; + } + + $query = DB::table('oauth_access_tokens')->where('revoked', false); + + if ($name) { + $names = explode(',', $name); + $query->whereIn('name', $names); + } + + if ($after) { + $date = Carbon::createFromFormat('Y-m-d', $after); + $query->where('created_at', '>', $date); + } + + if ($clientId) { + $clientIds = explode(',', $clientId); + $query->whereIn('client_id', $clientIds); + } + + $revokedCount = $query->update(['revoked' => true]); + + $this->info("Revoked $revokedCount tokens."); + } +} diff --git a/composer.json b/composer.json index 705309f357..3bab81abc5 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "processmaker/processmaker", - "version": "4.12.0", + "version": "4.12.1", "description": "BPM PHP Software", "keywords": [ "php bpm processmaker" @@ -107,7 +107,7 @@ "Gmail" ], "processmaker": { - "build": "fe0627fe", + "build": "4c2786fd", "cicd-enabled": true, "custom": { "package-ellucian-ethos": "1.17.0", @@ -156,11 +156,11 @@ "package-cdata": "1.4.5", "package-collections": "2.20.0", "package-comments": "1.15.0", - "package-conversational-forms": "1.11.0", - "package-data-sources": "1.30.0", - "package-decision-engine": "1.12.0", + "package-conversational-forms": "1.11.1", + "package-data-sources": "1.30.1", + "package-decision-engine": "1.12.1", "package-dynamic-ui": "1.24.0", - "package-files": "1.19.0", + "package-files": "1.19.2", "package-googleplaces": "1.12.0", "package-photo-video": "1.6.0", "package-pm-blocks": "1.9.0", diff --git a/composer.lock b/composer.lock index 0cf34435e0..ae34ebaff3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e2a1e8c8a231f9f6f1d47918f77f9694", + "content-hash": "4c9db9a559bc4165c5d334edf21c60e8", "packages": [ { "name": "aws/aws-crt-php", diff --git a/package-lock.json b/package-lock.json index ec947d05d9..eb67fd07a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@processmaker/processmaker", - "version": "4.12.0", + "version": "4.12.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@processmaker/processmaker", - "version": "4.12.0", + "version": "4.12.1", "hasInstallScript": true, "license": "ISC", "dependencies": { diff --git a/package.json b/package.json index 7ee0065443..5423b47294 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@processmaker/processmaker", - "version": "4.12.0", + "version": "4.12.1", "description": "ProcessMaker 4", "author": "DevOps ", "license": "ISC", diff --git a/resources/js/components/shared/FilterTableBodyMixin.js b/resources/js/components/shared/FilterTableBodyMixin.js index 9398984575..8a584bba20 100644 --- a/resources/js/components/shared/FilterTableBodyMixin.js +++ b/resources/js/components/shared/FilterTableBodyMixin.js @@ -52,10 +52,16 @@ export default { }; }, formatCategory(categories) { - return categories.map(item => item.name).join(', '); + return categories?.map(item => item.name).join(', '); }, getNestedPropertyValue(obj, header) { - return this.format(get(obj, header.field), header); + const value = get(obj, header.field); + + if (typeof header.cb === 'function') { + return header.cb(value, obj); + } + + return this.format(value, header); }, format(value, header) { let config = ""; diff --git a/resources/js/processes/screens/components/ScreenListing.vue b/resources/js/processes/screens/components/ScreenListing.vue index 9930a13f74..af144c813e 100644 --- a/resources/js/processes/screens/components/ScreenListing.vue +++ b/resources/js/processes/screens/components/ScreenListing.vue @@ -208,14 +208,12 @@ export default { title: () => this.$t("Category"), name: "categories", label: this.$t("Category"), - field: "category.name", + field: "categories", sortable: true, direction: "none", width: 150, sortField: "category.name", - callback(categories) { - return categories.map(item => item.name).join(', '); - }, + cb: (categories) => this.formatCategory(categories), }, { title: () => this.$t("Type"), diff --git a/resources/js/processes/scripts/components/ScriptListing.vue b/resources/js/processes/scripts/components/ScriptListing.vue index e8e9b4b894..0afa94283d 100644 --- a/resources/js/processes/scripts/components/ScriptListing.vue +++ b/resources/js/processes/scripts/components/ScriptListing.vue @@ -185,13 +185,11 @@ export default { name: "categories", sortField: "category.name", label: this.$t("Category"), - field: "category.name", + field: "categories", sortable: true, direction: "none", width: 150, - callback(categories) { - return categories.map(item => item.name).join(', '); - }, + cb: (categories) => this.formatCategory(categories), }, { title: () => this.$t("Language"), diff --git a/resources/views/processes/edit.blade.php b/resources/views/processes/edit.blade.php index 195dda7231..743e60175a 100644 --- a/resources/views/processes/edit.blade.php +++ b/resources/views/processes/edit.blade.php @@ -186,15 +186,6 @@ class="invalid-feedback" -
- - {{__('In addition to the process manager, these users and groups will have permission to reassign any task in this process, regardless of the "Allow Reassignment" task setting.')}} -
diff --git a/routes/api.php b/routes/api.php index 947297d3de..4bc4f33a5f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -59,7 +59,7 @@ Route::put('password/change', [ChangePasswordController::class, 'update'])->name('password.update'); Route::put('users/update_language', [UserController::class, 'updateLanguage'])->name('users.updateLanguage'); Route::get('users_task_count', [UserController::class, 'getUsersTaskCount'])->name('users.users_task_count') - ->middleware('can:view-users|create-processes|edit-processes|create-projects|view-projects'); + ->middleware('can:view-users'); // User Groups Route::put('users/{user}/groups', [UserController::class, 'updateGroups'])->name('users.groups.update')->middleware('can:edit-users'); diff --git a/tests/Feature/Api/UsersTest.php b/tests/Feature/Api/UsersTest.php index 30493b7023..2e4637c0a5 100644 --- a/tests/Feature/Api/UsersTest.php +++ b/tests/Feature/Api/UsersTest.php @@ -871,7 +871,8 @@ public function testGetUsersTaskCount() $users = $result->json()['data']; // Assert only the $user and $groupUser are in the list - $this->assertEqualsCanonicalizing([$user->id, $groupUser->id], collect($users)->pluck('id')->toArray()); + $this->assertContains($user->id, array_column($users, 'id')); + $this->assertContains($groupUser->id, array_column($users, 'id')); // Assert the $user has 3 active tasks $tokenCount = collect($users)->first(fn ($r) => $r['id'] === $user->id)['active_tasks_count'];