Skip to content

Commit

Permalink
fix: validate bot name when passed via URL params (#4712)
Browse files Browse the repository at this point in the history
* update lockfile

* add prelaunch task to build electron

* clean up electron start scripts

add server as project reference so that it will rebuild when building electron

* ignore tsbuildinfo files

* update extension lockfiles

* add start:electron and make default start electron

* validate new bot form when storage changes

* add start:dev:electron script

* revert changes to server tsconfig

* wait on client dev server before starting electron

* revert ts project changes

* add server build and client ping dependencies to electron task

Co-authored-by: Chris Whitten <christopher.whitten@microsoft.com>
Co-authored-by: Tony Anziano <tonyanziano5@gmail.com>
  • Loading branch information
3 people authored Nov 13, 2020
1 parent 4ccda16 commit aef39ca
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 26 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -397,3 +397,5 @@ Composer/.vscode/
# Docker App Data
.appdata
docker-compose.override.yml

*.tsbuildinfo
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"COMPOSER_ENABLE_ONEAUTH": "false"
},
"outputCapture": "std",
"preLaunchTask": "electron: build",
"outFiles": [
"${workspaceRoot}/Composer/packages/electron-server/build/**/*.js",
"${workspaceRoot}/Composer/packages/server/build/**/*.js",
Expand Down
19 changes: 18 additions & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,25 @@
"command": "yarn build",
"options": {
"cwd": "Composer/packages/server"
}
},
{
"label": "electron: build",
"type": "shell",
"command": "yarn build",
"options": {
"cwd": "Composer/packages/electron-server"
},
"problemMatcher": []
"dependsOn": ["server: build", "client: ping"]
},
{
"label": "client: ping",
"type": "shell",
"command": "./node_modules/.bin/wait-on",
"args": ["-t", "300000", "http://localhost:3000"],
"options": {
"cwd": "Composer"
}
}
]
}
3 changes: 3 additions & 0 deletions Composer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@
"start": "cross-env NODE_ENV=production PORT=3000 yarn start:server",
"startall": "yarn start",
"start:dev": "concurrently \"npm:start:client\" \"npm:start:server:dev\"",
"start:dev:electron": "concurrently \"npm:start:client\" \"npm:start:electron\"",
"start:client": "yarn workspace @bfc/client start",
"start:electron": "wait-on -t 300000 http://localhost:3000 && yarn workspace @bfc/electron-server start",
"start:server": "yarn workspace @bfc/server start",
"start:server:dev": "yarn workspace @bfc/server start:dev",
"runtime": "cd ../runtime/dotnet/azurewebapp && dotnet build && dotnet run",
Expand Down Expand Up @@ -121,6 +123,7 @@
"ts-loader": "7.0.4",
"tslib": "^2.0.0",
"typescript": "3.9.2",
"wait-on": "^5.2.0",
"wsrun": "^5.2.0"
}
}
24 changes: 22 additions & 2 deletions Composer/packages/client/__tests__/hooks/useForm.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ describe('useForm', () => {
expect(result.current.formData.requiredField).toEqual('new value');
});

it('can update the whole object', async () => {
it('can update the whole object and validates', async () => {
custValidate.mockReturnValue('custom');
const { result, waitForNextUpdate } = renderHook(() => useForm(fields));

await act(async () => {
Expand All @@ -69,6 +70,10 @@ describe('useForm', () => {
customValidationField: 'form',
asyncValidationField: 'data',
});

expect(result.current.formErrors).toEqual({
customValidationField: 'custom',
});
});
});

Expand All @@ -85,6 +90,21 @@ describe('useForm', () => {
});
});

it('can validate on command', async () => {
custValidate.mockReturnValue('custom');
asyncValidate.mockResolvedValue('async');
const { result, waitForNextUpdate } = renderHook(() => useForm(fields, { validateOnMount: false }));
await act(async () => {
result.current.validateForm();
await waitForNextUpdate();
});

expect(result.current.formErrors).toMatchObject({
customValidationField: 'custom',
asyncValidationField: 'async',
});
});

it('validates required fields', async () => {
const { result, waitForNextUpdate } = renderHook(() => useForm(fields));

Expand All @@ -108,7 +128,7 @@ describe('useForm', () => {
expect(result.current.formErrors.customValidationField).toEqual('my custom validation');
});

it('validates using an asyn validator', async () => {
it('validates using an async validator', async () => {
asyncValidate.mockResolvedValue('my async validation');
const { result, waitForNextUpdate } = renderHook(() => useForm(fields));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ const DefineConversation: React.FC<DefineConversationProps> = (props) => {
: '',
},
};
const { formData, formErrors, hasErrors, updateField, updateForm } = useForm(formConfig);
const { formData, formErrors, hasErrors, updateField, updateForm, validateForm } = useForm(formConfig);
const [isImported, setIsImported] = useState<boolean>(false);

useEffect(() => {
Expand All @@ -176,31 +176,30 @@ const DefineConversation: React.FC<DefineConversationProps> = (props) => {
? Path.join(focusedStorageFolder.parent, focusedStorageFolder.name)
: '',
};
updateForm(formData);
if (props.location?.search) {
const updatedFormData = {
...formData,
};

const decoded = decodeURIComponent(props.location.search);
const { name, description, schemaUrl } = querystring.parse(decoded);
if (description) {
updatedFormData.description = description as string;
formData.description = description as string;
}

if (schemaUrl) {
updatedFormData.schemaUrl = schemaUrl as string;
formData.schemaUrl = schemaUrl as string;
}

if (name) {
updatedFormData.name = name as string;
formData.name = name as string;
} else {
updatedFormData.name = getDefaultName();
formData.name = getDefaultName();
}
updateForm(updatedFormData);
}
updateForm(formData);
}, [templateId]);

useEffect(() => {
validateForm();
}, [focusedStorageFolder]);

const handleSubmit = useCallback(
(e) => {
e.preventDefault();
Expand Down
12 changes: 10 additions & 2 deletions Composer/packages/client/src/hooks/useForm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,17 @@ export function useForm<D extends object>(fields: FieldConfig<D>, opts: FormOpti

const updateForm = useCallback((newData: D) => {
setFormData(newData);
setFormErrors(mapValues(newData, () => undefined));
Object.entries(newData).forEach(([key, value]) => {
validateField(key as keyof D, fields[key], value);
});
}, []);

const validateForm = useCallback(() => {
Object.entries(formData).forEach(([key, value]) => {
validateField(key as keyof D, fields[key], value);
});
}, [fields, formData]);

useEffect(() => {
if (opts.validateOnMount) {
Object.entries(formData).forEach(([key, value]) => {
Expand All @@ -72,5 +80,5 @@ export function useForm<D extends object>(fields: FieldConfig<D>, opts: FormOpti
}
}, []);

return { formData, formErrors, updateField, updateForm, hasErrors: hasErrors(formErrors) };
return { formData, formErrors, updateField, updateForm, validateForm, hasErrors: hasErrors(formErrors) };
}
6 changes: 2 additions & 4 deletions Composer/packages/electron-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,15 @@
"node": ">=12"
},
"scripts": {
"build": "tsc -p tsconfig.build.json && ncp src/preload.js build/preload.js",
"build": "tsc -b tsconfig.build.json && ncp src/preload.js build/preload.js",
"clean": "rimraf build && rimraf dist && rimraf l10ntemp",
"copy-artifacts": "node scripts/copy-artifacts.js",
"dist": "node scripts/electronBuilderDist.js",
"dist:full": "yarn clean && yarn build && yarn run pack && yarn copy-artifacts && yarn dist",
"lint": "eslint --quiet ./src",
"lint:fix": "yarn lint --fix",
"pack": "node scripts/electronBuilderPack.js",
"start": "cross-env NODE_ENV=development electron .",
"start:electron": "./node_modules/.bin/electron --inspect=7777 --remote-debugging-port=7778 .",
"start:electron:dev": "cross-env NODE_ENV=development ELECTRON_TARGET_URL=http://localhost:3000/ npm run start:electron",
"start": "DEBUG=composer* cross-env NODE_ENV=development electron --inspect=7777 --remote-debugging-port=7778 .",
"test": "jest",
"test:watch": "jest --watch",
"l10n:extract": "cross-env NODE_ENV=production format-message extract -g underscored_crc32 -o locales/en-US.json l10ntemp/**/*.js",
Expand Down
7 changes: 2 additions & 5 deletions Composer/packages/electron-server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,11 @@
"outDir": "./build/",
"sourceMap": true,
"target": "es6",
"baseUrl": ".",
"paths": {
"@src/*": ["src/*"]
}
"baseUrl": "."
},
"include": [
"src/**/*.ts",
"scripts/*.js", // include scripts to geting proper linting
"scripts/*.js", // include scripts to get proper linting
"__tests__", // intellisense
"src/preload.js"
]
Expand Down
3 changes: 2 additions & 1 deletion Composer/packages/server/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./build/",
"sourceMap": true,
"target": "es6"
},
"include": ["src/**/*.ts"]
"include": ["src"]
}
58 changes: 58 additions & 0 deletions Composer/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2726,6 +2726,11 @@
resolved "https://botbuilder.myget.org/F/botbuilder-declarative/npm/@hapi/hoek/-/@hapi/hoek-8.5.0.tgz#2f9ce301c8898e1c3248b0a8564696b24d1a9a5a"
integrity sha1-L5zjAciJjhwySLCoVkaWsk0amlo=

"@hapi/hoek@^9.0.0":
version "9.1.0"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.1.0.tgz#6c9eafc78c1529248f8f4d92b0799a712b6052c6"
integrity sha512-i9YbZPN3QgfighY/1X1Pu118VUz2Fmmhd6b2n0/O8YVgGGfw0FbUYoA97k7FkpGJ+pLCFEDLUmAPPV4D1kpeFw==

"@hapi/joi@^15.0.0":
version "15.1.1"
resolved "https://botbuilder.myget.org/F/botbuilder-declarative/npm/@hapi/joi/-/@hapi/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7"
Expand All @@ -2743,6 +2748,13 @@
dependencies:
"@hapi/hoek" "^8.3.0"

"@hapi/topo@^5.0.0":
version "5.0.0"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.0.0.tgz#c19af8577fa393a06e9c77b60995af959be721e7"
integrity sha512-tFJlT47db0kMqVm3H4nQYgn6Pwg10GTZHb1pwmSiv1K4ks6drQOtfEF5ZnPjkvC+y4/bUPHK+bc87QvLcL+WMw==
dependencies:
"@hapi/hoek" "^9.0.0"

"@istanbuljs/load-nyc-config@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz#10602de5570baea82f8afbfa2630b24e7a8cfe5b"
Expand Down Expand Up @@ -3286,6 +3298,23 @@
dependencies:
any-observable "^0.3.0"

"@sideway/address@^4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.0.tgz#0b301ada10ac4e0e3fa525c90615e0b61a72b78d"
integrity sha512-wAH/JYRXeIFQRsxerIuLjgUu2Xszam+O5xKeatJ4oudShOOirfmsQ1D6LL54XOU2tizpCYku+s1wmU0SYdpoSA==
dependencies:
"@hapi/hoek" "^9.0.0"

"@sideway/formula@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c"
integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==

"@sideway/pinpoint@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==

"@sindresorhus/is@^0.14.0":
version "0.14.0"
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
Expand Down Expand Up @@ -12615,6 +12644,17 @@ jest@^26.0.1:
import-local "^3.0.2"
jest-cli "^26.0.1"

joi@^17.1.1:
version "17.3.0"
resolved "https://registry.yarnpkg.com/joi/-/joi-17.3.0.tgz#f1be4a6ce29bc1716665819ac361dfa139fff5d2"
integrity sha512-Qh5gdU6niuYbUIUV5ejbsMiiFmBdw8Kcp8Buj2JntszCkCfxJ9Cz76OtHxOZMPXrt5810iDIXs+n1nNVoquHgg==
dependencies:
"@hapi/hoek" "^9.0.0"
"@hapi/topo" "^5.0.0"
"@sideway/address" "^4.1.0"
"@sideway/formula" "^3.0.0"
"@sideway/pinpoint" "^2.0.0"

js-levenshtein@^1.1.3:
version "1.1.6"
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
Expand Down Expand Up @@ -17315,6 +17355,13 @@ rxjs@^6.1.0, rxjs@^6.3.3, rxjs@^6.4.0:
dependencies:
tslib "^1.9.0"

rxjs@^6.5.5:
version "6.6.3"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552"
integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==
dependencies:
tslib "^1.9.0"

safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
Expand Down Expand Up @@ -19645,6 +19692,17 @@ w3c-xmlserializer@^2.0.0:
dependencies:
xml-name-validator "^3.0.0"

wait-on@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-5.2.0.tgz#6711e74422523279714a36d52cf49fb47c9d9597"
integrity sha512-U1D9PBgGw2XFc6iZqn45VBubw02VsLwnZWteQ1au4hUVHasTZuFSKRzlTB2dqgLhji16YVI8fgpEpwUdCr8B6g==
dependencies:
axios "^0.19.2"
joi "^17.1.1"
lodash "^4.17.19"
minimist "^1.2.5"
rxjs "^6.5.5"

walker@^1.0.7, walker@~1.0.5:
version "1.0.7"
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb"
Expand Down

0 comments on commit aef39ca

Please sign in to comment.