@sanity/sdk 3.3.0-rc.0 → 3.3.0
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/_exports/_internal.d.ts +12 -4
- package/dist/_exports/_internal.d.ts.map +1 -1
- package/dist/_exports/_internal.js +24 -6
- package/dist/_exports/_internal.js.map +1 -1
- package/dist/_exports/agent.js +1 -1
- package/dist/_exports/comlink.d.ts +1 -1
- package/dist/_exports/dashboard.d.ts +1 -1
- package/dist/_exports/dashboard.js +1 -1
- package/dist/{authStore-BGoEGxOq.d.ts → applications-pRS8tuC2.d.ts} +349 -362
- package/dist/applications-pRS8tuC2.d.ts.map +1 -0
- package/dist/{clientStore-QDrJNTM4.js → clientStore-BI4D8HhJ.js} +10 -14
- package/dist/clientStore-BI4D8HhJ.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +123 -156
- package/dist/index.js.map +1 -1
- package/dist/{topicStore-Ct7IFNtY.js → topicStore-BJ54_X6H.js} +3 -1
- package/dist/topicStore-BJ54_X6H.js.map +1 -0
- package/dist/{topicStore-DXvuH9h4.d.ts → topicStore-D-jEwzlX.d.ts} +54 -25
- package/dist/topicStore-D-jEwzlX.d.ts.map +1 -0
- package/dist/{version-CIhX5ppJ.js → version-CD4aBigm.js} +3 -3
- package/dist/{version-CIhX5ppJ.js.map → version-CD4aBigm.js.map} +1 -1
- package/package.json +7 -7
- package/src/_exports/_internal.ts +2 -0
- package/src/applications/applicationOrigin.test.ts +51 -0
- package/src/applications/applicationOrigin.ts +26 -0
- package/src/auth/authStore.test.ts +0 -18
- package/src/auth/authStore.ts +1 -4
- package/src/auth/handleAuthCallback.test.ts +0 -33
- package/src/auth/handleAuthCallback.ts +1 -11
- package/src/auth/logout.test.ts +1 -9
- package/src/auth/logout.ts +1 -18
- package/src/auth/oauth/oauthActions.test.ts +0 -136
- package/src/auth/oauth/oauthActions.ts +29 -78
- package/src/auth/oauth/oauthAuth.test.ts +0 -23
- package/src/auth/oauth/oauthAuth.ts +8 -18
- package/src/dashboard/messageBus/bus.test.ts +39 -0
- package/src/dashboard/messageBus/bus.ts +32 -22
- package/src/dashboard/messageBus/topics.test.ts +36 -2
- package/src/dashboard/messageBus/topics.ts +51 -16
- package/src/installations/installations.test-d.ts +11 -0
- package/src/installations/installations.test.ts +6 -4
- package/src/installations/installations.ts +13 -2
- package/dist/authStore-BGoEGxOq.d.ts.map +0 -1
- package/dist/clientStore-QDrJNTM4.js.map +0 -1
- package/dist/topicStore-Ct7IFNtY.js.map +0 -1
- package/dist/topicStore-DXvuH9h4.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { D as getAuthLogger, E as REQUEST_TAG_PREFIX, O as configureLogging$1, S as AuthStateType, T as DEFAULT_BASE, b as getTokenFromLocation, c as getDashboardOrganizationId, d as getTokenState, f as setAuthToken, h as getCleanedUrl, i as authStore, k as createLogger, l as getIsInDashboardState, m as getAuthCode, n as getClient, o as getAuthState, p as createLoggedInAuthState, r as getClientState, s as getCurrentUserState, u as getLoginUrlState, w as DEFAULT_API_VERSION, y as getDefaultLocation } from "./clientStore-
|
|
1
|
+
import { D as getAuthLogger, E as REQUEST_TAG_PREFIX, O as configureLogging$1, S as AuthStateType, T as DEFAULT_BASE, b as getTokenFromLocation, c as getDashboardOrganizationId, d as getTokenState, f as setAuthToken, h as getCleanedUrl, i as authStore, k as createLogger, l as getIsInDashboardState, m as getAuthCode, n as getClient, o as getAuthState, p as createLoggedInAuthState, r as getClientState, s as getCurrentUserState, u as getLoginUrlState, w as DEFAULT_API_VERSION, y as getDefaultLocation } from "./clientStore-BI4D8HhJ.js";
|
|
2
2
|
import { c as isReleasePerspective, d as isMediaLibraryResource, i as bindActionGlobally, l as isCanvasResource, n as bindActionByResource, o as defineStore, r as bindActionByResourceAndPerspective, t as createStateSourceAction, u as isDatasetResource } from "./createStateSourceAction-DdAhEfnZ.js";
|
|
3
|
-
import { A as clearPendingTransaction, B as assertDatasetResource, C as getCommentsState, D as toCommentsKeyParts, E as resolveComments, F as rollbackCommentUpdate, G as defineMutation, H as provisionAddonDataset, I as setCommentCreateError, K as randomId, L as setPendingTransaction, M as receiveComment, N as removeCommentById, O as addComment, P as restoreComments, R as normalizeComment, T as resolveCommentThreads, U as COMMENTS_API_VERSION, V as getAddonDatasetState, W as defineFetcher, _ as updateLastLoadMoreRequest, a as resolveQuery, b as commentsStore, c as getAllReleasesState, d as getUsersKey, f as initializeRequest, g as setUsersError, h as setUsersData, j as getCommentsKey, k as applyCommentUpdate, l as addSubscription, m as removeSubscription, o as getPerspectiveState, p as parseUsersKey, q as randomUuid, r as getQueryState, s as getActiveReleasesState, t as CORE_SDK_VERSION, u as cancelRequest, v as PROJECT_API_VERSION, x as getCommentThreadsState, y as USERS_STATE_CLEAR_DELAY, z as toCommentFieldPath } from "./version-
|
|
3
|
+
import { A as clearPendingTransaction, B as assertDatasetResource, C as getCommentsState, D as toCommentsKeyParts, E as resolveComments, F as rollbackCommentUpdate, G as defineMutation, H as provisionAddonDataset, I as setCommentCreateError, K as randomId, L as setPendingTransaction, M as receiveComment, N as removeCommentById, O as addComment, P as restoreComments, R as normalizeComment, T as resolveCommentThreads, U as COMMENTS_API_VERSION, V as getAddonDatasetState, W as defineFetcher, _ as updateLastLoadMoreRequest, a as resolveQuery, b as commentsStore, c as getAllReleasesState, d as getUsersKey, f as initializeRequest, g as setUsersError, h as setUsersData, j as getCommentsKey, k as applyCommentUpdate, l as addSubscription, m as removeSubscription, o as getPerspectiveState, p as parseUsersKey, q as randomUuid, r as getQueryState, s as getActiveReleasesState, t as CORE_SDK_VERSION, u as cancelRequest, v as PROJECT_API_VERSION, x as getCommentThreadsState, y as USERS_STATE_CLEAR_DELAY, z as toCommentFieldPath } from "./version-CD4aBigm.js";
|
|
4
4
|
import { r as omitProperty, t as isDeepEqual } from "./object-CxXlSVg7.js";
|
|
5
5
|
import { n as setCleanupTimeout } from "./setCleanupTimeout-BiM6q1KF.js";
|
|
6
6
|
import { t as _defineProperty } from "./defineProperty-Bho9Ngsi.js";
|
|
@@ -303,6 +303,101 @@ function observeOrganizationVerificationState(instance, projectIds) {
|
|
|
303
303
|
}), distinctUntilChanged((prev, curr) => prev.error === curr.error));
|
|
304
304
|
}
|
|
305
305
|
/**
|
|
306
|
+
* @public
|
|
307
|
+
*/
|
|
308
|
+
const handleAuthCallback = bindActionGlobally(authStore, async ({ state, instance }, locationHref = getDefaultLocation()) => {
|
|
309
|
+
let logger = getAuthLogger(instance), { providedToken, callbackUrl, clientFactory, apiHost, storageArea, storageKey } = state.get().options;
|
|
310
|
+
if (providedToken) return logger.debug("Skipping auth callback - token already provided"), !1;
|
|
311
|
+
let { authState } = state.get();
|
|
312
|
+
if (authState.type === "logging-in" && authState.isExchangingToken) return logger.debug("Skipping auth callback - token exchange already in progress"), !1;
|
|
313
|
+
let cleanedUrl = getCleanedUrl(locationHref), tokenFromUrl = getTokenFromLocation(locationHref);
|
|
314
|
+
if (tokenFromUrl) return logger.info("Auth token found in URL, logging in"), state.set("setTokenFromUrl", { authState: createLoggedInAuthState(tokenFromUrl, null) }), cleanedUrl;
|
|
315
|
+
let authCode = getAuthCode(callbackUrl, locationHref);
|
|
316
|
+
if (!authCode) return logger.debug("No auth code found in callback URL"), !1;
|
|
317
|
+
let parsedUrl = new URL(locationHref), dashboardContext = {};
|
|
318
|
+
try {
|
|
319
|
+
let contextParam = parsedUrl.searchParams.get("_context");
|
|
320
|
+
if (contextParam) {
|
|
321
|
+
let parsedContext = JSON.parse(contextParam);
|
|
322
|
+
parsedContext && typeof parsedContext == "object" && (delete parsedContext.sid, dashboardContext = parsedContext, logger.debug("Dashboard context parsed from callback URL", { hasDashboardContext: !0 }));
|
|
323
|
+
}
|
|
324
|
+
} catch (err) {
|
|
325
|
+
logger.warn("Failed to parse dashboard context from callback URL", { error: err });
|
|
326
|
+
}
|
|
327
|
+
logger.info("Exchanging auth code for token"), state.set("exchangeSessionForToken", {
|
|
328
|
+
authState: {
|
|
329
|
+
type: "logging-in",
|
|
330
|
+
isExchangingToken: !0
|
|
331
|
+
},
|
|
332
|
+
dashboardContext
|
|
333
|
+
});
|
|
334
|
+
try {
|
|
335
|
+
let client = clientFactory({
|
|
336
|
+
apiVersion: DEFAULT_API_VERSION,
|
|
337
|
+
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
338
|
+
useProjectHostname: !1,
|
|
339
|
+
useCdn: !1,
|
|
340
|
+
...apiHost && { apiHost }
|
|
341
|
+
});
|
|
342
|
+
logger.debug("Fetching token from auth endpoint");
|
|
343
|
+
let { token } = await client.request({
|
|
344
|
+
method: "GET",
|
|
345
|
+
url: "/auth/fetch",
|
|
346
|
+
query: { sid: authCode },
|
|
347
|
+
tag: "fetch-token"
|
|
348
|
+
});
|
|
349
|
+
return logger.info("Auth token obtained successfully, user logged in"), storageArea?.setItem(storageKey, JSON.stringify({ token })), state.set("setToken", { authState: createLoggedInAuthState(token, null) }), cleanedUrl;
|
|
350
|
+
} catch (error) {
|
|
351
|
+
return logger.error("Failed to exchange auth code for token", { error }), state.set("exchangeSessionForTokenError", { authState: {
|
|
352
|
+
type: "error",
|
|
353
|
+
error
|
|
354
|
+
} }), cleanedUrl;
|
|
355
|
+
}
|
|
356
|
+
}), logout = bindActionGlobally(authStore, async ({ state, instance }) => {
|
|
357
|
+
let logger = getAuthLogger(instance), { clientFactory, apiHost, providedToken, storageArea, storageKey } = state.get().options;
|
|
358
|
+
if (providedToken) {
|
|
359
|
+
logger.debug("Skipping logout - token is statically provided");
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
let { authState } = state.get();
|
|
363
|
+
if (authState.type === "logged-out" && authState.isDestroyingSession) {
|
|
364
|
+
logger.debug("Skipping logout - already in progress");
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
let token = authState.type === "logged-in" && authState.token;
|
|
368
|
+
try {
|
|
369
|
+
if (token) {
|
|
370
|
+
logger.info("Logging out user"), state.set("loggingOut", { authState: {
|
|
371
|
+
type: "logged-out",
|
|
372
|
+
isDestroyingSession: !0
|
|
373
|
+
} });
|
|
374
|
+
let client = clientFactory({
|
|
375
|
+
token,
|
|
376
|
+
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
377
|
+
apiVersion: DEFAULT_API_VERSION,
|
|
378
|
+
...apiHost && { apiHost },
|
|
379
|
+
useProjectHostname: !1,
|
|
380
|
+
useCdn: !1
|
|
381
|
+
});
|
|
382
|
+
logger.debug("Calling logout endpoint"), await client.request({
|
|
383
|
+
url: "/auth/logout",
|
|
384
|
+
method: "POST",
|
|
385
|
+
tag: "logout"
|
|
386
|
+
});
|
|
387
|
+
} else logger.debug("No token to logout - already logged out");
|
|
388
|
+
} catch (error) {
|
|
389
|
+
throw logger.error("Logout request failed", { error }), error;
|
|
390
|
+
} finally {
|
|
391
|
+
logger.info("User logged out, clearing stored tokens"), state.set("logoutSuccess", {
|
|
392
|
+
authState: {
|
|
393
|
+
type: "logged-out",
|
|
394
|
+
isDestroyingSession: !1
|
|
395
|
+
},
|
|
396
|
+
oauthTokens: void 0
|
|
397
|
+
}), storageArea?.removeItem(storageKey), storageArea?.removeItem(`${storageKey}_last_refresh`);
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
/**
|
|
306
401
|
* Encodes a byte array as a base64url string (RFC 4648 §5) with no padding,
|
|
307
402
|
* as required for PKCE `code_verifier`/`code_challenge` values.
|
|
308
403
|
*
|
|
@@ -345,23 +440,7 @@ async function generateCodeChallenge(codeVerifier) {
|
|
|
345
440
|
return base64UrlEncode(new Uint8Array(digest));
|
|
346
441
|
}
|
|
347
442
|
/** sessionStorage key for the PKCE `code_verifier`. */
|
|
348
|
-
const OAUTH_VERIFIER_KEY = "__sanity_oauth_verifier", OAUTH_STATE_KEY = "__sanity_oauth_state"
|
|
349
|
-
"code",
|
|
350
|
-
"state",
|
|
351
|
-
"error",
|
|
352
|
-
"error_description"
|
|
353
|
-
];
|
|
354
|
-
/** Strips the OAuth callback params from a URL. */
|
|
355
|
-
function stripOAuthParams(href) {
|
|
356
|
-
let url = new URL(href, DEFAULT_BASE);
|
|
357
|
-
for (let param of OAUTH_CALLBACK_PARAMS) url.searchParams.delete(param);
|
|
358
|
-
return url.toString();
|
|
359
|
-
}
|
|
360
|
-
/** Whether `href` is the registered redirect URI (origin + pathname; query and hash ignored). */
|
|
361
|
-
function isCallbackRoute(href, redirectUri) {
|
|
362
|
-
let current = new URL(href, DEFAULT_BASE), redirect = new URL(redirectUri, DEFAULT_BASE);
|
|
363
|
-
return current.origin === redirect.origin && current.pathname === redirect.pathname;
|
|
364
|
-
}
|
|
443
|
+
const OAUTH_VERIFIER_KEY = "__sanity_oauth_verifier", OAUTH_STATE_KEY = "__sanity_oauth_state";
|
|
365
444
|
/** Builds the RFC 8707 resource indicator for an organisation. */
|
|
366
445
|
function getResourceIndicator(organizationId) {
|
|
367
446
|
return `urn:io.sanity:organization:${organizationId}`;
|
|
@@ -419,26 +498,37 @@ function toOAuthTokens(response) {
|
|
|
419
498
|
const startOAuthAuthorization = bindActionGlobally(authStore, async ({ state, instance }) => {
|
|
420
499
|
let logger = getAuthLogger(instance), options = getOAuthOptions(state.get()), codeVerifier = generateCodeVerifier(), oauthState = generateState(), codeChallenge = await generateCodeChallenge(codeVerifier), session = typeof sessionStorage < "u" ? sessionStorage : void 0;
|
|
421
500
|
session?.setItem(OAUTH_VERIFIER_KEY, codeVerifier), session?.setItem(OAUTH_STATE_KEY, oauthState);
|
|
422
|
-
let currentHref = getDefaultLocation();
|
|
423
|
-
if (currentHref !== "http://localhost") {
|
|
424
|
-
let returnTo = isCallbackRoute(currentHref, options.oauth.redirectUri) ? stripOAuthParams(currentHref) : currentHref;
|
|
425
|
-
session?.setItem(OAUTH_RETURN_TO_KEY, returnTo);
|
|
426
|
-
}
|
|
427
501
|
let authorizeUrl = new URL("/v1/auth/oauth/authorize", options.apiHost ?? "https://api.sanity.io");
|
|
428
502
|
authorizeUrl.searchParams.set("response_type", "code"), authorizeUrl.searchParams.set("client_id", options.oauth.clientId), authorizeUrl.searchParams.set("redirect_uri", options.oauth.redirectUri), authorizeUrl.searchParams.set("state", oauthState), authorizeUrl.searchParams.set("code_challenge", codeChallenge), authorizeUrl.searchParams.set("code_challenge_method", "S256"), authorizeUrl.searchParams.append("resource", getResourceIndicator(options.oauth.organizationId)), logger.info("Starting OAuth authorization"), typeof window < "u" && typeof window.location?.assign == "function" && window.location.assign(authorizeUrl.toString());
|
|
429
503
|
}), handleOAuthCallback = bindActionGlobally(authStore, async ({ state, instance }, locationHref = getDefaultLocation()) => {
|
|
430
504
|
let logger = getAuthLogger(instance), options = getOAuthOptions(state.get()), { authState } = state.get();
|
|
431
505
|
if (authState.type === "logging-in" && authState.isExchangingToken) return logger.debug("Skipping OAuth callback - token exchange already in progress"), !1;
|
|
432
|
-
let callbackUrl = new URL(locationHref, DEFAULT_BASE), code = callbackUrl.searchParams.get("code"), returnedState = callbackUrl.searchParams.get("state"), error = callbackUrl.searchParams.get("error"), errorDescription = callbackUrl.searchParams.get("error_description"), session = typeof sessionStorage < "u" ? sessionStorage : void 0,
|
|
506
|
+
let callbackUrl = new URL(locationHref, DEFAULT_BASE), code = callbackUrl.searchParams.get("code"), returnedState = callbackUrl.searchParams.get("state"), error = callbackUrl.searchParams.get("error"), errorDescription = callbackUrl.searchParams.get("error_description"), session = typeof sessionStorage < "u" ? sessionStorage : void 0, cleanedUrlObj = new URL(locationHref, DEFAULT_BASE);
|
|
507
|
+
for (let param of [
|
|
508
|
+
"code",
|
|
509
|
+
"state",
|
|
510
|
+
"error",
|
|
511
|
+
"error_description"
|
|
512
|
+
]) cleanedUrlObj.searchParams.delete(param);
|
|
513
|
+
let cleanedUrl = cleanedUrlObj.toString();
|
|
514
|
+
if (error) return logger.warn("OAuth callback returned an error", {
|
|
515
|
+
error,
|
|
516
|
+
errorDescription
|
|
517
|
+
}), clearOAuthArtifacts(session), state.set("oauthCallbackError", { authState: {
|
|
433
518
|
type: "error",
|
|
434
|
-
error: Error(
|
|
435
|
-
} }), cleanedUrl
|
|
436
|
-
if (error) return rejectCallback("oauthCallbackError", errorDescription ? `${error}: ${errorDescription}` : error);
|
|
519
|
+
error: Error(errorDescription ? `${error}: ${errorDescription}` : error)
|
|
520
|
+
} }), cleanedUrl;
|
|
437
521
|
if (!code) return logger.debug("No OAuth code found in callback URL"), !1;
|
|
438
522
|
let storedState = session?.getItem("__sanity_oauth_state") ?? null;
|
|
439
|
-
if (!returnedState || !storedState || returnedState !== storedState) return
|
|
523
|
+
if (!returnedState || !storedState || returnedState !== storedState) return logger.error("OAuth state mismatch — rejecting callback"), clearOAuthArtifacts(session), state.set("oauthStateMismatch", { authState: {
|
|
524
|
+
type: "error",
|
|
525
|
+
error: /* @__PURE__ */ Error("OAuth state mismatch")
|
|
526
|
+
} }), cleanedUrl;
|
|
440
527
|
let codeVerifier = session?.getItem("__sanity_oauth_verifier") ?? null;
|
|
441
|
-
if (!codeVerifier) return
|
|
528
|
+
if (!codeVerifier) return logger.error("OAuth code verifier missing — cannot exchange code"), clearOAuthArtifacts(session), state.set("oauthVerifierMissing", { authState: {
|
|
529
|
+
type: "error",
|
|
530
|
+
error: /* @__PURE__ */ Error("OAuth code verifier missing")
|
|
531
|
+
} }), cleanedUrl;
|
|
442
532
|
logger.info("Exchanging OAuth code for tokens"), state.set("oauthExchange", { authState: {
|
|
443
533
|
type: "logging-in",
|
|
444
534
|
isExchangingToken: !0
|
|
@@ -458,12 +548,10 @@ const startOAuthAuthorization = bindActionGlobally(authStore, async ({ state, in
|
|
|
458
548
|
body: params.toString(),
|
|
459
549
|
tag: "oauth.token"
|
|
460
550
|
}));
|
|
461
|
-
options.storageArea?.setItem(options.storageKey, serializeTokens(tokens))
|
|
462
|
-
let returnTo = getSameOriginReturnTo(session, options.oauth.redirectUri);
|
|
463
|
-
return clearOAuthArtifacts(session), logger.info("OAuth tokens obtained, user logged in"), state.set("oauthLoggedIn", {
|
|
551
|
+
return options.storageArea?.setItem(options.storageKey, serializeTokens(tokens)), clearOAuthArtifacts(session), logger.info("OAuth tokens obtained, user logged in"), state.set("oauthLoggedIn", {
|
|
464
552
|
authState: createLoggedInAuthState(tokens.accessToken, null),
|
|
465
553
|
oauthTokens: tokens
|
|
466
|
-
}),
|
|
554
|
+
}), cleanedUrl;
|
|
467
555
|
} catch (exchangeError) {
|
|
468
556
|
return logger.error("Failed to exchange OAuth code for tokens", { error: exchangeError }), clearOAuthArtifacts(session), state.set("oauthExchangeError", { authState: {
|
|
469
557
|
type: "error",
|
|
@@ -565,129 +653,8 @@ const revokeOAuthTokens = bindActionGlobally(authStore, async ({ state, instance
|
|
|
565
653
|
}), getOAuthTokensState = bindActionGlobally(authStore, createStateSourceAction(({ state }) => state.oauthTokens ?? null));
|
|
566
654
|
/** Removes the transient PKCE artifacts from session storage. */
|
|
567
655
|
function clearOAuthArtifacts(session) {
|
|
568
|
-
session?.removeItem(OAUTH_VERIFIER_KEY), session?.removeItem(OAUTH_STATE_KEY)
|
|
656
|
+
session?.removeItem(OAUTH_VERIFIER_KEY), session?.removeItem(OAUTH_STATE_KEY);
|
|
569
657
|
}
|
|
570
|
-
/**
|
|
571
|
-
* Reads the stashed pre-authorize location, only honouring it when it shares
|
|
572
|
-
* the registered redirect URI's origin so a tampered value cannot redirect
|
|
573
|
-
* off-site. (`origin` includes the scheme, so non-http(s) URLs are rejected.)
|
|
574
|
-
*/
|
|
575
|
-
function getSameOriginReturnTo(session, redirectUri) {
|
|
576
|
-
let returnTo = session?.getItem("__sanity_oauth_return_to") ?? null;
|
|
577
|
-
if (!returnTo) return null;
|
|
578
|
-
try {
|
|
579
|
-
return new URL(returnTo).origin === new URL(redirectUri).origin ? returnTo : null;
|
|
580
|
-
} catch {
|
|
581
|
-
return null;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
/**
|
|
585
|
-
* Handles the auth redirect callback. In OAuth mode this delegates to
|
|
586
|
-
* {@link handleOAuthCallback}; otherwise it exchanges the legacy `sid` for a
|
|
587
|
-
* long-lived token.
|
|
588
|
-
*
|
|
589
|
-
* @public
|
|
590
|
-
*/
|
|
591
|
-
const handleAuthCallback = bindActionGlobally(authStore, async ({ state, instance }, locationHref = getDefaultLocation()) => {
|
|
592
|
-
let logger = getAuthLogger(instance), { providedToken, callbackUrl, clientFactory, apiHost, storageArea, storageKey, oauth } = state.get().options;
|
|
593
|
-
if (providedToken) return logger.debug("Skipping auth callback - token already provided"), !1;
|
|
594
|
-
if (oauth) return logger.debug("OAuth mode - delegating to handleOAuthCallback"), handleOAuthCallback(instance, locationHref);
|
|
595
|
-
let { authState } = state.get();
|
|
596
|
-
if (authState.type === "logging-in" && authState.isExchangingToken) return logger.debug("Skipping auth callback - token exchange already in progress"), !1;
|
|
597
|
-
let cleanedUrl = getCleanedUrl(locationHref), tokenFromUrl = getTokenFromLocation(locationHref);
|
|
598
|
-
if (tokenFromUrl) return logger.info("Auth token found in URL, logging in"), state.set("setTokenFromUrl", { authState: createLoggedInAuthState(tokenFromUrl, null) }), cleanedUrl;
|
|
599
|
-
let authCode = getAuthCode(callbackUrl, locationHref);
|
|
600
|
-
if (!authCode) return logger.debug("No auth code found in callback URL"), !1;
|
|
601
|
-
let parsedUrl = new URL(locationHref), dashboardContext = {};
|
|
602
|
-
try {
|
|
603
|
-
let contextParam = parsedUrl.searchParams.get("_context");
|
|
604
|
-
if (contextParam) {
|
|
605
|
-
let parsedContext = JSON.parse(contextParam);
|
|
606
|
-
parsedContext && typeof parsedContext == "object" && (delete parsedContext.sid, dashboardContext = parsedContext, logger.debug("Dashboard context parsed from callback URL", { hasDashboardContext: !0 }));
|
|
607
|
-
}
|
|
608
|
-
} catch (err) {
|
|
609
|
-
logger.warn("Failed to parse dashboard context from callback URL", { error: err });
|
|
610
|
-
}
|
|
611
|
-
logger.info("Exchanging auth code for token"), state.set("exchangeSessionForToken", {
|
|
612
|
-
authState: {
|
|
613
|
-
type: "logging-in",
|
|
614
|
-
isExchangingToken: !0
|
|
615
|
-
},
|
|
616
|
-
dashboardContext
|
|
617
|
-
});
|
|
618
|
-
try {
|
|
619
|
-
let client = clientFactory({
|
|
620
|
-
apiVersion: DEFAULT_API_VERSION,
|
|
621
|
-
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
622
|
-
useProjectHostname: !1,
|
|
623
|
-
useCdn: !1,
|
|
624
|
-
...apiHost && { apiHost }
|
|
625
|
-
});
|
|
626
|
-
logger.debug("Fetching token from auth endpoint");
|
|
627
|
-
let { token } = await client.request({
|
|
628
|
-
method: "GET",
|
|
629
|
-
url: "/auth/fetch",
|
|
630
|
-
query: { sid: authCode },
|
|
631
|
-
tag: "fetch-token"
|
|
632
|
-
});
|
|
633
|
-
return logger.info("Auth token obtained successfully, user logged in"), storageArea?.setItem(storageKey, JSON.stringify({ token })), state.set("setToken", { authState: createLoggedInAuthState(token, null) }), cleanedUrl;
|
|
634
|
-
} catch (error) {
|
|
635
|
-
return logger.error("Failed to exchange auth code for token", { error }), state.set("exchangeSessionForTokenError", { authState: {
|
|
636
|
-
type: "error",
|
|
637
|
-
error
|
|
638
|
-
} }), cleanedUrl;
|
|
639
|
-
}
|
|
640
|
-
}), logout = bindActionGlobally(authStore, async ({ state, instance }) => {
|
|
641
|
-
let logger = getAuthLogger(instance), { clientFactory, apiHost, providedToken, storageArea, storageKey, oauth } = state.get().options;
|
|
642
|
-
if (providedToken) {
|
|
643
|
-
logger.debug("Skipping logout - token is statically provided");
|
|
644
|
-
return;
|
|
645
|
-
}
|
|
646
|
-
let { authState } = state.get();
|
|
647
|
-
if (authState.type === "logged-out" && authState.isDestroyingSession) {
|
|
648
|
-
logger.debug("Skipping logout - already in progress");
|
|
649
|
-
return;
|
|
650
|
-
}
|
|
651
|
-
if (oauth) {
|
|
652
|
-
logger.debug("OAuth mode - revoking tokens instead of calling /auth/logout"), state.set("loggingOut", { authState: {
|
|
653
|
-
type: "logged-out",
|
|
654
|
-
isDestroyingSession: !0
|
|
655
|
-
} }), await revokeOAuthTokens(instance);
|
|
656
|
-
return;
|
|
657
|
-
}
|
|
658
|
-
let token = authState.type === "logged-in" && authState.token;
|
|
659
|
-
try {
|
|
660
|
-
if (token) {
|
|
661
|
-
logger.info("Logging out user"), state.set("loggingOut", { authState: {
|
|
662
|
-
type: "logged-out",
|
|
663
|
-
isDestroyingSession: !0
|
|
664
|
-
} });
|
|
665
|
-
let client = clientFactory({
|
|
666
|
-
token,
|
|
667
|
-
requestTagPrefix: REQUEST_TAG_PREFIX,
|
|
668
|
-
apiVersion: DEFAULT_API_VERSION,
|
|
669
|
-
...apiHost && { apiHost },
|
|
670
|
-
useProjectHostname: !1,
|
|
671
|
-
useCdn: !1
|
|
672
|
-
});
|
|
673
|
-
logger.debug("Calling logout endpoint"), await client.request({
|
|
674
|
-
url: "/auth/logout",
|
|
675
|
-
method: "POST",
|
|
676
|
-
tag: "logout"
|
|
677
|
-
});
|
|
678
|
-
} else logger.debug("No token to logout - already logged out");
|
|
679
|
-
} catch (error) {
|
|
680
|
-
throw logger.error("Logout request failed", { error }), error;
|
|
681
|
-
} finally {
|
|
682
|
-
logger.info("User logged out, clearing stored tokens"), state.set("logoutSuccess", {
|
|
683
|
-
authState: {
|
|
684
|
-
type: "logged-out",
|
|
685
|
-
isDestroyingSession: !1
|
|
686
|
-
},
|
|
687
|
-
oauthTokens: void 0
|
|
688
|
-
}), storageArea?.removeItem(storageKey), storageArea?.removeItem(`${storageKey}_last_refresh`);
|
|
689
|
-
}
|
|
690
|
-
});
|
|
691
658
|
function weaken(node) {
|
|
692
659
|
return Array.isArray(node) ? node.map(weaken) : node && typeof node == "object" ? "_ref" in node ? {
|
|
693
660
|
...node,
|