Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue 2934 fix enterprise CORS issue #2935

Merged
merged 5 commits into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 1 addition & 2 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,4 @@ node ./build/tooling/bundle-content-scripts
cp -r $OUTDIR ./build/chrome-enterprise
cp -r $OUTDIR ./build/chrome-consumer
cp -r $OUTDIR ./build/firefox-consumer
node ./build/tooling/build-manifests
node ./build/tooling/build-types
node ./build/tooling/build-types-and-manifests
5 changes: 2 additions & 3 deletions conf/tsconfig.tooling.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@
"outDir": "../build/tooling"
},
"files": [
"../tooling/build-manifests.ts",
"../tooling/build-types-and-manifests.ts",
"../tooling/resolve-modules.ts",
"../tooling/bundle-content-scripts.ts",
"../tooling/fill-values.ts",
"../tooling/tsc-compiler.ts",
"../tooling/build-types.ts"
"../tooling/tsc-compiler.ts"
],
"include": [
"../tooling/tslint-rules/*.ts"
Expand Down
37 changes: 32 additions & 5 deletions test/source/patterns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import * as path from 'path';

import { readFileSync, readdirSync, statSync } from 'fs';

/**
* This test looks for petterns in the source code, as well as in the built product to look for issues.
*/

let errsFound = 0;

const getAllFilesInDir = (dir: string, filePattern: RegExp): string[] => {
Expand All @@ -29,7 +33,7 @@ const hasErrHandledComment = (line: string) => {
return /\/\/ error-handled/.test(line);
};

const validateLine = (line: string, location: string) => {
const validateTypeScriptLine = (line: string, location: string) => {
if (line.match(/\.(innerHTML|outerHTML) ?= ?/) && !hasXssComment(line)) {
console.error(`unchecked xss in ${location}:\n${line}\n`);
errsFound++;
Expand Down Expand Up @@ -60,12 +64,35 @@ const validateLine = (line: string, location: string) => {
}
};

const srcFilePaths = getAllFilesInDir('./extension', /\.ts$/);

for (const srcFilePath of srcFilePaths) {
/**
* lint problems in TS files - the type of issues that we don't have a linter for
*/
for (const srcFilePath of getAllFilesInDir('./extension', /\.ts$/)) {
const lines = readFileSync(srcFilePath).toString().split('\n');
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
validateLine(lines[lineIndex], `${srcFilePath}:${lineIndex + 1}`);
validateTypeScriptLine(lines[lineIndex], `${srcFilePath}:${lineIndex + 1}`);
}
}

/**
* check for problems in manifest file (because dynamically generated)
* https://github.com/FlowCrypt/flowcrypt-browser/issues/2934
*/
const expectedPermissions = ["storage", "tabs", "https://*.google.com/*", "https://www.googleapis.com/*", "https://flowcrypt.com/*", "unlimitedStorage"];
for (const buildType of ['chrome-consumer', 'chrome-enterprise', 'firefox-consumer']) {
const manifest = JSON.parse(readFileSync(`./build/${buildType}/manifest.json`).toString());
for (const expectedPermission of expectedPermissions) {
if (!manifest.permissions.includes(expectedPermission)) {
if (!(expectedPermission === 'unlimitedStorage' && buildType === 'firefox-consumer')) {
console.error(`Missing permission '${expectedPermission}' in ${buildType}/manifest.json`);
errsFound++;
}
}
}
const gmailCs = manifest.content_scripts.find((cs: any) => cs.matches.includes('https://mail.google.com/*'));
if (!gmailCs || !gmailCs.css.length || !gmailCs.js.length) {
console.error(`Missing content_scripts declaration for Gmail in ${buildType}/manifest.json`);
errsFound++;
}
}

Expand Down
7 changes: 4 additions & 3 deletions test/source/tests/page-recipe/oauth-page-recipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class OauthPageRecipe extends PageRecipe {
email_confirm_btn: '#identifierNext',
auth0_username: '#username',
auth0_password: '#password',
auth0_login_btn: '._button-login',
auth0_login_btn: 'button', // old: ._button-login
};
try {
await oauthPage.waitAny('#Email, #submit_approve_access, #identifierId, .w6VTHd, #profileIdentifier', { timeout: 45 });
Expand All @@ -47,9 +47,10 @@ export class OauthPageRecipe extends PageRecipe {
}
throw new Error('Oauth page didnt close after login. Should increase timeout or await close event');
}
await oauthPage.waitAny([selectors.approve_button, selectors.auth0_login_btn]);
if (await oauthPage.isElementPresent(selectors.auth0_login_btn)) {
await oauthPage.waitAny([selectors.approve_button, selectors.auth0_username]);
if (await oauthPage.isElementPresent(selectors.auth0_username)) {
await oauthPage.waitAndType(selectors.auth0_username, auth.email);
console.log(oauthPage.target.url());
await oauthPage.waitAndType(selectors.auth0_password, auth.password!);
await oauthPage.waitAndClick(selectors.auth0_login_btn);
await oauthPage.waitForNavigationIfAny();
Expand Down
39 changes: 0 additions & 39 deletions tooling/build-manifests.ts

This file was deleted.

92 changes: 92 additions & 0 deletions tooling/build-types-and-manifests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { readFileSync, writeFileSync } from 'fs';
import { execSync as exec } from 'child_process';

// tslint:disable:no-unsafe-any

/**
* This file was originally two files: one that edited manifests, and one that copied build folders and edited mock versions
* These steps somewhat overlap, so the two scripts were joined into one below. However, work was not yet done to assimilate them.
*/

/**
* first, modify appropriate manifests
*/

const DIR = './build';
const version: string = JSON.parse(readFileSync('./package.json').toString()).version;

const addManifest = (toBuildType: string, transform: (manifest: { [k: string]: any }) => void) => {
const manifest = JSON.parse(readFileSync(`${DIR}/generic-extension-wip/manifest.json`).toString());
transform(manifest);
writeFileSync(`${DIR}/${toBuildType}/manifest.json`, JSON.stringify(manifest, undefined, 2));
};

addManifest('chrome-consumer', manifest => {
manifest.version = version;
});

addManifest('firefox-consumer', manifest => {
manifest.version = version;
manifest.applications = { gecko: { id: 'firefox@cryptup.io', update_url: 'https://flowcrypt.com/api/update/firefox', strict_min_version: '60.0' } };
manifest.permissions = manifest.permissions.filter((p: string) => p !== 'unlimitedStorage');
delete manifest.minimum_chrome_version;
});

addManifest('chrome-enterprise', manifest => {
manifest.version = version;
manifest.name = 'FlowCrypt for Enterprise';
manifest.description = 'FlowCrypt Chrome Extension for Enterprise clients (stable)';
// careful - changing this will likely cause all extensions to be disabled in their user's browsers
manifest.permissions = ["storage", "tabs", "https://*.google.com/*", "https://www.googleapis.com/*", "https://flowcrypt.com/*", "unlimitedStorage"];
for (const csDef of manifest.content_scripts) {
csDef.matches = csDef.matches.filter((host: string) => host === 'https://mail.google.com/*');
}
manifest.content_scripts = manifest.content_scripts.filter((csDef: { matches: string[] }) => csDef.matches.length); // remove empty defs
if (!manifest.content_scripts.length) {
throw new Error('Content script defs ended up empty in enterprise manifest');
}
});

/**
* second, build copy and edit enterprise and mock versions
*/

const CHROME_CONSUMER = 'chrome-consumer';
const CHROME_ENTERPRISE = 'chrome-enterprise';
const MOCK_HOST: { [buildType: string]: string } = { 'chrome-consumer': 'http://localhost:8001', 'chrome-enterprise': 'http://google.mock.flowcryptlocal.com:8001' };

const buildDir = (buildType: string) => `./build/${buildType}`;

const edit = (filepath: string, editor: (content: string) => string) => {
writeFileSync(filepath, editor(readFileSync(filepath, { encoding: 'utf-8' })));
};

const makeMockBuild = (buildType: string) => {
const mockBuildType = `${buildType}-mock`;
exec(`cp -r ${buildDir(buildType)} ${buildDir(mockBuildType)}`);
const editor = (code: string) => {
return code
.replace(/const (GOOGLE_API_HOST|GOOGLE_OAUTH_SCREEN_HOST) = [^;]+;/g, `const $1 = '${MOCK_HOST[buildType]}';`)
.replace(/const (BACKEND_API_HOST) = [^;]+;/g, `const $1 = 'http://localhost:8001/api/';`)
.replace(/const (ATTESTER_API_HOST) = [^;]+;/g, `const $1 = 'http://localhost:8001/attester/';`)
.replace(/https:\/\/flowcrypt.com\/api\/help\/error/g, 'http://localhost:8001/api/help/error');
};
edit(`${buildDir(mockBuildType)}/js/common/core/const.js`, editor);
edit(`${buildDir(mockBuildType)}/js/common/platform/catch.js`, editor);
edit(`${buildDir(mockBuildType)}/js/content_scripts/webmail_bundle.js`, editor);
};

const updateEnterpriseBuild = () => {
const constFilepath = `${buildDir(CHROME_ENTERPRISE)}/js/common/core/const.js`;
edit(constFilepath, (code: string) => {
const flavorPattern = /export const FLAVOR = 'consumer';/g;
if (!flavorPattern.test(code)) {
throw new Error(`Expecting to find FLAVOR in ${constFilepath}`);
}
return code.replace(flavorPattern, `export const FLAVOR = 'enterprise';`);
});
};

updateEnterpriseBuild();
makeMockBuild(CHROME_CONSUMER);
makeMockBuild(CHROME_ENTERPRISE);
43 changes: 0 additions & 43 deletions tooling/build-types.ts

This file was deleted.

2 changes: 1 addition & 1 deletion tooling/fill-values.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { compilerOptions: { outDir: targetDirExtension } } = JSON.parse(readFileS
const { compilerOptions: { outDir: targetDirContentScripts } } = JSON.parse(readFileSync('./conf/tsconfig.content_scripts.json').toString());
const { version } = JSON.parse(readFileSync(`./package.json`).toString());

// mock values for a consumer-mock or enterprise-mock test builds are regex-replaced later in `build-types.ts`
// mock values for a consumer-mock or enterprise-mock test builds are regex-replaced later in `build-types-and-manifests.ts`
const replaceables: { needle: RegExp, val: string }[] = [
{ needle: /\[BUILD_REPLACEABLE_VERSION\]/g, val: version },
{ needle: /\[BUILD_REPLACEABLE_FLAVOR\]/g, val: 'consumer' },
Expand Down