From 83595c6aae38e97789fb9fd351e48623f68afa32 Mon Sep 17 00:00:00 2001 From: Randall Wilk <22842525+rawilk@users.noreply.github.com> Date: Thu, 13 Apr 2023 15:21:10 -0500 Subject: [PATCH] Content Security Policy Support (#98) --- src/FormComponents.php | 28 +++++++++++++++++++++++++++- tests/Unit/AssetsDirectiveTest.php | 10 ++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/FormComponents.php b/src/FormComponents.php index b2a15d1..a8cf34c 100644 --- a/src/FormComponents.php +++ b/src/FormComponents.php @@ -4,6 +4,8 @@ namespace Rawilk\FormComponents; +use Illuminate\Support\Facades\Vite; + final class FormComponents { /** @@ -22,6 +24,7 @@ public function javaScript(array $options = []): string private function javaScriptAssets(array $options = []): string { $assetsUrl = config('form-components.asset_url') ?: rtrim($options['asset_url'] ?? '', '/'); + $nonce = $this->getNonce($options); $manifest = json_decode(file_get_contents(__DIR__ . '/../dist/manifest.json'), true); $versionedFileName = $manifest['/form-components.js']; @@ -29,7 +32,30 @@ private function javaScriptAssets(array $options = []): string $fullAssetPath = "{$assetsUrl}/form-components{$versionedFileName}"; return << + HTML; } + + private function getNonce(array $options): string + { + if (isset($options['nonce'])) { + return "nonce=\"{$options['nonce']}\""; + } + + // If there is a csp package installed, i.e. spatie/laravel-csp, we'll check for the existence of the helper function. + if (function_exists('csp_nonce') && $nonce = csp_nonce()) { + return "nonce=\"{$nonce}\""; + } + + if (function_exists('cspNonce') && $nonce = cspNonce()) { + return "nonce=\"{$nonce}\""; + } + + // Lastly, we'll check for the existence of a csp nonce from Vite. + if (class_exists(Vite::class) && $nonce = Vite::cspNonce()) { + return "nonce=\"{$nonce}\""; + } + + return ''; + } } diff --git a/tests/Unit/AssetsDirectiveTest.php b/tests/Unit/AssetsDirectiveTest.php index 0dcd79f..4916eeb 100644 --- a/tests/Unit/AssetsDirectiveTest.php +++ b/tests/Unit/AssetsDirectiveTest.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Illuminate\Support\Str; use Rawilk\FormComponents\Facades\FormComponents; it('outputs the script source', function () { @@ -44,3 +45,12 @@ FormComponents::javaScript(['asset_url' => 'https://example.com']), ); }); + +it('can output a nonce on the script tag', function () { + $nonce = Str::random(32); + + $this->assertStringContainsString( + "nonce=\"{$nonce}\"", + FormComponents::javaScript(['nonce' => $nonce]), + ); +});