From de626475f9fd91c986f1903b902957f213f31e20 Mon Sep 17 00:00:00 2001 From: Dieter Stinglhamber Date: Thu, 10 Sep 2020 14:08:59 +0200 Subject: [PATCH 01/13] (feat): first draft of blade component --- composer.lock | 2 +- src/Components/Link.php | 24 ++++++++++++++++++++++++ src/Components/LinkMix.php | 24 ++++++++++++++++++++++++ src/Components/Script.php | 24 ++++++++++++++++++++++++ src/Components/ScriptMix.php | 24 ++++++++++++++++++++++++ src/SriServiceProvider.php | 17 ++++++++--------- 6 files changed, 105 insertions(+), 10 deletions(-) create mode 100644 src/Components/Link.php create mode 100644 src/Components/LinkMix.php create mode 100644 src/Components/Script.php create mode 100644 src/Components/ScriptMix.php diff --git a/composer.lock b/composer.lock index 679d7d5..ee74a85 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": "37d4646aed52bb0cf8a3ad17b3a76c38", + "content-hash": "0f468ffe892d763f45901486ff6fa6f1", "packages": [ { "name": "brick/math", diff --git a/src/Components/Link.php b/src/Components/Link.php new file mode 100644 index 0000000..b42f5d0 --- /dev/null +++ b/src/Components/Link.php @@ -0,0 +1,24 @@ + +href = $href; + } + + public function render(): string + { + return <<<'blade' + href) }}" {{ $this->attributes }} /> + blade; + } +} diff --git a/src/Components/LinkMix.php b/src/Components/LinkMix.php new file mode 100644 index 0000000..e55e3ae --- /dev/null +++ b/src/Components/LinkMix.php @@ -0,0 +1,24 @@ + +href = $href; + } + + public function render(): string + { + return <<<'blade' + href) }}" {{ $this->attributes }} /> + blade; + } +} diff --git a/src/Components/Script.php b/src/Components/Script.php new file mode 100644 index 0000000..3567659 --- /dev/null +++ b/src/Components/Script.php @@ -0,0 +1,24 @@ + +src = $src; + } + + public function render(): string + { + return <<<'blade' + "; - } else { - throw new \Exception('Invalid file'); - } - } - private function existsInConfigFile(string $path): bool { return array_key_exists($path, config('subresource-integrity.hashes')); @@ -106,7 +72,7 @@ private function existsInConfigFile(string $path): bool private function mixFileExists(): bool { - return file_exists($this->jsonFilePath()); + return file_exists($this->jsonFilePath); } private function getFileContent(string $path): string @@ -130,9 +96,4 @@ private function getFileContent(string $path): string return $fileContent; } - - private function jsonFilePath(): string - { - return config('subresource-integrity.mix_sri_path'); - } } diff --git a/src/SriServiceProvider.php b/src/SriServiceProvider.php index 078b364..d1119fc 100644 --- a/src/SriServiceProvider.php +++ b/src/SriServiceProvider.php @@ -6,8 +6,6 @@ use Illuminate\Support\ServiceProvider; use Elhebert\SubresourceIntegrity\Components\Link; use Elhebert\SubresourceIntegrity\Components\Script; -use Elhebert\SubresourceIntegrity\Components\LinkMix; -use Elhebert\SubresourceIntegrity\Components\ScriptMix; class SriServiceProvider extends ServiceProvider { @@ -17,6 +15,8 @@ public function register() return new Sri(config('subresource-integrity.algorithm')); }); + $this->app->alias(Sri::class, 'sri'); + $this->mergeConfigFrom( __DIR__.'/../config/subresource-integrity.php', 'subresource-integrity' @@ -30,8 +30,6 @@ public function boot() ]); Blade::component('sri.script', Script::class); - Blade::component('sri.script.mix', ScriptMix::class); Blade::component('sri.link', Link::class); - Blade::component('sri.link.mix', LinkMix::class); } } diff --git a/tests/BladeDirectiveTest.php b/tests/BladeDirectiveTest.php deleted file mode 100644 index 97c065b..0000000 --- a/tests/BladeDirectiveTest.php +++ /dev/null @@ -1,53 +0,0 @@ -artisan('view:clear'); - - parent::tearDown(); - } - - /** @test */ - public function it_renders_mixSri_directive() - { - config([ - 'subresource-integrity.mix_sri_path' => './tests/files/mix-sri.json', - ]); - - $this->app->instance('path.public', __DIR__.'/files'); - - $view = View::file(__DIR__.'/files/mixSri-view.blade.php', [ - 'asset' => 'css/app.css', - 'useCredentials' => false, - 'attributes' => '', - ])->render(); - - $this->assertStringContainsString('this-hash-is-valid', $view); - } - - /** @test */ - public function it_renders_assetSri_directive() - { - config([ - 'subresource-integrity.base_path' => './tests/files', - 'app.asset_url' => 'tests/files', - ]); - - $hash = hash('sha256', file_get_contents('./tests/files/app.js'), true); - $base64Hash = base64_encode($hash); - - $view = View::file(__DIR__.'/files/assetSri-view.blade.php', [ - 'asset' => 'app.js', - 'useCredentials' => false, - 'attributes' => '', - ])->render(); - - $this->assertStringContainsString('integrity="sha256-'.$base64Hash.'"', $view); - } -} diff --git a/tests/GenerateSriAssetTest.php b/tests/GenerateSriAssetTest.php deleted file mode 100644 index 9106bcc..0000000 --- a/tests/GenerateSriAssetTest.php +++ /dev/null @@ -1,129 +0,0 @@ - './tests/files', - 'app.asset_url' => 'tests/files', - ]); - } - - /** @test */ - public function it_generates_css_with_integrity() - { - $hash = hash('sha256', file_get_contents('./tests/files/app.css'), true); - $base64Hash = base64_encode($hash); - - $asset_string = Sri::asset('app.css'); - - $this->assertStringContainsString('link', $asset_string); - $this->assertStringContainsString('integrity="sha256-'.$base64Hash.'"', $asset_string); - } - - /** @test */ - public function it_generates_css_with_integrity_and_credentials() - { - $hash = hash('sha256', file_get_contents('./tests/files/app.css'), true); - $base64Hash = base64_encode($hash); - - $asset_string = Sri::asset('app.css', true); - - $this->assertStringContainsString('integrity="sha256-'.$base64Hash.'"', $asset_string); - $this->assertStringContainsString('crossorigin="use-credentials"', $asset_string); - $this->assertStringContainsString('link', $asset_string); - } - - /** @test */ - public function it_generates_css_with_integrity_and_attributes() - { - $hash = hash('sha256', file_get_contents('./tests/files/app.css'), true); - $base64Hash = base64_encode($hash); - - $asset_string = Sri::asset('app.css', false, 'rel="stylesheet"'); - - $this->assertStringContainsString('link', $asset_string); - $this->assertStringContainsString('integrity="sha256-'.$base64Hash.'"', $asset_string); - $this->assertStringContainsString('rel="stylesheet"', $asset_string); - } - - /** @test */ - public function it_generates_css_with_integrity_credentials_and_attributes() - { - $hash = hash('sha256', file_get_contents('./tests/files/app.css'), true); - $base64Hash = base64_encode($hash); - - $asset_string = Sri::asset('app.css', true, 'rel="stylesheet"'); - - $this->assertStringContainsString('link', $asset_string); - $this->assertStringContainsString('integrity="sha256-'.$base64Hash.'"', $asset_string); - $this->assertStringContainsString('crossorigin="use-credentials"', $asset_string); - $this->assertStringContainsString('rel="stylesheet"', $asset_string); - } - - /** @test */ - public function it_generates_js_with_integrity() - { - $hash = hash('sha256', file_get_contents('./tests/files/app.js'), true); - $base64Hash = base64_encode($hash); - - $asset_string = Sri::asset('app.js'); - - $this->assertStringContainsString('script', $asset_string); - $this->assertStringContainsString('integrity="sha256-'.$base64Hash.'"', $asset_string); - } - - /** @test */ - public function it_generates_js_with_integrity_and_credentials() - { - $hash = hash('sha256', file_get_contents('./tests/files/app.js'), true); - $base64Hash = base64_encode($hash); - - $asset_string = Sri::asset('app.js', true); - - $this->assertStringContainsString('script', $asset_string); - $this->assertStringContainsString('integrity="sha256-'.$base64Hash.'"', $asset_string); - $this->assertStringContainsString('crossorigin="use-credentials"', $asset_string); - } - - /** @test */ - public function it_generates_js_with_integrity_and_attributes() - { - $hash = hash('sha256', file_get_contents('./tests/files/app.js'), true); - $base64Hash = base64_encode($hash); - - $asset_string = Sri::asset('app.js', false, 'type="application/javascript" async'); - - $this->assertStringContainsString('script', $asset_string); - $this->assertStringContainsString('integrity="sha256-'.$base64Hash.'"', $asset_string); - $this->assertStringContainsString('type="application/javascript" async', $asset_string); - } - - /** @test */ - public function it_generates_js_with_integrity_credentials_and_attributes() - { - $hash = hash('sha256', file_get_contents('./tests/files/app.js'), true); - $base64Hash = base64_encode($hash); - - $asset_string = Sri::asset('app.js', true, 'type="application/javascript" async'); - - $this->assertStringContainsString('script', $asset_string); - $this->assertStringContainsString('integrity="sha256-'.$base64Hash.'"', $asset_string); - $this->assertStringContainsString('crossorigin="use-credentials"', $asset_string); - $this->assertStringContainsString('type="application/javascript" async', $asset_string); - } - - /** @test */ - public function it_throws_an_exception_if_file_extension_invalid() - { - $this->expectExceptionMessage('Invalid file'); - Sri::asset('app.jpeg'); - } -} diff --git a/tests/GenerateSriMixTest.php b/tests/GenerateSriMixTest.php deleted file mode 100644 index 8d75c2d..0000000 --- a/tests/GenerateSriMixTest.php +++ /dev/null @@ -1,108 +0,0 @@ - './tests/files/mix-sri.json', - 'view.paths' => ['./tests/files'], - ]); - - $this->app->instance('path.public', __DIR__.'/files'); - } - - /** @test */ - public function it_generates_css_with_integrity() - { - $mix_string = Sri::mix('css/app.css'); - - $this->assertStringContainsString('link', $mix_string); - $this->assertStringContainsString('this-hash-is-valid', $mix_string); - } - - /** @test */ - public function it_generates_css_with_integrity_and_credentials() - { - $mix_string = Sri::mix('css/app.css', true); - - $this->assertStringContainsString('link', $mix_string); - $this->assertStringContainsString('this-hash-is-valid', $mix_string); - $this->assertStringContainsString('crossorigin="use-credentials"', $mix_string); - } - - /** @test */ - public function it_generates_css_with_integrity_and_attributes() - { - $mix_string = Sri::mix('css/app.css', false, 'rel="stylesheet"'); - - $this->assertStringContainsString('link', $mix_string); - $this->assertStringContainsString('this-hash-is-valid', $mix_string); - $this->assertStringContainsString('rel="stylesheet"', $mix_string); - } - - /** @test */ - public function it_generates_css_with_integrity_credentials_and_attributes() - { - $mix_string = Sri::mix('css/app.css', true, 'rel="stylesheet"'); - - $this->assertStringContainsString('link', $mix_string); - $this->assertStringContainsString('this-hash-is-valid', $mix_string); - $this->assertStringContainsString('crossorigin="use-credentials"', $mix_string); - $this->assertStringContainsString('rel="stylesheet"', $mix_string); - } - - /** @test */ - public function it_generates_js_with_integrity() - { - $mix_string = Sri::mix('js/app.js'); - - $this->assertStringContainsString('script', $mix_string); - $this->assertStringContainsString('this-hash-is-valid', $mix_string); - } - - /** @test */ - public function it_generates_js_with_integrity_and_credentials() - { - $mix_string = Sri::mix('js/app.js', true); - - $this->assertStringContainsString('script', $mix_string); - $this->assertStringContainsString('this-hash-is-valid', $mix_string); - $this->assertStringContainsString('crossorigin="use-credentials"', $mix_string); - } - - /** @test */ - public function it_generates_js_with_integrity_and_attributes() - { - $mix_string = Sri::mix('js/app.js', false, 'type="application/javascript" async'); - - $this->assertStringContainsString('script', $mix_string); - $this->assertStringContainsString('this-hash-is-valid', $mix_string); - $this->assertStringContainsString('type="application/javascript" async', $mix_string); - } - - /** @test */ - public function it_generates_js_with_integrity_credentials_and_attributes() - { - $mix_string = Sri::mix('js/app.js', true, 'type="application/javascript" async'); - - $this->assertStringContainsString('script', $mix_string); - $this->assertStringContainsString('this-hash-is-valid', $mix_string); - $this->assertStringContainsString('crossorigin="use-credentials"', $mix_string); - $this->assertStringContainsString('type="application/javascript" async', $mix_string); - } - - /** @test */ - public function it_throws_an_exception_if_file_extension_invalid() - { - $this->expectExceptionMessage('Invalid file'); - - Sri::mix('app.jpeg'); - } -} diff --git a/tests/LinkComponentTest.php b/tests/LinkComponentTest.php new file mode 100644 index 0000000..068359f --- /dev/null +++ b/tests/LinkComponentTest.php @@ -0,0 +1,49 @@ +artisan('view:clear'); + + parent::tearDown(); + } + + /** @test */ + public function it_renders_the_component() + { + config([ + 'subresource-integrity.mix_sri_path' => './tests/files/mix-sri.json', + ]); + + $this->app->instance('path.public', __DIR__.'/files'); + + $view = View::file(__DIR__.'/files/link.blade.php', ['mix' => false])->render(); + + $this->assertStringContainsString( + '', + $view + ); + } + + /** @test */ + public function it_uses_mix_when_the_mix_attribute_is_passed() + { + config([ + 'subresource-integrity.mix_sri_path' => './tests/files/mix-sri.json', + ]); + + $this->app->instance('path.public', __DIR__.'/files'); + + $view = View::file(__DIR__.'/files/link.blade.php', ['mix' => true])->render(); + + $this->assertStringContainsString( + '', + $view + ); + } +} diff --git a/tests/ScriptComponentTest.php b/tests/ScriptComponentTest.php new file mode 100644 index 0000000..7417b9a --- /dev/null +++ b/tests/ScriptComponentTest.php @@ -0,0 +1,49 @@ +artisan('view:clear'); + + parent::tearDown(); + } + + /** @test */ + public function it_renders_the_component() + { + config([ + 'subresource-integrity.mix_sri_path' => './tests/files/mix-sri.json', + ]); + + $this->app->instance('path.public', __DIR__.'/files'); + + $view = View::file(__DIR__.'/files/script.blade.php', ['mix' => false])->render(); + + $this->assertStringContainsString( + ' + + + ``` ## Contributing diff --git a/src/Components/Link.php b/src/Components/Link.php index e056e0c..42f71f4 100644 --- a/src/Components/Link.php +++ b/src/Components/Link.php @@ -13,10 +13,14 @@ class Link extends Component /** @var bool */ public $mix = false; - public function __construct(string $href, bool $mix = false) + /** @var string */ + public $crossorigin = 'anonymous'; + + public function __construct(string $href, bool $mix = false, string $crossorigin = 'anonymous') { $this->href = $href; $this->mix = $mix; + $this->crossorigin = $crossorigin; } public function integrity(): string @@ -32,7 +36,9 @@ public function path(): string public function render(): string { return <<<'blade' - + @once + + @endonce blade; } } diff --git a/src/Components/Script.php b/src/Components/Script.php index c1e7462..6cc93bb 100644 --- a/src/Components/Script.php +++ b/src/Components/Script.php @@ -13,10 +13,14 @@ class Script extends Component /** @var bool */ public $mix; - public function __construct(string $src, bool $mix = false) + /** @var string */ + public $crossorigin = 'anonymous'; + + public function __construct(string $src, bool $mix = false, string $crossorigin = 'anonymous') { $this->src = $src; $this->mix = $mix; + $this->crossorigin = $crossorigin; } public function integrity(): string @@ -32,7 +36,9 @@ public function path(): string public function render(): string { return <<<'blade' -