authvital-sdk 0.1.1-dev.3.cefb119.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/README.md +657 -0
- package/dist/chunk-ETJ5ICJ7.mjs +412 -0
- package/dist/chunk-FXVD4Y5G.js +412 -0
- package/dist/chunk-JNEJMHGA.mjs +235 -0
- package/dist/chunk-JPODZIZT.mjs +95 -0
- package/dist/chunk-QPYBK2J4.js +235 -0
- package/dist/chunk-R4OHZZQP.js +95 -0
- package/dist/index.d.mts +615 -0
- package/dist/index.d.ts +615 -0
- package/dist/index.js +1299 -0
- package/dist/index.mjs +1299 -0
- package/dist/invitations-EFJA5C6L.mjs +22 -0
- package/dist/invitations-LZHJ3AZY.js +22 -0
- package/dist/oauth-K7E7OCWI.js +34 -0
- package/dist/oauth-UAFXEKZ7.mjs +34 -0
- package/dist/server.d.mts +2656 -0
- package/dist/server.d.ts +2656 -0
- package/dist/server.js +2915 -0
- package/dist/server.mjs +2915 -0
- package/dist/webhook-router-DdfXLtHa.d.mts +461 -0
- package/dist/webhook-router-DdfXLtHa.d.ts +461 -0
- package/package.json +71 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// src/client/invitations.ts
|
|
2
|
+
var INVITE_TOKEN_KEY = "authvital_invite_token";
|
|
3
|
+
function storeInviteToken(token) {
|
|
4
|
+
if (typeof window === "undefined") return;
|
|
5
|
+
sessionStorage.setItem(INVITE_TOKEN_KEY, token);
|
|
6
|
+
}
|
|
7
|
+
function getStoredInviteToken() {
|
|
8
|
+
if (typeof window === "undefined") return null;
|
|
9
|
+
return sessionStorage.getItem(INVITE_TOKEN_KEY);
|
|
10
|
+
}
|
|
11
|
+
function clearStoredInviteToken() {
|
|
12
|
+
if (typeof window === "undefined") return;
|
|
13
|
+
sessionStorage.removeItem(INVITE_TOKEN_KEY);
|
|
14
|
+
}
|
|
15
|
+
function captureInviteTokenFromUrl() {
|
|
16
|
+
if (typeof window === "undefined") return null;
|
|
17
|
+
const params = new URLSearchParams(window.location.search);
|
|
18
|
+
const token = params.get("invite_token") || params.get("token");
|
|
19
|
+
if (token && window.location.pathname.includes("/invite")) {
|
|
20
|
+
storeInviteToken(token);
|
|
21
|
+
return token;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
async function getInvitation(authVitalHost, token) {
|
|
26
|
+
const response = await fetch(`${authVitalHost}/api/invitations/token/${token}`);
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
const error = await response.json().catch(() => ({}));
|
|
29
|
+
throw new Error(error.message || `Failed to get invitation: ${response.status}`);
|
|
30
|
+
}
|
|
31
|
+
return response.json();
|
|
32
|
+
}
|
|
33
|
+
async function createInvitation(authVitalHost, _accessToken, params) {
|
|
34
|
+
const response = await fetch(`${authVitalHost}/api/invitations`, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: { "Content-Type": "application/json" },
|
|
37
|
+
credentials: "include",
|
|
38
|
+
// Send httpOnly cookie
|
|
39
|
+
body: JSON.stringify(params)
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const error = await response.json().catch(() => ({}));
|
|
43
|
+
throw new Error(error.message || `Failed to create invitation: ${response.status}`);
|
|
44
|
+
}
|
|
45
|
+
return response.json();
|
|
46
|
+
}
|
|
47
|
+
async function consumeInvitation(authVitalHost, _accessToken, token) {
|
|
48
|
+
const response = await fetch(`${authVitalHost}/api/invitations/consume`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: { "Content-Type": "application/json" },
|
|
51
|
+
credentials: "include",
|
|
52
|
+
// Send httpOnly cookie
|
|
53
|
+
body: JSON.stringify({ token })
|
|
54
|
+
});
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
const error = await response.json().catch(() => ({}));
|
|
57
|
+
throw new Error(error.message || `Failed to consume invitation: ${response.status}`);
|
|
58
|
+
}
|
|
59
|
+
return response.json();
|
|
60
|
+
}
|
|
61
|
+
async function listTenantInvitations(authVitalHost, _accessToken, tenantId) {
|
|
62
|
+
const response = await fetch(`${authVitalHost}/api/invitations/tenant/${tenantId}`, {
|
|
63
|
+
credentials: "include"
|
|
64
|
+
// Send httpOnly cookie
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const error = await response.json().catch(() => ({}));
|
|
68
|
+
throw new Error(error.message || `Failed to list invitations: ${response.status}`);
|
|
69
|
+
}
|
|
70
|
+
return response.json();
|
|
71
|
+
}
|
|
72
|
+
async function revokeInvitation(authVitalHost, _accessToken, invitationId) {
|
|
73
|
+
const response = await fetch(`${authVitalHost}/api/invitations/${invitationId}`, {
|
|
74
|
+
method: "DELETE",
|
|
75
|
+
credentials: "include"
|
|
76
|
+
// Send httpOnly cookie
|
|
77
|
+
});
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
const error = await response.json().catch(() => ({}));
|
|
80
|
+
throw new Error(error.message || `Failed to revoke invitation: ${response.status}`);
|
|
81
|
+
}
|
|
82
|
+
return response.json();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export {
|
|
86
|
+
storeInviteToken,
|
|
87
|
+
getStoredInviteToken,
|
|
88
|
+
clearStoredInviteToken,
|
|
89
|
+
captureInviteTokenFromUrl,
|
|
90
|
+
getInvitation,
|
|
91
|
+
createInvitation,
|
|
92
|
+
consumeInvitation,
|
|
93
|
+
listTenantInvitations,
|
|
94
|
+
revokeInvitation
|
|
95
|
+
};
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/client/oauth.ts
|
|
2
|
+
function encodeState(csrf, codeVerifier) {
|
|
3
|
+
const encodedVerifier = btoa(codeVerifier).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
4
|
+
return `${csrf}:${encodedVerifier}`;
|
|
5
|
+
}
|
|
6
|
+
function decodeState(state) {
|
|
7
|
+
const colonIndex = state.indexOf(":");
|
|
8
|
+
if (colonIndex === -1) return null;
|
|
9
|
+
const csrf = state.substring(0, colonIndex);
|
|
10
|
+
const encodedVerifier = state.substring(colonIndex + 1);
|
|
11
|
+
try {
|
|
12
|
+
const padded = encodedVerifier + "===".slice(0, (4 - encodedVerifier.length % 4) % 4);
|
|
13
|
+
const codeVerifier = atob(padded.replace(/-/g, "+").replace(/_/g, "/"));
|
|
14
|
+
return { csrf, codeVerifier };
|
|
15
|
+
} catch (e) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function loginToAuthVital(authVitalHost, options) {
|
|
20
|
+
const screen = _optionalChain([options, 'optionalAccess', _ => _.screen]) || "login";
|
|
21
|
+
const page = screen === "signup" ? "/auth/signup" : "/auth/login";
|
|
22
|
+
const url = new URL(`${authVitalHost}${page}`);
|
|
23
|
+
if (_optionalChain([options, 'optionalAccess', _2 => _2.clientId])) {
|
|
24
|
+
url.searchParams.set("client_id", options.clientId);
|
|
25
|
+
}
|
|
26
|
+
window.location.href = url.toString();
|
|
27
|
+
}
|
|
28
|
+
function signupAtAuthVital(authVitalHost, options) {
|
|
29
|
+
loginToAuthVital(authVitalHost, { ...options, screen: "signup" });
|
|
30
|
+
}
|
|
31
|
+
function generateCodeVerifier() {
|
|
32
|
+
const array = new Uint8Array(32);
|
|
33
|
+
crypto.getRandomValues(array);
|
|
34
|
+
return base64UrlEncode(array);
|
|
35
|
+
}
|
|
36
|
+
async function generateCodeChallenge(verifier) {
|
|
37
|
+
const encoder = new TextEncoder();
|
|
38
|
+
const data = encoder.encode(verifier);
|
|
39
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
40
|
+
return base64UrlEncode(new Uint8Array(digest));
|
|
41
|
+
}
|
|
42
|
+
function base64UrlEncode(buffer) {
|
|
43
|
+
let binary = "";
|
|
44
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
45
|
+
binary += String.fromCharCode(buffer[i]);
|
|
46
|
+
}
|
|
47
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
48
|
+
}
|
|
49
|
+
var LOGIN_ATTEMPT_KEY = "authvital_login_attempt";
|
|
50
|
+
var LOGIN_COOLDOWN_MS = 5e3;
|
|
51
|
+
function canAttemptLogin() {
|
|
52
|
+
const lastAttempt = sessionStorage.getItem(LOGIN_ATTEMPT_KEY);
|
|
53
|
+
if (!lastAttempt) return true;
|
|
54
|
+
return Date.now() - parseInt(lastAttempt, 10) > LOGIN_COOLDOWN_MS;
|
|
55
|
+
}
|
|
56
|
+
function recordLoginAttempt() {
|
|
57
|
+
sessionStorage.setItem(LOGIN_ATTEMPT_KEY, Date.now().toString());
|
|
58
|
+
}
|
|
59
|
+
function clearLoginAttempt() {
|
|
60
|
+
sessionStorage.removeItem(LOGIN_ATTEMPT_KEY);
|
|
61
|
+
}
|
|
62
|
+
async function startAuthorizationFlow(config, params = {}) {
|
|
63
|
+
if (!canAttemptLogin()) {
|
|
64
|
+
throw new Error("Too many login attempts. Please wait a moment and try again.");
|
|
65
|
+
}
|
|
66
|
+
recordLoginAttempt();
|
|
67
|
+
const codeVerifier = generateCodeVerifier();
|
|
68
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
69
|
+
const csrf = params.state || generateCodeVerifier().substring(0, 16);
|
|
70
|
+
const state = encodeState(csrf, codeVerifier);
|
|
71
|
+
const authorizeUrl = new URL(`${config.authVitalHost}/oauth/authorize`);
|
|
72
|
+
authorizeUrl.searchParams.set("client_id", config.clientId);
|
|
73
|
+
authorizeUrl.searchParams.set("redirect_uri", config.redirectUri);
|
|
74
|
+
authorizeUrl.searchParams.set("response_type", "code");
|
|
75
|
+
authorizeUrl.searchParams.set("scope", config.scope || "openid profile email");
|
|
76
|
+
authorizeUrl.searchParams.set("state", state);
|
|
77
|
+
authorizeUrl.searchParams.set("code_challenge", codeChallenge);
|
|
78
|
+
authorizeUrl.searchParams.set("code_challenge_method", "S256");
|
|
79
|
+
if (params.nonce) {
|
|
80
|
+
authorizeUrl.searchParams.set("nonce", params.nonce);
|
|
81
|
+
}
|
|
82
|
+
if (params.screen === "signup") {
|
|
83
|
+
authorizeUrl.searchParams.set("screen", "signup");
|
|
84
|
+
}
|
|
85
|
+
window.location.href = authorizeUrl.toString();
|
|
86
|
+
}
|
|
87
|
+
async function startLogin(options) {
|
|
88
|
+
await startAuthorizationFlow(
|
|
89
|
+
{
|
|
90
|
+
authVitalHost: options.authVitalHost,
|
|
91
|
+
clientId: options.clientId,
|
|
92
|
+
redirectUri: options.redirectUri,
|
|
93
|
+
scope: options.scope
|
|
94
|
+
},
|
|
95
|
+
{ state: options.state }
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
async function startSignup(options) {
|
|
99
|
+
await startAuthorizationFlow(
|
|
100
|
+
{
|
|
101
|
+
authVitalHost: options.authVitalHost,
|
|
102
|
+
clientId: options.clientId,
|
|
103
|
+
redirectUri: options.redirectUri,
|
|
104
|
+
scope: options.scope
|
|
105
|
+
},
|
|
106
|
+
{ state: options.state, screen: "signup" }
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
var callbackInProgress = null;
|
|
110
|
+
async function handleCallback(config) {
|
|
111
|
+
if (callbackInProgress) {
|
|
112
|
+
await callbackInProgress;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const params = new URLSearchParams(window.location.search);
|
|
116
|
+
const code = params.get("code");
|
|
117
|
+
const state = params.get("state");
|
|
118
|
+
const error = params.get("error");
|
|
119
|
+
const errorDescription = params.get("error_description");
|
|
120
|
+
if (error) {
|
|
121
|
+
throw new Error(errorDescription || error);
|
|
122
|
+
}
|
|
123
|
+
if (!code) {
|
|
124
|
+
throw new Error("No authorization code received");
|
|
125
|
+
}
|
|
126
|
+
if (!state) {
|
|
127
|
+
throw new Error("No state parameter received");
|
|
128
|
+
}
|
|
129
|
+
const decoded = decodeState(state);
|
|
130
|
+
if (!decoded) {
|
|
131
|
+
throw new Error("Invalid state format - could not extract PKCE verifier");
|
|
132
|
+
}
|
|
133
|
+
callbackInProgress = exchangeCodeForTokens(config, code, decoded.codeVerifier);
|
|
134
|
+
try {
|
|
135
|
+
await callbackInProgress;
|
|
136
|
+
window.history.replaceState({}, "", window.location.pathname);
|
|
137
|
+
clearLoginAttempt();
|
|
138
|
+
} finally {
|
|
139
|
+
callbackInProgress = null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function extractCallbackParams() {
|
|
143
|
+
const params = new URLSearchParams(window.location.search);
|
|
144
|
+
const code = params.get("code");
|
|
145
|
+
const state = params.get("state");
|
|
146
|
+
const error = params.get("error");
|
|
147
|
+
const errorDescription = params.get("error_description");
|
|
148
|
+
if (error) {
|
|
149
|
+
return { code: null, codeVerifier: null, csrf: null, error, errorDescription };
|
|
150
|
+
}
|
|
151
|
+
if (!state) {
|
|
152
|
+
return { code, codeVerifier: null, csrf: null, error: "missing_state", errorDescription: "No state parameter" };
|
|
153
|
+
}
|
|
154
|
+
const decoded = decodeState(state);
|
|
155
|
+
if (!decoded) {
|
|
156
|
+
return { code, codeVerifier: null, csrf: null, error: "invalid_state", errorDescription: "Could not decode state" };
|
|
157
|
+
}
|
|
158
|
+
return { code, codeVerifier: decoded.codeVerifier, csrf: decoded.csrf, error: null, errorDescription: null };
|
|
159
|
+
}
|
|
160
|
+
async function exchangeCodeForTokens(config, code, codeVerifier) {
|
|
161
|
+
const response = await fetch(`${config.authVitalHost}/oauth/token`, {
|
|
162
|
+
method: "POST",
|
|
163
|
+
headers: { "Content-Type": "application/json" },
|
|
164
|
+
credentials: "include",
|
|
165
|
+
// Important: receive and send cookies
|
|
166
|
+
body: JSON.stringify({
|
|
167
|
+
grant_type: "authorization_code",
|
|
168
|
+
code,
|
|
169
|
+
redirect_uri: config.redirectUri,
|
|
170
|
+
client_id: config.clientId,
|
|
171
|
+
code_verifier: codeVerifier
|
|
172
|
+
})
|
|
173
|
+
});
|
|
174
|
+
if (!response.ok) {
|
|
175
|
+
const error = await response.json().catch(() => ({}));
|
|
176
|
+
throw new Error(error.message || "Token exchange failed");
|
|
177
|
+
}
|
|
178
|
+
return response.json();
|
|
179
|
+
}
|
|
180
|
+
async function checkAuthStatus(authVitalHost) {
|
|
181
|
+
try {
|
|
182
|
+
const response = await fetch(`${authVitalHost}/api/auth/me`, {
|
|
183
|
+
method: "GET",
|
|
184
|
+
credentials: "include"
|
|
185
|
+
// Send cookies
|
|
186
|
+
});
|
|
187
|
+
if (!response.ok) {
|
|
188
|
+
return { authenticated: false };
|
|
189
|
+
}
|
|
190
|
+
const data = await response.json();
|
|
191
|
+
return {
|
|
192
|
+
authenticated: _nullishCoalesce(data.authenticated, () => ( false)),
|
|
193
|
+
user: data.user
|
|
194
|
+
};
|
|
195
|
+
} catch (e2) {
|
|
196
|
+
return { authenticated: false };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
async function logout(authVitalHost, options) {
|
|
200
|
+
sessionStorage.removeItem(LOGIN_ATTEMPT_KEY);
|
|
201
|
+
const logoutUrl = new URL(`${authVitalHost}/api/auth/logout/redirect`);
|
|
202
|
+
if (_optionalChain([options, 'optionalAccess', _3 => _3.postLogoutRedirectUri])) {
|
|
203
|
+
logoutUrl.searchParams.set("post_logout_redirect_uri", options.postLogoutRedirectUri);
|
|
204
|
+
}
|
|
205
|
+
window.location.href = logoutUrl.toString();
|
|
206
|
+
}
|
|
207
|
+
function decodeJwt(token) {
|
|
208
|
+
try {
|
|
209
|
+
const parts = token.split(".");
|
|
210
|
+
if (parts.length !== 3) return null;
|
|
211
|
+
const payload = parts[1];
|
|
212
|
+
const decoded = atob(payload.replace(/-/g, "+").replace(/_/g, "/"));
|
|
213
|
+
return JSON.parse(decoded);
|
|
214
|
+
} catch (e3) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
exports.encodeState = encodeState; exports.decodeState = decodeState; exports.loginToAuthVital = loginToAuthVital; exports.signupAtAuthVital = signupAtAuthVital; exports.generateCodeVerifier = generateCodeVerifier; exports.generateCodeChallenge = generateCodeChallenge; exports.startAuthorizationFlow = startAuthorizationFlow; exports.startLogin = startLogin; exports.startSignup = startSignup; exports.handleCallback = handleCallback; exports.extractCallbackParams = extractCallbackParams; exports.exchangeCodeForTokens = exchangeCodeForTokens; exports.checkAuthStatus = checkAuthStatus; exports.logout = logout; exports.decodeJwt = decodeJwt;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});// src/client/invitations.ts
|
|
2
|
+
var INVITE_TOKEN_KEY = "authvital_invite_token";
|
|
3
|
+
function storeInviteToken(token) {
|
|
4
|
+
if (typeof window === "undefined") return;
|
|
5
|
+
sessionStorage.setItem(INVITE_TOKEN_KEY, token);
|
|
6
|
+
}
|
|
7
|
+
function getStoredInviteToken() {
|
|
8
|
+
if (typeof window === "undefined") return null;
|
|
9
|
+
return sessionStorage.getItem(INVITE_TOKEN_KEY);
|
|
10
|
+
}
|
|
11
|
+
function clearStoredInviteToken() {
|
|
12
|
+
if (typeof window === "undefined") return;
|
|
13
|
+
sessionStorage.removeItem(INVITE_TOKEN_KEY);
|
|
14
|
+
}
|
|
15
|
+
function captureInviteTokenFromUrl() {
|
|
16
|
+
if (typeof window === "undefined") return null;
|
|
17
|
+
const params = new URLSearchParams(window.location.search);
|
|
18
|
+
const token = params.get("invite_token") || params.get("token");
|
|
19
|
+
if (token && window.location.pathname.includes("/invite")) {
|
|
20
|
+
storeInviteToken(token);
|
|
21
|
+
return token;
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
async function getInvitation(authVitalHost, token) {
|
|
26
|
+
const response = await fetch(`${authVitalHost}/api/invitations/token/${token}`);
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
const error = await response.json().catch(() => ({}));
|
|
29
|
+
throw new Error(error.message || `Failed to get invitation: ${response.status}`);
|
|
30
|
+
}
|
|
31
|
+
return response.json();
|
|
32
|
+
}
|
|
33
|
+
async function createInvitation(authVitalHost, _accessToken, params) {
|
|
34
|
+
const response = await fetch(`${authVitalHost}/api/invitations`, {
|
|
35
|
+
method: "POST",
|
|
36
|
+
headers: { "Content-Type": "application/json" },
|
|
37
|
+
credentials: "include",
|
|
38
|
+
// Send httpOnly cookie
|
|
39
|
+
body: JSON.stringify(params)
|
|
40
|
+
});
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const error = await response.json().catch(() => ({}));
|
|
43
|
+
throw new Error(error.message || `Failed to create invitation: ${response.status}`);
|
|
44
|
+
}
|
|
45
|
+
return response.json();
|
|
46
|
+
}
|
|
47
|
+
async function consumeInvitation(authVitalHost, _accessToken, token) {
|
|
48
|
+
const response = await fetch(`${authVitalHost}/api/invitations/consume`, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: { "Content-Type": "application/json" },
|
|
51
|
+
credentials: "include",
|
|
52
|
+
// Send httpOnly cookie
|
|
53
|
+
body: JSON.stringify({ token })
|
|
54
|
+
});
|
|
55
|
+
if (!response.ok) {
|
|
56
|
+
const error = await response.json().catch(() => ({}));
|
|
57
|
+
throw new Error(error.message || `Failed to consume invitation: ${response.status}`);
|
|
58
|
+
}
|
|
59
|
+
return response.json();
|
|
60
|
+
}
|
|
61
|
+
async function listTenantInvitations(authVitalHost, _accessToken, tenantId) {
|
|
62
|
+
const response = await fetch(`${authVitalHost}/api/invitations/tenant/${tenantId}`, {
|
|
63
|
+
credentials: "include"
|
|
64
|
+
// Send httpOnly cookie
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const error = await response.json().catch(() => ({}));
|
|
68
|
+
throw new Error(error.message || `Failed to list invitations: ${response.status}`);
|
|
69
|
+
}
|
|
70
|
+
return response.json();
|
|
71
|
+
}
|
|
72
|
+
async function revokeInvitation(authVitalHost, _accessToken, invitationId) {
|
|
73
|
+
const response = await fetch(`${authVitalHost}/api/invitations/${invitationId}`, {
|
|
74
|
+
method: "DELETE",
|
|
75
|
+
credentials: "include"
|
|
76
|
+
// Send httpOnly cookie
|
|
77
|
+
});
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
const error = await response.json().catch(() => ({}));
|
|
80
|
+
throw new Error(error.message || `Failed to revoke invitation: ${response.status}`);
|
|
81
|
+
}
|
|
82
|
+
return response.json();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
exports.storeInviteToken = storeInviteToken; exports.getStoredInviteToken = getStoredInviteToken; exports.clearStoredInviteToken = clearStoredInviteToken; exports.captureInviteTokenFromUrl = captureInviteTokenFromUrl; exports.getInvitation = getInvitation; exports.createInvitation = createInvitation; exports.consumeInvitation = consumeInvitation; exports.listTenantInvitations = listTenantInvitations; exports.revokeInvitation = revokeInvitation;
|