woodsportal-client-sdk 1.1.5-dev.0 → 2.0.705
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/CHANGELOG.md +128 -0
- package/README.md +199 -77
- package/dist/adapters/angular/index.d.ts +88 -5
- package/dist/adapters/angular/index.js +12 -7
- package/dist/adapters/angular/index.js.map +1 -1
- package/dist/adapters/native/index.d.ts +3 -0
- package/dist/adapters/native/index.js +11 -0
- package/dist/adapters/native/index.js.map +1 -0
- package/dist/adapters/react/index.d.ts +88 -5
- package/dist/adapters/react/index.js +9 -16
- package/dist/adapters/react/index.js.map +1 -1
- package/dist/adapters/vue/index.d.ts +88 -5
- package/dist/adapters/vue/index.js +12 -7
- package/dist/adapters/vue/index.js.map +1 -1
- package/dist/auth-error-codes-D7CXVBEN.js +3 -0
- package/dist/auth-error-codes-D7CXVBEN.js.map +1 -0
- package/dist/auth-interceptor-policy-K46P4VM4.js +6 -0
- package/dist/auth-interceptor-policy-K46P4VM4.js.map +1 -0
- package/dist/auth-utils-JGNW73IJ.js +7 -0
- package/dist/{auth-utils-A4WPJMPK.js.map → auth-utils-JGNW73IJ.js.map} +1 -1
- package/dist/chunk-2OLIVT2F.js +343 -0
- package/dist/chunk-2OLIVT2F.js.map +1 -0
- package/dist/chunk-32ERSTFY.js +354 -0
- package/dist/chunk-32ERSTFY.js.map +1 -0
- package/dist/{chunk-Y5MRAAGK.js → chunk-AYTO6ND7.js} +3 -3
- package/dist/chunk-AYTO6ND7.js.map +1 -0
- package/dist/chunk-BXHEEGBF.js +2747 -0
- package/dist/chunk-BXHEEGBF.js.map +1 -0
- package/dist/chunk-COHBSTHF.js +82 -0
- package/dist/chunk-COHBSTHF.js.map +1 -0
- package/dist/chunk-CUVU6DCT.js +3 -0
- package/dist/chunk-CUVU6DCT.js.map +1 -0
- package/dist/chunk-D5GHE2CO.js +172 -0
- package/dist/chunk-D5GHE2CO.js.map +1 -0
- package/dist/chunk-DB6W3CJT.js +73 -0
- package/dist/chunk-DB6W3CJT.js.map +1 -0
- package/dist/chunk-ITBMRGCP.js +16 -0
- package/dist/chunk-ITBMRGCP.js.map +1 -0
- package/dist/chunk-JRT5XSVY.js +161 -0
- package/dist/chunk-JRT5XSVY.js.map +1 -0
- package/dist/chunk-JSXP2F2H.js +1849 -0
- package/dist/chunk-JSXP2F2H.js.map +1 -0
- package/dist/chunk-KGNMN7B3.js +173 -0
- package/dist/chunk-KGNMN7B3.js.map +1 -0
- package/dist/chunk-MLBZ5FQA.js +1305 -0
- package/dist/chunk-MLBZ5FQA.js.map +1 -0
- package/dist/chunk-OH7VT6MX.js +22 -0
- package/dist/chunk-OH7VT6MX.js.map +1 -0
- package/dist/chunk-VDMDWMMX.js +519 -0
- package/dist/chunk-VDMDWMMX.js.map +1 -0
- package/dist/chunk-XDYXEYDM.js +1081 -0
- package/dist/chunk-XDYXEYDM.js.map +1 -0
- package/dist/crmCacheRefresh-B9sAQzI7.d.ts +292 -0
- package/dist/cross-tab-session-FCAQTXUB.js +11 -0
- package/dist/cross-tab-session-FCAQTXUB.js.map +1 -0
- package/dist/entries/auth.d.ts +96 -0
- package/dist/entries/auth.js +19 -0
- package/dist/entries/auth.js.map +1 -0
- package/dist/entries/crm.d.ts +239 -0
- package/dist/entries/crm.js +33 -0
- package/dist/entries/crm.js.map +1 -0
- package/dist/index-CWYPrDBp.d.ts +56 -0
- package/dist/index.d.ts +642 -394
- package/dist/index.js +96 -1698
- package/dist/index.js.map +1 -1
- package/dist/route-guard-contract-CSJMmfDA.d.ts +856 -0
- package/dist/storage-migration-CWOS6CNV.js +4 -0
- package/dist/storage-migration-CWOS6CNV.js.map +1 -0
- package/dist/use-file-BcO5l-Zf.d.ts +29 -0
- package/dist/use-sync-BQfzHacf.d.ts +66 -0
- package/package.json +155 -110
- package/dist/auth-utils-A4WPJMPK.js +0 -4
- package/dist/chunk-J7MDPY5P.js +0 -54
- package/dist/chunk-J7MDPY5P.js.map +0 -1
- package/dist/chunk-NB7AINV4.js +0 -35
- package/dist/chunk-NB7AINV4.js.map +0 -1
- package/dist/chunk-RDCT25UV.js +0 -1066
- package/dist/chunk-RDCT25UV.js.map +0 -1
- package/dist/chunk-Y5MRAAGK.js.map +0 -1
- package/dist/chunk-YLZA5S7A.js +0 -102
- package/dist/chunk-YLZA5S7A.js.map +0 -1
- package/dist/use-sync-LbURBOs_.d.ts +0 -29
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// src/main/core/auth/auth-error-codes.ts
|
|
2
|
+
var AuthErrorCode = {
|
|
3
|
+
AUTHENTICATION_FAILED: "AUTHENTICATION_FAILED",
|
|
4
|
+
TOKEN_INVALID: "AUTH_TOKEN_INVALID",
|
|
5
|
+
TOKEN_EXPIRED: "AUTH_TOKEN_EXPIRED",
|
|
6
|
+
ACCOUNT_LOCKED: "AUTH_ACCOUNT_LOCKED",
|
|
7
|
+
ACCOUNT_DISABLED: "AUTH_ACCOUNT_DISABLED",
|
|
8
|
+
LOGIN_FAILED: "LOGIN_FAILED",
|
|
9
|
+
INVALID_CREDENTIALS: "AUTH_INVALID_CREDENTIALS",
|
|
10
|
+
TWO_FACTOR_REQUIRED: "AUTH_2FA_REQUIRED",
|
|
11
|
+
EMAIL_NOT_VERIFIED: "AUTH_EMAIL_NOT_VERIFIED",
|
|
12
|
+
ACCESS_DENIED: "ACCESS_DENIED",
|
|
13
|
+
ACCESS_FORBIDDEN: "ACCESS_FORBIDDEN",
|
|
14
|
+
ACCESS_UNAUTHORIZED: "ACCESS_UNAUTHORIZED",
|
|
15
|
+
MISSING_REFRESH_TOKEN: "MISSING_REFRESH_TOKEN",
|
|
16
|
+
MISSING_HEADERS: "MISSING_HEADERS",
|
|
17
|
+
OAUTH_PROCESSING_ERROR: "OAUTH_PROCESSING_ERROR",
|
|
18
|
+
HUBSPOT_REAUTH_REQUIRED: "HUBSPOT_REAUTH_REQUIRED",
|
|
19
|
+
PORTAL_INACTIVE: "PORTAL_INACTIVE",
|
|
20
|
+
AMBIGUOUS_HUB_ID: "AMBIGUOUS_HUB_ID",
|
|
21
|
+
COMMERCIAL_ACCESS_EXPIRED: "COMMERCIAL_ACCESS_EXPIRED"
|
|
22
|
+
};
|
|
23
|
+
function parseApiErrorPayload(data) {
|
|
24
|
+
if (!data || typeof data !== "object") {
|
|
25
|
+
return {};
|
|
26
|
+
}
|
|
27
|
+
const payload = data;
|
|
28
|
+
return {
|
|
29
|
+
errorCode: typeof payload.errorCode === "string" ? payload.errorCode : void 0,
|
|
30
|
+
errorMessage: typeof payload.errorMessage === "string" ? payload.errorMessage : typeof payload.message === "string" ? payload.message : void 0,
|
|
31
|
+
detailedMessage: typeof payload.detailedMessage === "string" ? payload.detailedMessage : void 0,
|
|
32
|
+
correlationId: typeof payload.correlationId === "string" ? payload.correlationId : void 0,
|
|
33
|
+
statusCode: typeof payload.statusCode === "number" ? payload.statusCode : void 0,
|
|
34
|
+
category: typeof payload.category === "string" ? payload.category : void 0
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function getUnauthorizedPageCopy(errorCode, fallbackMessage) {
|
|
38
|
+
switch (errorCode) {
|
|
39
|
+
case AuthErrorCode.HUBSPOT_REAUTH_REQUIRED:
|
|
40
|
+
return {
|
|
41
|
+
title: "HubSpot re-authorization required",
|
|
42
|
+
message: fallbackMessage ?? "Reconnect your HubSpot account to continue using WoodsPortal.",
|
|
43
|
+
buttonLabel: "Go to HubSpot Accounts",
|
|
44
|
+
clearSessionOnMount: false
|
|
45
|
+
};
|
|
46
|
+
case AuthErrorCode.ACCOUNT_LOCKED:
|
|
47
|
+
case AuthErrorCode.ACCOUNT_DISABLED:
|
|
48
|
+
return {
|
|
49
|
+
title: "Account unavailable",
|
|
50
|
+
message: fallbackMessage ?? "Your account is locked or disabled. Contact support if you need access.",
|
|
51
|
+
buttonLabel: "Go to Login",
|
|
52
|
+
clearSessionOnMount: true
|
|
53
|
+
};
|
|
54
|
+
case AuthErrorCode.ACCESS_DENIED:
|
|
55
|
+
case AuthErrorCode.ACCESS_FORBIDDEN:
|
|
56
|
+
return {
|
|
57
|
+
title: "Access denied",
|
|
58
|
+
message: fallbackMessage ?? "You do not have permission to perform this action.",
|
|
59
|
+
buttonLabel: "Go to Login",
|
|
60
|
+
clearSessionOnMount: false
|
|
61
|
+
};
|
|
62
|
+
case AuthErrorCode.TOKEN_EXPIRED:
|
|
63
|
+
case AuthErrorCode.TOKEN_INVALID:
|
|
64
|
+
return {
|
|
65
|
+
title: "Session expired",
|
|
66
|
+
message: fallbackMessage ?? "Your session has expired. Please log in again to continue.",
|
|
67
|
+
buttonLabel: "Go to Login",
|
|
68
|
+
clearSessionOnMount: true
|
|
69
|
+
};
|
|
70
|
+
default:
|
|
71
|
+
return {
|
|
72
|
+
title: "Unauthorized",
|
|
73
|
+
message: fallbackMessage ?? "Your session may have expired or you do not have the required permissions. Please log in again to continue.",
|
|
74
|
+
buttonLabel: "Go to Login",
|
|
75
|
+
clearSessionOnMount: true
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { AuthErrorCode, getUnauthorizedPageCopy, parseApiErrorPayload };
|
|
81
|
+
//# sourceMappingURL=chunk-COHBSTHF.js.map
|
|
82
|
+
//# sourceMappingURL=chunk-COHBSTHF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/main/core/auth/auth-error-codes.ts"],"names":[],"mappings":"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","file":"chunk-COHBSTHF.js","sourcesContent":["/** Auth-related API error codes (woodsportal-api ErrorCode.java + API-ERROR-CODES.md). */\nexport const AuthErrorCode = {\n AUTHENTICATION_FAILED: 'AUTHENTICATION_FAILED',\n TOKEN_INVALID: 'AUTH_TOKEN_INVALID',\n TOKEN_EXPIRED: 'AUTH_TOKEN_EXPIRED',\n ACCOUNT_LOCKED: 'AUTH_ACCOUNT_LOCKED',\n ACCOUNT_DISABLED: 'AUTH_ACCOUNT_DISABLED',\n LOGIN_FAILED: 'LOGIN_FAILED',\n INVALID_CREDENTIALS: 'AUTH_INVALID_CREDENTIALS',\n TWO_FACTOR_REQUIRED: 'AUTH_2FA_REQUIRED',\n EMAIL_NOT_VERIFIED: 'AUTH_EMAIL_NOT_VERIFIED',\n ACCESS_DENIED: 'ACCESS_DENIED',\n ACCESS_FORBIDDEN: 'ACCESS_FORBIDDEN',\n ACCESS_UNAUTHORIZED: 'ACCESS_UNAUTHORIZED',\n MISSING_REFRESH_TOKEN: 'MISSING_REFRESH_TOKEN',\n MISSING_HEADERS: 'MISSING_HEADERS',\n OAUTH_PROCESSING_ERROR: 'OAUTH_PROCESSING_ERROR',\n HUBSPOT_REAUTH_REQUIRED: 'HUBSPOT_REAUTH_REQUIRED',\n PORTAL_INACTIVE: 'PORTAL_INACTIVE',\n AMBIGUOUS_HUB_ID: 'AMBIGUOUS_HUB_ID',\n COMMERCIAL_ACCESS_EXPIRED: 'COMMERCIAL_ACCESS_EXPIRED'\n} as const\n\nexport type AuthErrorCodeValue = (typeof AuthErrorCode)[keyof typeof AuthErrorCode]\n\nexport type ApiErrorPayload = {\n errorCode?: string\n errorMessage?: string\n detailedMessage?: string\n correlationId?: string\n statusCode?: number\n category?: string\n}\n\nexport type StoredAuthError = ApiErrorPayload & { ts?: number }\n\nexport function parseApiErrorPayload(data: unknown): ApiErrorPayload {\n if (!data || typeof data !== 'object') {\n return {}\n }\n const payload = data as Record<string, unknown>\n return {\n errorCode: typeof payload.errorCode === 'string' ? payload.errorCode : undefined,\n errorMessage:\n typeof payload.errorMessage === 'string' ? payload.errorMessage : typeof payload.message === 'string' ? payload.message : undefined,\n detailedMessage: typeof payload.detailedMessage === 'string' ? payload.detailedMessage : undefined,\n correlationId: typeof payload.correlationId === 'string' ? payload.correlationId : undefined,\n statusCode: typeof payload.statusCode === 'number' ? payload.statusCode : undefined,\n category: typeof payload.category === 'string' ? payload.category : undefined\n }\n}\n\nexport type UnauthorizedPageCopy = {\n title: string\n message: string\n buttonLabel: string\n clearSessionOnMount: boolean\n}\n\nexport function getUnauthorizedPageCopy(errorCode?: string, fallbackMessage?: string): UnauthorizedPageCopy {\n switch (errorCode) {\n case AuthErrorCode.HUBSPOT_REAUTH_REQUIRED:\n return {\n title: 'HubSpot re-authorization required',\n message: fallbackMessage ?? 'Reconnect your HubSpot account to continue using WoodsPortal.',\n buttonLabel: 'Go to HubSpot Accounts',\n clearSessionOnMount: false\n }\n case AuthErrorCode.ACCOUNT_LOCKED:\n case AuthErrorCode.ACCOUNT_DISABLED:\n return {\n title: 'Account unavailable',\n message: fallbackMessage ?? 'Your account is locked or disabled. Contact support if you need access.',\n buttonLabel: 'Go to Login',\n clearSessionOnMount: true\n }\n case AuthErrorCode.ACCESS_DENIED:\n case AuthErrorCode.ACCESS_FORBIDDEN:\n return {\n title: 'Access denied',\n message: fallbackMessage ?? 'You do not have permission to perform this action.',\n buttonLabel: 'Go to Login',\n clearSessionOnMount: false\n }\n case AuthErrorCode.TOKEN_EXPIRED:\n case AuthErrorCode.TOKEN_INVALID:\n return {\n title: 'Session expired',\n message: fallbackMessage ?? 'Your session has expired. Please log in again to continue.',\n buttonLabel: 'Go to Login',\n clearSessionOnMount: true\n }\n default:\n return {\n title: 'Unauthorized',\n message:\n fallbackMessage ?? 'Your session may have expired or you do not have the required permissions. Please log in again to continue.',\n buttonLabel: 'Go to Login',\n clearSessionOnMount: true\n }\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-CUVU6DCT.js"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { multiObjectStore, objectStore } from './chunk-2OLIVT2F.js';
|
|
2
|
+
import { actions2, tableStore, tableUiStore, noteStore, emailStore, userStore, syncStore, formStore, fileStore } from './chunk-JSXP2F2H.js';
|
|
3
|
+
import { getSubscriptionType, clearAdapterSessionData, setSubscriptionType, clearAccessToken, resetSessionAuthState, clearSessionRefreshExhaustedState } from './chunk-XDYXEYDM.js';
|
|
4
|
+
import { clearClientAuthCookies, clearClientIframeRefreshLocalKeys, getClientType } from './chunk-32ERSTFY.js';
|
|
5
|
+
import { WP_STORAGE_KEYS } from './chunk-KGNMN7B3.js';
|
|
6
|
+
|
|
7
|
+
// src/main/core/http/session-teardown.ts
|
|
8
|
+
function resetSessionStores() {
|
|
9
|
+
actions2.clearTablePrependData();
|
|
10
|
+
tableStore.setState({
|
|
11
|
+
queryParams: null,
|
|
12
|
+
multiObjectsQueryParams: {},
|
|
13
|
+
objectsData: null,
|
|
14
|
+
tableData: [],
|
|
15
|
+
tablePrependData: [],
|
|
16
|
+
hubspotObjectTypeId: "",
|
|
17
|
+
selectedPipeline: "",
|
|
18
|
+
viewType: ""
|
|
19
|
+
});
|
|
20
|
+
tableUiStore.setState({
|
|
21
|
+
tableUniqueId: null,
|
|
22
|
+
gridData: [],
|
|
23
|
+
sort: "-hs_createdate",
|
|
24
|
+
limit: 10,
|
|
25
|
+
after: "",
|
|
26
|
+
page: 1,
|
|
27
|
+
nextPage: 1,
|
|
28
|
+
stageId: "",
|
|
29
|
+
totalItems: 1,
|
|
30
|
+
numOfPages: 1,
|
|
31
|
+
currentPage: 1,
|
|
32
|
+
search: "",
|
|
33
|
+
filterPropertyName: "hs_pipeline",
|
|
34
|
+
filterOperator: "eq",
|
|
35
|
+
filterValue: "",
|
|
36
|
+
isPrimaryCompany: null,
|
|
37
|
+
view: null,
|
|
38
|
+
selectedPipeline: "",
|
|
39
|
+
tableParam: {},
|
|
40
|
+
tableDefPermissions: {}
|
|
41
|
+
});
|
|
42
|
+
noteStore.setState({ notes: [], prependNotes: [], id: "", queryParams: null });
|
|
43
|
+
emailStore.setState({ emails: [], prependEmails: [], id: "", queryParams: null });
|
|
44
|
+
userStore.setState({ profile: null });
|
|
45
|
+
syncStore.setState({
|
|
46
|
+
apiSync: false,
|
|
47
|
+
sync: false,
|
|
48
|
+
isSyncLoading: false,
|
|
49
|
+
isSyncDisable: false
|
|
50
|
+
});
|
|
51
|
+
formStore.setState({ form: null });
|
|
52
|
+
fileStore.setState({ files: null, id: "", queryParams: null });
|
|
53
|
+
multiObjectStore.setState({ objects: {}, objectsPrependData: {}, meta: {} });
|
|
54
|
+
objectStore.setState({ object: null, id: "" });
|
|
55
|
+
}
|
|
56
|
+
function clearClientSdkSession() {
|
|
57
|
+
const subscriptionType = getSubscriptionType();
|
|
58
|
+
clearAdapterSessionData();
|
|
59
|
+
clearClientAuthCookies();
|
|
60
|
+
if (subscriptionType != null && subscriptionType !== "") {
|
|
61
|
+
void setSubscriptionType(subscriptionType);
|
|
62
|
+
}
|
|
63
|
+
clearClientIframeRefreshLocalKeys();
|
|
64
|
+
clearAccessToken();
|
|
65
|
+
resetSessionStores();
|
|
66
|
+
resetSessionAuthState();
|
|
67
|
+
clearSessionRefreshExhaustedState();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/main/core/http/cross-tab-session.ts
|
|
71
|
+
var REV_KEY = WP_STORAGE_KEYS.c.auth.rev;
|
|
72
|
+
var CHANNEL_NAME = "woodsportal:session-sync";
|
|
73
|
+
function writeRevSignal() {
|
|
74
|
+
if (typeof window === "undefined" || !window.localStorage) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
window.localStorage.setItem(REV_KEY, String(Date.now()));
|
|
79
|
+
} catch {
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function getBroadcastChannel() {
|
|
83
|
+
if (typeof BroadcastChannel === "undefined") {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
return new BroadcastChannel(CHANNEL_NAME);
|
|
88
|
+
} catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function signalSessionChanged(kind = "rev") {
|
|
93
|
+
writeRevSignal();
|
|
94
|
+
const channel = getBroadcastChannel();
|
|
95
|
+
if (channel) {
|
|
96
|
+
const message = { type: kind, ts: Date.now() };
|
|
97
|
+
channel.postMessage(message);
|
|
98
|
+
channel.close();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
var listenerInstalled = false;
|
|
102
|
+
var broadcastChannel = null;
|
|
103
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
104
|
+
function dispatch(kind) {
|
|
105
|
+
listeners.forEach((fn) => {
|
|
106
|
+
try {
|
|
107
|
+
fn(kind);
|
|
108
|
+
} catch {
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
function handleRemoteSessionChange(kind) {
|
|
113
|
+
if (kind === "rev") {
|
|
114
|
+
clearAccessToken();
|
|
115
|
+
}
|
|
116
|
+
dispatch(kind);
|
|
117
|
+
}
|
|
118
|
+
function installCrossTabSessionListener(onChange) {
|
|
119
|
+
if (getClientType() === "mobile") {
|
|
120
|
+
return () => void 0;
|
|
121
|
+
}
|
|
122
|
+
if (typeof window === "undefined") {
|
|
123
|
+
return () => void 0;
|
|
124
|
+
}
|
|
125
|
+
if (onChange) {
|
|
126
|
+
listeners.add(onChange);
|
|
127
|
+
}
|
|
128
|
+
if (!listenerInstalled) {
|
|
129
|
+
listenerInstalled = true;
|
|
130
|
+
window.addEventListener("storage", (event) => {
|
|
131
|
+
if (event.key !== REV_KEY || event.newValue == null) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
handleRemoteSessionChange("rev");
|
|
135
|
+
});
|
|
136
|
+
try {
|
|
137
|
+
broadcastChannel?.close();
|
|
138
|
+
broadcastChannel = new BroadcastChannel(CHANNEL_NAME);
|
|
139
|
+
broadcastChannel.onmessage = (event) => {
|
|
140
|
+
const kind = event.data?.type === "login" ? "login" : "rev";
|
|
141
|
+
handleRemoteSessionChange(kind);
|
|
142
|
+
};
|
|
143
|
+
} catch {
|
|
144
|
+
}
|
|
145
|
+
window.addEventListener("pageshow", (event) => {
|
|
146
|
+
if (event.persisted) {
|
|
147
|
+
handleRemoteSessionChange("rev");
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return () => {
|
|
152
|
+
if (onChange) {
|
|
153
|
+
listeners.delete(onChange);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function applyCrossTabSessionRevocation() {
|
|
158
|
+
clearClientSdkSession();
|
|
159
|
+
}
|
|
160
|
+
function resetCrossTabSessionSyncForTests() {
|
|
161
|
+
try {
|
|
162
|
+
broadcastChannel?.close();
|
|
163
|
+
} catch {
|
|
164
|
+
}
|
|
165
|
+
broadcastChannel = null;
|
|
166
|
+
listenerInstalled = false;
|
|
167
|
+
listeners.clear();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export { applyCrossTabSessionRevocation, clearClientSdkSession, installCrossTabSessionListener, resetCrossTabSessionSyncForTests, resetSessionStores, signalSessionChanged };
|
|
171
|
+
//# sourceMappingURL=chunk-D5GHE2CO.js.map
|
|
172
|
+
//# sourceMappingURL=chunk-D5GHE2CO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/main/core/http/session-teardown.ts","../src/main/core/http/cross-tab-session.ts"],"names":["actions"],"mappings":"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","file":"chunk-D5GHE2CO.js","sourcesContent":["import { clearAccessToken, clearSessionRefreshExhaustedState, resetSessionAuthState } from './token-store'\nimport { clearAdapterSessionData, getSubscriptionType, setSubscriptionType } from './auth-utils'\nimport { clearClientAuthCookies } from '../utils/cookie'\nimport { clearClientIframeRefreshLocalKeys } from '../utils/storage-migration'\nimport {\n tableStore,\n tableActions,\n tableUiStore,\n noteStore,\n emailStore,\n userStore,\n syncStore,\n formStore,\n fileStore,\n multiObjectStore,\n objectStore\n} from '../../state/index.js'\n\n/** Reset CRM nanostores to empty session state (logout / forced 401). */\nexport function resetSessionStores(): void {\n tableActions.clearTablePrependData()\n tableStore.setState({\n queryParams: null,\n multiObjectsQueryParams: {},\n objectsData: null,\n tableData: [],\n tablePrependData: [],\n hubspotObjectTypeId: '',\n selectedPipeline: '',\n viewType: ''\n })\n tableUiStore.setState({\n tableUniqueId: null,\n gridData: [],\n sort: '-hs_createdate',\n limit: 10,\n after: '',\n page: 1,\n nextPage: 1,\n stageId: '',\n totalItems: 1,\n numOfPages: 1,\n currentPage: 1,\n search: '',\n filterPropertyName: 'hs_pipeline',\n filterOperator: 'eq',\n filterValue: '',\n isPrimaryCompany: null,\n view: null,\n selectedPipeline: '',\n tableParam: {},\n tableDefPermissions: {}\n })\n noteStore.setState({ notes: [], prependNotes: [], id: '', queryParams: null })\n emailStore.setState({ emails: [], prependEmails: [], id: '', queryParams: null })\n userStore.setState({ profile: null })\n syncStore.setState({\n apiSync: false,\n sync: false,\n isSyncLoading: false,\n isSyncDisable: false\n })\n formStore.setState({ form: null })\n fileStore.setState({ files: null, id: '', queryParams: null })\n multiObjectStore.setState({ objects: {}, objectsPrependData: {}, meta: {} })\n objectStore.setState({ object: null, id: '' })\n}\n\n/**\n * Full client SDK session teardown (cookies, sessionStorage, iframe keys, memory token, CRM stores).\n * Consumer apps should also clear TanStack Query + local UI state after calling this.\n * Preserves the subscription cookie/storage key so non-auth plan metadata is not lost during\n * incidental session cleanup; explicit logout still clears it through `clearClientAuthCookies()`.\n */\nexport function clearClientSdkSession(): void {\n const subscriptionType = getSubscriptionType()\n clearAdapterSessionData()\n clearClientAuthCookies()\n if (subscriptionType != null && subscriptionType !== '') {\n void setSubscriptionType(subscriptionType)\n }\n clearClientIframeRefreshLocalKeys()\n clearAccessToken()\n resetSessionStores()\n resetSessionAuthState()\n clearSessionRefreshExhaustedState()\n}\n","import { WP_STORAGE_KEYS } from '../utils/wp-storage-keys'\nimport { getClientType } from './client-type'\nimport { clearClientSdkSession } from './session-teardown'\nimport { clearAccessToken } from './token-store'\n\nconst REV_KEY = WP_STORAGE_KEYS.c.auth.rev\nconst CHANNEL_NAME = 'woodsportal:session-sync'\n\ntype SessionSyncMessage = { type: 'rev' | 'login'; ts: number }\n\nfunction writeRevSignal(): void {\n if (typeof window === 'undefined' || !window.localStorage) {\n return\n }\n try {\n window.localStorage.setItem(REV_KEY, String(Date.now()))\n } catch {\n // ignore\n }\n}\n\nfunction getBroadcastChannel(): BroadcastChannel | null {\n if (typeof BroadcastChannel === 'undefined') {\n return null\n }\n try {\n return new BroadcastChannel(CHANNEL_NAME)\n } catch {\n return null\n }\n}\n\n/** Notify other tabs that session ended or restarted. */\nexport function signalSessionChanged(kind: 'rev' | 'login' = 'rev'): void {\n writeRevSignal()\n const channel = getBroadcastChannel()\n if (channel) {\n const message: SessionSyncMessage = { type: kind, ts: Date.now() }\n channel.postMessage(message)\n channel.close()\n }\n}\n\nexport type SessionSyncListener = (kind: 'rev' | 'login') => void\n\nlet listenerInstalled = false\nlet broadcastChannel: BroadcastChannel | null = null\nconst listeners = new Set<SessionSyncListener>()\n\nfunction dispatch(kind: 'rev' | 'login'): void {\n listeners.forEach((fn) => {\n try {\n fn(kind)\n } catch {\n // consumer error\n }\n })\n}\n\nfunction handleRemoteSessionChange(kind: 'rev' | 'login'): void {\n if (kind === 'rev') {\n clearAccessToken()\n }\n dispatch(kind)\n}\n\n/**\n * Listen for logout/login in other tabs (localStorage + BroadcastChannel).\n * Returns unsubscribe function.\n */\nexport function installCrossTabSessionListener(onChange?: SessionSyncListener): () => void {\n if (getClientType() === 'mobile') {\n return () => undefined\n }\n\n if (typeof window === 'undefined') {\n return () => undefined\n }\n\n if (onChange) {\n listeners.add(onChange)\n }\n\n if (!listenerInstalled) {\n listenerInstalled = true\n\n window.addEventListener('storage', (event) => {\n if (event.key !== REV_KEY || event.newValue == null) {\n return\n }\n handleRemoteSessionChange('rev')\n })\n\n try {\n broadcastChannel?.close()\n broadcastChannel = new BroadcastChannel(CHANNEL_NAME)\n broadcastChannel.onmessage = (event: MessageEvent<SessionSyncMessage>) => {\n const kind = event.data?.type === 'login' ? 'login' : 'rev'\n handleRemoteSessionChange(kind)\n }\n } catch {\n // BroadcastChannel unavailable\n }\n\n window.addEventListener('pageshow', (event) => {\n if (event.persisted) {\n handleRemoteSessionChange('rev')\n }\n })\n }\n\n return () => {\n if (onChange) {\n listeners.delete(onChange)\n }\n }\n}\n\n/** Remote tab signalled logout — clear readable session artifacts. */\nexport function applyCrossTabSessionRevocation(): void {\n clearClientSdkSession()\n}\n\n/** Test-only: close BroadcastChannel and allow listener reinstall (prevents open-handle hangs). */\nexport function resetCrossTabSessionSyncForTests(): void {\n try {\n broadcastChannel?.close()\n } catch {\n // ignore\n }\n broadcastChannel = null\n listenerInstalled = false\n listeners.clear()\n}\n"]}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// src/main/core/storage/session-storage-registry.ts
|
|
2
|
+
var adapter = null;
|
|
3
|
+
function registerSessionStorageAdapter(next) {
|
|
4
|
+
adapter = next;
|
|
5
|
+
}
|
|
6
|
+
function getSessionStorageAdapter() {
|
|
7
|
+
return adapter;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/main/core/storage/session-scoped-storage.ts
|
|
11
|
+
function getBrowserSessionStorage() {
|
|
12
|
+
if (typeof globalThis === "undefined") {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
if (globalThis.sessionStorage != null) {
|
|
17
|
+
return globalThis.sessionStorage;
|
|
18
|
+
}
|
|
19
|
+
const win = globalThis.window;
|
|
20
|
+
return win?.sessionStorage ?? null;
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function readSessionScopedItem(key) {
|
|
26
|
+
const adapter2 = getSessionStorageAdapter();
|
|
27
|
+
if (adapter2) {
|
|
28
|
+
return adapter2.getItem(key);
|
|
29
|
+
}
|
|
30
|
+
const storage = getBrowserSessionStorage();
|
|
31
|
+
if (!storage) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
return storage.getItem(key);
|
|
36
|
+
} catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function writeSessionScopedItem(key, value) {
|
|
41
|
+
const adapter2 = getSessionStorageAdapter();
|
|
42
|
+
if (adapter2) {
|
|
43
|
+
adapter2.setItem(key, value);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const storage = getBrowserSessionStorage();
|
|
47
|
+
if (!storage) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
storage.setItem(key, value);
|
|
52
|
+
} catch {
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function removeSessionScopedItem(key) {
|
|
56
|
+
const adapter2 = getSessionStorageAdapter();
|
|
57
|
+
if (adapter2) {
|
|
58
|
+
adapter2.removeItem(key);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const storage = getBrowserSessionStorage();
|
|
62
|
+
if (!storage) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
storage.removeItem(key);
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { getSessionStorageAdapter, readSessionScopedItem, registerSessionStorageAdapter, removeSessionScopedItem, writeSessionScopedItem };
|
|
72
|
+
//# sourceMappingURL=chunk-DB6W3CJT.js.map
|
|
73
|
+
//# sourceMappingURL=chunk-DB6W3CJT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/main/core/storage/session-storage-registry.ts","../src/main/core/storage/session-scoped-storage.ts"],"names":["adapter"],"mappings":";AAEA,IAAI,OAAA,GAAwC,IAAA;AAErC,SAAS,8BAA8B,IAAA,EAAmC;AAC7E,EAAA,OAAA,GAAU,IAAA;AACd;AAEO,SAAS,wBAAA,GAAyD;AACrE,EAAA,OAAO,OAAA;AACX;;;ACRA,SAAS,wBAAA,GAA2C;AAChD,EAAA,IAAI,OAAO,eAAe,WAAA,EAAa;AACnC,IAAA,OAAO,IAAA;AAAA,EACX;AACA,EAAA,IAAI;AACA,IAAA,IAAI,UAAA,CAAW,kBAAkB,IAAA,EAAM;AACnC,MAAA,OAAO,UAAA,CAAW,cAAA;AAAA,IACtB;AACA,IAAA,MAAM,MAAM,UAAA,CAAW,MAAA;AACvB,IAAA,OAAO,KAAK,cAAA,IAAkB,IAAA;AAAA,EAClC,CAAA,CAAA,MAAQ;AACJ,IAAA,OAAO,IAAA;AAAA,EACX;AACJ;AAGO,SAAS,sBAAsB,GAAA,EAA4B;AAC9D,EAAA,MAAMA,WAAU,wBAAA,EAAyB;AACzC,EAAA,IAAIA,QAAAA,EAAS;AACT,IAAA,OAAOA,QAAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,EAC9B;AAEA,EAAA,MAAM,UAAU,wBAAA,EAAyB;AACzC,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA,OAAO,IAAA;AAAA,EACX;AAEA,EAAA,IAAI;AACA,IAAA,OAAO,OAAA,CAAQ,QAAQ,GAAG,CAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AACJ,IAAA,OAAO,IAAA;AAAA,EACX;AACJ;AAEO,SAAS,sBAAA,CAAuB,KAAa,KAAA,EAAqB;AACrE,EAAA,MAAMA,WAAU,wBAAA,EAAyB;AACzC,EAAA,IAAIA,QAAAA,EAAS;AACT,IAAAA,QAAAA,CAAQ,OAAA,CAAQ,GAAA,EAAK,KAAK,CAAA;AAC1B,IAAA;AAAA,EACJ;AAEA,EAAA,MAAM,UAAU,wBAAA,EAAyB;AACzC,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA;AAAA,EACJ;AAEA,EAAA,IAAI;AACA,IAAA,OAAA,CAAQ,OAAA,CAAQ,KAAK,KAAK,CAAA;AAAA,EAC9B,CAAA,CAAA,MAAQ;AAAA,EAER;AACJ;AAEO,SAAS,wBAAwB,GAAA,EAAmB;AACvD,EAAA,MAAMA,WAAU,wBAAA,EAAyB;AACzC,EAAA,IAAIA,QAAAA,EAAS;AACT,IAAAA,QAAAA,CAAQ,WAAW,GAAG,CAAA;AACtB,IAAA;AAAA,EACJ;AAEA,EAAA,MAAM,UAAU,wBAAA,EAAyB;AACzC,EAAA,IAAI,CAAC,OAAA,EAAS;AACV,IAAA;AAAA,EACJ;AAEA,EAAA,IAAI;AACA,IAAA,OAAA,CAAQ,WAAW,GAAG,CAAA;AAAA,EAC1B,CAAA,CAAA,MAAQ;AAAA,EAER;AACJ","file":"chunk-DB6W3CJT.js","sourcesContent":["import type { SessionStorageAdapter } from './session-storage-adapter'\n\nlet adapter: SessionStorageAdapter | null = null\n\nexport function registerSessionStorageAdapter(next: SessionStorageAdapter): void {\n adapter = next\n}\n\nexport function getSessionStorageAdapter(): SessionStorageAdapter | null {\n return adapter\n}\n\n/** Test helper — restore default web cookie storage for refresh tokens. */\nexport function clearSessionStorageAdapterForTests(): void {\n adapter = null\n}\n","import { getSessionStorageAdapter } from './session-storage-registry'\n\nfunction getBrowserSessionStorage(): Storage | null {\n if (typeof globalThis === 'undefined') {\n return null\n }\n try {\n if (globalThis.sessionStorage != null) {\n return globalThis.sessionStorage\n }\n const win = globalThis.window as (Window & typeof globalThis) | undefined\n return win?.sessionStorage ?? null\n } catch {\n return null\n }\n}\n\n/** Tab-scoped or adapter-backed ephemeral session keys (MFA pending, refresh exhausted, auth errors). */\nexport function readSessionScopedItem(key: string): string | null {\n const adapter = getSessionStorageAdapter()\n if (adapter) {\n return adapter.getItem(key)\n }\n\n const storage = getBrowserSessionStorage()\n if (!storage) {\n return null\n }\n\n try {\n return storage.getItem(key)\n } catch {\n return null\n }\n}\n\nexport function writeSessionScopedItem(key: string, value: string): void {\n const adapter = getSessionStorageAdapter()\n if (adapter) {\n adapter.setItem(key, value)\n return\n }\n\n const storage = getBrowserSessionStorage()\n if (!storage) {\n return\n }\n\n try {\n storage.setItem(key, value)\n } catch {\n // ignore quota / private mode\n }\n}\n\nexport function removeSessionScopedItem(key: string): void {\n const adapter = getSessionStorageAdapter()\n if (adapter) {\n adapter.removeItem(key)\n return\n }\n\n const storage = getBrowserSessionStorage()\n if (!storage) {\n return\n }\n\n try {\n storage.removeItem(key)\n } catch {\n // ignore\n }\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createAdapterHooks } from './chunk-OH7VT6MX.js';
|
|
2
|
+
import { useSyncExternalStore } from 'react';
|
|
3
|
+
|
|
4
|
+
function createReactStoreComposable(store, actions) {
|
|
5
|
+
return function useStore() {
|
|
6
|
+
const state = useSyncExternalStore(store.subscribe, store.getState, store.getState);
|
|
7
|
+
return { ...state, ...actions };
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// src/main/adapters/react/index.ts
|
|
12
|
+
var { useTable, useTableUi, useMultiObjectActions, useObject, useNote, useEmail, useUser, useSync, useUploader, useFile } = createAdapterHooks(createReactStoreComposable);
|
|
13
|
+
|
|
14
|
+
export { useEmail, useFile, useMultiObjectActions, useNote, useObject, useSync, useTable, useTableUi, useUploader, useUser };
|
|
15
|
+
//# sourceMappingURL=chunk-ITBMRGCP.js.map
|
|
16
|
+
//# sourceMappingURL=chunk-ITBMRGCP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/main/adapters/shared/createReactComposable.ts","../src/main/adapters/react/index.ts"],"names":[],"mappings":";;;AAGO,SAAS,0BAAA,CAA2E,OAAkC,OAAA,EAAmB;AAC5I,EAAA,OAAO,SAAS,QAAA,GAA8B;AAC1C,IAAA,MAAM,QAAQ,oBAAA,CAAqB,KAAA,CAAM,WAAW,KAAA,CAAM,QAAA,EAAU,MAAM,QAAQ,CAAA;AAClF,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,GAAG,OAAA,EAAQ;AAAA,EAClC,CAAA;AACJ;;;ACLO,IAAM,EAAE,QAAA,EAAU,UAAA,EAAY,qBAAA,EAAuB,SAAA,EAAW,OAAA,EAAS,QAAA,EAAU,OAAA,EAAS,OAAA,EAAS,WAAA,EAAa,OAAA,EAAQ,GAC7H,mBAAmB,0BAA0B","file":"chunk-ITBMRGCP.js","sourcesContent":["import { useSyncExternalStore } from 'react'\nimport type { SubscribableStore } from './bindStoreWithActions'\n\nexport function createReactStoreComposable<TState extends object, TActions extends object>(store: SubscribableStore<TState>, actions: TActions) {\n return function useStore(): TState & TActions {\n const state = useSyncExternalStore(store.subscribe, store.getState, store.getState)\n return { ...state, ...actions }\n }\n}\n","import { createAdapterHooks } from '../shared/createAdapterHooks'\nimport { createReactStoreComposable } from '../shared/createReactComposable'\n\nexport const { useTable, useTableUi, useMultiObjectActions, useObject, useNote, useEmail, useUser, useSync, useUploader, useFile } =\n createAdapterHooks(createReactStoreComposable)\n"]}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { writeSessionScopedItem, removeSessionScopedItem, readSessionScopedItem } from './chunk-DB6W3CJT.js';
|
|
2
|
+
import { WP_STORAGE_KEYS } from './chunk-KGNMN7B3.js';
|
|
3
|
+
import { AuthErrorCode } from './chunk-COHBSTHF.js';
|
|
4
|
+
|
|
5
|
+
// src/main/core/auth/auth-interceptor-policy.ts
|
|
6
|
+
var DEFAULT_SESSION_PROBE_SUFFIXES = ["/auth/me"];
|
|
7
|
+
var REFRESH_ENDPOINT_SUFFIXES = ["/auth/refresh", "/auth/refresh-cookie"];
|
|
8
|
+
function isRefreshEndpointUrl(url) {
|
|
9
|
+
const path = normalizeRequestUrl(url);
|
|
10
|
+
if (!path) return false;
|
|
11
|
+
return REFRESH_ENDPOINT_SUFFIXES.some((suffix) => path.endsWith(suffix));
|
|
12
|
+
}
|
|
13
|
+
function normalizeRequestUrl(url) {
|
|
14
|
+
if (!url) return "";
|
|
15
|
+
try {
|
|
16
|
+
if (url.startsWith("http")) {
|
|
17
|
+
return new URL(url).pathname;
|
|
18
|
+
}
|
|
19
|
+
} catch {
|
|
20
|
+
}
|
|
21
|
+
return url.split("?")[0] ?? url;
|
|
22
|
+
}
|
|
23
|
+
function isOptionalAuthFailureUrl(url, config) {
|
|
24
|
+
const path = normalizeRequestUrl(url);
|
|
25
|
+
if (!path) return false;
|
|
26
|
+
if (config.optionalAuthFailurePaths?.includes(path)) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if (config.includeAdminMfaSecurityPrefixes) {
|
|
30
|
+
if (path.includes("/api/admin/auth/security/")) return true;
|
|
31
|
+
if (path.includes("/api/admin/auth/mfa/webauthn/")) return true;
|
|
32
|
+
if (path.includes("/api/auth/security/")) return true;
|
|
33
|
+
if (path.includes("/api/auth/mfa/webauthn/")) return true;
|
|
34
|
+
}
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
function isSessionProbeUrl(url, config) {
|
|
38
|
+
const path = normalizeRequestUrl(url);
|
|
39
|
+
if (!path) return false;
|
|
40
|
+
if (config.sessionProbePaths?.includes(path)) return true;
|
|
41
|
+
return DEFAULT_SESSION_PROBE_SUFFIXES.some((suffix) => path.endsWith(suffix));
|
|
42
|
+
}
|
|
43
|
+
function persistAuthError(payload) {
|
|
44
|
+
const data = {
|
|
45
|
+
...payload,
|
|
46
|
+
ts: Date.now()
|
|
47
|
+
};
|
|
48
|
+
writeSessionScopedItem(WP_STORAGE_KEYS.c.auth.err, JSON.stringify(data));
|
|
49
|
+
removeSessionScopedItem("authError");
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
52
|
+
function readPersistedAuthError() {
|
|
53
|
+
const raw = readSessionScopedItem(WP_STORAGE_KEYS.c.auth.err) ?? readSessionScopedItem("authError");
|
|
54
|
+
if (!raw) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
return JSON.parse(raw);
|
|
59
|
+
} catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function logoutAction(errorCode, routes) {
|
|
64
|
+
if (errorCode === AuthErrorCode.HUBSPOT_REAUTH_REQUIRED) {
|
|
65
|
+
return {
|
|
66
|
+
kind: "redirect",
|
|
67
|
+
route: routes.accountSelect,
|
|
68
|
+
clearSession: false
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
kind: "logout",
|
|
73
|
+
route: routes.unauthorized,
|
|
74
|
+
clearSession: true
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function resolveByErrorCode(errorCode, status, url, isRetryRequest, policy) {
|
|
78
|
+
const { routes } = policy;
|
|
79
|
+
switch (errorCode) {
|
|
80
|
+
case AuthErrorCode.TOKEN_EXPIRED:
|
|
81
|
+
case AuthErrorCode.TOKEN_INVALID:
|
|
82
|
+
case AuthErrorCode.AUTHENTICATION_FAILED:
|
|
83
|
+
return isRetryRequest ? logoutAction(errorCode, routes) : { kind: "refresh_retry" };
|
|
84
|
+
case AuthErrorCode.MISSING_REFRESH_TOKEN:
|
|
85
|
+
case AuthErrorCode.ACCESS_UNAUTHORIZED:
|
|
86
|
+
return logoutAction(errorCode, routes);
|
|
87
|
+
case AuthErrorCode.ACCOUNT_LOCKED:
|
|
88
|
+
case AuthErrorCode.ACCOUNT_DISABLED:
|
|
89
|
+
return {
|
|
90
|
+
kind: "redirect",
|
|
91
|
+
route: routes.unauthorized,
|
|
92
|
+
clearSession: true
|
|
93
|
+
};
|
|
94
|
+
case AuthErrorCode.LOGIN_FAILED:
|
|
95
|
+
case AuthErrorCode.INVALID_CREDENTIALS:
|
|
96
|
+
return { kind: "reject" };
|
|
97
|
+
case AuthErrorCode.EMAIL_NOT_VERIFIED:
|
|
98
|
+
return {
|
|
99
|
+
kind: "redirect",
|
|
100
|
+
route: routes.resendEmail,
|
|
101
|
+
clearSession: false
|
|
102
|
+
};
|
|
103
|
+
case AuthErrorCode.TWO_FACTOR_REQUIRED:
|
|
104
|
+
return {
|
|
105
|
+
kind: "redirect",
|
|
106
|
+
route: routes.twoFa,
|
|
107
|
+
clearSession: false
|
|
108
|
+
};
|
|
109
|
+
case AuthErrorCode.HUBSPOT_REAUTH_REQUIRED:
|
|
110
|
+
return {
|
|
111
|
+
kind: "redirect",
|
|
112
|
+
route: routes.accountSelect,
|
|
113
|
+
clearSession: false
|
|
114
|
+
};
|
|
115
|
+
case AuthErrorCode.OAUTH_PROCESSING_ERROR:
|
|
116
|
+
case AuthErrorCode.PORTAL_INACTIVE:
|
|
117
|
+
case AuthErrorCode.AMBIGUOUS_HUB_ID:
|
|
118
|
+
case AuthErrorCode.MISSING_HEADERS:
|
|
119
|
+
case AuthErrorCode.COMMERCIAL_ACCESS_EXPIRED:
|
|
120
|
+
return { kind: "reject" };
|
|
121
|
+
case AuthErrorCode.ACCESS_DENIED:
|
|
122
|
+
case AuthErrorCode.ACCESS_FORBIDDEN:
|
|
123
|
+
if (isSessionProbeUrl(url, policy)) {
|
|
124
|
+
return {
|
|
125
|
+
kind: "redirect",
|
|
126
|
+
route: routes.unauthorized,
|
|
127
|
+
clearSession: false
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
return { kind: "reject" };
|
|
131
|
+
default:
|
|
132
|
+
if (status === 401) {
|
|
133
|
+
return isRetryRequest ? logoutAction(errorCode, routes) : { kind: "refresh_retry" };
|
|
134
|
+
}
|
|
135
|
+
if (status === 403) {
|
|
136
|
+
return isSessionProbeUrl(url, policy) ? {
|
|
137
|
+
kind: "redirect",
|
|
138
|
+
route: routes.unauthorized,
|
|
139
|
+
clearSession: false
|
|
140
|
+
} : { kind: "reject" };
|
|
141
|
+
}
|
|
142
|
+
return { kind: "reject" };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function resolveAuthErrorAction(input) {
|
|
146
|
+
const { status, errorCode, url, skipGlobalAuthRedirect, isRetryRequest, policy } = input;
|
|
147
|
+
if (status !== 401 && status !== 403) {
|
|
148
|
+
return { kind: "reject" };
|
|
149
|
+
}
|
|
150
|
+
if (skipGlobalAuthRedirect || isOptionalAuthFailureUrl(url, policy)) {
|
|
151
|
+
return { kind: "reject" };
|
|
152
|
+
}
|
|
153
|
+
if (isRefreshEndpointUrl(url)) {
|
|
154
|
+
return { kind: "reject" };
|
|
155
|
+
}
|
|
156
|
+
return resolveByErrorCode(errorCode, status, url ?? "", isRetryRequest, policy);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export { isOptionalAuthFailureUrl, isRefreshEndpointUrl, isSessionProbeUrl, persistAuthError, readPersistedAuthError, resolveAuthErrorAction };
|
|
160
|
+
//# sourceMappingURL=chunk-JRT5XSVY.js.map
|
|
161
|
+
//# sourceMappingURL=chunk-JRT5XSVY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/main/core/auth/auth-interceptor-policy.ts"],"names":[],"mappings":"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","file":"chunk-JRT5XSVY.js","sourcesContent":["import { AuthErrorCode, type ApiErrorPayload } from './auth-error-codes.js'\nimport { WP_STORAGE_KEYS } from '../utils/wp-storage-keys.js'\nimport { readSessionScopedItem, removeSessionScopedItem, writeSessionScopedItem } from '../storage/session-scoped-storage.js'\n\nexport type WoodsportalRequestConfig = {\n __isRetryRequest?: boolean\n skipGlobalAuthRedirect?: boolean\n url?: string\n}\n\nexport type AuthErrorAction =\n | { kind: 'refresh_retry' }\n | { kind: 'reject' }\n | { kind: 'redirect'; route: string; clearSession: boolean }\n | { kind: 'logout'; route: string; clearSession: boolean }\n\n/** Lane-specific routes for auth error redirects (hash or path prefixes supplied by each app). */\nexport type AuthPolicyRoutes = {\n unauthorized: string\n login: string\n twoFa: string\n resendEmail: string\n accountSelect: string\n}\n\nexport type AuthInterceptorPolicyConfig = {\n routes: AuthPolicyRoutes\n /** Request paths that must not trigger global logout (e.g. MFA enrollment). */\n optionalAuthFailurePaths?: string[]\n /** Paths treated as session probes (401/403 → unauthorized page). */\n sessionProbePaths?: string[]\n /** When true, optional MFA/security path prefixes match. */\n includeAdminMfaSecurityPrefixes?: boolean\n}\n\nconst DEFAULT_SESSION_PROBE_SUFFIXES = ['/auth/me']\n\nconst REFRESH_ENDPOINT_SUFFIXES = ['/auth/refresh', '/auth/refresh-cookie'] as const\n\n/** True when the failed request is a token refresh call (must not trigger nested refresh_retry). */\nexport function isRefreshEndpointUrl(url: string | undefined): boolean {\n const path = normalizeRequestUrl(url)\n if (!path) return false\n return REFRESH_ENDPOINT_SUFFIXES.some((suffix) => path.endsWith(suffix))\n}\n\nfunction normalizeRequestUrl(url?: string): string {\n if (!url) return ''\n try {\n if (url.startsWith('http')) {\n return new URL(url).pathname\n }\n } catch {\n // fall through\n }\n return url.split('?')[0] ?? url\n}\n\nexport function isOptionalAuthFailureUrl(url: string | undefined, config: AuthInterceptorPolicyConfig): boolean {\n const path = normalizeRequestUrl(url)\n if (!path) return false\n\n if (config.optionalAuthFailurePaths?.includes(path)) {\n return true\n }\n\n if (config.includeAdminMfaSecurityPrefixes) {\n if (path.includes('/api/admin/auth/security/')) return true\n if (path.includes('/api/admin/auth/mfa/webauthn/')) return true\n if (path.includes('/api/auth/security/')) return true\n if (path.includes('/api/auth/mfa/webauthn/')) return true\n }\n\n return false\n}\n\nexport function isSessionProbeUrl(url: string | undefined, config: AuthInterceptorPolicyConfig): boolean {\n const path = normalizeRequestUrl(url)\n if (!path) return false\n if (config.sessionProbePaths?.includes(path)) return true\n return DEFAULT_SESSION_PROBE_SUFFIXES.some((suffix) => path.endsWith(suffix))\n}\n\nexport function persistAuthError(payload: ApiErrorPayload): ApiErrorPayload & { ts: number } {\n const data = {\n ...payload,\n ts: Date.now()\n }\n writeSessionScopedItem(WP_STORAGE_KEYS.c.auth.err, JSON.stringify(data))\n removeSessionScopedItem('authError')\n return data\n}\n\n/** Read persisted auth error (canonical key with legacy fallback). */\nexport function readPersistedAuthError(): (ApiErrorPayload & { ts: number }) | null {\n const raw = readSessionScopedItem(WP_STORAGE_KEYS.c.auth.err) ?? readSessionScopedItem('authError')\n if (!raw) {\n return null\n }\n try {\n return JSON.parse(raw) as ApiErrorPayload & { ts: number }\n } catch {\n return null\n }\n}\n\nfunction logoutAction(errorCode: string | undefined, routes: AuthPolicyRoutes): AuthErrorAction {\n if (errorCode === AuthErrorCode.HUBSPOT_REAUTH_REQUIRED) {\n return {\n kind: 'redirect',\n route: routes.accountSelect,\n clearSession: false\n }\n }\n return {\n kind: 'logout',\n route: routes.unauthorized,\n clearSession: true\n }\n}\n\nfunction resolveByErrorCode(\n errorCode: string | undefined,\n status: number,\n url: string,\n isRetryRequest: boolean | undefined,\n policy: AuthInterceptorPolicyConfig\n): AuthErrorAction {\n const { routes } = policy\n\n switch (errorCode) {\n case AuthErrorCode.TOKEN_EXPIRED:\n case AuthErrorCode.TOKEN_INVALID:\n case AuthErrorCode.AUTHENTICATION_FAILED:\n return isRetryRequest ? logoutAction(errorCode, routes) : { kind: 'refresh_retry' }\n\n case AuthErrorCode.MISSING_REFRESH_TOKEN:\n case AuthErrorCode.ACCESS_UNAUTHORIZED:\n return logoutAction(errorCode, routes)\n\n case AuthErrorCode.ACCOUNT_LOCKED:\n case AuthErrorCode.ACCOUNT_DISABLED:\n return {\n kind: 'redirect',\n route: routes.unauthorized,\n clearSession: true\n }\n\n case AuthErrorCode.LOGIN_FAILED:\n case AuthErrorCode.INVALID_CREDENTIALS:\n return { kind: 'reject' }\n\n case AuthErrorCode.EMAIL_NOT_VERIFIED:\n return {\n kind: 'redirect',\n route: routes.resendEmail,\n clearSession: false\n }\n\n case AuthErrorCode.TWO_FACTOR_REQUIRED:\n return {\n kind: 'redirect',\n route: routes.twoFa,\n clearSession: false\n }\n\n case AuthErrorCode.HUBSPOT_REAUTH_REQUIRED:\n return {\n kind: 'redirect',\n route: routes.accountSelect,\n clearSession: false\n }\n\n case AuthErrorCode.OAUTH_PROCESSING_ERROR:\n case AuthErrorCode.PORTAL_INACTIVE:\n case AuthErrorCode.AMBIGUOUS_HUB_ID:\n case AuthErrorCode.MISSING_HEADERS:\n case AuthErrorCode.COMMERCIAL_ACCESS_EXPIRED:\n return { kind: 'reject' }\n\n case AuthErrorCode.ACCESS_DENIED:\n case AuthErrorCode.ACCESS_FORBIDDEN:\n if (isSessionProbeUrl(url, policy)) {\n return {\n kind: 'redirect',\n route: routes.unauthorized,\n clearSession: false\n }\n }\n return { kind: 'reject' }\n\n default:\n if (status === 401) {\n return isRetryRequest ? logoutAction(errorCode, routes) : { kind: 'refresh_retry' }\n }\n if (status === 403) {\n return isSessionProbeUrl(url, policy)\n ? {\n kind: 'redirect',\n route: routes.unauthorized,\n clearSession: false\n }\n : { kind: 'reject' }\n }\n return { kind: 'reject' }\n }\n}\n\nexport function resolveAuthErrorAction(input: {\n status: number\n errorCode?: string\n url?: string\n skipGlobalAuthRedirect?: boolean\n isRetryRequest?: boolean\n policy: AuthInterceptorPolicyConfig\n}): AuthErrorAction {\n const { status, errorCode, url, skipGlobalAuthRedirect, isRetryRequest, policy } = input\n\n if (status !== 401 && status !== 403) {\n return { kind: 'reject' }\n }\n\n if (skipGlobalAuthRedirect || isOptionalAuthFailureUrl(url, policy)) {\n return { kind: 'reject' }\n }\n\n if (isRefreshEndpointUrl(url)) {\n return { kind: 'reject' }\n }\n\n return resolveByErrorCode(errorCode, status, url ?? '', isRetryRequest, policy)\n}\n"]}
|