Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/output
client/www/
6 changes: 5 additions & 1 deletion client/electron/types/socks/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,9 @@ declare module 'socks' {
callback: (err: Error, socket: net.Socket, info: SocksAddress) => void
): void;

export function createUDPFrame(target: SocksAddress, data: Buffer, frame?: number): Buffer;
export function createUDPFrame(
target: SocksAddress,
data: Buffer,
frame?: number
): Buffer;
}
26 changes: 20 additions & 6 deletions client/web/app/app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,34 @@ describe('unwrapInvite', () => {

it('detects ss fragment', () => {
const s = 'ss://myhost.com:3333';
expect(unwrapInvite(`https://whatever.com/invite.html#${encodeURIComponent(s)}`)).toEqual(s);
expect(
unwrapInvite(`https://whatever.com/invite.html#${encodeURIComponent(s)}`)
).toEqual(s);
});

it('handles fragment after redirect', () => {
const s = 'ss://myhost.com:3333';
expect(unwrapInvite(`https://whatever.com/invite.html#/en/invite/${encodeURIComponent(s)}`)).toEqual(s);
expect(
unwrapInvite(
`https://whatever.com/invite.html#/en/invite/${encodeURIComponent(s)}`
)
).toEqual(s);
});
});

describe('isOutlineAccessKey', () => {
it('ignores empty string', () => expect(isOutlineAccessKey('')).toBe(false));
it('ignores garbage', () => expect(isOutlineAccessKey('i am not a outline service location')).toBe(false));
it('ignores random https links', () => expect(isOutlineAccessKey('https://example.com')).toBe(false));
it('ignores garbage', () =>
expect(isOutlineAccessKey('i am not a outline service location')).toBe(
false
));
it('ignores random https links', () =>
expect(isOutlineAccessKey('https://example.com')).toBe(false));

it('detects static keys', () => expect(isOutlineAccessKey('ss://myhost.com:3333')).toBe(true));
it('detects dynamic keys', () => expect(isOutlineAccessKey('ssconf://my.cool.server.com:3423#veryfast')).toBe(true));
it('detects static keys', () =>
expect(isOutlineAccessKey('ss://myhost.com:3333')).toBe(true));
it('detects dynamic keys', () =>
expect(
isOutlineAccessKey('ssconf://my.cool.server.com:3423#veryfast')
).toBe(true));
});
30 changes: 16 additions & 14 deletions client/web/app/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@ export interface EnvironmentVariables {

// According to http://caniuse.com/#feat=fetch fetch didn't land iOS Safari
// until v10.3 released 3/26/17, so use XMLHttpRequest instead.
export const onceEnvVars: Promise<EnvironmentVariables> = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = () => {
try {
const json = JSON.parse(xhr.responseText);
console.debug('Resolving with envVars:', json);
resolve(json as EnvironmentVariables);
} catch (err) {
reject(err);
}
};
xhr.open('GET', 'environment.json', true);
xhr.send();
});
export const onceEnvVars: Promise<EnvironmentVariables> = new Promise(
(resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = () => {
try {
const json = JSON.parse(xhr.responseText);
console.debug('Resolving with envVars:', json);
resolve(json as EnvironmentVariables);
} catch (err) {
reject(err);
}
};
xhr.open('GET', 'environment.json', true);
xhr.send();
}
);
18 changes: 13 additions & 5 deletions client/web/app/settings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import {InMemoryStorage} from '@outline/infrastructure/memory_storage';

import {Settings, SettingsKey} from './settings';


const FAKE_SETTINGS_KEYS = ['key', 'key1', 'key2'];

describe('Settings', () => {
Expand All @@ -29,8 +28,13 @@ describe('Settings', () => {
});

it('loads existing settings', () => {
const store = new Map([[Settings.STORAGE_KEY, '{"key1": "value1", "key2": "value2"}']]);
const settings = new Settings(new InMemoryStorage(store), FAKE_SETTINGS_KEYS);
const store = new Map([
[Settings.STORAGE_KEY, '{"key1": "value1", "key2": "value2"}'],
]);
const settings = new Settings(
new InMemoryStorage(store),
FAKE_SETTINGS_KEYS
);
expect(settings.get('key1')).toEqual('value1');
expect(settings.get('key2')).toEqual('value2');
});
Expand Down Expand Up @@ -69,7 +73,9 @@ describe('Settings', () => {
it('is initialized with default valid keys', () => {
// Constructor uses SettingKeys as the default value for valid keys.
const settings = new Settings(new InMemoryStorage());
expect(settings.isValidSetting(SettingsKey.VPN_WARNING_DISMISSED)).toBeTruthy();
expect(
settings.isValidSetting(SettingsKey.VPN_WARNING_DISMISSED)
).toBeTruthy();
});

it('throws when setting an invalid key', () => {
Expand All @@ -80,7 +86,9 @@ describe('Settings', () => {
});

it('throws when storage is corrupted', () => {
const storage = new InMemoryStorage(new Map([[Settings.STORAGE_KEY, '"malformed": "json"']]));
const storage = new InMemoryStorage(
new Map([[Settings.STORAGE_KEY, '"malformed": "json"']])
);
expect(() => {
new Settings(storage, FAKE_SETTINGS_KEYS);
}).toThrowError(SyntaxError);
Expand Down
2 changes: 1 addition & 1 deletion client/web/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

const path = require('path');

module.exports = async function(config) {
module.exports = async function (config) {
const testConfig = await import('./webpack_test.mjs');

config.set({
Expand Down
43 changes: 33 additions & 10 deletions client/web/shared/error_reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,36 @@ import {Integration as SentryIntegration} from '@sentry/types';
export type Tags = {[id: string]: string | boolean | number};

export interface OutlineErrorReporter {
report(userFeedback: string, feedbackCategory: string, userEmail?: string, tags?: Tags): Promise<void>;
report(
userFeedback: string,
feedbackCategory: string,
userEmail?: string,
tags?: Tags
): Promise<void>;
}

export class SentryErrorReporter implements OutlineErrorReporter {
constructor(appVersion: string, dsn: string, private tags: Tags) {
constructor(
appVersion: string,
dsn: string,
private tags: Tags
) {
if (dsn) {
Sentry.init({dsn, release: appVersion, integrations: getSentryBrowserIntegrations});
Sentry.init({
dsn,
release: appVersion,
integrations: getSentryBrowserIntegrations,
});
}
this.setUpUnhandledRejectionListener();
}

async report(userFeedback: string, feedbackCategory: string, userEmail?: string, tags?: Tags): Promise<void> {
async report(
userFeedback: string,
feedbackCategory: string,
userEmail?: string,
tags?: Tags
): Promise<void> {
const combinedTags = {...this.tags, ...tags};
Sentry.captureEvent({
message: userFeedback,
Expand Down Expand Up @@ -57,18 +75,23 @@ export class SentryErrorReporter implements OutlineErrorReporter {
// Chrome is the only browser that supports the unhandledrejection event.
// This is fine for Android, but will not work in iOS.
const unhandledRejection = 'unhandledrejection';
window.addEventListener(unhandledRejection, (event: PromiseRejectionEvent) => {
const reason = event.reason;
const msg = reason.stack ? reason.stack : reason;
Sentry.addBreadcrumb({message: msg, category: unhandledRejection});
});
window.addEventListener(
unhandledRejection,
(event: PromiseRejectionEvent) => {
const reason = event.reason;
const msg = reason.stack ? reason.stack : reason;
Sentry.addBreadcrumb({message: msg, category: unhandledRejection});
}
);
}
}

// Returns a list of Sentry browser integrations that maintains the default integrations,
// but replaces the Breadcrumbs integration with a custom one that only collects console statements.
// See https://docs.sentry.io/platforms/javascript/configuration/integrations/default/
export function getSentryBrowserIntegrations(defaultIntegrations: SentryIntegration[]): SentryIntegration[] {
export function getSentryBrowserIntegrations(
defaultIntegrations: SentryIntegration[]
): SentryIntegration[] {
const integrations = defaultIntegrations.filter(integration => {
return integration.name !== 'Breadcrumbs';
});
Expand Down
6 changes: 5 additions & 1 deletion client/web/types/clipboard.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ type FailureCallback = (error: Error) => void;

interface CordovaPlugins {
clipboard: {
copy(text: string, onSuccess: SuccessCallback, onFailure: FailureCallback): void;
copy(
text: string,
onSuccess: SuccessCallback,
onFailure: FailureCallback
): void;
paste(onSuccess: SuccessCallback, onFailure: FailureCallback): void;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,13 @@ export default {
},
};

export const Example = ({connectionState}: ServerConnectionIndicator) =>
html`
<div style="width: clamp(64px, 100vw, 512px); height: clamp(64px, 100vh, 512px);">
<server-connection-indicator
connection-state="${connectionState ?? ServerConnectionState.DISCONNECTED}"
></server-connection-indicator>
</div>
`;
export const Example = ({connectionState}: ServerConnectionIndicator) => html`
<div
style="width: clamp(64px, 100vw, 512px); height: clamp(64px, 100vh, 512px);"
>
<server-connection-indicator
connection-state="${connectionState ??
ServerConnectionState.DISCONNECTED}"
></server-connection-indicator>
</div>
`;
5 changes: 3 additions & 2 deletions client/web/views/servers_view/server_list/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,6 @@ export default {
},
};

export const Example = ({servers}: ServerList) =>
html` <server-list .localize="${localize}" .servers="${servers}"></server-list> `;
export const Example = ({servers}: ServerList) => html`
<server-list .localize="${localize}" .servers="${servers}"></server-list>
`;
17 changes: 15 additions & 2 deletions commitlint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,26 @@ module.exports = {
'manager',
'manager/linux',
'manager/macos',
'manager/windows'
'manager/windows',
],
],
'type-enum': [
2,
'always',
['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'proposal', 'refactor', 'revert', 'style', 'test'],
[
'build',
'chore',
'ci',
'docs',
'feat',
'fix',
'perf',
'proposal',
'refactor',
'revert',
'style',
'test',
],
],
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,7 @@ const UNSUPPORTED_ISSUE_TYPE_HELPPAGES = new Map([
IssueType.CANNOT_ADD_SERVER,
'https://support.google.com/outline/answer/15331223',
],
[
IssueType.CONNECTION,
'https://support.google.com/outline/answer/15331126',
],
[IssueType.CONNECTION, 'https://support.google.com/outline/answer/15331126'],
]);

@customElement('outline-contact-us-dialog')
Expand Down
Loading