@mohasinac/appkit 4.5.1 → 4.5.2

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.
@@ -1,4 +1,4 @@
1
- import type { ReactNode } from "react";
1
+ import { type ReactNode } from "react";
2
2
  import type { LayoutRole } from "../../../shared/features/layout/types";
3
3
  export interface RoleGuardProps {
4
4
  /** Single role or array. Omit for auth-only (any signed-in user). */
@@ -12,13 +12,34 @@ import { jsx as _jsx } from "react/jsx-runtime";
12
12
  * route overrides. Everything else defaults to appkit's ROUTES.
13
13
  */
14
14
  import { useRouter } from "next/navigation";
15
+ import { useEffect, useRef, useState } from "react";
15
16
  import { ProtectedRoute } from "../../../../features/auth/components/Guards";
16
17
  import { useSession } from "../../../../react/contexts/SessionContext";
17
18
  import { ROUTES } from "../../../../next/routing/route-map";
18
19
  export function RoleGuard({ role, requireAuth = true, loginPath, unauthorizedPath, loadingComponent, children, }) {
19
- const { user, loading } = useSession();
20
+ const { user, loading, refreshUser } = useSession();
20
21
  const router = useRouter();
21
- return (_jsx(ProtectedRoute, { user: user, loading: loading, requireAuth: requireAuth, requireRole: role, onNavigate: (path) => router.push(path), routes: {
22
+ // SessionContext only refreshes role/disabled periodically (every 5
23
+ // minutes) or on a hard reload/re-login — never on ordinary client-side
24
+ // navigation. A user just approved as a seller, or just un-banned, would
25
+ // otherwise keep getting redirected to /unauthorized by this exact guard
26
+ // for up to 5 minutes even though the same check against live Firestore
27
+ // data would already pass. Force one fresh check per mount (i.e. once per
28
+ // navigation into a role-gated layout, since Next.js layouts persist
29
+ // across sibling route changes) before trusting a denial.
30
+ const hasRefreshedRef = useRef(false);
31
+ const [verifying, setVerifying] = useState(true);
32
+ useEffect(() => {
33
+ if (loading || hasRefreshedRef.current)
34
+ return;
35
+ hasRefreshedRef.current = true;
36
+ if (!user) {
37
+ setVerifying(false);
38
+ return;
39
+ }
40
+ refreshUser().finally(() => setVerifying(false));
41
+ }, [loading, user, refreshUser]);
42
+ return (_jsx(ProtectedRoute, { user: user, loading: loading || verifying, requireAuth: requireAuth, requireRole: role, onNavigate: (path) => router.push(path), routes: {
22
43
  loginPath: loginPath ?? String(ROUTES.AUTH.LOGIN),
23
44
  unauthorizedPath: unauthorizedPath ?? String(ROUTES.ERRORS.UNAUTHORIZED),
24
45
  }, loadingComponent: loadingComponent, children: children }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/appkit",
3
- "version": "4.5.1",
3
+ "version": "4.5.2",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"