@snokam/auth 5.5.5 → 6.0.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/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [6.0.0](https://github.com/snokam/components/compare/@snokam/auth@5.5.5...@snokam/auth@6.0.0) (2026-10-31)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **my-page:** ssr impersonation, loading skeleton, restore hero photos and blobs ([c7bf3e4](https://github.com/snokam/components/commit/c7bf3e46b4416f997427b84513eb0da6c8865f63))
|
|
11
|
+
- **my-page:** ssr session, no full page loader, steady hero status lines ([4f9f80b](https://github.com/snokam/components/commit/4f9f80bf01dfeaafa36dc61bbd40b905105366bd))
|
|
12
|
+
|
|
13
|
+
- feat(ui)!: compact page header, review fixes for shared packages ([2be4532](https://github.com/snokam/components/commit/2be453241302b8c5d275a8aeeaadfd4aee106f88))
|
|
14
|
+
|
|
15
|
+
### BREAKING CHANGES
|
|
16
|
+
|
|
17
|
+
- PageHeader no longer takes tone or transitions; it is
|
|
18
|
+
always the compact dark header with a wave and optional breadcrumbs.
|
|
19
|
+
|
|
20
|
+
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
|
21
|
+
|
|
6
22
|
## [5.5.5](https://github.com/snokam/components/compare/@snokam/auth@5.5.4...@snokam/auth@5.5.5) (2026-10-28)
|
|
7
23
|
|
|
8
24
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snokam/auth",
|
|
3
3
|
"description": "Snøkam auth components",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "6.0.0",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
7
7
|
"files": [
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"@snokam/identity": "1.1.0",
|
|
30
30
|
"@snokam/platform-client": "5.3.2",
|
|
31
31
|
"@snokam/react-query": "1.1.0",
|
|
32
|
-
"@snokam/sanity-page-content": "6.
|
|
32
|
+
"@snokam/sanity-page-content": "6.9.0",
|
|
33
33
|
"@snokam/tenant": "4.4.1",
|
|
34
|
-
"@snokam/ui": "
|
|
34
|
+
"@snokam/ui": "7.0.0"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"next": "16.3.8",
|
package/src/app-router/server.ts
CHANGED
|
@@ -3,6 +3,12 @@ import {
|
|
|
3
3
|
type Session,
|
|
4
4
|
} from "next-auth";
|
|
5
5
|
import type { NextAuthOptions } from "next-auth";
|
|
6
|
+
import { cookies } from "next/headers";
|
|
7
|
+
import {
|
|
8
|
+
IMP_ACTIVE_COOKIE,
|
|
9
|
+
parseActiveCookie,
|
|
10
|
+
type ImpersonationActive,
|
|
11
|
+
} from "../impersonation/cookies";
|
|
6
12
|
import {
|
|
7
13
|
apiScope,
|
|
8
14
|
appUrl,
|
|
@@ -43,3 +49,8 @@ export async function getAuth(authOptions: NextAuthOptions) {
|
|
|
43
49
|
user: session?.user,
|
|
44
50
|
};
|
|
45
51
|
}
|
|
52
|
+
|
|
53
|
+
export async function getServerImpersonation(): Promise<ImpersonationActive | null> {
|
|
54
|
+
const store = await cookies();
|
|
55
|
+
return parseActiveCookie(store.get(IMP_ACTIVE_COOKIE)?.value);
|
|
56
|
+
}
|
|
@@ -12,6 +12,7 @@ interface Props {
|
|
|
12
12
|
employee: unknown;
|
|
13
13
|
isLoading: boolean;
|
|
14
14
|
allowAnonymous?: boolean;
|
|
15
|
+
blockWhileLoading?: boolean;
|
|
15
16
|
children: ReactNode;
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -20,6 +21,7 @@ export const EmployeeGate = ({
|
|
|
20
21
|
employee,
|
|
21
22
|
isLoading,
|
|
22
23
|
allowAnonymous = false,
|
|
24
|
+
blockWhileLoading = true,
|
|
23
25
|
children,
|
|
24
26
|
}: Props) => {
|
|
25
27
|
const { isAuthenticated, inProgress } = useAuth();
|
|
@@ -39,6 +41,10 @@ export const EmployeeGate = ({
|
|
|
39
41
|
return <>{children}</>;
|
|
40
42
|
}
|
|
41
43
|
|
|
44
|
+
if (isAuthenticated && isLoading && !blockWhileLoading) {
|
|
45
|
+
return <>{children}</>;
|
|
46
|
+
}
|
|
47
|
+
|
|
42
48
|
if (inProgress || (isAuthenticated && isLoading)) {
|
|
43
49
|
return <PageLoader />;
|
|
44
50
|
}
|
|
@@ -9,7 +9,11 @@ import {
|
|
|
9
9
|
useState,
|
|
10
10
|
type ReactNode,
|
|
11
11
|
} from "react";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
IMP_ACTIVE_COOKIE,
|
|
14
|
+
parseActiveCookie,
|
|
15
|
+
type ImpersonationActive,
|
|
16
|
+
} from "./cookies";
|
|
13
17
|
import { clearAuthTokenCache } from "../hooks";
|
|
14
18
|
import { useSessionRenewal } from "./renewal";
|
|
15
19
|
import { useOptionalConfig } from "@snokam/tenant";
|
|
@@ -60,18 +64,25 @@ function readActiveCookie(): ImpersonationActive | null {
|
|
|
60
64
|
.find((part) => part.startsWith(`${IMP_ACTIVE_COOKIE}=`));
|
|
61
65
|
if (!match) return null;
|
|
62
66
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
return parsed;
|
|
67
|
+
return parseActiveCookie(
|
|
68
|
+
decodeURIComponent(match.slice(IMP_ACTIVE_COOKIE.length + 1))
|
|
69
|
+
);
|
|
67
70
|
} catch {
|
|
68
71
|
return null;
|
|
69
72
|
}
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
export function ImpersonationProvider({
|
|
75
|
+
export function ImpersonationProvider({
|
|
76
|
+
children,
|
|
77
|
+
initialActive = null,
|
|
78
|
+
}: {
|
|
79
|
+
children: ReactNode;
|
|
80
|
+
initialActive?: ImpersonationActive | null;
|
|
81
|
+
}) {
|
|
73
82
|
const apiBaseUrl = useOptionalConfig()?.NEXT_PUBLIC_PLATFORM_API_BASE_URL;
|
|
74
|
-
const [active, setActive] = useState<ImpersonationActive | null>(
|
|
83
|
+
const [active, setActive] = useState<ImpersonationActive | null>(
|
|
84
|
+
initialActive
|
|
85
|
+
);
|
|
75
86
|
const [starting, setStarting] = useState(false);
|
|
76
87
|
const [exiting, setExiting] = useState(false);
|
|
77
88
|
|
|
@@ -23,6 +23,19 @@ export interface ImpersonationActive {
|
|
|
23
23
|
origins?: string[];
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
export function parseActiveCookie(
|
|
27
|
+
json: string | undefined
|
|
28
|
+
): ImpersonationActive | null {
|
|
29
|
+
if (!json) return null;
|
|
30
|
+
try {
|
|
31
|
+
const parsed = JSON.parse(json) as ImpersonationActive;
|
|
32
|
+
if (parsed.expiresOn * 1000 <= Date.now()) return null;
|
|
33
|
+
return parsed;
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
interface MintedToken {
|
|
27
40
|
accessToken: string;
|
|
28
41
|
expiresOn: number;
|