Skip to content

Commit 4646b4e

Browse files
committed
fix: make slack management routing configurable
1 parent d500c34 commit 4646b4e

6 files changed

Lines changed: 40 additions & 6 deletions

File tree

ui/entrypoint.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ set -eu
44
API_BASE_URL="${SPRITZ_API_BASE_URL:-}"
55
WEBSOCKET_BASE_URL="${SPRITZ_UI_WEBSOCKET_BASE_URL:-}"
66
CHAT_PATH_PREFIX="${SPRITZ_UI_CHAT_PATH_PREFIX:-}"
7+
SLACK_GATEWAY_BASE_PATH="${SPRITZ_UI_SLACK_GATEWAY_BASE_PATH:-}"
78
OWNER_ID="${SPRITZ_UI_OWNER_ID:-}"
89
AUTH_MODE="${SPRITZ_UI_AUTH_MODE:-}"
910
AUTH_TOKEN_STORAGE="${SPRITZ_UI_AUTH_TOKEN_STORAGE:-}"
@@ -38,6 +39,9 @@ fi
3839
if [ -z "$CHAT_PATH_PREFIX" ]; then
3940
CHAT_PATH_PREFIX="/c"
4041
fi
42+
if [ -z "$SLACK_GATEWAY_BASE_PATH" ]; then
43+
SLACK_GATEWAY_BASE_PATH="/slack-gateway"
44+
fi
4145
if [ -z "$ASSET_VERSION" ]; then
4246
ASSET_VERSION="$(date +%s)"
4347
fi
@@ -49,6 +53,7 @@ escape_sed() {
4953
API_BASE_URL_ESCAPED="$(escape_sed "$API_BASE_URL")"
5054
WEBSOCKET_BASE_URL_ESCAPED="$(escape_sed "$WEBSOCKET_BASE_URL")"
5155
CHAT_PATH_PREFIX_ESCAPED="$(escape_sed "$CHAT_PATH_PREFIX")"
56+
SLACK_GATEWAY_BASE_PATH_ESCAPED="$(escape_sed "$SLACK_GATEWAY_BASE_PATH")"
5257
OWNER_ID_ESCAPED="$(escape_sed "$OWNER_ID")"
5358
AUTH_MODE_ESCAPED="$(escape_sed "$AUTH_MODE")"
5459
AUTH_TOKEN_STORAGE_ESCAPED="$(escape_sed "$AUTH_TOKEN_STORAGE")"
@@ -80,6 +85,7 @@ ASSET_VERSION_ESCAPED="$(escape_sed "$ASSET_VERSION")"
8085
sed "s|__SPRITZ_API_BASE_URL__|${API_BASE_URL_ESCAPED}|g" "${HTML_DIR}/config.js" \
8186
| sed "s|__SPRITZ_UI_WEBSOCKET_BASE_URL__|${WEBSOCKET_BASE_URL_ESCAPED}|g" \
8287
| sed "s|__SPRITZ_UI_CHAT_PATH_PREFIX__|${CHAT_PATH_PREFIX_ESCAPED}|g" \
88+
| sed "s|__SPRITZ_UI_SLACK_GATEWAY_BASE_PATH__|${SLACK_GATEWAY_BASE_PATH_ESCAPED}|g" \
8389
| sed "s|__SPRITZ_OWNER_ID__|${OWNER_ID_ESCAPED}|g" \
8490
| sed "s|__SPRITZ_UI_AUTH_MODE__|${AUTH_MODE_ESCAPED}|g" \
8591
| sed "s|__SPRITZ_UI_AUTH_TOKEN_STORAGE__|${AUTH_TOKEN_STORAGE_ESCAPED}|g" \

ui/public/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ window.SPRITZ_CONFIG = {
22
apiBaseUrl: '__SPRITZ_API_BASE_URL__',
33
websocketBaseUrl: '__SPRITZ_UI_WEBSOCKET_BASE_URL__',
44
chatPathPrefix: '__SPRITZ_UI_CHAT_PATH_PREFIX__',
5+
slackGatewayBasePath: '__SPRITZ_UI_SLACK_GATEWAY_BASE_PATH__',
56
ownerId: '__SPRITZ_OWNER_ID__',
67
presets: __SPRITZ_UI_PRESETS__,
78
repoDefaults: {

ui/src/App.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { CreatePage } from '@/pages/create';
88
import { SettingsPage } from '@/pages/settings';
99
import { TerminalPage } from '@/pages/terminal';
1010
import { chatCatchAllRoutePath } from '@/lib/urls';
11+
import { slackGatewayBasePath } from '@/lib/slack-management';
1112

1213
/**
1314
* Maps legacy SPA-mounted Slack gateway paths to the real server-rendered
@@ -18,7 +19,12 @@ export function buildLegacySlackGatewayRedirectURL(
1819
search: string,
1920
hash: string,
2021
): string {
21-
const nextPath = pathname.startsWith('/spritz/') ? pathname.slice('/spritz'.length) : pathname;
22+
const legacyPrefix = '/spritz/slack-gateway';
23+
const nextPath = pathname.startsWith(legacyPrefix)
24+
? `${slackGatewayBasePath()}${pathname.slice(legacyPrefix.length)}`
25+
: pathname.startsWith('/spritz/')
26+
? pathname.slice('/spritz'.length)
27+
: pathname;
2228
return `${nextPath}${search}${hash}`;
2329
}
2430

@@ -35,9 +41,14 @@ function LegacySlackGatewayRedirectPage() {
3541
const location = useLocation();
3642

3743
if (typeof window !== 'undefined') {
38-
browserLocation.replace(
39-
buildLegacySlackGatewayRedirectURL(location.pathname, location.search, location.hash),
44+
const redirectURL = buildLegacySlackGatewayRedirectURL(
45+
location.pathname,
46+
location.search,
47+
location.hash,
4048
);
49+
if (redirectURL !== `${location.pathname}${location.search}${location.hash}`) {
50+
browserLocation.replace(redirectURL);
51+
}
4152
}
4253

4354
return null;

ui/src/lib/config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export interface SpritzConfig {
8484
apiBaseUrl: string;
8585
websocketBaseUrl: string;
8686
chatPathPrefix: string;
87+
slackGatewayBasePath: string;
8788
ownerId: string;
8889
presets: Preset[] | string;
8990
repoDefaults: RepoDefaults;
@@ -105,6 +106,7 @@ export function resolveConfig(raw: RawSpritzConfig = {}): SpritzConfig {
105106
apiBaseUrl: raw.apiBaseUrl || '',
106107
websocketBaseUrl: raw.websocketBaseUrl || '',
107108
chatPathPrefix: raw.chatPathPrefix || '/c',
109+
slackGatewayBasePath: raw.slackGatewayBasePath || '/slack-gateway',
108110
ownerId: raw.ownerId || '',
109111
presets: raw.presets || [],
110112
repoDefaults: {

ui/src/lib/slack-management.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { config } from './config';
2+
13
export interface SlackInstallTargetProfile {
24
name: string;
35
imageUrl?: string;
@@ -81,7 +83,18 @@ export interface SlackWorkspaceTestResult {
8183
postedMessageTs?: string;
8284
}
8385

84-
const SLACK_GATEWAY_BASE_PATH = '/slack-gateway';
86+
export function slackGatewayBasePath(): string {
87+
const normalized = String(config.slackGatewayBasePath || '/slack-gateway')
88+
.trim()
89+
.replace(/\/+$/g, '');
90+
if (!normalized) return '/slack-gateway';
91+
return normalized.startsWith('/') ? normalized : `/${normalized}`;
92+
}
93+
94+
export function slackGatewayPath(path: string): string {
95+
const normalizedPath = `/${String(path || '').replace(/^\/+/g, '')}`;
96+
return `${slackGatewayBasePath()}${normalizedPath}`;
97+
}
8598

8699
async function parseGatewayResponse(res: Response): Promise<unknown> {
87100
const text = await res.text();
@@ -110,7 +123,7 @@ export async function slackGatewayRequest<T>(
110123
if (options.body && !headers.has('Content-Type')) {
111124
headers.set('Content-Type', 'application/json');
112125
}
113-
const res = await fetch(`${SLACK_GATEWAY_BASE_PATH}${path}`, {
126+
const res = await fetch(slackGatewayPath(path), {
114127
credentials: 'include',
115128
...options,
116129
headers,

ui/src/pages/settings.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
installationRoutePath,
2424
primaryConnection,
2525
slackGatewayRequest,
26+
slackGatewayPath,
2627
type SlackInstallResult,
2728
type SlackInstallSelection,
2829
type SlackInstallTarget,
@@ -213,7 +214,7 @@ function WorkspaceListPage() {
213214
title="Slack Workspaces"
214215
description="Manage workspace-level Slack app installations and their selected targets."
215216
action={
216-
<a href="/slack-gateway/slack/install" className={buttonVariants({ size: 'lg' })}>
217+
<a href={slackGatewayPath('/slack/install')} className={buttonVariants({ size: 'lg' })}>
217218
<PlugIcon aria-hidden="true" />
218219
Install
219220
</a>

0 commit comments

Comments
 (0)