Use window messaging to pass sensitive data to terminal iframe (#929)
* Use window messaging to pass sensitive data to terminal iframe * Address feedback * Format * Update * Add tests
This commit is contained in:
parent
cfce78242c
commit
854bd2c149
|
@ -1,154 +1,90 @@
|
||||||
|
import { shallow } from "enzyme";
|
||||||
|
import React from "react";
|
||||||
import * as DataModels from "../../../Contracts/DataModels";
|
import * as DataModels from "../../../Contracts/DataModels";
|
||||||
import { NotebookTerminalComponent } from "./NotebookTerminalComponent";
|
import { NotebookTerminalComponent, NotebookTerminalComponentProps } from "./NotebookTerminalComponent";
|
||||||
|
|
||||||
const createTestDatabaseAccount = (): DataModels.DatabaseAccount => {
|
const testAccount: DataModels.DatabaseAccount = {
|
||||||
return {
|
id: "id",
|
||||||
id: "testId",
|
kind: "kind",
|
||||||
kind: "testKind",
|
location: "location",
|
||||||
location: "testLocation",
|
name: "name",
|
||||||
name: "testName",
|
|
||||||
properties: {
|
properties: {
|
||||||
cassandraEndpoint: null,
|
|
||||||
documentEndpoint: "https://testDocumentEndpoint.azure.com/",
|
documentEndpoint: "https://testDocumentEndpoint.azure.com/",
|
||||||
gremlinEndpoint: null,
|
|
||||||
tableEndpoint: null,
|
|
||||||
},
|
},
|
||||||
type: "testType",
|
type: "type",
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createTestMongo32DatabaseAccount = (): DataModels.DatabaseAccount => {
|
const testMongo32Account: DataModels.DatabaseAccount = {
|
||||||
return {
|
...testAccount,
|
||||||
id: "testId",
|
|
||||||
kind: "testKind",
|
|
||||||
location: "testLocation",
|
|
||||||
name: "testName",
|
|
||||||
properties: {
|
|
||||||
cassandraEndpoint: null,
|
|
||||||
documentEndpoint: "https://testDocumentEndpoint.azure.com/",
|
|
||||||
gremlinEndpoint: null,
|
|
||||||
tableEndpoint: null,
|
|
||||||
},
|
|
||||||
type: "testType",
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createTestMongo36DatabaseAccount = (): DataModels.DatabaseAccount => {
|
const testMongo36Account: DataModels.DatabaseAccount = {
|
||||||
return {
|
...testAccount,
|
||||||
id: "testId",
|
|
||||||
kind: "testKind",
|
|
||||||
location: "testLocation",
|
|
||||||
name: "testName",
|
|
||||||
properties: {
|
properties: {
|
||||||
cassandraEndpoint: null,
|
|
||||||
documentEndpoint: "https://testDocumentEndpoint.azure.com/",
|
|
||||||
gremlinEndpoint: null,
|
|
||||||
tableEndpoint: null,
|
|
||||||
mongoEndpoint: "https://testMongoEndpoint.azure.com/",
|
mongoEndpoint: "https://testMongoEndpoint.azure.com/",
|
||||||
},
|
},
|
||||||
type: "testType",
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createTestCassandraDatabaseAccount = (): DataModels.DatabaseAccount => {
|
const testCassandraAccount: DataModels.DatabaseAccount = {
|
||||||
return {
|
...testAccount,
|
||||||
id: "testId",
|
|
||||||
kind: "testKind",
|
|
||||||
location: "testLocation",
|
|
||||||
name: "testName",
|
|
||||||
properties: {
|
properties: {
|
||||||
cassandraEndpoint: "https://testCassandraEndpoint.azure.com/",
|
cassandraEndpoint: "https://testCassandraEndpoint.azure.com/",
|
||||||
documentEndpoint: null,
|
|
||||||
gremlinEndpoint: null,
|
|
||||||
tableEndpoint: null,
|
|
||||||
},
|
},
|
||||||
type: "testType",
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createTerminal = (): NotebookTerminalComponent => {
|
const testNotebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo = {
|
||||||
return new NotebookTerminalComponent({
|
authToken: "authToken",
|
||||||
notebookServerInfo: {
|
notebookServerEndpoint: "https://testNotebookServerEndpoint.azure.com",
|
||||||
authToken: "testAuthToken",
|
|
||||||
notebookServerEndpoint: "https://testNotebookServerEndpoint.azure.com/",
|
|
||||||
},
|
|
||||||
databaseAccount: createTestDatabaseAccount(),
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createMongo32Terminal = (): NotebookTerminalComponent => {
|
const testMongoNotebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo = {
|
||||||
return new NotebookTerminalComponent({
|
authToken: "authToken",
|
||||||
notebookServerInfo: {
|
|
||||||
authToken: "testAuthToken",
|
|
||||||
notebookServerEndpoint: "https://testNotebookServerEndpoint.azure.com/mongo",
|
notebookServerEndpoint: "https://testNotebookServerEndpoint.azure.com/mongo",
|
||||||
},
|
|
||||||
databaseAccount: createTestMongo32DatabaseAccount(),
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createMongo36Terminal = (): NotebookTerminalComponent => {
|
const testCassandraNotebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo = {
|
||||||
return new NotebookTerminalComponent({
|
authToken: "authToken",
|
||||||
notebookServerInfo: {
|
|
||||||
authToken: "testAuthToken",
|
|
||||||
notebookServerEndpoint: "https://testNotebookServerEndpoint.azure.com/mongo",
|
|
||||||
},
|
|
||||||
databaseAccount: createTestMongo36DatabaseAccount(),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const createCassandraTerminal = (): NotebookTerminalComponent => {
|
|
||||||
return new NotebookTerminalComponent({
|
|
||||||
notebookServerInfo: {
|
|
||||||
authToken: "testAuthToken",
|
|
||||||
notebookServerEndpoint: "https://testNotebookServerEndpoint.azure.com/cassandra",
|
notebookServerEndpoint: "https://testNotebookServerEndpoint.azure.com/cassandra",
|
||||||
},
|
|
||||||
databaseAccount: createTestCassandraDatabaseAccount(),
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("NotebookTerminalComponent", () => {
|
describe("NotebookTerminalComponent", () => {
|
||||||
it("getTerminalParams: Test for terminal", () => {
|
it("renders terminal", () => {
|
||||||
const terminal: NotebookTerminalComponent = createTerminal();
|
const props: NotebookTerminalComponentProps = {
|
||||||
const params: Map<string, string> = terminal.getTerminalParams();
|
databaseAccount: testAccount,
|
||||||
|
notebookServerInfo: testNotebookServerInfo,
|
||||||
|
};
|
||||||
|
|
||||||
expect(params).toEqual(
|
const wrapper = shallow(<NotebookTerminalComponent {...props} />);
|
||||||
new Map<string, string>([["terminal", "true"]])
|
expect(wrapper).toMatchSnapshot();
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("getTerminalParams: Test for Mongo 3.2 terminal", () => {
|
it("renders mongo 3.2 shell", () => {
|
||||||
const terminal: NotebookTerminalComponent = createMongo32Terminal();
|
const props: NotebookTerminalComponentProps = {
|
||||||
const params: Map<string, string> = terminal.getTerminalParams();
|
databaseAccount: testMongo32Account,
|
||||||
|
notebookServerInfo: testMongoNotebookServerInfo,
|
||||||
|
};
|
||||||
|
|
||||||
expect(params).toEqual(
|
const wrapper = shallow(<NotebookTerminalComponent {...props} />);
|
||||||
new Map<string, string>([
|
expect(wrapper).toMatchSnapshot();
|
||||||
["terminal", "true"],
|
|
||||||
["terminalEndpoint", new URL(terminal.props.databaseAccount.properties.documentEndpoint).host],
|
|
||||||
])
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("getTerminalParams: Test for Mongo 3.6 terminal", () => {
|
it("renders mongo 3.6 shell", () => {
|
||||||
const terminal: NotebookTerminalComponent = createMongo36Terminal();
|
const props: NotebookTerminalComponentProps = {
|
||||||
const params: Map<string, string> = terminal.getTerminalParams();
|
databaseAccount: testMongo36Account,
|
||||||
|
notebookServerInfo: testMongoNotebookServerInfo,
|
||||||
|
};
|
||||||
|
|
||||||
expect(params).toEqual(
|
const wrapper = shallow(<NotebookTerminalComponent {...props} />);
|
||||||
new Map<string, string>([
|
expect(wrapper).toMatchSnapshot();
|
||||||
["terminal", "true"],
|
|
||||||
["terminalEndpoint", new URL(terminal.props.databaseAccount.properties.mongoEndpoint).host],
|
|
||||||
])
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("getTerminalParams: Test for Cassandra terminal", () => {
|
it("renders cassandra shell", () => {
|
||||||
const terminal: NotebookTerminalComponent = createCassandraTerminal();
|
const props: NotebookTerminalComponentProps = {
|
||||||
const params: Map<string, string> = terminal.getTerminalParams();
|
databaseAccount: testCassandraAccount,
|
||||||
|
notebookServerInfo: testCassandraNotebookServerInfo,
|
||||||
|
};
|
||||||
|
|
||||||
expect(params).toEqual(
|
const wrapper = shallow(<NotebookTerminalComponent {...props} />);
|
||||||
new Map<string, string>([
|
expect(wrapper).toMatchSnapshot();
|
||||||
["terminal", "true"],
|
|
||||||
["terminalEndpoint", new URL(terminal.props.databaseAccount.properties.cassandraEndpoint).host],
|
|
||||||
])
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
* Wrapper around Notebook server terminal
|
* Wrapper around Notebook server terminal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import postRobot from "post-robot";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as DataModels from "../../../Contracts/DataModels";
|
import * as DataModels from "../../../Contracts/DataModels";
|
||||||
import * as StringUtils from "../../../Utils/StringUtils";
|
import { TerminalProps } from "../../../Terminal/TerminalProps";
|
||||||
import { userContext } from "../../../UserContext";
|
import { userContext } from "../../../UserContext";
|
||||||
import { TerminalQueryParams } from "../../../Common/Constants";
|
import * as StringUtils from "../../../Utils/StringUtils";
|
||||||
import { handleError } from "../../../Common/ErrorHandlingUtils";
|
|
||||||
|
|
||||||
export interface NotebookTerminalComponentProps {
|
export interface NotebookTerminalComponentProps {
|
||||||
notebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo;
|
notebookServerInfo: DataModels.NotebookWorkspaceConnectionInfo;
|
||||||
|
@ -15,79 +15,69 @@ export interface NotebookTerminalComponentProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class NotebookTerminalComponent extends React.Component<NotebookTerminalComponentProps> {
|
export class NotebookTerminalComponent extends React.Component<NotebookTerminalComponentProps> {
|
||||||
|
private terminalWindow: Window;
|
||||||
|
|
||||||
constructor(props: NotebookTerminalComponentProps) {
|
constructor(props: NotebookTerminalComponentProps) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount(): void {
|
||||||
|
this.sendPropsToTerminalFrame();
|
||||||
|
}
|
||||||
|
|
||||||
public render(): JSX.Element {
|
public render(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className="notebookTerminalContainer">
|
<div className="notebookTerminalContainer">
|
||||||
<iframe
|
<iframe
|
||||||
title="Terminal to Notebook Server"
|
title="Terminal to Notebook Server"
|
||||||
src={NotebookTerminalComponent.createNotebookAppSrc(this.props.notebookServerInfo, this.getTerminalParams())}
|
onLoad={(event) => this.handleFrameLoad(event)}
|
||||||
|
src="terminal.html"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getTerminalParams(): Map<string, string> {
|
handleFrameLoad(event: React.SyntheticEvent<HTMLIFrameElement, Event>): void {
|
||||||
let params: Map<string, string> = new Map<string, string>();
|
this.terminalWindow = (event.target as HTMLIFrameElement).contentWindow;
|
||||||
params.set(TerminalQueryParams.Terminal, "true");
|
this.sendPropsToTerminalFrame();
|
||||||
|
|
||||||
const terminalEndpoint: string = this.tryGetTerminalEndpoint();
|
|
||||||
if (terminalEndpoint) {
|
|
||||||
params.set(TerminalQueryParams.TerminalEndpoint, terminalEndpoint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
sendPropsToTerminalFrame(): void {
|
||||||
|
if (!this.terminalWindow) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
public tryGetTerminalEndpoint(): string | null {
|
const props: TerminalProps = {
|
||||||
let terminalEndpoint: string | null;
|
terminalEndpoint: this.tryGetTerminalEndpoint(),
|
||||||
|
notebookServerEndpoint: this.props.notebookServerInfo?.notebookServerEndpoint,
|
||||||
|
authToken: this.props.notebookServerInfo?.authToken,
|
||||||
|
subscriptionId: userContext.subscriptionId,
|
||||||
|
apiType: userContext.apiType,
|
||||||
|
authType: userContext.authType,
|
||||||
|
databaseAccount: userContext.databaseAccount,
|
||||||
|
};
|
||||||
|
|
||||||
const notebookServerEndpoint: string = this.props.notebookServerInfo.notebookServerEndpoint;
|
postRobot.send(this.terminalWindow, "props", props, {
|
||||||
|
domain: window.location.origin,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public tryGetTerminalEndpoint(): string | undefined {
|
||||||
|
let terminalEndpoint: string | undefined;
|
||||||
|
|
||||||
|
const notebookServerEndpoint = this.props.notebookServerInfo?.notebookServerEndpoint;
|
||||||
if (StringUtils.endsWith(notebookServerEndpoint, "mongo")) {
|
if (StringUtils.endsWith(notebookServerEndpoint, "mongo")) {
|
||||||
let mongoShellEndpoint: string = this.props.databaseAccount.properties.mongoEndpoint;
|
// mongoEndpoint is only available for Mongo 3.6 and higher, fallback to documentEndpoint otherwise
|
||||||
if (!mongoShellEndpoint) {
|
terminalEndpoint =
|
||||||
// mongoEndpoint is only available for Mongo 3.6 and higher.
|
this.props.databaseAccount?.properties.mongoEndpoint || this.props.databaseAccount?.properties.documentEndpoint;
|
||||||
// Fallback to documentEndpoint otherwise.
|
|
||||||
mongoShellEndpoint = this.props.databaseAccount.properties.documentEndpoint;
|
|
||||||
}
|
|
||||||
terminalEndpoint = mongoShellEndpoint;
|
|
||||||
} else if (StringUtils.endsWith(notebookServerEndpoint, "cassandra")) {
|
} else if (StringUtils.endsWith(notebookServerEndpoint, "cassandra")) {
|
||||||
terminalEndpoint = this.props.databaseAccount.properties.cassandraEndpoint;
|
terminalEndpoint = this.props.databaseAccount?.properties.cassandraEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (terminalEndpoint) {
|
if (terminalEndpoint) {
|
||||||
return new URL(terminalEndpoint).host;
|
return new URL(terminalEndpoint).host;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static createNotebookAppSrc(
|
return undefined;
|
||||||
serverInfo: DataModels.NotebookWorkspaceConnectionInfo,
|
|
||||||
params: Map<string, string>
|
|
||||||
): string {
|
|
||||||
if (!serverInfo.notebookServerEndpoint) {
|
|
||||||
handleError(
|
|
||||||
"Notebook server endpoint not defined. Terminal will fail to connect to jupyter server.",
|
|
||||||
"NotebookTerminalComponent/createNotebookAppSrc"
|
|
||||||
);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
params.set(TerminalQueryParams.Server, serverInfo.notebookServerEndpoint);
|
|
||||||
if (serverInfo.authToken && serverInfo.authToken.length > 0) {
|
|
||||||
params.set(TerminalQueryParams.Token, serverInfo.authToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
params.set(TerminalQueryParams.SubscriptionId, userContext.subscriptionId);
|
|
||||||
|
|
||||||
let result: string = "terminal.html?";
|
|
||||||
for (let key of params.keys()) {
|
|
||||||
result += `${key}=${encodeURIComponent(params.get(key))}&`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`NotebookTerminalComponent renders cassandra shell 1`] = `
|
||||||
|
<div
|
||||||
|
className="notebookTerminalContainer"
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
onLoad={[Function]}
|
||||||
|
src="terminal.html"
|
||||||
|
title="Terminal to Notebook Server"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`NotebookTerminalComponent renders mongo 3.2 shell 1`] = `
|
||||||
|
<div
|
||||||
|
className="notebookTerminalContainer"
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
onLoad={[Function]}
|
||||||
|
src="terminal.html"
|
||||||
|
title="Terminal to Notebook Server"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`NotebookTerminalComponent renders mongo 3.6 shell 1`] = `
|
||||||
|
<div
|
||||||
|
className="notebookTerminalContainer"
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
onLoad={[Function]}
|
||||||
|
src="terminal.html"
|
||||||
|
title="Terminal to Notebook Server"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`NotebookTerminalComponent renders terminal 1`] = `
|
||||||
|
<div
|
||||||
|
className="notebookTerminalContainer"
|
||||||
|
>
|
||||||
|
<iframe
|
||||||
|
onLoad={[Function]}
|
||||||
|
src="terminal.html"
|
||||||
|
title="Terminal to Notebook Server"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
`;
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { AuthType } from "../AuthType";
|
||||||
|
import * as DataModels from "../Contracts/DataModels";
|
||||||
|
import { ApiType } from "../UserContext";
|
||||||
|
|
||||||
|
export interface TerminalProps {
|
||||||
|
authToken: string;
|
||||||
|
notebookServerEndpoint: string;
|
||||||
|
terminalEndpoint: string;
|
||||||
|
databaseAccount: DataModels.DatabaseAccount;
|
||||||
|
authType: AuthType;
|
||||||
|
apiType: ApiType;
|
||||||
|
subscriptionId: string;
|
||||||
|
}
|
|
@ -1,43 +1,36 @@
|
||||||
import { ServerConnection } from "@jupyterlab/services";
|
import { ServerConnection } from "@jupyterlab/services";
|
||||||
import "@jupyterlab/terminal/style/index.css";
|
import "@jupyterlab/terminal/style/index.css";
|
||||||
import { HttpHeaders, TerminalQueryParams } from "../Common/Constants";
|
import postRobot from "post-robot";
|
||||||
|
import { HttpHeaders } from "../Common/Constants";
|
||||||
import { Action } from "../Shared/Telemetry/TelemetryConstants";
|
import { Action } from "../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { updateUserContext } from "../UserContext";
|
import { updateUserContext } from "../UserContext";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { JupyterLabAppFactory } from "./JupyterLabAppFactory";
|
import { JupyterLabAppFactory } from "./JupyterLabAppFactory";
|
||||||
|
import { TerminalProps } from "./TerminalProps";
|
||||||
|
|
||||||
const getUrlVars = (): { [key: string]: string } => {
|
const createServerSettings = (props: TerminalProps): ServerConnection.ISettings => {
|
||||||
const vars: { [key: string]: string } = {};
|
|
||||||
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, (_m, key, value): string => {
|
|
||||||
vars[key] = decodeURIComponent(value);
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
return vars;
|
|
||||||
};
|
|
||||||
|
|
||||||
const createServerSettings = (urlVars: { [key: string]: string }): ServerConnection.ISettings => {
|
|
||||||
let body: BodyInit | undefined;
|
let body: BodyInit | undefined;
|
||||||
let headers: HeadersInit | undefined;
|
let headers: HeadersInit | undefined;
|
||||||
if (urlVars.hasOwnProperty(TerminalQueryParams.TerminalEndpoint)) {
|
if (props.terminalEndpoint) {
|
||||||
body = JSON.stringify({
|
body = JSON.stringify({
|
||||||
endpoint: urlVars[TerminalQueryParams.TerminalEndpoint],
|
endpoint: props.terminalEndpoint,
|
||||||
});
|
});
|
||||||
headers = {
|
headers = {
|
||||||
[HttpHeaders.contentType]: "application/json",
|
[HttpHeaders.contentType]: "application/json",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const server = urlVars[TerminalQueryParams.Server];
|
const server = props.notebookServerEndpoint;
|
||||||
let options: Partial<ServerConnection.ISettings> = {
|
let options: Partial<ServerConnection.ISettings> = {
|
||||||
baseUrl: server,
|
baseUrl: server,
|
||||||
init: { body, headers },
|
init: { body, headers },
|
||||||
fetch: window.parent.fetch,
|
fetch: window.parent.fetch,
|
||||||
};
|
};
|
||||||
if (urlVars.hasOwnProperty(TerminalQueryParams.Token)) {
|
if (props.authToken) {
|
||||||
options = {
|
options = {
|
||||||
baseUrl: server,
|
baseUrl: server,
|
||||||
token: urlVars[TerminalQueryParams.Token],
|
token: props.authToken,
|
||||||
appendToken: true,
|
appendToken: true,
|
||||||
init: { body, headers },
|
init: { body, headers },
|
||||||
fetch: window.parent.fetch,
|
fetch: window.parent.fetch,
|
||||||
|
@ -47,30 +40,41 @@ const createServerSettings = (urlVars: { [key: string]: string }): ServerConnect
|
||||||
return ServerConnection.makeSettings(options);
|
return ServerConnection.makeSettings(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
const main = async (): Promise<void> => {
|
const initTerminal = async (props: TerminalProps) => {
|
||||||
const urlVars = getUrlVars();
|
// Initialize userContext (only properties which are needed by TelemetryProcessor)
|
||||||
|
|
||||||
// Initialize userContext. Currently only subscriptionId is required by TelemetryProcessor
|
|
||||||
updateUserContext({
|
updateUserContext({
|
||||||
subscriptionId: urlVars[TerminalQueryParams.SubscriptionId],
|
subscriptionId: props.subscriptionId,
|
||||||
|
apiType: props.apiType,
|
||||||
|
authType: props.authType,
|
||||||
|
databaseAccount: props.databaseAccount,
|
||||||
});
|
});
|
||||||
|
|
||||||
const serverSettings = createServerSettings(urlVars);
|
const serverSettings = createServerSettings(props);
|
||||||
|
|
||||||
const data = { baseUrl: serverSettings.baseUrl };
|
const data = { baseUrl: serverSettings.baseUrl };
|
||||||
const startTime = TelemetryProcessor.traceStart(Action.OpenTerminal, data);
|
const startTime = TelemetryProcessor.traceStart(Action.OpenTerminal, data);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (urlVars.hasOwnProperty(TerminalQueryParams.Terminal)) {
|
|
||||||
await JupyterLabAppFactory.createTerminalApp(serverSettings);
|
await JupyterLabAppFactory.createTerminalApp(serverSettings);
|
||||||
} else {
|
|
||||||
throw new Error("Only terminal is supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
TelemetryProcessor.traceSuccess(Action.OpenTerminal, data, startTime);
|
TelemetryProcessor.traceSuccess(Action.OpenTerminal, data, startTime);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
TelemetryProcessor.traceFailure(Action.OpenTerminal, data, startTime);
|
TelemetryProcessor.traceFailure(Action.OpenTerminal, data, startTime);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const main = async (): Promise<void> => {
|
||||||
|
postRobot.on(
|
||||||
|
"props",
|
||||||
|
{
|
||||||
|
window: window.parent,
|
||||||
|
domain: window.location.origin,
|
||||||
|
},
|
||||||
|
async (event) => {
|
||||||
|
// Typescript definition for event is wrong. So read props by casting to <any>
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const props = (event as any).data as TerminalProps;
|
||||||
|
await initTerminal(props);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
window.addEventListener("load", main);
|
window.addEventListener("load", main);
|
||||||
|
|
Loading…
Reference in New Issue