mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
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:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user