mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Sanitize db name for dacpac/bacpac file names (#5479)
* Sanitize db name for filename * Add unit tests * lower timeout to 60 seconds * add extra coverageConfig.json and missing character check
This commit is contained in:
1
extensions/dacpac/.gitignore
vendored
1
extensions/dacpac/.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
|
coverage
|
||||||
*.vsix
|
*.vsix
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
|
coverage/**
|
||||||
|
coverageConfig.json
|
||||||
src/**
|
src/**
|
||||||
tsconfig.json
|
tsconfig.json
|
||||||
|
|||||||
17
extensions/dacpac/coverageConfig.json
Normal file
17
extensions/dacpac/coverageConfig.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"enabled": false,
|
||||||
|
"relativeSourcePath": "..",
|
||||||
|
"relativeCoverageDir": "../../coverage",
|
||||||
|
"ignorePatterns": [
|
||||||
|
"**/node_modules/**"
|
||||||
|
],
|
||||||
|
"includePid": false,
|
||||||
|
"reports": [
|
||||||
|
"cobertura"
|
||||||
|
],
|
||||||
|
"verbose": false,
|
||||||
|
"remapOptions": {
|
||||||
|
"basePath": ".",
|
||||||
|
"useAbsolutePaths": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,7 +55,12 @@
|
|||||||
"htmlparser2": "^3.10.1",
|
"htmlparser2": "^3.10.1",
|
||||||
"vscode-nls": "^3.2.1"
|
"vscode-nls": "^3.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {
|
||||||
|
"@types/mocha": "^5.2.5",
|
||||||
|
"mocha": "^5.2.0",
|
||||||
|
"should": "^13.2.1",
|
||||||
|
"vscodetestcover": "^1.0.2"
|
||||||
|
},
|
||||||
"__metadata": {
|
"__metadata": {
|
||||||
"id": "33",
|
"id": "33",
|
||||||
"publisherDisplayName": "Microsoft",
|
"publisherDisplayName": "Microsoft",
|
||||||
|
|||||||
47
extensions/dacpac/src/test/dacpac.test.ts
Normal file
47
extensions/dacpac/src/test/dacpac.test.ts
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import 'mocha';
|
||||||
|
import * as should from 'should';
|
||||||
|
import * as os from 'os';
|
||||||
|
import { isValidFilenameCharacter, sanitizeStringForFilename } from '../wizard/api/utils';
|
||||||
|
|
||||||
|
|
||||||
|
describe('Sanitize database name for filename tests', function (): void {
|
||||||
|
it('Should only validate if one character is passed', async () => {
|
||||||
|
should(isValidFilenameCharacter(null)).equal(false);
|
||||||
|
should(isValidFilenameCharacter('')).equal(false);
|
||||||
|
should(isValidFilenameCharacter('abc')).equal(false);
|
||||||
|
should(isValidFilenameCharacter('c')).equal(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should determine invalid file name characters', async () => {
|
||||||
|
// invalid for both Windows and non-Windows
|
||||||
|
should(isValidFilenameCharacter('\\')).equal(false);
|
||||||
|
should(isValidFilenameCharacter('/')).equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should determine invalid Windows file name characters', async () => {
|
||||||
|
let isWindows = os.platform() === 'win32';
|
||||||
|
|
||||||
|
// invalid only for Windows
|
||||||
|
should(isValidFilenameCharacter('?')).equal(isWindows ? false : true);
|
||||||
|
should(isValidFilenameCharacter(':')).equal(isWindows ? false : true);
|
||||||
|
should(isValidFilenameCharacter('*')).equal(isWindows ? false : true);
|
||||||
|
should(isValidFilenameCharacter('<')).equal(isWindows ? false : true);
|
||||||
|
should(isValidFilenameCharacter('>')).equal(isWindows ? false : true);
|
||||||
|
should(isValidFilenameCharacter('|')).equal(isWindows ? false : true);
|
||||||
|
should(isValidFilenameCharacter('"')).equal(isWindows ? false : true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should sanitize database name for filename', async () => {
|
||||||
|
let invalidDbName = '"in|valid*<>db/?name';
|
||||||
|
let expectedWindows = '_in_valid___db__name';
|
||||||
|
let expectedNonWindows = '"in|valid*<>db_?name';
|
||||||
|
let isWindows = os.platform() === 'win32';
|
||||||
|
should(sanitizeStringForFilename(invalidDbName)).equal(isWindows ? expectedWindows : expectedNonWindows);
|
||||||
|
});
|
||||||
|
});
|
||||||
34
extensions/dacpac/src/test/index.ts
Normal file
34
extensions/dacpac/src/test/index.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
import * as testRunner from 'vscodetestcover';
|
||||||
|
|
||||||
|
const suite = 'DacFx Tests';
|
||||||
|
|
||||||
|
const testOptions: any = {
|
||||||
|
ui: 'bdd',
|
||||||
|
useColors: true,
|
||||||
|
timeout: 60000
|
||||||
|
};
|
||||||
|
|
||||||
|
const coverageConfig: any = {
|
||||||
|
coverConfig: '../../coverageConfig.json'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
|
||||||
|
testOptions.reporter = 'mocha-multi-reporters';
|
||||||
|
testOptions.reporterOptions = {
|
||||||
|
reporterEnabled: 'spec, mocha-junit-reporter',
|
||||||
|
mochaJunitReporterReporterOptions: {
|
||||||
|
testsuitesTitle: `${suite} ${process.platform}`,
|
||||||
|
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
testRunner.configure(testOptions, coverageConfig);
|
||||||
|
|
||||||
|
export = testRunner;
|
||||||
@@ -12,6 +12,7 @@ import * as path from 'path';
|
|||||||
import { DataTierApplicationWizard } from '../dataTierApplicationWizard';
|
import { DataTierApplicationWizard } from '../dataTierApplicationWizard';
|
||||||
import { DacFxDataModel } from './models';
|
import { DacFxDataModel } from './models';
|
||||||
import { BasePage } from './basePage';
|
import { BasePage } from './basePage';
|
||||||
|
import { sanitizeStringForFilename } from './utils';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ export abstract class DacFxConfigPage extends BasePage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected generateFilePathFromDatabaseAndTimestamp(): string {
|
protected generateFilePathFromDatabaseAndTimestamp(): string {
|
||||||
return path.join(this.getRootPath(), this.model.database + '-' + this.getDateTime() + this.fileExtension);
|
return path.join(this.getRootPath(), sanitizeStringForFilename(this.model.database) + '-' + this.getDateTime() + this.fileExtension);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected getDateTime(): string {
|
protected getDateTime(): string {
|
||||||
|
|||||||
43
extensions/dacpac/src/wizard/api/utils.ts
Normal file
43
extensions/dacpac/src/wizard/api/utils.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
import * as os from 'os';
|
||||||
|
const INVALID_FILE_CHARS_Windows = /[\\/:\*\?"<>\|]/g;
|
||||||
|
const INVALID_FILE_CHARS = /[\\/]/g;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if a given character is a valid filename character
|
||||||
|
* @param c Character to validate
|
||||||
|
*/
|
||||||
|
export function isValidFilenameCharacter(c: string): boolean {
|
||||||
|
// only a character should be passed
|
||||||
|
if (!c || c.length !== 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let isWindows = os.platform() === 'win32';
|
||||||
|
INVALID_FILE_CHARS_Windows.lastIndex = 0;
|
||||||
|
INVALID_FILE_CHARS.lastIndex = 0;
|
||||||
|
if (isWindows && INVALID_FILE_CHARS_Windows.test(c)) {
|
||||||
|
return false;
|
||||||
|
} else if (!isWindows && INVALID_FILE_CHARS.test(c)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces invalid filename characters in a string with underscores
|
||||||
|
* @param s The string to be sanitized for a filename
|
||||||
|
*/
|
||||||
|
export function sanitizeStringForFilename(s: string): string {
|
||||||
|
// replace invalid characters with an underscore
|
||||||
|
let result = '';
|
||||||
|
for (let i = 0; i < s.length; ++i) {
|
||||||
|
result += this.isValidFilenameCharacter(s[i]) ? s[i] : '_';
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -8,10 +8,10 @@ import * as azdata from 'azdata';
|
|||||||
import * as nls from 'vscode-nls';
|
import * as nls from 'vscode-nls';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as os from 'os';
|
|
||||||
import { DacFxDataModel } from '../api/models';
|
import { DacFxDataModel } from '../api/models';
|
||||||
import { DataTierApplicationWizard, Operation } from '../dataTierApplicationWizard';
|
import { DataTierApplicationWizard, Operation } from '../dataTierApplicationWizard';
|
||||||
import { DacFxConfigPage } from '../api/dacFxConfigPage';
|
import { DacFxConfigPage } from '../api/dacFxConfigPage';
|
||||||
|
import { sanitizeStringForFilename } from '../api/utils';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ export class DeployActionPage extends DacFxConfigPage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private setDefaultScriptFilePath(): void {
|
private setDefaultScriptFilePath(): void {
|
||||||
this.fileTextBox.value = path.join(this.getRootPath(), this.model.database + '_UpgradeDACScript_' + this.getDateTime() + '.sql');
|
this.fileTextBox.value = path.join(this.getRootPath(), sanitizeStringForFilename(this.model.database) + '_UpgradeDACScript_' + this.getDateTime() + '.sql');
|
||||||
this.model.scriptFilePath = this.fileTextBox.value;
|
this.model.scriptFilePath = this.fileTextBox.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,7 @@ call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\admin-too
|
|||||||
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\agent --extensionTestsPath=%~dp0\..\extensions\agent\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222
|
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\agent --extensionTestsPath=%~dp0\..\extensions\agent\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222
|
||||||
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\azurecore --extensionTestsPath=%~dp0\..\extensions\azurecore\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --disableExtensions --remote-debugging-port=9222
|
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\azurecore --extensionTestsPath=%~dp0\..\extensions\azurecore\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --disableExtensions --remote-debugging-port=9222
|
||||||
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\cms --extensionTestsPath=%~dp0\..\extensions\cms\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222
|
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\cms --extensionTestsPath=%~dp0\..\extensions\cms\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222
|
||||||
|
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\dacpac --extensionTestsPath=%~dp0\..\extensions\dacpac\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222
|
||||||
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\notebook --extensionTestsPath=%~dp0\..\extensions\notebook\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222
|
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\notebook --extensionTestsPath=%~dp0\..\extensions\notebook\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222
|
||||||
|
|
||||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ echo $VSCODEEXTDIR
|
|||||||
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/agent --extensionTestsPath=$ROOT/extensions/agent/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/agent --extensionTestsPath=$ROOT/extensions/agent/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
||||||
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/azurecore --extensionTestsPath=$ROOT/extensions/azurecore/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/azurecore --extensionTestsPath=$ROOT/extensions/azurecore/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
||||||
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/cms --extensionTestsPath=$ROOT/extensions/cms/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/cms --extensionTestsPath=$ROOT/extensions/cms/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
||||||
|
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/dacpac --extensionTestsPath=$ROOT/extensions/dacpac/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
||||||
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/notebook --extensionTestsPath=$ROOT/extensions/notebook/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/notebook --extensionTestsPath=$ROOT/extensions/notebook/out/test --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
||||||
|
|
||||||
rm -r $VSCODEUSERDATADIR
|
rm -r $VSCODEUSERDATADIR
|
||||||
|
|||||||
Reference in New Issue
Block a user