@entropy-softworks/ui 2026.8.34 → 2026.8.36
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 +30 -0
- package/lib/components/auth/PasswordStrengthMeter.d.ts +9 -0
- package/lib/components/auth/PasswordStrengthMeter.d.ts.map +1 -1
- package/lib/components/auth/PasswordStrengthMeter.jsx +10 -4
- package/lib/components/auth/PasswordStrengthMeter.jsx.map +1 -1
- package/lib/components/profile/SecurityTab.d.ts +5 -1
- package/lib/components/profile/SecurityTab.d.ts.map +1 -1
- package/lib/components/profile/SecurityTab.jsx.map +1 -1
- package/lib/components/segmented-toggle.d.ts +9 -0
- package/lib/components/segmented-toggle.d.ts.map +1 -1
- package/lib/components/segmented-toggle.jsx +4 -0
- package/lib/components/segmented-toggle.jsx.map +1 -1
- package/lib/components/social-connections.d.ts +22 -5
- package/lib/components/social-connections.d.ts.map +1 -1
- package/lib/components/social-connections.jsx +37 -11
- package/lib/components/social-connections.jsx.map +1 -1
- package/lib/context/AppConfigContext.d.ts +27 -0
- package/lib/context/AppConfigContext.d.ts.map +1 -1
- package/lib/context/AppConfigContext.jsx.map +1 -1
- package/lib/demos/extension-popup.d.ts +212 -0
- package/lib/demos/extension-popup.d.ts.map +1 -0
- package/lib/demos/extension-popup.jsx +1172 -0
- package/lib/demos/extension-popup.jsx.map +1 -0
- package/lib/demos/index.d.ts +11 -0
- package/lib/demos/index.d.ts.map +1 -0
- package/lib/demos/index.js +14 -0
- package/lib/demos/index.js.map +1 -0
- package/lib/screens/auth/AuthScreen.d.ts +75 -1
- package/lib/screens/auth/AuthScreen.d.ts.map +1 -1
- package/lib/screens/auth/AuthScreen.jsx +356 -122
- package/lib/screens/auth/AuthScreen.jsx.map +1 -1
- package/lib/services/auth.service.d.ts +41 -1
- package/lib/services/auth.service.d.ts.map +1 -1
- package/lib/services/auth.service.js +53 -7
- package/lib/services/auth.service.js.map +1 -1
- package/package.json +7 -1
- package/src/components/auth/PasswordStrengthMeter.tsx +25 -3
- package/src/components/profile/SecurityTab.tsx +11 -1
- package/src/components/segmented-toggle.tsx +13 -0
- package/src/components/social-connections.tsx +66 -20
- package/src/context/AppConfigContext.tsx +27 -0
- package/src/demos/extension-popup.tsx +2051 -0
- package/src/demos/index.ts +38 -0
- package/src/screens/auth/AuthScreen.tsx +701 -312
- package/src/services/auth.service.ts +62 -8
|
@@ -273,18 +273,54 @@ class AuthService {
|
|
|
273
273
|
}
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
+
/**
|
|
277
|
+
* The signed-in user, from local state if it is there and from the server if
|
|
278
|
+
* it is not.
|
|
279
|
+
*
|
|
280
|
+
* The server fallback is the whole point. On web `loadPersistedUser` returns
|
|
281
|
+
* a module-level variable, which is null in every freshly loaded document —
|
|
282
|
+
* so this used to answer "nobody" on each page load and refresh while the
|
|
283
|
+
* session cookie was perfectly valid. `useAuth.checkAuth` reads that as a
|
|
284
|
+
* session it cannot resolve and calls `logout()`, which POSTs
|
|
285
|
+
* `/auth/logout` and destroys the session server-side. The user is signed
|
|
286
|
+
* out by the act of loading the page.
|
|
287
|
+
*
|
|
288
|
+
* Observed on Access on 2026-08-22: the portal and the admin console are
|
|
289
|
+
* separate SPAs on one origin, so every navigation between them is a fresh
|
|
290
|
+
* document and therefore a guaranteed logout — which presents as an infinite
|
|
291
|
+
* sign-in loop. Its audit log recorded the logouts nobody asked for.
|
|
292
|
+
*
|
|
293
|
+
* Native was affected too, if less visibly: `isAuthenticated` there is
|
|
294
|
+
* satisfied by a token in SecureStore, so a token that outlived its cached
|
|
295
|
+
* user record produced the same spurious logout.
|
|
296
|
+
*
|
|
297
|
+
* It does NOT route through `isAuthenticated`. That method's web branch falls
|
|
298
|
+
* back to calling this one, so going the other way would recurse until the
|
|
299
|
+
* stack gave out on exactly the signed-out path this is meant to make cheap.
|
|
300
|
+
*/
|
|
276
301
|
static async getCurrentUser(): Promise<User | null> {
|
|
277
|
-
|
|
302
|
+
const persisted = await loadPersistedUser();
|
|
303
|
+
if (persisted) {
|
|
304
|
+
return persisted;
|
|
305
|
+
}
|
|
306
|
+
return AuthService.fetchMe(false);
|
|
278
307
|
}
|
|
279
308
|
|
|
280
|
-
|
|
309
|
+
/**
|
|
310
|
+
* `GET /auth/me`, persisting whatever comes back.
|
|
311
|
+
*
|
|
312
|
+
* `logoutOn401` is a parameter rather than a fixed behaviour because the two
|
|
313
|
+
* callers need opposite things from the same request. A *refresh* of a
|
|
314
|
+
* session believed live that returns 401 means the session died and local
|
|
315
|
+
* state should be cleared. A *lookup* that returns 401 means there was no
|
|
316
|
+
* session to begin with — the ordinary state of a signed-out visitor — and
|
|
317
|
+
* tearing down on that would fire a logout on every anonymous page load.
|
|
318
|
+
*/
|
|
319
|
+
private static async fetchMe(logoutOn401: boolean): Promise<User | null> {
|
|
281
320
|
try {
|
|
282
|
-
if (!(await this.isAuthenticated())) {
|
|
283
|
-
return null;
|
|
284
|
-
}
|
|
285
321
|
const response = await apiFetch("/auth/me", { method: "GET" });
|
|
286
322
|
if (!response.ok) {
|
|
287
|
-
if (response.status === 401) {
|
|
323
|
+
if (logoutOn401 && response.status === 401) {
|
|
288
324
|
await this.logout();
|
|
289
325
|
}
|
|
290
326
|
return null;
|
|
@@ -297,6 +333,13 @@ class AuthService {
|
|
|
297
333
|
}
|
|
298
334
|
}
|
|
299
335
|
|
|
336
|
+
static async refreshUserData(): Promise<User | null> {
|
|
337
|
+
if (!(await this.isAuthenticated())) {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
return AuthService.fetchMe(true);
|
|
341
|
+
}
|
|
342
|
+
|
|
300
343
|
/**
|
|
301
344
|
* Web: HttpOnly cookies aren't readable from JS. We use the
|
|
302
345
|
* presence of the (non-HttpOnly) `csrf_token` cookie — set by the
|
|
@@ -339,7 +382,14 @@ class AuthService {
|
|
|
339
382
|
static async changePassword(
|
|
340
383
|
currentPassword: string,
|
|
341
384
|
newPassword: string,
|
|
342
|
-
reWrappedKey?: {
|
|
385
|
+
reWrappedKey?: {
|
|
386
|
+
symmetric_key_enc: string;
|
|
387
|
+
kdf: string;
|
|
388
|
+
kdf_salt: string;
|
|
389
|
+
kdf_iterations: number;
|
|
390
|
+
kdf_memory_kib?: number;
|
|
391
|
+
kdf_lanes?: number;
|
|
392
|
+
}
|
|
343
393
|
): Promise<void> {
|
|
344
394
|
const body: Record<string, unknown> = {
|
|
345
395
|
current_password: currentPassword.normalize("NFC"),
|
|
@@ -347,7 +397,11 @@ class AuthService {
|
|
|
347
397
|
};
|
|
348
398
|
if (reWrappedKey) {
|
|
349
399
|
body.symmetric_key_enc = reWrappedKey.symmetric_key_enc;
|
|
350
|
-
body.
|
|
400
|
+
body.kdf = reWrappedKey.kdf;
|
|
401
|
+
body.kdf_salt = reWrappedKey.kdf_salt;
|
|
402
|
+
body.kdf_iterations = reWrappedKey.kdf_iterations;
|
|
403
|
+
body.kdf_memory_kib = reWrappedKey.kdf_memory_kib;
|
|
404
|
+
body.kdf_lanes = reWrappedKey.kdf_lanes;
|
|
351
405
|
}
|
|
352
406
|
const response = await apiFetch("/auth/password", {
|
|
353
407
|
method: "PUT",
|