From 248f17946042bb244d22a3927f8f7c7128a60b8a Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 21 Mar 2025 18:46:22 +0000 Subject: [PATCH 1/2] fix(cli): replace $SESSION_TOKEN placeholder for external apps --- cli/open.go | 18 +++++++++++++++++- cli/open_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/cli/open.go b/cli/open.go index 10a58f1c3693a..9e70cdd37b253 100644 --- a/cli/open.go +++ b/cli/open.go @@ -301,6 +301,10 @@ func (r *RootCmd) openApp() *serpent.Command { pathAppURL := strings.TrimPrefix(region.PathAppURL, baseURL.String()) appURL := buildAppLinkURL(baseURL, ws, agt, foundApp, region.WildcardHostname, pathAppURL) + if foundApp.External { + appURL = replacePlaceholderExternalSessionTokenString(client, appURL) + } + // Check if we're inside a workspace. Generally, we know // that if we're inside a workspace, `open` can't be used. insideAWorkspace := inv.Environ.Get("CODER") == "true" @@ -314,7 +318,7 @@ func (r *RootCmd) openApp() *serpent.Command { if !testOpenError { err = open.Run(appURL) } else { - err = xerrors.New("test.open-error") + err = xerrors.New("test.open-error: " + appURL) } return err }, @@ -511,3 +515,15 @@ func buildAppLinkURL(baseURL *url.URL, workspace codersdk.Workspace, agent coder } return u.String() } + +// replacePlaceholderExternalSessionTokenString replaces any $SESSION_TOKEN +// strings in the URL with the actual session token. +// This is consistent behaviour with the frontend. See: site/src/modules/resources/AppLink/AppLink.tsx +func replacePlaceholderExternalSessionTokenString(client *codersdk.Client, appURL string) string { + if !strings.Contains(appURL, "$SESSION_TOKEN") { + return appURL + } + + // We will just re-use the existing session token we're already using. + return strings.ReplaceAll(appURL, "$SESSION_TOKEN", client.SessionToken()) +} diff --git a/cli/open_test.go b/cli/open_test.go index 23a4316b75c31..e36d20a59aaf4 100644 --- a/cli/open_test.go +++ b/cli/open_test.go @@ -381,4 +381,29 @@ func TestOpenApp(t *testing.T) { w.RequireError() w.RequireContains("region not found") }) + + t.Run("ExternalAppSessionToken", func(t *testing.T) { + t.Parallel() + + client, ws, _ := setupWorkspaceForAgent(t, func(agents []*proto.Agent) []*proto.Agent { + agents[0].Apps = []*proto.App{ + { + Slug: "app1", + Url: "https://example.com/app1?token=$SESSION_TOKEN", + External: true, + }, + } + return agents + }) + inv, root := clitest.New(t, "open", "app", ws.Name, "app1", "--test.open-error") + clitest.SetupConfig(t, client, root) + pty := ptytest.New(t) + inv.Stdin = pty.Input() + inv.Stdout = pty.Output() + + w := clitest.StartWithWaiter(t, inv) + w.RequireError() + w.RequireContains("test.open-error") + w.RequireContains(client.SessionToken()) + }) } From 5e7fc661d7b66b4bd7682789b016da28f46ade17 Mon Sep 17 00:00:00 2001 From: Cian Johnston Date: Fri, 21 Mar 2025 20:32:14 +0000 Subject: [PATCH 2/2] i can spel gud --- cli/open.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/open.go b/cli/open.go index 9e70cdd37b253..ef62e1542d0bf 100644 --- a/cli/open.go +++ b/cli/open.go @@ -518,7 +518,7 @@ func buildAppLinkURL(baseURL *url.URL, workspace codersdk.Workspace, agent coder // replacePlaceholderExternalSessionTokenString replaces any $SESSION_TOKEN // strings in the URL with the actual session token. -// This is consistent behaviour with the frontend. See: site/src/modules/resources/AppLink/AppLink.tsx +// This is consistent behavior with the frontend. See: site/src/modules/resources/AppLink/AppLink.tsx func replacePlaceholderExternalSessionTokenString(client *codersdk.Client, appURL string) string { if !strings.Contains(appURL, "$SESSION_TOKEN") { return appURL