1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Convert shell authentication IPC to injectable RequestChannel

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-06-03 13:18:54 -04:00
parent 78ead4f2b9
commit ea8c262d3c
20 changed files with 54 additions and 110 deletions

View File

@ -4,9 +4,9 @@
*/ */
import { getInjectionToken } from "@ogre-tools/injectable"; import { getInjectionToken } from "@ogre-tools/injectable";
import type { JsonValue } from "type-fest"; import type { IpcValue } from "./allowed-types";
export interface MessageChannel<Message extends JsonValue | void = void> { export interface MessageChannel<Message extends IpcValue | void = void> {
id: string; id: string;
_messageSignature?: Message; _messageSignature?: Message;
} }

View File

@ -4,20 +4,16 @@
*/ */
import { getInjectionToken } from "@ogre-tools/injectable"; import { getInjectionToken } from "@ogre-tools/injectable";
import type { SetRequired } from "type-fest"; import type { SetRequired } from "type-fest";
import type { IpcValue } from "./allowed-types";
import type { MessageChannel } from "./message-channel-injection-token"; import type { MessageChannel } from "./message-channel-injection-token";
export interface MessageToChannel { export interface MessageToChannel {
<TChannel extends MessageChannel<TMessage>, TMessage extends void>( <Channel extends MessageChannel<void>>(channel: Channel): void;
channel: TChannel, <
): void; Channel extends MessageChannel<IpcValue>,
Message = SetRequired<Channel, "_messageSignature">["_messageSignature"],
<TChannel extends MessageChannel<any>>( >(channel: Channel, message: Message): void;
channel: TChannel,
message: SetRequired<TChannel, "_messageSignature">["_messageSignature"],
): void;
} }
export const messageToChannelInjectionToken = getInjectionToken<MessageToChannel>({
export const messageToChannelInjectionToken = id: "message-to-message-channel",
getInjectionToken<MessageToChannel>({ });
id: "message-to-message-channel",
});

View File

@ -4,6 +4,7 @@
*/ */
import { getInjectionToken } from "@ogre-tools/injectable"; import { getInjectionToken } from "@ogre-tools/injectable";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
export interface SyncBox<Value> { export interface SyncBox<Value> {
id: string; id: string;
value: IComputedValue<Value>; value: IComputedValue<Value>;

View File

@ -1,15 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { pipeline } from "@ogre-tools/fp";
import { defaultTo } from "lodash/fp";
import { withErrorSuppression } from "./with-error-suppression/with-error-suppression";
export const tentativeParseJson = (toBeParsed: any) => pipeline(
toBeParsed,
withErrorSuppression(JSON.parse),
defaultTo(toBeParsed),
);

View File

@ -1,15 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { pipeline } from "@ogre-tools/fp";
import { defaultTo } from "lodash/fp";
import { withErrorSuppression } from "./with-error-suppression/with-error-suppression";
export const tentativeStringifyJson = (toBeParsed: any) => pipeline(
toBeParsed,
withErrorSuppression(JSON.stringify),
defaultTo(toBeParsed),
);

View File

@ -22,7 +22,7 @@ const lensProxyPortInjectable = getInjectable({
}, },
set: (port: number) => { set: (port: number) => {
if (port) { if (portNumber) {
throw new Error( throw new Error(
"Tried to set port number for LensProxy when it has already been set.", "Tried to set port number for LensProxy when it has already been set.",
); );

View File

@ -86,7 +86,7 @@ export class LensProxy {
const reqHandler = isInternal ? dependencies.shellApiRequest : dependencies.kubeApiUpgradeRequest; const reqHandler = isInternal ? dependencies.shellApiRequest : dependencies.kubeApiUpgradeRequest;
(async () => reqHandler({ req, socket, head, cluster }))() (async () => reqHandler({ req, socket, head, cluster }))()
.catch(error => logger.error("[LENS-PROXY]: failed to handle proxy upgrade", error)); .catch(error => logger.error(`[LENS-PROXY]: failed to handle proxy upgrade: ${error}`));
} }
}); });
} }

View File

@ -21,7 +21,7 @@ const shellApiRequestInjectable = getInjectable({
return ({ req, socket, head }) => { return ({ req, socket, head }) => {
const cluster = getClusterForRequest(req); const cluster = getClusterForRequest(req);
const { searchParams } = new URL(req.url); const { searchParams } = new URL(req.url, "https://127.0.0.1");
const nodeName = searchParams.get("node") || undefined; const nodeName = searchParams.get("node") || undefined;
const shellToken = searchParams.get("shellToken"); const shellToken = searchParams.get("shellToken");
const tabId = searchParams.get("id"); const tabId = searchParams.get("id");

View File

@ -6,8 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
import type { IpcMainEvent } from "electron"; import type { IpcMainEvent } from "electron";
import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable";
import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token";
import { pipeline } from "@ogre-tools/fp"; import { toJS } from "../../../../renderer/utils";
import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json";
const enlistMessageChannelListenerInjectable = getInjectable({ const enlistMessageChannelListenerInjectable = getInjectable({
id: "enlist-message-channel-listener-for-main", id: "enlist-message-channel-listener-for-main",
@ -16,13 +15,7 @@ const enlistMessageChannelListenerInjectable = getInjectable({
const ipcMain = di.inject(ipcMainInjectable); const ipcMain = di.inject(ipcMainInjectable);
return ({ channel, handler }) => { return ({ channel, handler }) => {
const nativeOnCallback = (_: IpcMainEvent, message: unknown) => { const nativeOnCallback = (_: IpcMainEvent, message: unknown) => toJS(handler(message));
pipeline(
message,
tentativeParseJson,
handler,
);
};
ipcMain.on(channel.id, nativeOnCallback); ipcMain.on(channel.id, nativeOnCallback);

View File

@ -6,9 +6,7 @@ import { getInjectable } from "@ogre-tools/injectable";
import type { IpcMainInvokeEvent } from "electron"; import type { IpcMainInvokeEvent } from "electron";
import ipcMainInjectable from "../ipc-main/ipc-main.injectable"; import ipcMainInjectable from "../ipc-main/ipc-main.injectable";
import { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token"; import { enlistRequestChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-request-channel-listener-injection-token";
import { pipeline } from "@ogre-tools/fp"; import { toJS } from "../../../../renderer/utils";
import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json";
import { tentativeStringifyJson } from "../../../../common/utils/tentative-stringify-json";
const enlistRequestChannelListenerInjectable = getInjectable({ const enlistRequestChannelListenerInjectable = getInjectable({
id: "enlist-request-channel-listener-for-main", id: "enlist-request-channel-listener-for-main",
@ -17,8 +15,7 @@ const enlistRequestChannelListenerInjectable = getInjectable({
const ipcMain = di.inject(ipcMainInjectable); const ipcMain = di.inject(ipcMainInjectable);
return ({ channel, handler }) => { return ({ channel, handler }) => {
const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => const nativeHandleCallback = (_: IpcMainInvokeEvent, request: unknown) => toJS(handler(request));
pipeline(request, tentativeParseJson, handler, tentativeStringifyJson);
ipcMain.handle(channel.id, nativeHandleCallback); ipcMain.handle(channel.id, nativeHandleCallback);

View File

@ -4,9 +4,8 @@
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token";
import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json";
import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable"; import getVisibleWindowsInjectable from "../../start-main-application/lens-window/get-visible-windows.injectable";
import type { MessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token";
const messageToChannelInjectable = getInjectable({ const messageToChannelInjectable = getInjectable({
id: "message-to-channel", id: "message-to-channel",
@ -14,15 +13,14 @@ const messageToChannelInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const getVisibleWindows = di.inject(getVisibleWindowsInjectable); const getVisibleWindows = di.inject(getVisibleWindowsInjectable);
// TODO: Figure out way to improve typing in internals return ((channel, message) => {
// Notice that this should be injected using "messageToChannelInjectionToken" which is typed correctly. for (const window of getVisibleWindows()) {
return (channel: MessageChannel<any>, message?: unknown) => { window.send({
const stringifiedMessage = tentativeStringifyJson(message); channel: channel.id,
data: message !== undefined ? [message] : [],
getVisibleWindows().forEach((lensWindow) => });
lensWindow.send({ channel: channel.id, data: stringifiedMessage ? [stringifiedMessage] : [] }), }
); }) as MessageToChannel;
};
}, },
injectionToken: messageToChannelInjectionToken, injectionToken: messageToChannelInjectionToken,

View File

@ -5,6 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import hostedClusterIdInjectable from "../cluster-frame-context/hosted-cluster-id.injectable"; import hostedClusterIdInjectable from "../cluster-frame-context/hosted-cluster-id.injectable";
import getShellAuthTokenInjectable from "../../common/shell-authentication/get-auth-token.injectable";
import type { TerminalApiQuery } from "./terminal-api"; import type { TerminalApiQuery } from "./terminal-api";
import { TerminalApi } from "./terminal-api"; import { TerminalApi } from "./terminal-api";
@ -14,12 +15,14 @@ const createTerminalApiInjectable = getInjectable({
id: "create-terminal-api", id: "create-terminal-api",
instantiate: (di): CreateTerminalApi => { instantiate: (di): CreateTerminalApi => {
const hostedClusterId = di.inject(hostedClusterIdInjectable); const hostedClusterId = di.inject(hostedClusterIdInjectable);
const getShellAuthToken = di.inject(getShellAuthTokenInjectable);
return (query) => { return (query) => {
assert(hostedClusterId, "Can only create terminal APIs within a cluster frame"); assert(hostedClusterId, "Can only create terminal APIs within a cluster frame");
return new TerminalApi({ return new TerminalApi({
hostedClusterId, hostedClusterId,
getShellAuthToken,
}, query); }, query);
}; };
}, },

View File

@ -71,6 +71,8 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
clusterId: this.dependencies.hostedClusterId, clusterId: this.dependencies.hostedClusterId,
tabId: this.query.id, tabId: this.query.id,
}); });
console.log("authTokenArray", authTokenArray);
const { hostname, protocol, port } = location; const { hostname, protocol, port } = location;
const socketUrl = url.format({ const socketUrl = url.format({
protocol: protocol.includes("https") ? "wss" : "ws", protocol: protocol.includes("https") ? "wss" : "ws",

View File

@ -6,8 +6,6 @@ import ipcRendererInjectable from "../ipc-renderer.injectable";
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { IpcRendererEvent } from "electron"; import type { IpcRendererEvent } from "electron";
import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token"; import { enlistMessageChannelListenerInjectionToken } from "../../../../common/utils/channel/enlist-message-channel-listener-injection-token";
import { tentativeParseJson } from "../../../../common/utils/tentative-parse-json";
import { pipeline } from "@ogre-tools/fp";
const enlistMessageChannelListenerInjectable = getInjectable({ const enlistMessageChannelListenerInjectable = getInjectable({
id: "enlist-message-channel-listener-for-renderer", id: "enlist-message-channel-listener-for-renderer",
@ -16,13 +14,7 @@ const enlistMessageChannelListenerInjectable = getInjectable({
const ipcRenderer = di.inject(ipcRendererInjectable); const ipcRenderer = di.inject(ipcRendererInjectable);
return ({ channel, handler }) => { return ({ channel, handler }) => {
const nativeCallback = (_: IpcRendererEvent, message: unknown) => { const nativeCallback = (_: IpcRendererEvent, message: unknown) => handler(message);
pipeline(
message,
tentativeParseJson,
handler,
);
};
ipcRenderer.on(channel.id, nativeCallback); ipcRenderer.on(channel.id, nativeCallback);

View File

@ -3,9 +3,9 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { MessageToChannel } from "../../../common/utils/channel/message-to-channel-injection-token";
import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token"; import { messageToChannelInjectionToken } from "../../../common/utils/channel/message-to-channel-injection-token";
import sendToMainInjectable from "./send-to-main.injectable"; import sendToMainInjectable from "./send-to-main.injectable";
import type { MessageChannel } from "../../../common/utils/channel/message-channel-injection-token";
const messageToChannelInjectable = getInjectable({ const messageToChannelInjectable = getInjectable({
id: "message-to-channel", id: "message-to-channel",
@ -13,11 +13,9 @@ const messageToChannelInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const sendToMain = di.inject(sendToMainInjectable); const sendToMain = di.inject(sendToMainInjectable);
// TODO: Figure out way to improve typing in internals return ((channel, message) => {
// Notice that this should be injected using "messageToChannelInjectionToken" which is typed correctly.
return (channel: MessageChannel<any>, message?: unknown) => {
sendToMain(channel.id, message); sendToMain(channel.id, message);
}; }) as MessageToChannel;
}, },
injectionToken: messageToChannelInjectionToken, injectionToken: messageToChannelInjectionToken,

View File

@ -5,9 +5,7 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import ipcRendererInjectable from "./ipc-renderer.injectable"; import ipcRendererInjectable from "./ipc-renderer.injectable";
import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token"; import { requestFromChannelInjectionToken } from "../../../common/utils/channel/request-from-channel-injection-token";
import { pipeline } from "@ogre-tools/fp"; import type { RequestChannel } from "../../../common/utils/channel/request-channel-injection-token";
import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json";
import { tentativeParseJson } from "../../../common/utils/tentative-parse-json";
const requestFromChannelInjectable = getInjectable({ const requestFromChannelInjectable = getInjectable({
id: "request-from-channel", id: "request-from-channel",
@ -15,13 +13,11 @@ const requestFromChannelInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const ipcRenderer = di.inject(ipcRendererInjectable); const ipcRenderer = di.inject(ipcRendererInjectable);
return async (channel, ...[request]) => return async (channel, ...[request]) => {
await pipeline( const { id } = channel as unknown as RequestChannel<any, any>;
request,
tentativeStringifyJson, return ipcRenderer.invoke(id, request);
(req) => ipcRenderer.invoke(channel.id, req), };
tentativeParseJson,
);
}, },
injectionToken: requestFromChannelInjectionToken, injectionToken: requestFromChannelInjectionToken,

View File

@ -3,9 +3,7 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { JsonValue } from "type-fest";
import ipcRendererInjectable from "./ipc-renderer.injectable"; import ipcRendererInjectable from "./ipc-renderer.injectable";
import { tentativeStringifyJson } from "../../../common/utils/tentative-stringify-json";
const sendToMainInjectable = getInjectable({ const sendToMainInjectable = getInjectable({
id: "send-to-main", id: "send-to-main",
@ -13,11 +11,8 @@ const sendToMainInjectable = getInjectable({
instantiate: (di) => { instantiate: (di) => {
const ipcRenderer = di.inject(ipcRendererInjectable); const ipcRenderer = di.inject(ipcRendererInjectable);
// TODO: Figure out way to improve typing in internals return (channelId: string, message: unknown) => {
return <T>(channelId: string, message: JsonValue extends T ? T : never ) => { ipcRenderer.send(channelId, message);
const stringifiedMessage = tentativeStringifyJson(message);
ipcRenderer.send(channelId, ...(stringifiedMessage ? [stringifiedMessage] : []));
}; };
}, },
}); });

View File

@ -20,6 +20,11 @@ const provideInitialValuesForSyncBoxesInjectable = getInjectable({
run: async () => { run: async () => {
const initialValues = await requestFromChannel(syncBoxInitialValueChannel); const initialValues = await requestFromChannel(syncBoxInitialValueChannel);
console.log({
initialValues,
type: typeof initialValues,
});
initialValues.forEach(({ id, value }) => { initialValues.forEach(({ id, value }) => {
setSyncBoxState(id, value); setSyncBoxState(id, value);
}); });

View File

@ -9,7 +9,6 @@ import type { SendToViewArgs } from "../../main/start-main-application/lens-wind
import enlistMessageChannelListenerInjectableInRenderer from "../../renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable"; import enlistMessageChannelListenerInjectableInRenderer from "../../renderer/utils/channel/channel-listeners/enlist-message-channel-listener.injectable";
import type { DiContainer } from "@ogre-tools/injectable"; import type { DiContainer } from "@ogre-tools/injectable";
import assert from "assert"; import assert from "assert";
import { tentativeParseJson } from "../../common/utils/tentative-parse-json";
export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => { export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => {
const messageChannelListenerFakesForRenderer = new Map< const messageChannelListenerFakesForRenderer = new Map<
@ -48,9 +47,7 @@ export const overrideMessagingFromMainToWindow = (mainDi: DiContainer) => {
); );
} }
const message = tentativeParseJson(data[0]); listeners.forEach((listener) => listener.handler(data[0]));
listeners.forEach((listener) => listener.handler(message));
}, },
); );

View File

@ -44,11 +44,12 @@ export const overrideRequestingFromWindowToMain = (mainDi: DiContainer) => {
requestFromChannelInjectable, requestFromChannelInjectable,
() => async (channel, ...[request]) => { () => async (channel, ...[request]) => {
const requestListener = requestChannelListenerFakesForMain.get(channel.id); const { id } = channel as unknown as RequestChannel<any, any>;
const requestListener = requestChannelListenerFakesForMain.get(id);
if (!requestListener) { if (!requestListener) {
throw new Error( throw new Error(
`Tried to get value from channel "${channel.id}", but no listeners were registered`, `Tried to get value from channel "${id}", but no listeners were registered`,
); );
} }