From 5b1fded0b43d7fe733c4aa0a37c4be361c6b6f89 Mon Sep 17 00:00:00 2001 From: Duncan McClean <19637309+duncanmcclean@users.noreply.github.com> Date: Wed, 10 Jan 2024 19:02:26 +0000 Subject: [PATCH 001/149] [4.x] Fix Bard's sticky toolbar in Live Preview (#9301) Fix Bard's sticky toolbar in Live Preview --- resources/css/components/fieldtypes/bard.css | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/css/components/fieldtypes/bard.css b/resources/css/components/fieldtypes/bard.css index b3886b5d60..9a4291b95d 100644 --- a/resources/css/components/fieldtypes/bard.css +++ b/resources/css/components/fieldtypes/bard.css @@ -73,7 +73,8 @@ } /* Only top-level Bard fields should have a sticky header */ -.workspace .publish-fields:not(.replicator-set-body) > .bard-fieldtype .bard-fixed-toolbar { +.workspace .publish-fields:not(.replicator-set-body) > .bard-fieldtype .bard-fixed-toolbar, +.live-preview .publish-fields:not(.replicator-set-body) > .bard-fieldtype .bard-fixed-toolbar { @apply sticky; } @@ -109,6 +110,9 @@ /* Fixed toolbar inside a stack */ .stack-content .bard-fieldtype .bard-fieldtype .bard-fixed-toolbar { top: 16px; } + + /* We don't need the `top` when in Live Preview */ + .live-preview .bard-fixed-toolbar { top: 0; } } .bard-floating-toolbar { From c9694ae72ac19c4cc5c953baf838e7057879bf34 Mon Sep 17 00:00:00 2001 From: Robin van der Vleuten Date: Wed, 10 Jan 2024 20:05:50 +0100 Subject: [PATCH 002/149] [4.x] Use correct set_time_limit no limit value (#9297) Use correct set_time_limit no limit value --- config/system.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/system.php b/config/system.php index 293191c200..05ffa7e48f 100644 --- a/config/system.php +++ b/config/system.php @@ -108,7 +108,7 @@ */ 'php_memory_limit' => '-1', - 'php_max_execution_time' => '-1', + 'php_max_execution_time' => '0', 'ajax_timeout' => '600000', 'pcre_backtrack_limit' => '-1', From 3e2f68d115b22e82b7afa4b58fc54841184e779c Mon Sep 17 00:00:00 2001 From: Tin <31577031+modrictin@users.noreply.github.com> Date: Wed, 10 Jan 2024 20:17:09 +0100 Subject: [PATCH 003/149] [4.x] Fix Asset browser firing 2 requests on initial Assets page load (#8981) Update Browser.vue --- resources/js/components/assets/Browser/Browser.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/js/components/assets/Browser/Browser.vue b/resources/js/components/assets/Browser/Browser.vue index ea5930ac63..f26158c5dc 100644 --- a/resources/js/components/assets/Browser/Browser.vue +++ b/resources/js/components/assets/Browser/Browser.vue @@ -453,6 +453,7 @@ export default { }, container(container) { + this.initializing = true; this.preferencesPrefix = `assets.${container.id}`; this.mode = this.getPreference('mode') || 'table'; this.setInitialPerPage(); @@ -464,7 +465,7 @@ export default { }, parameters(after, before) { - if (JSON.stringify(before) === JSON.stringify(after)) return; + if (this.initializing || JSON.stringify(before) === JSON.stringify(after)) return; this.loadAssets(); }, From a4364638ee4b4da821d523abe0817b1716905830 Mon Sep 17 00:00:00 2001 From: Duncan McClean <19637309+duncanmcclean@users.noreply.github.com> Date: Thu, 11 Jan 2024 15:39:43 +0000 Subject: [PATCH 004/149] [4.x] Fix spacing around fullscreen button on Stacked Grid (#9307) Fix spacing around fullscreen button on Stacked Grid --- resources/js/components/fieldtypes/grid/Grid.vue | 1 + resources/js/components/fieldtypes/grid/Stacked.vue | 11 +++++++++-- resources/js/components/fieldtypes/grid/View.vue | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/resources/js/components/fieldtypes/grid/Grid.vue b/resources/js/components/fieldtypes/grid/Grid.vue index e1ac28b9c3..868a163a0b 100644 --- a/resources/js/components/fieldtypes/grid/Grid.vue +++ b/resources/js/components/fieldtypes/grid/Grid.vue @@ -28,6 +28,7 @@ :can-delete-rows="canDeleteRows" :can-add-rows="canAddRows" :allow-fullscreen="config.fullscreen" + :hide-display="config.hide_display" @updated="updated" @meta-updated="updateRowMeta" @removed="removed" diff --git a/resources/js/components/fieldtypes/grid/Stacked.vue b/resources/js/components/fieldtypes/grid/Stacked.vue index 00ca0e36ea..d7024d62fc 100644 --- a/resources/js/components/fieldtypes/grid/Stacked.vue +++ b/resources/js/components/fieldtypes/grid/Stacked.vue @@ -18,7 +18,14 @@ @dragend="$emit('blur')" @input="(rows) => $emit('sorted', rows)" > -
+
diff --git a/resources/js/components/fieldtypes/grid/View.vue b/resources/js/components/fieldtypes/grid/View.vue index 515afd072b..38f830c90b 100644 --- a/resources/js/components/fieldtypes/grid/View.vue +++ b/resources/js/components/fieldtypes/grid/View.vue @@ -1,7 +1,7 @@ ')); + + $this->assertEquals($asset, $return); + Storage::disk('test')->assertExists('path/to/asset.svg'); + $this->assertEquals('path/to/asset.svg', $asset->path()); + + // Ensure the inline scripts were stripped out. + $this->assertStringNotContainsString('contents()); + $this->assertStringNotContainsString('Bad stuff could go in here.', $asset->contents()); + $this->assertStringNotContainsString('', $asset->contents()); + } + public function nonGlideableFileExtensions() { return [ @@ -1763,7 +1785,7 @@ public function it_doesnt_process_or_error_when_uploading_non_glideable_file_wit // Ensure a glide server is never instantiated for these extensions... Facades\Glide::partialMock()->shouldReceive('server')->never(); - $return = $asset->upload(UploadedFile::fake()->create("file.{$extension}")); + $return = $asset->upload(UploadedFile::fake()->createWithContent("file.{$extension}", '')); $this->assertEquals($asset, $return); $this->assertDirectoryExists($glideDir = storage_path('statamic/glide/tmp')); From 95b81e630ebb05bbd5e037c2bbd73d0aa15bfe00 Mon Sep 17 00:00:00 2001 From: Roy Duineveld Date: Fri, 19 Jan 2024 20:38:58 +0100 Subject: [PATCH 034/149] [4.x] Uniform image validation (#9290) --- src/Assets/Asset.php | 3 ++- tests/Assets/AssetTest.php | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index 79c74ef161..c6ebfa8004 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -4,6 +4,7 @@ use ArrayAccess; use Facades\Statamic\Assets\Attributes; +use Facades\Statamic\Imaging\ImageValidator; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Cache; @@ -485,7 +486,7 @@ public function isPreviewable() */ public function isImage() { - return $this->extensionIsOneOf(['jpg', 'jpeg', 'png', 'gif', 'webp']); + return ImageValidator::isValidExtension($this->extension()); } /** diff --git a/tests/Assets/AssetTest.php b/tests/Assets/AssetTest.php index a2b6321a28..94aec7455d 100644 --- a/tests/Assets/AssetTest.php +++ b/tests/Assets/AssetTest.php @@ -1613,7 +1613,7 @@ private function uploadFileTest() Storage::disk('test')->assertMissing('path/to/asset.jpg'); // This should only get called when glide processing source image on upload... - ImageValidator::shouldReceive('isValidImage')->never(); + ImageValidator::partialMock()->shouldReceive('isValidImage')->never(); $return = $asset->upload(UploadedFile::fake()->image('asset.jpg', 13, 15)); @@ -1663,7 +1663,8 @@ public function it_can_upload_an_image_into_a_container_with_glide_config() Facades\AssetContainer::shouldReceive('findByHandle')->with('test_container')->andReturn($this->container); Storage::disk('test')->assertMissing('path/to/asset.jpg'); - ImageValidator::shouldReceive('isValidImage') + ImageValidator::partialMock() + ->shouldReceive('isValidImage') ->with('jpg', 'image/jpeg') ->andReturnTrue() ->once(); @@ -1710,7 +1711,8 @@ public function it_can_upload_an_image_into_a_container_with_new_extension_forma Facades\AssetContainer::shouldReceive('findByHandle')->with('test_container')->andReturn($this->container); Storage::disk('test')->assertMissing('path/to/asset.jpg'); - ImageValidator::shouldReceive('isValidImage') + ImageValidator::partialMock() + ->shouldReceive('isValidImage') ->with('jpg', 'image/jpeg') ->andReturnTrue() ->once(); From 0742d1ade91eedc0279fa12b81687e668f833279 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Mon, 22 Jan 2024 14:58:21 +0000 Subject: [PATCH 035/149] [4.x] Bard: Only configure placeholder extension when placeholder is provided (#9369) --- .../js/components/fieldtypes/bard/BardFieldtype.vue | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/resources/js/components/fieldtypes/bard/BardFieldtype.vue b/resources/js/components/fieldtypes/bard/BardFieldtype.vue index d558ef9855..b671102bad 100644 --- a/resources/js/components/fieldtypes/bard/BardFieldtype.vue +++ b/resources/js/components/fieldtypes/bard/BardFieldtype.vue @@ -706,6 +706,7 @@ export default { getExtensions() { let modeExts = this.inputIsInline ? [DocumentInline] : [DocumentBlock, HardBreak]; + if (this.config.inline === 'break') { modeExts.push(HardBreak.extend({ addKeyboardShortcuts() { @@ -716,8 +717,12 @@ export default { }, })); } - - // Allow passthrough of Ctrl/Cmd + Enter to submit the form + + if (this.config.placeholder) { + modeExts.push(Placeholder.configure({ placeholder: __(this.config.placeholder) })); + } + + // Allow passthrough of Ctrl/Cmd + Enter to submit the form const DisableCtrlEnter = Extension.create({ addKeyboardShortcuts() { return { @@ -735,7 +740,6 @@ export default { Gapcursor, History, Paragraph, - Placeholder.configure({ placeholder: __(this.config.placeholder) }), Set.configure({ bard: this }), Text ]; From 8fee8369068f72170a99f67183f556aa15df21bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Jan 2024 10:34:36 -0500 Subject: [PATCH 036/149] [4.x] Bump vite from 4.2.3 to 4.5.2 (#9367) --- package-lock.json | 210 ++++++++++++++++++++++++---------------------- package.json | 2 +- 2 files changed, 109 insertions(+), 103 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0747dabb6c..5239388d9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -94,7 +94,7 @@ "laravel-vite-plugin": "^0.7.2", "postcss": "^8.4.31", "tailwindcss": "^3.3.0", - "vite": "^4.2.3" + "vite": "^4.5.2" } }, "node_modules/@ampproject/remapping": { @@ -1764,9 +1764,9 @@ "dev": true }, "node_modules/@esbuild/android-arm": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.14.tgz", - "integrity": "sha512-0CnlwnjDU8cks0yJLXfkaU/uoLyRf9VZJs4p1PskBr2AlAHeEsFEwJEo0of/Z3g+ilw5mpyDwThlxzNEIxOE4g==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", "cpu": [ "arm" ], @@ -1780,9 +1780,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.14.tgz", - "integrity": "sha512-eLOpPO1RvtsP71afiFTvS7tVFShJBCT0txiv/xjFBo5a7R7Gjw7X0IgIaFoLKhqXYAXhahoXm7qAmRXhY4guJg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", "cpu": [ "arm64" ], @@ -1796,9 +1796,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.14.tgz", - "integrity": "sha512-nrfQYWBfLGfSGLvRVlt6xi63B5IbfHm3tZCdu/82zuFPQ7zez4XjmRtF/wIRYbJQ/DsZrxJdEvYFE67avYXyng==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", "cpu": [ "x64" ], @@ -1812,9 +1812,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.14.tgz", - "integrity": "sha512-eoSjEuDsU1ROwgBH/c+fZzuSyJUVXQTOIN9xuLs9dE/9HbV/A5IqdXHU1p2OfIMwBwOYJ9SFVGGldxeRCUJFyw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", "cpu": [ "arm64" ], @@ -1828,9 +1828,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.14.tgz", - "integrity": "sha512-zN0U8RWfrDttdFNkHqFYZtOH8hdi22z0pFm0aIJPsNC4QQZv7je8DWCX5iA4Zx6tRhS0CCc0XC2m7wKsbWEo5g==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", "cpu": [ "x64" ], @@ -1844,9 +1844,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.14.tgz", - "integrity": "sha512-z0VcD4ibeZWVQCW1O7szaLxGsx54gcCnajEJMdYoYjLiq4g1jrP2lMq6pk71dbS5+7op/L2Aod+erw+EUr28/A==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", "cpu": [ "arm64" ], @@ -1860,9 +1860,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.14.tgz", - "integrity": "sha512-hd9mPcxfTgJlolrPlcXkQk9BMwNBvNBsVaUe5eNUqXut6weDQH8whcNaKNF2RO8NbpT6GY8rHOK2A9y++s+ehw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", "cpu": [ "x64" ], @@ -1876,9 +1876,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.14.tgz", - "integrity": "sha512-BNTl+wSJ1omsH8s3TkQmIIIQHwvwJrU9u1ggb9XU2KTVM4TmthRIVyxSp2qxROJHhZuW/r8fht46/QE8hU8Qvg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", "cpu": [ "arm" ], @@ -1892,9 +1892,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.14.tgz", - "integrity": "sha512-FhAMNYOq3Iblcj9i+K0l1Fp/MHt+zBeRu/Qkf0LtrcFu3T45jcwB6A1iMsemQ42vR3GBhjNZJZTaCe3VFPbn9g==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", "cpu": [ "arm64" ], @@ -1908,9 +1908,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.14.tgz", - "integrity": "sha512-91OK/lQ5y2v7AsmnFT+0EyxdPTNhov3y2CWMdizyMfxSxRqHazXdzgBKtlmkU2KYIc+9ZK3Vwp2KyXogEATYxQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", "cpu": [ "ia32" ], @@ -1924,9 +1924,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.14.tgz", - "integrity": "sha512-vp15H+5NR6hubNgMluqqKza85HcGJgq7t6rMH7O3Y6ApiOWPkvW2AJfNojUQimfTp6OUrACUXfR4hmpcENXoMQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", "cpu": [ "loong64" ], @@ -1940,9 +1940,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.14.tgz", - "integrity": "sha512-90TOdFV7N+fgi6c2+GO9ochEkmm9kBAKnuD5e08GQMgMINOdOFHuYLPQ91RYVrnWwQ5683sJKuLi9l4SsbJ7Hg==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", "cpu": [ "mips64el" ], @@ -1956,9 +1956,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.14.tgz", - "integrity": "sha512-NnBGeoqKkTugpBOBZZoktQQ1Yqb7aHKmHxsw43NddPB2YWLAlpb7THZIzsRsTr0Xw3nqiPxbA1H31ZMOG+VVPQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", "cpu": [ "ppc64" ], @@ -1972,9 +1972,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.14.tgz", - "integrity": "sha512-0qdlKScLXA8MGVy21JUKvMzCYWovctuP8KKqhtE5A6IVPq4onxXhSuhwDd2g5sRCzNDlDjitc5sX31BzDoL5Fw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", "cpu": [ "riscv64" ], @@ -1988,9 +1988,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.14.tgz", - "integrity": "sha512-Hdm2Jo1yaaOro4v3+6/zJk6ygCqIZuSDJHdHaf8nVH/tfOuoEX5Riv03Ka15LmQBYJObUTNS1UdyoMk0WUn9Ww==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", "cpu": [ "s390x" ], @@ -2004,9 +2004,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.14.tgz", - "integrity": "sha512-8KHF17OstlK4DuzeF/KmSgzrTWQrkWj5boluiiq7kvJCiQVzUrmSkaBvcLB2UgHpKENO2i6BthPkmUhNDaJsVw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", "cpu": [ "x64" ], @@ -2020,9 +2020,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.14.tgz", - "integrity": "sha512-nVwpqvb3yyXztxIT2+VsxJhB5GCgzPdk1n0HHSnchRAcxqKO6ghXwHhJnr0j/B+5FSyEqSxF4q03rbA2fKXtUQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", "cpu": [ "x64" ], @@ -2036,9 +2036,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.14.tgz", - "integrity": "sha512-1RZ7uQQ9zcy/GSAJL1xPdN7NDdOOtNEGiJalg/MOzeakZeTrgH/DoCkbq7TaPDiPhWqnDF+4bnydxRqQD7il6g==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", "cpu": [ "x64" ], @@ -2052,9 +2052,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.14.tgz", - "integrity": "sha512-nqMjDsFwv7vp7msrwWRysnM38Sd44PKmW8EzV01YzDBTcTWUpczQg6mGao9VLicXSgW/iookNK6AxeogNVNDZA==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", "cpu": [ "x64" ], @@ -2068,9 +2068,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.14.tgz", - "integrity": "sha512-xrD0mccTKRBBIotrITV7WVQAwNJ5+1va6L0H9zN92v2yEdjfAN7864cUaZwJS7JPEs53bDTzKFbfqVlG2HhyKQ==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", "cpu": [ "arm64" ], @@ -2084,9 +2084,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.14.tgz", - "integrity": "sha512-nXpkz9bbJrLLyUTYtRotSS3t5b+FOuljg8LgLdINWFs3FfqZMtbnBCZFUmBzQPyxqU87F8Av+3Nco/M3hEcu1w==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", "cpu": [ "ia32" ], @@ -2100,9 +2100,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.14.tgz", - "integrity": "sha512-gPQmsi2DKTaEgG14hc3CHXHp62k8g6qr0Pas+I4lUxRMugGSATh/Bi8Dgusoz9IQ0IfdrvLpco6kujEIBoaogA==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", "cpu": [ "x64" ], @@ -4901,9 +4901,9 @@ } }, "node_modules/esbuild": { - "version": "0.17.14", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.14.tgz", - "integrity": "sha512-vOO5XhmVj/1XQR9NQ1UPq6qvMYL7QFJU57J5fKBKBKxp17uDt5PgxFDb4A2nEiXhr1qQs4x0F5+66hVVw4ruNw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", "dev": true, "hasInstallScript": true, "bin": { @@ -4913,28 +4913,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.14", - "@esbuild/android-arm64": "0.17.14", - "@esbuild/android-x64": "0.17.14", - "@esbuild/darwin-arm64": "0.17.14", - "@esbuild/darwin-x64": "0.17.14", - "@esbuild/freebsd-arm64": "0.17.14", - "@esbuild/freebsd-x64": "0.17.14", - "@esbuild/linux-arm": "0.17.14", - "@esbuild/linux-arm64": "0.17.14", - "@esbuild/linux-ia32": "0.17.14", - "@esbuild/linux-loong64": "0.17.14", - "@esbuild/linux-mips64el": "0.17.14", - "@esbuild/linux-ppc64": "0.17.14", - "@esbuild/linux-riscv64": "0.17.14", - "@esbuild/linux-s390x": "0.17.14", - "@esbuild/linux-x64": "0.17.14", - "@esbuild/netbsd-x64": "0.17.14", - "@esbuild/openbsd-x64": "0.17.14", - "@esbuild/sunos-x64": "0.17.14", - "@esbuild/win32-arm64": "0.17.14", - "@esbuild/win32-ia32": "0.17.14", - "@esbuild/win32-x64": "0.17.14" + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" } }, "node_modules/escalade": { @@ -9038,9 +9038,9 @@ } }, "node_modules/rollup": { - "version": "3.20.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.20.2.tgz", - "integrity": "sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -9805,15 +9805,14 @@ } }, "node_modules/vite": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.2.3.tgz", - "integrity": "sha512-kLU+m2q0Y434Y1kCy3TchefAdtFso0ILi0dLyFV8Us3InXTU11H/B5ZTqCKIQHzSKNxVG/yEx813EA9f1imQ9A==", + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.2.tgz", + "integrity": "sha512-tBCZBNSBbHQkaGyhGCDUGqeo2ph8Fstyp6FMSvTtsXeZSPpSMGlviAOav2hxVTqFcx8Hj/twtWKsMJXNY0xI8w==", "dev": true, "dependencies": { - "esbuild": "^0.17.5", - "postcss": "^8.4.21", - "resolve": "^1.22.1", - "rollup": "^3.18.0" + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" }, "bin": { "vite": "bin/vite.js" @@ -9821,12 +9820,16 @@ "engines": { "node": "^14.18.0 || >=16.0.0" }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@types/node": ">= 14", "less": "*", + "lightningcss": "^1.21.0", "sass": "*", "stylus": "*", "sugarss": "*", @@ -9839,6 +9842,9 @@ "less": { "optional": true }, + "lightningcss": { + "optional": true + }, "sass": { "optional": true }, diff --git a/package.json b/package.json index 9d8f78b210..64c33a9109 100644 --- a/package.json +++ b/package.json @@ -99,6 +99,6 @@ "laravel-vite-plugin": "^0.7.2", "postcss": "^8.4.31", "tailwindcss": "^3.3.0", - "vite": "^4.2.3" + "vite": "^4.5.2" } } From 7f76ab663a7a81e5e2757e68d01c9c4c9ba9f669 Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Mon, 22 Jan 2024 15:36:15 +0000 Subject: [PATCH 037/149] [4.x] Hide actions on form index/show pages when user is missing relevant permissions (#9371) --- resources/js/components/forms/Listing.vue | 6 ++-- resources/views/forms/show.blade.php | 32 ++++++++++--------- .../Controllers/CP/Forms/FormsController.php | 2 ++ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/resources/js/components/forms/Listing.vue b/resources/js/components/forms/Listing.vue index b564498b27..7c1ebc03f1 100644 --- a/resources/js/components/forms/Listing.vue +++ b/resources/js/components/forms/Listing.vue @@ -13,9 +13,9 @@ {{ form.title }} @@ -66,6 +67,7 @@ export default { trans_choice(`vue script trans_choice backtick quote :param`, 2, { param: 'test' }), __('vue script with/slash'), + __('vue script with bracket(s)'), ]; } From 5ae2b5cd12b2a98685b20249b250b71fefb1dbe2 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Tue, 23 Jan 2024 16:00:39 -0500 Subject: [PATCH 043/149] [4.x] Avoid caching URLs with a token (#9381) --- src/StaticCaching/Middleware/Cache.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/StaticCaching/Middleware/Cache.php b/src/StaticCaching/Middleware/Cache.php index 4d9f3ce20c..7b889214ab 100644 --- a/src/StaticCaching/Middleware/Cache.php +++ b/src/StaticCaching/Middleware/Cache.php @@ -116,7 +116,7 @@ private function canBeCached($request) return false; } - if ($request->isLivePreview()) { + if ($request->statamicToken()) { return false; } @@ -141,7 +141,7 @@ private function shouldBeCached($request, $response) return false; } - if ($request->isLivePreview()) { + if ($request->statamicToken()) { return false; } From ec9e5c51dc5237846385c48a5e7bb519d3c506cf Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Tue, 23 Jan 2024 16:33:47 -0500 Subject: [PATCH 044/149] [4.x] Only use site language for form submission validation messages if submitted from front-end (#9383) --- src/Http/Requests/FrontendFormRequest.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Http/Requests/FrontendFormRequest.php b/src/Http/Requests/FrontendFormRequest.php index 19df613aaf..f4537dfe99 100644 --- a/src/Http/Requests/FrontendFormRequest.php +++ b/src/Http/Requests/FrontendFormRequest.php @@ -116,8 +116,11 @@ private function normalizeAssetsValues($fields) public function validateResolved() { - $site = Site::findByUrl(URL::previous()) ?? Site::default(); + // If this was submitted from a front-end form, we want to use the appropriate language + // for the translation messages. If there's no previous url, it was likely submitted + // directly in a headless format. In that case, we'll just use the default lang. + $site = ($previousUrl = session()->previousUrl()) ? Site::findByUrl($previousUrl) : null; - return $this->withLocale($site->lang(), fn () => parent::validateResolved()); + return $this->withLocale($site?->lang(), fn () => parent::validateResolved()); } } From 1f78d859c72d6c559893c3ca77284a5ba728eebc Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Tue, 23 Jan 2024 21:56:37 +0000 Subject: [PATCH 045/149] [4.x] Catch errors when sending user activation email (#9382) --- resources/lang/en/messages.php | 1 + src/Http/Controllers/CP/Users/UsersController.php | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/resources/lang/en/messages.php b/resources/lang/en/messages.php index 9a9953f62a..8741ceb7b9 100644 --- a/resources/lang/en/messages.php +++ b/resources/lang/en/messages.php @@ -224,6 +224,7 @@ 'updater_require_version_command' => 'To require a specific version, run the following command', 'updater_update_to_latest_command' => 'To update to the latest version, run the following command', 'updates_available' => 'Updates are available!', + 'user_activation_email_not_sent_error' => 'The activation email couldn\'t be sent. Please check your email configuration and try again.', 'user_groups_handle_instructions' => 'Used to reference this user group on the frontend. It\'s non-trivial to change later.', 'user_groups_intro' => 'User groups allow you to organize users and apply permission-based roles in aggregate.', 'user_groups_role_instructions' => 'Assign roles to give users in this group all of their corresponding permissions.', diff --git a/src/Http/Controllers/CP/Users/UsersController.php b/src/Http/Controllers/CP/Users/UsersController.php index 11b944dabd..c441abfaf2 100644 --- a/src/Http/Controllers/CP/Users/UsersController.php +++ b/src/Http/Controllers/CP/Users/UsersController.php @@ -6,6 +6,7 @@ use Statamic\Auth\Passwords\PasswordReset; use Statamic\Contracts\Auth\User as UserContract; use Statamic\Exceptions\NotFoundHttpException; +use Statamic\Facades\CP\Toast; use Statamic\Facades\Scope; use Statamic\Facades\Search; use Statamic\Facades\User; @@ -16,6 +17,7 @@ use Statamic\Notifications\ActivateAccount; use Statamic\Query\Scopes\Filters\Concerns\QueriesFilters; use Statamic\Search\Result; +use Symfony\Component\Mailer\Exception\TransportException; class UsersController extends CpController { @@ -184,7 +186,13 @@ public function store(Request $request) if ($request->invitation['send']) { ActivateAccount::subject($request->invitation['subject']); ActivateAccount::body($request->invitation['message']); - $user->generateTokenAndSendActivateAccountNotification(); + + try { + $user->generateTokenAndSendActivateAccountNotification(); + } catch (TransportException $e) { + Toast::error(__('statamic::messages.user_activation_email_not_sent_error')); + } + $url = null; } else { $url = PasswordReset::url($user->generateActivateAccountToken(), PasswordReset::BROKER_ACTIVATIONS); From 829f294c4ae7efc431ae9ca86508f6197a35a9ce Mon Sep 17 00:00:00 2001 From: Duncan McClean Date: Wed, 24 Jan 2024 14:43:40 +0000 Subject: [PATCH 046/149] [4.x] Fix importing fieldsets in custom blueprint namespaces (#9387) --- src/Http/View/Composers/FieldComposer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Http/View/Composers/FieldComposer.php b/src/Http/View/Composers/FieldComposer.php index bc03118b58..626e2dcfcd 100644 --- a/src/Http/View/Composers/FieldComposer.php +++ b/src/Http/View/Composers/FieldComposer.php @@ -12,6 +12,7 @@ class FieldComposer { const VIEWS = [ + 'statamic::blueprints.edit', 'statamic::*.blueprints.edit', 'statamic::fieldsets.edit', ]; From ecfe5892851c20cd02ae536e11e7e162ca89a550 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Wed, 24 Jan 2024 16:50:22 +0000 Subject: [PATCH 047/149] [4.x] Add console import for file based groups and roles to database (#6774) --- src/Console/Commands/ImportGroups.php | 80 ++++++++++++++++++++++++ src/Console/Commands/ImportRoles.php | 80 ++++++++++++++++++++++++ src/Providers/ConsoleServiceProvider.php | 2 + 3 files changed, 162 insertions(+) create mode 100644 src/Console/Commands/ImportGroups.php create mode 100644 src/Console/Commands/ImportRoles.php diff --git a/src/Console/Commands/ImportGroups.php b/src/Console/Commands/ImportGroups.php new file mode 100644 index 0000000000..1598eb756b --- /dev/null +++ b/src/Console/Commands/ImportGroups.php @@ -0,0 +1,80 @@ +error('You do not have eloquent driven groups enabled'); + + return; + } + + $this->importGroups(); + + return 0; + } + + private function importGroups() + { + app()->bind(GroupContract::class, FileGroup::class); + app()->bind(GroupRepositoryContract::class, FileRepository::class); + + Facade::clearResolvedInstance(GroupContract::class); + Facade::clearResolvedInstance(GroupRepositoryContract::class); + + $groups = UserGroup::path(config('statamic.users.paths.groups', resource_path('users/groups.yaml')))->all(); + + app()->bind(GroupContract::class, EloquentGroup::class); + app()->bind(GroupRepositoryContract::class, EloquentRepository::class); + + Facade::clearResolvedInstance(GroupContract::class); + Facade::clearResolvedInstance(GroupRepositoryContract::class); + + $this->withProgressBar($groups, function ($group) { + $eloquentGroup = UserGroup::make() + ->handle($group->handle()) + ->title($group->title()) + ->roles($group->roles()); + + $eloquentGroup->save(); + }); + + $this->newLine(); + $this->info('Groups imported'); + } +} diff --git a/src/Console/Commands/ImportRoles.php b/src/Console/Commands/ImportRoles.php new file mode 100644 index 0000000000..49abf026fc --- /dev/null +++ b/src/Console/Commands/ImportRoles.php @@ -0,0 +1,80 @@ +error('You do not have eloquent driven roles enabled'); + + return; + } + + $this->importRoles(); + + return 0; + } + + private function importRoles() + { + app()->bind(RoleContract::class, FileRole::class); + app()->bind(RoleRepositoryContract::class, FileRepository::class); + + Facade::clearResolvedInstance(RoleContract::class); + Facade::clearResolvedInstance(RoleRepositoryContract::class); + + $roles = Role::path(config('statamic.users.paths.roles', resource_path('users/roles.yaml')))->all(); + + app()->bind(RoleContract::class, EloquentRole::class); + app()->bind(RoleRepositoryContract::class, EloquentRepository::class); + + Facade::clearResolvedInstance(RoleContract::class); + Facade::clearResolvedInstance(RoleRepositoryContract::class); + + $this->withProgressBar($roles, function ($role) { + $eloquentRole = Role::make($role->handle()) + ->title($role->title()) + ->permissions($role->permissions()) + ->preferences($role->preferences()); + + $eloquentRole->save(); + }); + + $this->newLine(); + $this->info('Roles imported'); + } +} diff --git a/src/Providers/ConsoleServiceProvider.php b/src/Providers/ConsoleServiceProvider.php index ed67494388..9353ccb1ae 100644 --- a/src/Providers/ConsoleServiceProvider.php +++ b/src/Providers/ConsoleServiceProvider.php @@ -43,6 +43,8 @@ class ConsoleServiceProvider extends ServiceProvider Commands\Multisite::class, Commands\SiteClear::class, Commands\UpdatesRun::class, + Commands\ImportGroups::class, + Commands\ImportRoles::class, Commands\ImportUsers::class, ]; From 5a9a76292c65239449f147d1146ee8578c595b35 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Wed, 24 Jan 2024 18:38:00 -0500 Subject: [PATCH 048/149] [4.x] Revert overzealous file extension renaming feature (#9389) --- src/Assets/AssetUploader.php | 13 +------------ src/Assets/FileUploader.php | 4 +--- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/Assets/AssetUploader.php b/src/Assets/AssetUploader.php index 2b69451e7c..f13c2e4ac5 100644 --- a/src/Assets/AssetUploader.php +++ b/src/Assets/AssetUploader.php @@ -26,7 +26,7 @@ public static function asset(Asset $asset) protected function uploadPath(UploadedFile $file) { - $ext = $this->getNewExtension() ?? $this->getFileExtension($file); + $ext = $this->getNewExtension() ?? $file->getClientOriginalExtension(); if (config('statamic.assets.lowercase')) { $ext = strtolower($ext); @@ -71,17 +71,6 @@ protected function getNewExtension() return $ext; } - private function getFileExtension(UploadedFile $file) - { - $extension = $file->getClientOriginalExtension(); - $guessed = $file->guessExtension(); - - // Only use the guessed extension if it's different than the original. - // This allows us to maintain the casing of the original extension - // if the the "lowercase filenames" config option is disabled. - return strtolower($extension) === strtolower($guessed) ? $extension : $guessed; - } - public static function getSafeFilename($string) { $replacements = [ diff --git a/src/Assets/FileUploader.php b/src/Assets/FileUploader.php index e36d5e40aa..58a1e3f086 100644 --- a/src/Assets/FileUploader.php +++ b/src/Assets/FileUploader.php @@ -22,9 +22,7 @@ public static function container(?string $container = null) protected function uploadPath(UploadedFile $file) { - $filename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME); - - return now()->timestamp.'/'.$filename.'.'.$file->guessExtension(); + return now()->timestamp.'/'.$file->getClientOriginalName(); } protected function uploadPathPrefix() From dc72cb5ceb9acfbc5725fa329b0eeee9ed18dd46 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Thu, 25 Jan 2024 08:53:36 -0500 Subject: [PATCH 049/149] [4.x] Make copy reset password link action opt-in (#9390) --- src/Actions/CopyPasswordResetLink.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Actions/CopyPasswordResetLink.php b/src/Actions/CopyPasswordResetLink.php index 713bcdfcde..ab19f96a61 100644 --- a/src/Actions/CopyPasswordResetLink.php +++ b/src/Actions/CopyPasswordResetLink.php @@ -16,7 +16,7 @@ public static function title() public function visibleTo($item) { - return $item instanceof UserContract; + return config('statamic.users.allow_copy_reset_password_link', false) && $item instanceof UserContract; } public function visibleToBulk($items) From 2a2e9fcd15f2de7ca1bd4c6505d7bc8596b3264c Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Thu, 25 Jan 2024 09:04:04 -0500 Subject: [PATCH 050/149] [4.x] Revert uniform image validation (#9392) --- src/Assets/Asset.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Assets/Asset.php b/src/Assets/Asset.php index c6ebfa8004..79c74ef161 100644 --- a/src/Assets/Asset.php +++ b/src/Assets/Asset.php @@ -4,7 +4,6 @@ use ArrayAccess; use Facades\Statamic\Assets\Attributes; -use Facades\Statamic\Imaging\ImageValidator; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Cache; @@ -486,7 +485,7 @@ public function isPreviewable() */ public function isImage() { - return ImageValidator::isValidExtension($this->extension()); + return $this->extensionIsOneOf(['jpg', 'jpeg', 'png', 'gif', 'webp']); } /** From 77210435363e328f72e5466fca33c0d54592f14b Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Thu, 25 Jan 2024 13:03:27 -0500 Subject: [PATCH 051/149] [4.x] Support data in Eloquent based user groups (#9395) --- src/Auth/Eloquent/UserGroup.php | 2 ++ src/Auth/Eloquent/UserGroupModel.php | 1 + src/Console/Commands/ImportGroups.php | 3 +- .../stubs/auth/statamic_groups_table.php.stub | 1 + .../CP/Users/UserGroupsController.php | 6 +++- tests/Auth/Eloquent/EloquentUserGroupTest.php | 32 +++++++++++++++---- 6 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/Auth/Eloquent/UserGroup.php b/src/Auth/Eloquent/UserGroup.php index e2897096ba..e2ef88ea88 100644 --- a/src/Auth/Eloquent/UserGroup.php +++ b/src/Auth/Eloquent/UserGroup.php @@ -15,6 +15,7 @@ public static function fromModel(UserGroupModel $model) ->title($model->title) ->handle($model->handle) ->roles($model->roles ?? []) + ->data($model->data ?? []) ->model($model); } @@ -25,6 +26,7 @@ public function toModel() 'title' => $this->title, 'handle' => $this->handle, 'roles' => $this->roles->keys(), + 'data' => $this->data->all(), ]); } diff --git a/src/Auth/Eloquent/UserGroupModel.php b/src/Auth/Eloquent/UserGroupModel.php index 8c4622080e..8a77ab3b6a 100644 --- a/src/Auth/Eloquent/UserGroupModel.php +++ b/src/Auth/Eloquent/UserGroupModel.php @@ -12,6 +12,7 @@ class UserGroupModel extends Eloquent protected $casts = [ 'roles' => 'json', + 'data' => 'json', 'created_at' => 'datetime', 'updated_at' => 'datetime', ]; diff --git a/src/Console/Commands/ImportGroups.php b/src/Console/Commands/ImportGroups.php index 1598eb756b..0d8a522f84 100644 --- a/src/Console/Commands/ImportGroups.php +++ b/src/Console/Commands/ImportGroups.php @@ -69,7 +69,8 @@ private function importGroups() $eloquentGroup = UserGroup::make() ->handle($group->handle()) ->title($group->title()) - ->roles($group->roles()); + ->roles($group->roles()) + ->data($group->data()->except(['title', 'roles'])); $eloquentGroup->save(); }); diff --git a/src/Console/Commands/stubs/auth/statamic_groups_table.php.stub b/src/Console/Commands/stubs/auth/statamic_groups_table.php.stub index 6eccf18bd3..a8e45464fd 100644 --- a/src/Console/Commands/stubs/auth/statamic_groups_table.php.stub +++ b/src/Console/Commands/stubs/auth/statamic_groups_table.php.stub @@ -17,6 +17,7 @@ class StatamicGroupsTable extends Migration $table->id(); $table->string('handle')->unique(); $table->string('title'); + $table->json('data')->nullable(); $table->json('roles')->nullable(); $table->timestamps(); }); diff --git a/src/Http/Controllers/CP/Users/UserGroupsController.php b/src/Http/Controllers/CP/Users/UserGroupsController.php index b4109b5414..7ff480fbcf 100644 --- a/src/Http/Controllers/CP/Users/UserGroupsController.php +++ b/src/Http/Controllers/CP/Users/UserGroupsController.php @@ -74,7 +74,11 @@ public function edit(Request $request, $group) $fields = $blueprint ->fields() - ->addValues($group->data()->merge(['handle' => $group->handle()])->all()) + ->addValues($group->data()->merge([ + 'title' => $group->title(), + 'handle' => $group->handle(), + 'roles' => $group->roles()->map->handle()->values()->all(), + ])->all()) ->preProcess(); $viewData = [ diff --git a/tests/Auth/Eloquent/EloquentUserGroupTest.php b/tests/Auth/Eloquent/EloquentUserGroupTest.php index bb8756f925..b274085d82 100644 --- a/tests/Auth/Eloquent/EloquentUserGroupTest.php +++ b/tests/Auth/Eloquent/EloquentUserGroupTest.php @@ -5,9 +5,11 @@ use Illuminate\Filesystem\Filesystem; use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Support\Carbon; +use Illuminate\Support\Collection; use Statamic\Auth\Eloquent\User as EloquentUser; use Statamic\Auth\Eloquent\UserGroup as EloquentGroup; use Statamic\Auth\Eloquent\UserGroupModel; +use Statamic\Facades\UserGroup; use Tests\TestCase; class EloquentUserGroupTest extends TestCase @@ -62,13 +64,11 @@ public static function tearDownAfterClass(): void public function makeGroup() { - return (new EloquentGroup) - ->model(UserGroupModel::create([ - 'handle' => $this->faker->word, - 'title' => $this->faker->words(2, true), - 'roles' => [], - ]) - ); + return EloquentGroup::fromModel(UserGroupModel::create([ + 'handle' => $this->faker->word, + 'title' => $this->faker->words(2, true), + 'roles' => [], + ])); } public function makeUser() @@ -115,4 +115,22 @@ public function it_assigns_a_group_to_a_user_then_removes_it() $this->assertCount(0, $user->groups()); } + + /** @test */ + public function it_sets_and_gets_data() + { + $group = $this->makeGroup(); + + $this->assertInstanceOf(Collection::class, $data = $group->data()); + $this->assertEquals([], $data->all()); + + $group->data(['alfa' => 'bravo']); + $group->set('charlie', 'delta'); + $this->assertEquals(['alfa' => 'bravo', 'charlie' => 'delta'], $group->data()->all()); + + $group->save(); + + $group = UserGroup::all()->first(); + $this->assertEquals(['alfa' => 'bravo', 'charlie' => 'delta'], $group->data()->all()); + } } From f9032ecaeefcb7e2850b82b46ec826d2f25d2d10 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Thu, 25 Jan 2024 13:26:19 -0500 Subject: [PATCH 052/149] changelog --- CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d95d5f9a5..5397db14bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ # Release Notes +## 4.46.0 (2024-01-25) + +### What's new +- Allow roles and groups to be database driven. [#5686](https://github.com/statamic/cms/issues/5686) by @ryanmitchell +- Add console command to import file-based groups and roles into database. [#6774](https://github.com/statamic/cms/issues/6774) by @ryanmitchell +- SVG images get sanitized upon upload. [#9365](https://github.com/statamic/cms/issues/9365) by @duncanmcclean +- Allow `.html` to be stripped from `parent_uri` in routes. [#9364](https://github.com/statamic/cms/issues/9364) by @duncanmcclean + +### What's improved +- German translations. [#9374](https://github.com/statamic/cms/issues/9374) by @helloDanuk + +### What's fixed +- Support data in Eloquent based user groups. [#9395](https://github.com/statamic/cms/issues/9395) by @jasonvarga +- Revert overzealous file extension renaming feature. [#9389](https://github.com/statamic/cms/issues/9389) by @jasonvarga +- Make copy reset password link action opt-in. [#9390](https://github.com/statamic/cms/issues/9390) by @jasonvarga +- Fix importing fieldsets in custom blueprint namespaces. [#9387](https://github.com/statamic/cms/issues/9387) by @duncanmcclean +- Catch errors when sending user activation email. [#9382](https://github.com/statamic/cms/issues/9382) by @duncanmcclean +- Only use site language for form submission validation messages if submitted from front-end. [#9383](https://github.com/statamic/cms/issues/9383) by @jasonvarga +- Avoid caching URLs with a token. [#9381](https://github.com/statamic/cms/issues/9381) by @jasonvarga +- Fix user groups/roles querying. [#6131](https://github.com/statamic/cms/issues/6131) by @ryanmitchell +- Avoid saving icons to field configs. [#9372](https://github.com/statamic/cms/issues/9372) by @duncanmcclean +- Hide actions on form index/show pages when user is missing relevant permissions. [#9371](https://github.com/statamic/cms/issues/9371) by @duncanmcclean +- Bard: Only configure placeholder extension when placeholder is provided. [#9369](https://github.com/statamic/cms/issues/9369) by @duncanmcclean +- Always show slug rengerate button if enabled. [#9366](https://github.com/statamic/cms/issues/9366) by @jasonvarga +- Fix some translations. [#9361](https://github.com/statamic/cms/issues/9361) by @peimn +- Fix whereTime affecting the date as well as time. [#9360](https://github.com/statamic/cms/issues/9360) by @ryanmitchell +- Passthrough Cmd/Ctrl + Enter inside Bard. [#9313](https://github.com/statamic/cms/issues/9313) by @godismyjudge95 +- Support brackets in translation strings in translator helper. [#9380](https://github.com/statamic/cms/issues/9380) by @jasonvarga +- Bump vite from 4.2.3 to 4.5.2. [#9367](https://github.com/statamic/cms/issues/9367) by @dependabot + + + ## 4.45.0 (2024-01-18) ### What's new From 12456d283f45cb3f491ad630305b5d9afd1fac20 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Thu, 25 Jan 2024 13:45:33 -0500 Subject: [PATCH 053/149] [4.x] Make copy reset password link action opt-in (#9397) --- src/Actions/CopyPasswordResetLink.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Actions/CopyPasswordResetLink.php b/src/Actions/CopyPasswordResetLink.php index ab19f96a61..224445851e 100644 --- a/src/Actions/CopyPasswordResetLink.php +++ b/src/Actions/CopyPasswordResetLink.php @@ -2,6 +2,7 @@ namespace Statamic\Actions; +use Exception; use Statamic\Auth\Passwords\PasswordReset; use Statamic\Contracts\Auth\User as UserContract; @@ -43,6 +44,10 @@ public function buttonText() public function run($items, $values) { + if (! config('statamic.users.allow_copy_reset_password_link', false)) { + throw new Exception('Copying password reset links is not allowed.'); + } + $user = $items->first(); $passwordResetLink = $user->password() From 23215679fd9620b5b0c4740e81f3dc48b89ae3a6 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Thu, 25 Jan 2024 13:46:32 -0500 Subject: [PATCH 054/149] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5397db14bb..fef1809c72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ ### What's fixed - Support data in Eloquent based user groups. [#9395](https://github.com/statamic/cms/issues/9395) by @jasonvarga - Revert overzealous file extension renaming feature. [#9389](https://github.com/statamic/cms/issues/9389) by @jasonvarga -- Make copy reset password link action opt-in. [#9390](https://github.com/statamic/cms/issues/9390) by @jasonvarga +- Make copy reset password link action opt-in. [#9390](https://github.com/statamic/cms/issues/9390) [#9397](https://github.com/statamic/cms/issues/9397) by @jasonvarga - Fix importing fieldsets in custom blueprint namespaces. [#9387](https://github.com/statamic/cms/issues/9387) by @duncanmcclean - Catch errors when sending user activation email. [#9382](https://github.com/statamic/cms/issues/9382) by @duncanmcclean - Only use site language for form submission validation messages if submitted from front-end. [#9383](https://github.com/statamic/cms/issues/9383) by @jasonvarga From a0efa0889493febaf3bc9df4f1c8838eb36791d5 Mon Sep 17 00:00:00 2001 From: Peiman Nourani Date: Thu, 25 Jan 2024 23:26:25 +0330 Subject: [PATCH 055/149] [4.x] Translate dimension conjunction (#9393) --- resources/js/components/assets/Editor/Editor.vue | 2 +- resources/lang/en/messages.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/js/components/assets/Editor/Editor.vue b/resources/js/components/assets/Editor/Editor.vue index ce6f193d28..a04e9473aa 100644 --- a/resources/js/components/assets/Editor/Editor.vue +++ b/resources/js/components/assets/Editor/Editor.vue @@ -143,7 +143,7 @@