feat: allow magic string to generate session token for external apps (#9878)

* fix: make non-http external app links open in the current window

* Allow magic string to be replaced with a session token for external apps

* Improve readibility
This commit is contained in:
Kyle Carberry
2023-09-26 16:04:24 -05:00
committed by GitHub
parent 75366ec6b5
commit 726a4dadf2
@@ -4,7 +4,7 @@ import { makeStyles } from "@mui/styles";
import Tooltip from "@mui/material/Tooltip";
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
import { PrimaryAgentButton } from "components/Resources/AgentButton";
import { FC } from "react";
import { FC, useState } from "react";
import { combineClasses } from "utils/combineClasses";
import * as TypesGen from "../../../api/typesGenerated";
import { generateRandomString } from "../../../utils/random";
@@ -12,6 +12,7 @@ import { BaseIcon } from "./BaseIcon";
import { ShareIcon } from "./ShareIcon";
import { useProxy } from "contexts/ProxyContext";
import { createAppLinkHref } from "utils/apps";
import { getApiKey } from "api/api";
const Language = {
appTitle: (appName: string, identifier: string): string =>
@@ -28,6 +29,7 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
const { proxy } = useProxy();
const preferredPathBase = proxy.preferredPathAppURL;
const appsHost = proxy.preferredWildcardHostname;
const [fetchingSessionToken, setFetchingSessionToken] = useState(false);
const styles = useStyles();
const username = workspace.owner_name;
@@ -72,6 +74,9 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
primaryTooltip =
"Your admin has not configured subdomain application access";
}
if (fetchingSessionToken) {
canClick = false;
}
const isPrivateApp = app.sharing_level === "owner";
@@ -96,13 +101,38 @@ export const AppLink: FC<AppLinkProps> = ({ app, workspace, agent }) => {
className={canClick ? styles.link : styles.disabledLink}
onClick={
canClick
? (event) => {
? async (event) => {
event.preventDefault();
window.open(
href,
Language.appTitle(appDisplayName, generateRandomString(12)),
"width=900,height=600",
);
// This is an external URI like "vscode://", so
// it needs to be opened with the browser protocol handler.
if (app.external && !app.url.startsWith("http")) {
// If the protocol is external the browser does not
// redirect the user from the page.
// This is a magic undocumented string that is replaced
// with a brand-new session token from the backend.
// This only exists for external URLs, and should only
// be used internally, and is highly subject to break.
const magicTokenString = "$SESSION_TOKEN";
const hasMagicToken = href.indexOf(magicTokenString);
let url = href;
if (hasMagicToken !== -1) {
setFetchingSessionToken(true);
const key = await getApiKey();
url = href.replaceAll(magicTokenString, key.key);
setFetchingSessionToken(false);
}
window.location.href = url;
} else {
window.open(
href,
Language.appTitle(
appDisplayName,
generateRandomString(12),
),
"width=900,height=600",
);
}
}
: undefined
}