@jskit-ai/auth-web 0.1.105 → 0.1.107
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/package.descriptor.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export default Object.freeze({
|
|
2
2
|
"packageVersion": 1,
|
|
3
3
|
"packageId": "@jskit-ai/auth-web",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.107",
|
|
5
5
|
"kind": "runtime",
|
|
6
6
|
"description": "Auth web module: Fastify auth routes plus web login/sign-out scaffolds.",
|
|
7
7
|
"dependsOn": [
|
|
@@ -260,10 +260,10 @@ export default Object.freeze({
|
|
|
260
260
|
"dependencies": {
|
|
261
261
|
"runtime": {
|
|
262
262
|
"@mdi/js": "^7.4.47",
|
|
263
|
-
"@jskit-ai/auth-core": "0.1.
|
|
264
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
265
|
-
"@jskit-ai/kernel": "0.1.
|
|
266
|
-
"@jskit-ai/shell-web": "0.1.
|
|
263
|
+
"@jskit-ai/auth-core": "0.1.105",
|
|
264
|
+
"@jskit-ai/http-runtime": "0.1.105",
|
|
265
|
+
"@jskit-ai/kernel": "0.1.107",
|
|
266
|
+
"@jskit-ai/shell-web": "0.1.106"
|
|
267
267
|
},
|
|
268
268
|
"dev": {}
|
|
269
269
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jskit-ai/auth-web",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.107",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test"
|
|
@@ -19,11 +19,11 @@
|
|
|
19
19
|
"./client/runtime/useSignOut": "./src/client/runtime/useSignOut.js"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@jskit-ai/auth-core": "0.1.
|
|
22
|
+
"@jskit-ai/auth-core": "0.1.105",
|
|
23
23
|
"@mdi/js": "^7.4.47",
|
|
24
|
-
"@jskit-ai/kernel": "0.1.
|
|
25
|
-
"@jskit-ai/shell-web": "0.1.
|
|
26
|
-
"@jskit-ai/http-runtime": "0.1.
|
|
24
|
+
"@jskit-ai/kernel": "0.1.107",
|
|
25
|
+
"@jskit-ai/shell-web": "0.1.106",
|
|
26
|
+
"@jskit-ai/http-runtime": "0.1.105"
|
|
27
27
|
},
|
|
28
28
|
"peerDependencies": {
|
|
29
29
|
"@tanstack/vue-query": "^5.90.5",
|
|
@@ -160,6 +160,13 @@ export function useLoginViewActions({
|
|
|
160
160
|
email: normalizedEmail,
|
|
161
161
|
password: String(state.password.value || "")
|
|
162
162
|
};
|
|
163
|
+
const invitationToken = String(state.invitationToken?.value || "").trim();
|
|
164
|
+
if (invitationToken) {
|
|
165
|
+
registerPayload.invitation = {
|
|
166
|
+
token: invitationToken,
|
|
167
|
+
source: "workspace-invite"
|
|
168
|
+
};
|
|
169
|
+
}
|
|
163
170
|
ensureCommandSectionValid(authRegisterCommand, "body", registerPayload, "Unable to register.");
|
|
164
171
|
|
|
165
172
|
const registerResult = await request(AUTH_PATHS.REGISTER, {
|
|
@@ -25,9 +25,24 @@ import {
|
|
|
25
25
|
clearRememberedAccountHint
|
|
26
26
|
} from "./rememberedAccountStorage.js";
|
|
27
27
|
|
|
28
|
+
function readWindowSearchParam(name = "") {
|
|
29
|
+
if (typeof window !== "object" || !window.location) {
|
|
30
|
+
return "";
|
|
31
|
+
}
|
|
32
|
+
return String(new URLSearchParams(window.location.search || "").get(name) || "").trim();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function resolveInitialMode() {
|
|
36
|
+
const mode = readWindowSearchParam("mode").toLowerCase();
|
|
37
|
+
if ([LOGIN_MODE, REGISTER_MODE, FORGOT_MODE, OTP_MODE].includes(mode)) {
|
|
38
|
+
return mode;
|
|
39
|
+
}
|
|
40
|
+
return LOGIN_MODE;
|
|
41
|
+
}
|
|
42
|
+
|
|
28
43
|
export function useLoginViewState({ placementContext } = {}) {
|
|
29
|
-
const mode = ref(
|
|
30
|
-
const email = ref("");
|
|
44
|
+
const mode = ref(resolveInitialMode());
|
|
45
|
+
const email = ref(normalizeEmailAddress(readWindowSearchParam("email")));
|
|
31
46
|
const password = ref("");
|
|
32
47
|
const confirmPassword = ref("");
|
|
33
48
|
const otpCode = ref("");
|
|
@@ -51,6 +66,7 @@ export function useLoginViewState({ placementContext } = {}) {
|
|
|
51
66
|
const infoMessage = ref("");
|
|
52
67
|
const pendingEmailConfirmationMessage = ref("");
|
|
53
68
|
const pendingEmailConfirmationAddress = ref("");
|
|
69
|
+
const invitationToken = ref(readWindowSearchParam("invitationToken") || readWindowSearchParam("inviteToken"));
|
|
54
70
|
|
|
55
71
|
const isLogin = computed(() => mode.value === LOGIN_MODE);
|
|
56
72
|
const isRegister = computed(() => mode.value === REGISTER_MODE);
|
|
@@ -273,6 +289,7 @@ export function useLoginViewState({ placementContext } = {}) {
|
|
|
273
289
|
infoMessage,
|
|
274
290
|
pendingEmailConfirmationMessage,
|
|
275
291
|
pendingEmailConfirmationAddress,
|
|
292
|
+
invitationToken,
|
|
276
293
|
isLogin,
|
|
277
294
|
isRegister,
|
|
278
295
|
isForgot,
|
|
@@ -36,6 +36,7 @@ function createMinimalLoginViewState(requestedReturnTo = "/") {
|
|
|
36
36
|
otpRequestPending: { value: false },
|
|
37
37
|
registerConfirmationResendPending: { value: false },
|
|
38
38
|
pendingEmailConfirmationAddress: { value: "" },
|
|
39
|
+
invitationToken: { value: "" },
|
|
39
40
|
rememberAccountOnDevice: { value: true },
|
|
40
41
|
oauthProviders: { value: [] },
|
|
41
42
|
oauthDefaultProvider: { value: "google" },
|
|
@@ -178,3 +179,67 @@ test("useLoginViewActions keeps retry message for generic post-login unauthentic
|
|
|
178
179
|
|
|
179
180
|
assert.equal(state.errorMessage.value, "Login succeeded but the session is not active yet. Please retry.");
|
|
180
181
|
});
|
|
182
|
+
|
|
183
|
+
test("useLoginViewActions includes invitation context when registering from an invite link", async () => {
|
|
184
|
+
clearAuthCsrfTokenCache();
|
|
185
|
+
const state = createMinimalLoginViewState("/invite/invite-token");
|
|
186
|
+
state.isRegister.value = true;
|
|
187
|
+
state.invitationToken.value = "invite-token";
|
|
188
|
+
const originalFetch = globalThis.fetch;
|
|
189
|
+
const registerBodies = [];
|
|
190
|
+
let sessionReads = 0;
|
|
191
|
+
|
|
192
|
+
globalThis.fetch = async (url, options = {}) => {
|
|
193
|
+
const normalizedUrl = String(url || "");
|
|
194
|
+
const method = String(options.method || "GET").toUpperCase();
|
|
195
|
+
|
|
196
|
+
if (normalizedUrl === "/api/session" && method === "GET") {
|
|
197
|
+
sessionReads += 1;
|
|
198
|
+
return createJsonResponse(
|
|
199
|
+
sessionReads === 1
|
|
200
|
+
? { authenticated: false, csrfToken: "csrf-a" }
|
|
201
|
+
: { authenticated: true, csrfToken: "csrf-b" }
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (normalizedUrl === "/api/register" && method === "POST") {
|
|
206
|
+
registerBodies.push(JSON.parse(String(options.body || "{}")));
|
|
207
|
+
return createJsonResponse({ ok: true, username: "Ada", requiresEmailConfirmation: false });
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
throw new Error(`Unexpected fetch call: ${method} ${normalizedUrl}`);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
const actions = useLoginViewActions({
|
|
215
|
+
state,
|
|
216
|
+
validation: {
|
|
217
|
+
canSubmit: { value: true }
|
|
218
|
+
},
|
|
219
|
+
queryClient: {
|
|
220
|
+
async fetchQuery({ queryFn }) {
|
|
221
|
+
return queryFn();
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
errorRuntime: {
|
|
225
|
+
report() {}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
await actions.submitAuth();
|
|
230
|
+
} finally {
|
|
231
|
+
globalThis.fetch = originalFetch;
|
|
232
|
+
clearAuthCsrfTokenCache();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
assert.deepEqual(registerBodies, [
|
|
236
|
+
{
|
|
237
|
+
email: "ada@example.com",
|
|
238
|
+
password: "password-123",
|
|
239
|
+
invitation: {
|
|
240
|
+
token: "invite-token",
|
|
241
|
+
source: "workspace-invite"
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
]);
|
|
245
|
+
});
|