From 7e17452a07d96408466d3fe319497db076af367c Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Thu, 19 Oct 2017 22:25:33 -0700 Subject: [PATCH] fix(@angular/cli): add a flag to let assets outside of outDir On top of #7778 Fixes #8122 --- packages/@angular/cli/lib/config/schema.json | 5 ++++ .../cli/models/webpack-configs/common.ts | 16 ++++++++++--- .../cli/models/webpack-configs/utils.ts | 1 + tests/e2e/tests/build/assets.ts | 23 ++++++++++++++++++- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/packages/@angular/cli/lib/config/schema.json b/packages/@angular/cli/lib/config/schema.json index 3ba988cb8f08..8520dcc1c9b9 100644 --- a/packages/@angular/cli/lib/config/schema.json +++ b/packages/@angular/cli/lib/config/schema.json @@ -72,6 +72,11 @@ "type": "string", "default": "", "description": "The output path (relative to the outDir)." + }, + "allowOutsideOutDir": { + "type": "boolean", + "description": "Allow assets to be copied outside the outDir.", + "default": false } }, "additionalProperties": false diff --git a/packages/@angular/cli/models/webpack-configs/common.ts b/packages/@angular/cli/models/webpack-configs/common.ts index 8c2111b25516..16bd9a49a0ef 100644 --- a/packages/@angular/cli/models/webpack-configs/common.ts +++ b/packages/@angular/cli/models/webpack-configs/common.ts @@ -95,12 +95,22 @@ export function getCommonConfig(wco: WebpackConfigOptions) { asset.output = asset.output || ''; asset.glob = asset.glob || ''; - // Prevent asset configurations from writing outside of the output path + // Prevent asset configurations from writing outside of the output path, except if the user + // specify a configuration flag. + // Also prevent writing outside the project path. That is not overridable. const fullOutputPath = path.resolve(buildOptions.outputPath, asset.output); - if (!fullOutputPath.startsWith(path.resolve(buildOptions.outputPath))) { - const message = 'An asset cannot be written to a location outside of the output path.'; + if (!fullOutputPath.startsWith(projectRoot)) { + const message = 'An asset cannot be written to a location outside the project.'; throw new SilentError(message); } + if (!fullOutputPath.startsWith(path.resolve(buildOptions.outputPath))) { + if (!asset.allowOutsideOutDir) { + const message = 'An asset cannot be written to a location outside of the output path. ' + + 'You can override this message by setting the `allowOutsideOutDir` ' + + 'property on the asset to true in the CLI configuration.'; + throw new SilentError(message); + } + } // Ensure trailing slash. if (isDirectory(path.resolve(asset.input))) { diff --git a/packages/@angular/cli/models/webpack-configs/utils.ts b/packages/@angular/cli/models/webpack-configs/utils.ts index 4eee09a29e78..8679dc5a81cf 100644 --- a/packages/@angular/cli/models/webpack-configs/utils.ts +++ b/packages/@angular/cli/models/webpack-configs/utils.ts @@ -92,4 +92,5 @@ export interface AssetPattern { glob: string; input?: string; output?: string; + allowOutsideOutDir?: boolean; } diff --git a/tests/e2e/tests/build/assets.ts b/tests/e2e/tests/build/assets.ts index 20f32e1dbf3f..f553b7c1d7f7 100644 --- a/tests/e2e/tests/build/assets.ts +++ b/tests/e2e/tests/build/assets.ts @@ -30,10 +30,31 @@ export default function () { .then(() => updateJsonFile('.angular-cli.json', configJson => { const app = configJson['apps'][0]; app['assets'] = [ - { 'glob': '**/*', 'input': '../node_modules/some-package/', 'output': '../package-folder' } + { 'glob': '**/*', 'input': '../node_modules/some-package/', 'output': '../temp' } ]; })) .then(() => expectToFail(() => ng('build'))) + + // Set an exception for the invalid asset config in .angular-cli.json. + .then(() => updateJsonFile('.angular-cli.json', configJson => { + const app = configJson['apps'][0]; + app['assets'] = [ + { 'glob': '**/*', 'input': '../node_modules/some-package/', 'output': '../temp', + 'allowOutsideOutDir': true } + ]; + })) + .then(() => ng('build')) + + // This asset should fail even with the exception above. + .then(() => updateJsonFile('.angular-cli.json', configJson => { + const app = configJson['apps'][0]; + app['assets'] = [ + { 'glob': '**/*', 'input': '../node_modules/some-package/', 'output': '../../temp', + 'allowOutsideOutDir': true } + ]; + })) + .then(() => expectToFail(() => ng('build'))) + // Add asset config in .angular-cli.json. .then(() => updateJsonFile('.angular-cli.json', configJson => { const app = configJson['apps'][0];