@sentry/junior-dashboard 0.97.0 → 0.97.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +32 -7
- package/dist/index.js +32 -7
- package/package.json +3 -3
- package/src/app.ts +48 -6
- package/src/url.ts +1 -4
package/dist/app.js
CHANGED
|
@@ -54,7 +54,7 @@ function stripTrailingSlashes(value) {
|
|
|
54
54
|
return end === value.length ? value : value.slice(0, end);
|
|
55
55
|
}
|
|
56
56
|
function resolveDashboardBaseURL(config = {}) {
|
|
57
|
-
const explicit = config.baseURL ?? process.env.
|
|
57
|
+
const explicit = config.baseURL ?? process.env.JUNIOR_BASE_URL;
|
|
58
58
|
if (explicit?.trim()) {
|
|
59
59
|
return stripTrailingSlashes(withHttps(explicit.trim()));
|
|
60
60
|
}
|
|
@@ -1912,9 +1912,9 @@ function requestedReturnPath(url, basePath) {
|
|
|
1912
1912
|
}
|
|
1913
1913
|
return `${returnUrl.pathname}${returnUrl.search}`;
|
|
1914
1914
|
}
|
|
1915
|
-
function dashboardLoginUrl(request, basePath) {
|
|
1915
|
+
function dashboardLoginUrl(request, basePath, canonicalBaseURL) {
|
|
1916
1916
|
const requestUrl = new URL(request.url);
|
|
1917
|
-
const url = new URL(request.url);
|
|
1917
|
+
const url = canonicalBaseURL ? new URL(canonicalBaseURL) : new URL(request.url);
|
|
1918
1918
|
url.pathname = dashboardLoginPath(basePath);
|
|
1919
1919
|
url.search = "";
|
|
1920
1920
|
const returnPath = dashboardReturnPath(requestUrl, basePath);
|
|
@@ -1923,6 +1923,19 @@ function dashboardLoginUrl(request, basePath) {
|
|
|
1923
1923
|
}
|
|
1924
1924
|
return url.toString();
|
|
1925
1925
|
}
|
|
1926
|
+
function canonicalLoginUrl(request, canonicalBaseURL) {
|
|
1927
|
+
if (!canonicalBaseURL) {
|
|
1928
|
+
return void 0;
|
|
1929
|
+
}
|
|
1930
|
+
const requestUrl = new URL(request.url);
|
|
1931
|
+
const canonicalUrl = new URL(canonicalBaseURL);
|
|
1932
|
+
if (requestUrl.origin === canonicalUrl.origin) {
|
|
1933
|
+
return void 0;
|
|
1934
|
+
}
|
|
1935
|
+
canonicalUrl.pathname = requestUrl.pathname;
|
|
1936
|
+
canonicalUrl.search = requestUrl.search;
|
|
1937
|
+
return canonicalUrl.toString();
|
|
1938
|
+
}
|
|
1926
1939
|
function dashboardLoginPath(basePath) {
|
|
1927
1940
|
return basePath === "/" ? "/auth/login" : `${basePath}/auth/login`;
|
|
1928
1941
|
}
|
|
@@ -1950,11 +1963,14 @@ function isAuthorized(session, allowedDomains, allowedEmails) {
|
|
|
1950
1963
|
session.user.emailVerified && domain && allowedDomains.includes(domain)
|
|
1951
1964
|
);
|
|
1952
1965
|
}
|
|
1953
|
-
function unauthorized(request, basePath) {
|
|
1966
|
+
function unauthorized(request, basePath, canonicalBaseURL) {
|
|
1954
1967
|
if (isJsonRoute(new URL(request.url).pathname)) {
|
|
1955
1968
|
return Response.json({ error: "unauthenticated" }, { status: 401 });
|
|
1956
1969
|
}
|
|
1957
|
-
return Response.redirect(
|
|
1970
|
+
return Response.redirect(
|
|
1971
|
+
dashboardLoginUrl(request, basePath, canonicalBaseURL),
|
|
1972
|
+
302
|
|
1973
|
+
);
|
|
1958
1974
|
}
|
|
1959
1975
|
function forbidden(request) {
|
|
1960
1976
|
if (!isJsonRoute(new URL(request.url).pathname)) {
|
|
@@ -2163,6 +2179,11 @@ function createDashboardApp(rawOptions) {
|
|
|
2163
2179
|
const allowedDomains = normalizeValues(options.allowedGoogleDomains);
|
|
2164
2180
|
const allowedEmails = normalizeValues(options.allowedEmails);
|
|
2165
2181
|
const authRequired = options.authRequired !== false;
|
|
2182
|
+
const configuredBaseURL = options.baseURL ?? process.env.JUNIOR_BASE_URL;
|
|
2183
|
+
let canonicalBaseURL;
|
|
2184
|
+
if (authRequired && (configuredBaseURL || !options.auth)) {
|
|
2185
|
+
canonicalBaseURL = resolveDashboardBaseURL({ baseURL: configuredBaseURL });
|
|
2186
|
+
}
|
|
2166
2187
|
if (authRequired && allowedDomains.length === 0 && allowedEmails.length === 0) {
|
|
2167
2188
|
throw new Error(
|
|
2168
2189
|
"Junior dashboard auth requires allowedGoogleDomains or allowedEmails"
|
|
@@ -2177,6 +2198,10 @@ function createDashboardApp(rawOptions) {
|
|
|
2177
2198
|
}) : void 0;
|
|
2178
2199
|
const app = new Hono();
|
|
2179
2200
|
app.get(dashboardLoginPath(basePath), async (c) => {
|
|
2201
|
+
const canonicalUrl = canonicalLoginUrl(c.req.raw, canonicalBaseURL);
|
|
2202
|
+
if (canonicalUrl) {
|
|
2203
|
+
return Response.redirect(canonicalUrl, 302);
|
|
2204
|
+
}
|
|
2180
2205
|
const returnUrl = callbackUrl(c.req.raw, basePath);
|
|
2181
2206
|
if (!auth) {
|
|
2182
2207
|
return Response.redirect(returnUrl, 302);
|
|
@@ -2198,11 +2223,11 @@ function createDashboardApp(rawOptions) {
|
|
|
2198
2223
|
return;
|
|
2199
2224
|
}
|
|
2200
2225
|
if (!auth) {
|
|
2201
|
-
return unauthorized(c.req.raw, basePath);
|
|
2226
|
+
return unauthorized(c.req.raw, basePath, canonicalBaseURL);
|
|
2202
2227
|
}
|
|
2203
2228
|
const session = await auth.getSession(c.req.raw);
|
|
2204
2229
|
if (!session) {
|
|
2205
|
-
return unauthorized(c.req.raw, basePath);
|
|
2230
|
+
return unauthorized(c.req.raw, basePath, canonicalBaseURL);
|
|
2206
2231
|
}
|
|
2207
2232
|
if (!isAuthorized(session, allowedDomains, allowedEmails)) {
|
|
2208
2233
|
return forbidden(c.req.raw);
|
package/dist/index.js
CHANGED
|
@@ -54,7 +54,7 @@ function stripTrailingSlashes(value) {
|
|
|
54
54
|
return end === value.length ? value : value.slice(0, end);
|
|
55
55
|
}
|
|
56
56
|
function resolveDashboardBaseURL(config = {}) {
|
|
57
|
-
const explicit = config.baseURL ?? process.env.
|
|
57
|
+
const explicit = config.baseURL ?? process.env.JUNIOR_BASE_URL;
|
|
58
58
|
if (explicit?.trim()) {
|
|
59
59
|
return stripTrailingSlashes(withHttps(explicit.trim()));
|
|
60
60
|
}
|
|
@@ -1912,9 +1912,9 @@ function requestedReturnPath(url, basePath) {
|
|
|
1912
1912
|
}
|
|
1913
1913
|
return `${returnUrl.pathname}${returnUrl.search}`;
|
|
1914
1914
|
}
|
|
1915
|
-
function dashboardLoginUrl(request, basePath) {
|
|
1915
|
+
function dashboardLoginUrl(request, basePath, canonicalBaseURL) {
|
|
1916
1916
|
const requestUrl = new URL(request.url);
|
|
1917
|
-
const url = new URL(request.url);
|
|
1917
|
+
const url = canonicalBaseURL ? new URL(canonicalBaseURL) : new URL(request.url);
|
|
1918
1918
|
url.pathname = dashboardLoginPath(basePath);
|
|
1919
1919
|
url.search = "";
|
|
1920
1920
|
const returnPath = dashboardReturnPath(requestUrl, basePath);
|
|
@@ -1923,6 +1923,19 @@ function dashboardLoginUrl(request, basePath) {
|
|
|
1923
1923
|
}
|
|
1924
1924
|
return url.toString();
|
|
1925
1925
|
}
|
|
1926
|
+
function canonicalLoginUrl(request, canonicalBaseURL) {
|
|
1927
|
+
if (!canonicalBaseURL) {
|
|
1928
|
+
return void 0;
|
|
1929
|
+
}
|
|
1930
|
+
const requestUrl = new URL(request.url);
|
|
1931
|
+
const canonicalUrl = new URL(canonicalBaseURL);
|
|
1932
|
+
if (requestUrl.origin === canonicalUrl.origin) {
|
|
1933
|
+
return void 0;
|
|
1934
|
+
}
|
|
1935
|
+
canonicalUrl.pathname = requestUrl.pathname;
|
|
1936
|
+
canonicalUrl.search = requestUrl.search;
|
|
1937
|
+
return canonicalUrl.toString();
|
|
1938
|
+
}
|
|
1926
1939
|
function dashboardLoginPath(basePath) {
|
|
1927
1940
|
return basePath === "/" ? "/auth/login" : `${basePath}/auth/login`;
|
|
1928
1941
|
}
|
|
@@ -1950,11 +1963,14 @@ function isAuthorized(session, allowedDomains, allowedEmails) {
|
|
|
1950
1963
|
session.user.emailVerified && domain && allowedDomains.includes(domain)
|
|
1951
1964
|
);
|
|
1952
1965
|
}
|
|
1953
|
-
function unauthorized(request, basePath) {
|
|
1966
|
+
function unauthorized(request, basePath, canonicalBaseURL) {
|
|
1954
1967
|
if (isJsonRoute(new URL(request.url).pathname)) {
|
|
1955
1968
|
return Response.json({ error: "unauthenticated" }, { status: 401 });
|
|
1956
1969
|
}
|
|
1957
|
-
return Response.redirect(
|
|
1970
|
+
return Response.redirect(
|
|
1971
|
+
dashboardLoginUrl(request, basePath, canonicalBaseURL),
|
|
1972
|
+
302
|
|
1973
|
+
);
|
|
1958
1974
|
}
|
|
1959
1975
|
function forbidden(request) {
|
|
1960
1976
|
if (!isJsonRoute(new URL(request.url).pathname)) {
|
|
@@ -2163,6 +2179,11 @@ function createDashboardApp(rawOptions) {
|
|
|
2163
2179
|
const allowedDomains = normalizeValues(options.allowedGoogleDomains);
|
|
2164
2180
|
const allowedEmails = normalizeValues(options.allowedEmails);
|
|
2165
2181
|
const authRequired = options.authRequired !== false;
|
|
2182
|
+
const configuredBaseURL = options.baseURL ?? process.env.JUNIOR_BASE_URL;
|
|
2183
|
+
let canonicalBaseURL;
|
|
2184
|
+
if (authRequired && (configuredBaseURL || !options.auth)) {
|
|
2185
|
+
canonicalBaseURL = resolveDashboardBaseURL({ baseURL: configuredBaseURL });
|
|
2186
|
+
}
|
|
2166
2187
|
if (authRequired && allowedDomains.length === 0 && allowedEmails.length === 0) {
|
|
2167
2188
|
throw new Error(
|
|
2168
2189
|
"Junior dashboard auth requires allowedGoogleDomains or allowedEmails"
|
|
@@ -2177,6 +2198,10 @@ function createDashboardApp(rawOptions) {
|
|
|
2177
2198
|
}) : void 0;
|
|
2178
2199
|
const app = new Hono();
|
|
2179
2200
|
app.get(dashboardLoginPath(basePath), async (c) => {
|
|
2201
|
+
const canonicalUrl = canonicalLoginUrl(c.req.raw, canonicalBaseURL);
|
|
2202
|
+
if (canonicalUrl) {
|
|
2203
|
+
return Response.redirect(canonicalUrl, 302);
|
|
2204
|
+
}
|
|
2180
2205
|
const returnUrl = callbackUrl(c.req.raw, basePath);
|
|
2181
2206
|
if (!auth) {
|
|
2182
2207
|
return Response.redirect(returnUrl, 302);
|
|
@@ -2198,11 +2223,11 @@ function createDashboardApp(rawOptions) {
|
|
|
2198
2223
|
return;
|
|
2199
2224
|
}
|
|
2200
2225
|
if (!auth) {
|
|
2201
|
-
return unauthorized(c.req.raw, basePath);
|
|
2226
|
+
return unauthorized(c.req.raw, basePath, canonicalBaseURL);
|
|
2202
2227
|
}
|
|
2203
2228
|
const session = await auth.getSession(c.req.raw);
|
|
2204
2229
|
if (!session) {
|
|
2205
|
-
return unauthorized(c.req.raw, basePath);
|
|
2230
|
+
return unauthorized(c.req.raw, basePath, canonicalBaseURL);
|
|
2206
2231
|
}
|
|
2207
2232
|
if (!isAuthorized(session, allowedDomains, allowedEmails)) {
|
|
2208
2233
|
return forbidden(c.req.raw);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior-dashboard",
|
|
3
|
-
"version": "0.97.
|
|
3
|
+
"version": "0.97.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -34,8 +34,8 @@
|
|
|
34
34
|
"recharts": "^3.8.1",
|
|
35
35
|
"shiki": "4.1.0",
|
|
36
36
|
"zod": "^4.4.3",
|
|
37
|
-
"@sentry/junior": "0.97.
|
|
38
|
-
"@sentry/junior-plugin-api": "0.97.
|
|
37
|
+
"@sentry/junior": "0.97.1",
|
|
38
|
+
"@sentry/junior-plugin-api": "0.97.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@tailwindcss/cli": "^4.3.0",
|
package/src/app.ts
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
readMockConversationStats,
|
|
33
33
|
readMockConversationSubagent,
|
|
34
34
|
} from "./mock-conversations";
|
|
35
|
+
import { resolveDashboardBaseURL } from "./url";
|
|
35
36
|
|
|
36
37
|
const DEFAULT_BASE_PATH = "/";
|
|
37
38
|
const DEFAULT_AUTH_PATH = "/api/auth";
|
|
@@ -196,9 +197,15 @@ function requestedReturnPath(url: URL, basePath: string): string | undefined {
|
|
|
196
197
|
return `${returnUrl.pathname}${returnUrl.search}`;
|
|
197
198
|
}
|
|
198
199
|
|
|
199
|
-
function dashboardLoginUrl(
|
|
200
|
+
function dashboardLoginUrl(
|
|
201
|
+
request: Request,
|
|
202
|
+
basePath: string,
|
|
203
|
+
canonicalBaseURL?: string,
|
|
204
|
+
): string {
|
|
200
205
|
const requestUrl = new URL(request.url);
|
|
201
|
-
const url =
|
|
206
|
+
const url = canonicalBaseURL
|
|
207
|
+
? new URL(canonicalBaseURL)
|
|
208
|
+
: new URL(request.url);
|
|
202
209
|
url.pathname = dashboardLoginPath(basePath);
|
|
203
210
|
url.search = "";
|
|
204
211
|
const returnPath = dashboardReturnPath(requestUrl, basePath);
|
|
@@ -208,6 +215,25 @@ function dashboardLoginUrl(request: Request, basePath: string): string {
|
|
|
208
215
|
return url.toString();
|
|
209
216
|
}
|
|
210
217
|
|
|
218
|
+
function canonicalLoginUrl(
|
|
219
|
+
request: Request,
|
|
220
|
+
canonicalBaseURL: string | undefined,
|
|
221
|
+
): string | undefined {
|
|
222
|
+
if (!canonicalBaseURL) {
|
|
223
|
+
return undefined;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const requestUrl = new URL(request.url);
|
|
227
|
+
const canonicalUrl = new URL(canonicalBaseURL);
|
|
228
|
+
if (requestUrl.origin === canonicalUrl.origin) {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
canonicalUrl.pathname = requestUrl.pathname;
|
|
233
|
+
canonicalUrl.search = requestUrl.search;
|
|
234
|
+
return canonicalUrl.toString();
|
|
235
|
+
}
|
|
236
|
+
|
|
211
237
|
function dashboardLoginPath(basePath: string): string {
|
|
212
238
|
return basePath === "/" ? "/auth/login" : `${basePath}/auth/login`;
|
|
213
239
|
}
|
|
@@ -244,11 +270,18 @@ function isAuthorized(
|
|
|
244
270
|
);
|
|
245
271
|
}
|
|
246
272
|
|
|
247
|
-
function unauthorized(
|
|
273
|
+
function unauthorized(
|
|
274
|
+
request: Request,
|
|
275
|
+
basePath: string,
|
|
276
|
+
canonicalBaseURL?: string,
|
|
277
|
+
): Response {
|
|
248
278
|
if (isJsonRoute(new URL(request.url).pathname)) {
|
|
249
279
|
return Response.json({ error: "unauthenticated" }, { status: 401 });
|
|
250
280
|
}
|
|
251
|
-
return Response.redirect(
|
|
281
|
+
return Response.redirect(
|
|
282
|
+
dashboardLoginUrl(request, basePath, canonicalBaseURL),
|
|
283
|
+
302,
|
|
284
|
+
);
|
|
252
285
|
}
|
|
253
286
|
|
|
254
287
|
function forbidden(request: Request): Response {
|
|
@@ -492,6 +525,11 @@ export function createDashboardApp(
|
|
|
492
525
|
const allowedEmails = normalizeValues(options.allowedEmails);
|
|
493
526
|
|
|
494
527
|
const authRequired = options.authRequired !== false;
|
|
528
|
+
const configuredBaseURL = options.baseURL ?? process.env.JUNIOR_BASE_URL;
|
|
529
|
+
let canonicalBaseURL: string | undefined;
|
|
530
|
+
if (authRequired && (configuredBaseURL || !options.auth)) {
|
|
531
|
+
canonicalBaseURL = resolveDashboardBaseURL({ baseURL: configuredBaseURL });
|
|
532
|
+
}
|
|
495
533
|
|
|
496
534
|
if (
|
|
497
535
|
authRequired &&
|
|
@@ -516,6 +554,10 @@ export function createDashboardApp(
|
|
|
516
554
|
const app = new Hono<{ Variables: Variables }>();
|
|
517
555
|
|
|
518
556
|
app.get(dashboardLoginPath(basePath), async (c) => {
|
|
557
|
+
const canonicalUrl = canonicalLoginUrl(c.req.raw, canonicalBaseURL);
|
|
558
|
+
if (canonicalUrl) {
|
|
559
|
+
return Response.redirect(canonicalUrl, 302);
|
|
560
|
+
}
|
|
519
561
|
const returnUrl = callbackUrl(c.req.raw, basePath);
|
|
520
562
|
if (!auth) {
|
|
521
563
|
return Response.redirect(returnUrl, 302);
|
|
@@ -548,11 +590,11 @@ export function createDashboardApp(
|
|
|
548
590
|
}
|
|
549
591
|
|
|
550
592
|
if (!auth) {
|
|
551
|
-
return unauthorized(c.req.raw, basePath);
|
|
593
|
+
return unauthorized(c.req.raw, basePath, canonicalBaseURL);
|
|
552
594
|
}
|
|
553
595
|
const session = await auth.getSession(c.req.raw);
|
|
554
596
|
if (!session) {
|
|
555
|
-
return unauthorized(c.req.raw, basePath);
|
|
597
|
+
return unauthorized(c.req.raw, basePath, canonicalBaseURL);
|
|
556
598
|
}
|
|
557
599
|
if (!isAuthorized(session, allowedDomains, allowedEmails)) {
|
|
558
600
|
return forbidden(c.req.raw);
|
package/src/url.ts
CHANGED
|
@@ -33,10 +33,7 @@ export function normalizeDashboardPath(
|
|
|
33
33
|
export function resolveDashboardBaseURL(
|
|
34
34
|
config: DashboardBaseURLConfig = {},
|
|
35
35
|
): string {
|
|
36
|
-
const explicit =
|
|
37
|
-
config.baseURL ??
|
|
38
|
-
process.env.BETTER_AUTH_URL ??
|
|
39
|
-
process.env.JUNIOR_BASE_URL;
|
|
36
|
+
const explicit = config.baseURL ?? process.env.JUNIOR_BASE_URL;
|
|
40
37
|
if (explicit?.trim()) {
|
|
41
38
|
return stripTrailingSlashes(withHttps(explicit.trim()));
|
|
42
39
|
}
|