From f581b79dab1c5b8048ab621f0b37a88fb1e29d4d Mon Sep 17 00:00:00 2001 From: Rias Date: Fri, 10 Jul 2026 20:33:00 +0200 Subject: [PATCH 1/4] Fix Testbench workbench serving --- composer.json | 5 ++++- testbench.yaml | 2 +- workbench/.env.example | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index b7ca4051a62..9f8968bf1a1 100644 --- a/composer.json +++ b/composer.json @@ -142,7 +142,10 @@ ], "clear": "@php vendor/bin/testbench package:purge-skeleton --ansi", "prepare": "@php vendor/bin/testbench package:discover --ansi", - "build": "@php vendor/bin/testbench workbench:build --ansi", + "build": [ + "@php vendor/bin/testbench package:create-sqlite-db --ansi", + "@php vendor/bin/testbench workbench:build --ansi" + ], "serve": [ "Composer\\Config::disableProcessTimeout", "@php vendor/bin/testbench package:sync-skeleton --ansi", diff --git a/testbench.yaml b/testbench.yaml index bd4f20c94da..f61b1625f09 100644 --- a/testbench.yaml +++ b/testbench.yaml @@ -18,7 +18,7 @@ workbench: install: false # We run the Craft install in DatabaseSeeder user: 1 sync: - - from: resources + - from: cms-assets/resources to: public/vendor/craft - from: storage to: workbench/storage diff --git a/workbench/.env.example b/workbench/.env.example index 45a02fd3a90..20eee2ace41 100644 --- a/workbench/.env.example +++ b/workbench/.env.example @@ -7,7 +7,7 @@ APP_KEY=base64:6BDzvwO4hrN7Twv6/gaQ6oZMB/CvpUArZXho189U75E= APP_URL=http://127.0.0.1:8000 DB_CONNECTION=sqlite -DB_DATABASE=workbench/database/database.sqlite +SESSION_DRIVER=database FROM_EMAIL_NAME="Craft CMS" FROM_EMAIL_ADDRESS=info@craftcms.com From 51937e5b3a2a745f636798ccdfc7a520746690b6 Mon Sep 17 00:00:00 2001 From: Rias Date: Fri, 10 Jul 2026 20:33:19 +0200 Subject: [PATCH 2/4] Modernize elevated session confirmation --- CHANGELOG.md | 5 + packages/craftcms-legacy/cp/src/Craft.js | 2 - .../components/HtmlFragmentRenderer.vue | 8 + resources/js/common/layouts/AppLayout.vue | 2 + resources/js/common/types/globals.d.ts | 2 +- resources/js/cp.ts | 1 + resources/js/legacy.ts | 3 + .../auth/components/login/login-form.ts | 10 ++ .../ElevatedSessionHost.test.ts | 96 ++++++++++ .../elevated-session/ElevatedSessionHost.vue | 113 ++++++++++++ .../elevated-session-form.test.ts | 66 +++++++ .../elevated-session/elevated-session-form.ts | 170 ++++++++++++++++++ .../auth/elevated-session/index.test.ts | 41 +++++ .../js/modules/auth/elevated-session/index.ts | 71 ++++++++ .../auth/elevated-session/manager.test.ts | 142 +++++++++++++++ .../modules/auth/elevated-session/manager.ts | 166 +++++++++++++++++ .../settings/composables/useSettingsSave.ts | 75 ++++++-- resources/js/pages/graphql/schemas/Edit.vue | 8 +- resources/js/pages/graphql/tokens/Edit.vue | 7 +- .../js/pages/settings/users/groups/Edit.vue | 9 +- resources/js/pages/users/Permissions.vue | 14 +- resources/js/pages/users/SignInProviders.vue | 55 ++++-- routes/actions.php | 3 + routes/cp.php | 5 +- src/Auth/Concerns/ConfirmsPasswords.php | 13 +- src/Auth/LoginRateLimiter.php | 29 +++ src/Http/Controllers/Auth/LoginController.php | 7 +- .../Auth/SessionInfoController.php | 63 +++++++ .../Controllers/Gql/SchemasController.php | 13 +- src/Http/Controllers/Gql/TokensController.php | 11 +- .../Settings/Users/UserGroupsController.php | 11 -- .../Users/PermissionsController.php | 15 +- .../Users/SignInProvidersController.php | 14 +- .../Middleware/RequireConfirmedPassword.php | 21 +++ src/Route/RouteServiceProvider.php | 10 ++ .../Auth/Concerns/ConfirmsPasswordsTest.php | 21 ++- .../Controllers/Auth/LoginControllerTest.php | 56 ++++++ .../Auth/SessionInfoControllerTest.php | 123 +++++++++++++ .../User/SignInProvidersControllerTest.php | 23 +-- .../RequireConfirmedPasswordTest.php | 39 ++++ 40 files changed, 1428 insertions(+), 115 deletions(-) create mode 100644 resources/js/modules/auth/elevated-session/ElevatedSessionHost.test.ts create mode 100644 resources/js/modules/auth/elevated-session/ElevatedSessionHost.vue create mode 100644 resources/js/modules/auth/elevated-session/elevated-session-form.test.ts create mode 100644 resources/js/modules/auth/elevated-session/elevated-session-form.ts create mode 100644 resources/js/modules/auth/elevated-session/index.test.ts create mode 100644 resources/js/modules/auth/elevated-session/index.ts create mode 100644 resources/js/modules/auth/elevated-session/manager.test.ts create mode 100644 resources/js/modules/auth/elevated-session/manager.ts create mode 100644 src/Auth/LoginRateLimiter.php create mode 100644 src/Http/Middleware/RequireConfirmedPassword.php create mode 100644 tests/Feature/Http/Middleware/RequireConfirmedPasswordTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 11d9a9c8abc..c7e06ae291b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Release Notes for Craft CMS 6 +## Unreleased + +- Updated elevated session prompts to use the modern control panel frontend while preserving the legacy JavaScript APIs. +- Login attempts are now rate limited. + ## 6.0.0-alpha.11 - 2026-07-07 - Users can now connect their accounts to one or more Socialite providers. ([#19202](https://github.com/craftcms/cms/pull/19202)) diff --git a/packages/craftcms-legacy/cp/src/Craft.js b/packages/craftcms-legacy/cp/src/Craft.js index 8b3aac249fd..5278931ddab 100644 --- a/packages/craftcms-legacy/cp/src/Craft.js +++ b/packages/craftcms-legacy/cp/src/Craft.js @@ -61,8 +61,6 @@ import './js/ElementDeletionManager.js'; import './js/ElementEditor.js'; import './js/ElementFieldSettings.js'; import './js/ElementTableSorter.js'; -import './js/ElevatedSessionForm.js'; -import './js/ElevatedSessionManager.js'; import './js/EntryIndex.js'; import './js/EntrySelectInput.js'; import './js/EntryTypeSelectInput.js'; diff --git a/resources/js/common/components/HtmlFragmentRenderer.vue b/resources/js/common/components/HtmlFragmentRenderer.vue index 3f193ce8e78..53dd9c50853 100644 --- a/resources/js/common/components/HtmlFragmentRenderer.vue +++ b/resources/js/common/components/HtmlFragmentRenderer.vue @@ -11,6 +11,10 @@ fragment?: CraftCms.Cms.View.HtmlFragment | null; }>(); + const emit = defineEmits<{ + rendered: [element: HTMLElement]; + }>(); + const container = ref(null); const disposers: AppendHtmlDisposer[] = []; let lastKey = ''; @@ -86,6 +90,10 @@ ) { return; } + + if (currentRunId === runId) { + emit('rendered', element); + } }, {immediate: true} ); diff --git a/resources/js/common/layouts/AppLayout.vue b/resources/js/common/layouts/AppLayout.vue index f4e28db29ab..b491cc15b2f 100644 --- a/resources/js/common/layouts/AppLayout.vue +++ b/resources/js/common/layouts/AppLayout.vue @@ -15,6 +15,7 @@ import SystemInfo from '@/common/components/SystemInfo.vue'; import UserMenu from '@/common/components/UserMenu.vue'; import ErrorSummary from '@/common/form/ErrorSummary.vue'; + import ElevatedSessionHost from '@/modules/auth/elevated-session/ElevatedSessionHost.vue'; import {useActionRedirect} from '@/common/composables/useActionRedirect'; import {useAnnouncer} from '@/common/composables/useAnnouncer'; import {useAppendHtml} from '@/common/composables/useAppendHtml'; @@ -396,6 +397,7 @@ +