nextauthz 1.3.34 → 1.3.37
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/dist/index.d.mts +6 -9
- package/dist/index.d.ts +6 -9
- package/dist/index.js +74 -73
- package/dist/index.mjs +81 -74
- package/package.json +1 -1
- package/readme.md +1 -1
- package/src/AuthGuard.tsx +11 -18
- package/src/AuthProvider.tsx +90 -99
- package/src/RoleGuard.tsx +18 -21
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
type User = {
|
|
5
5
|
[key: string]: any;
|
|
@@ -10,7 +10,7 @@ type AuthContextType<UserType extends User = User> = {
|
|
|
10
10
|
role: string | null;
|
|
11
11
|
isAuthenticated: boolean;
|
|
12
12
|
isAuthChecked: boolean;
|
|
13
|
-
login: (tokens: Record<string, string>, userData?: UserType
|
|
13
|
+
login: (tokens: Record<string, string>, userData?: UserType) => void;
|
|
14
14
|
logout: () => void;
|
|
15
15
|
setUser: (user: UserType | null) => void;
|
|
16
16
|
tokenKey: string;
|
|
@@ -24,22 +24,19 @@ declare function createAuthContext<UserType extends User = User>(option?: {
|
|
|
24
24
|
children: ReactNode;
|
|
25
25
|
}) => react_jsx_runtime.JSX.Element;
|
|
26
26
|
useAuth: () => AuthContextType<UserType>;
|
|
27
|
-
tokenKey: string;
|
|
28
27
|
};
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
declare const AuthGuard: ({ children, redirectTo, fallback, }: {
|
|
31
30
|
children: React.ReactNode;
|
|
32
31
|
redirectTo?: string;
|
|
33
32
|
fallback?: React.ReactNode;
|
|
34
|
-
};
|
|
35
|
-
declare const AuthGuard: ({ children, redirectTo, fallback, }: AuthGuardProps) => react_jsx_runtime.JSX.Element | null;
|
|
33
|
+
}) => react_jsx_runtime.JSX.Element | null;
|
|
36
34
|
|
|
37
|
-
|
|
35
|
+
declare const RoleGuard: ({ children, allowedRoles, redirectTo, fallback, }: {
|
|
38
36
|
children: React.ReactNode;
|
|
39
37
|
allowedRoles: string[];
|
|
40
38
|
redirectTo?: string;
|
|
41
39
|
fallback?: React.ReactNode;
|
|
42
|
-
};
|
|
43
|
-
declare const RoleGuard: ({ children, allowedRoles, redirectTo, fallback, }: RoleGuardProps) => react_jsx_runtime.JSX.Element | null;
|
|
40
|
+
}) => react_jsx_runtime.JSX.Element | null;
|
|
44
41
|
|
|
45
42
|
export { AuthGuard, RoleGuard, createAuthContext };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
type User = {
|
|
5
5
|
[key: string]: any;
|
|
@@ -10,7 +10,7 @@ type AuthContextType<UserType extends User = User> = {
|
|
|
10
10
|
role: string | null;
|
|
11
11
|
isAuthenticated: boolean;
|
|
12
12
|
isAuthChecked: boolean;
|
|
13
|
-
login: (tokens: Record<string, string>, userData?: UserType
|
|
13
|
+
login: (tokens: Record<string, string>, userData?: UserType) => void;
|
|
14
14
|
logout: () => void;
|
|
15
15
|
setUser: (user: UserType | null) => void;
|
|
16
16
|
tokenKey: string;
|
|
@@ -24,22 +24,19 @@ declare function createAuthContext<UserType extends User = User>(option?: {
|
|
|
24
24
|
children: ReactNode;
|
|
25
25
|
}) => react_jsx_runtime.JSX.Element;
|
|
26
26
|
useAuth: () => AuthContextType<UserType>;
|
|
27
|
-
tokenKey: string;
|
|
28
27
|
};
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
declare const AuthGuard: ({ children, redirectTo, fallback, }: {
|
|
31
30
|
children: React.ReactNode;
|
|
32
31
|
redirectTo?: string;
|
|
33
32
|
fallback?: React.ReactNode;
|
|
34
|
-
};
|
|
35
|
-
declare const AuthGuard: ({ children, redirectTo, fallback, }: AuthGuardProps) => react_jsx_runtime.JSX.Element | null;
|
|
33
|
+
}) => react_jsx_runtime.JSX.Element | null;
|
|
36
34
|
|
|
37
|
-
|
|
35
|
+
declare const RoleGuard: ({ children, allowedRoles, redirectTo, fallback, }: {
|
|
38
36
|
children: React.ReactNode;
|
|
39
37
|
allowedRoles: string[];
|
|
40
38
|
redirectTo?: string;
|
|
41
39
|
fallback?: React.ReactNode;
|
|
42
|
-
};
|
|
43
|
-
declare const RoleGuard: ({ children, allowedRoles, redirectTo, fallback, }: RoleGuardProps) => react_jsx_runtime.JSX.Element | null;
|
|
40
|
+
}) => react_jsx_runtime.JSX.Element | null;
|
|
44
41
|
|
|
45
42
|
export { AuthGuard, RoleGuard, createAuthContext };
|
package/dist/index.js
CHANGED
|
@@ -60,92 +60,95 @@ var useAuthStore = (0, import_zustand.create)((set) => ({
|
|
|
60
60
|
// src/AuthProvider.tsx
|
|
61
61
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
62
62
|
function createAuthContext(option) {
|
|
63
|
-
const AuthContext = (0, import_react.createContext)(
|
|
63
|
+
const AuthContext = (0, import_react.createContext)(
|
|
64
|
+
void 0
|
|
65
|
+
);
|
|
64
66
|
const AuthProvider = ({ children }) => {
|
|
65
67
|
const storage = option?.storage ?? "cookie";
|
|
66
68
|
const tokenKey = option?.tokenKey ?? "access_token";
|
|
67
69
|
const rolePath = option?.rolePath ?? "role";
|
|
70
|
+
const manager = (0, import_react_token_manager.useTokenManager)();
|
|
71
|
+
const user = useAuthStore((s) => s.user);
|
|
72
|
+
const role = useAuthStore((s) => s.role);
|
|
73
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
|
74
|
+
const isAuthChecked = useAuthStore((s) => s.isAuthChecked);
|
|
75
|
+
const setUser = useAuthStore((s) => s.setUser);
|
|
76
|
+
const setRole = useAuthStore((s) => s.setRole);
|
|
77
|
+
const setAuth = useAuthStore((s) => s.setAuth);
|
|
78
|
+
const setAuthChecked = useAuthStore((s) => s.setAuthChecked);
|
|
79
|
+
const resetAuth = useAuthStore((s) => s.resetAuth);
|
|
68
80
|
(0, import_react.useEffect)(() => {
|
|
69
81
|
(0, import_react_token_manager.configureTokenManager)({ storage });
|
|
70
82
|
}, [storage]);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
isAuthChecked,
|
|
79
|
-
isAuthenticated,
|
|
80
|
-
setAuth,
|
|
81
|
-
setAuthChecked
|
|
82
|
-
} = useAuthStore();
|
|
83
|
-
const extractRole = (userObj) => {
|
|
84
|
-
if (!userObj || !rolePath) return null;
|
|
85
|
-
return rolePath.split(".").reduce((acc, key) => acc?.[key], userObj) ?? null;
|
|
86
|
-
};
|
|
83
|
+
const extractRole = (0, import_react.useCallback)(
|
|
84
|
+
(userObj) => {
|
|
85
|
+
if (!userObj) return null;
|
|
86
|
+
return rolePath.split(".").reduce((acc, key) => acc?.[key], userObj) ?? null;
|
|
87
|
+
},
|
|
88
|
+
[rolePath]
|
|
89
|
+
);
|
|
87
90
|
(0, import_react.useEffect)(() => {
|
|
88
|
-
const storedUser = manager.getSingleToken("user");
|
|
89
91
|
const token = manager.getSingleToken(tokenKey);
|
|
90
92
|
if (token && !manager.isExpired(token)) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
setAuth(true);
|
|
94
|
+
if (user) {
|
|
95
|
+
try {
|
|
96
|
+
setUser(user);
|
|
97
|
+
setRole(extractRole(user));
|
|
98
|
+
} catch {
|
|
99
|
+
resetAuth();
|
|
97
100
|
}
|
|
98
|
-
} catch {
|
|
99
|
-
resetAuth();
|
|
100
101
|
}
|
|
101
102
|
} else {
|
|
102
103
|
resetAuth();
|
|
103
104
|
}
|
|
104
105
|
setAuthChecked(true);
|
|
105
|
-
}, [tokenKey]);
|
|
106
|
-
const login = (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
106
|
+
}, [tokenKey, manager, user, setAuth, setAuthChecked, setUser, setRole, resetAuth, extractRole]);
|
|
107
|
+
const login = (0, import_react.useCallback)(
|
|
108
|
+
(tokens, userData) => {
|
|
109
|
+
const tokenValue = tokens[tokenKey] ?? tokens["access_token"] ?? Object.values(tokens)[0];
|
|
110
|
+
manager.setTokens({
|
|
111
|
+
...tokens,
|
|
112
|
+
[tokenKey]: tokenValue,
|
|
113
|
+
user: JSON.stringify(userData ?? null)
|
|
114
|
+
});
|
|
115
|
+
if (userData) {
|
|
116
|
+
setUser(userData);
|
|
117
|
+
setRole(extractRole(userData));
|
|
118
|
+
}
|
|
119
|
+
setAuth(true);
|
|
120
|
+
setAuthChecked(true);
|
|
121
|
+
},
|
|
122
|
+
[tokenKey, manager, setUser, setRole, extractRole, setAuth, setAuthChecked]
|
|
123
|
+
);
|
|
124
|
+
const logout = (0, import_react.useCallback)(() => {
|
|
119
125
|
manager.clearTokens();
|
|
120
126
|
resetAuth();
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
tokenKey
|
|
127
|
+
}, [manager, resetAuth]);
|
|
128
|
+
const value = (0, import_react.useMemo)(
|
|
129
|
+
() => ({
|
|
130
|
+
user,
|
|
131
|
+
role,
|
|
132
|
+
isAuthenticated,
|
|
133
|
+
isAuthChecked,
|
|
134
|
+
login,
|
|
135
|
+
logout,
|
|
136
|
+
setUser: (u) => {
|
|
137
|
+
setUser(u);
|
|
138
|
+
setRole(extractRole(u));
|
|
134
139
|
},
|
|
135
|
-
|
|
136
|
-
}
|
|
140
|
+
tokenKey
|
|
141
|
+
}),
|
|
142
|
+
[user, role, isAuthenticated, isAuthChecked, login, logout, setUser, tokenKey, extractRole]
|
|
137
143
|
);
|
|
144
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AuthContext.Provider, { value, children });
|
|
138
145
|
};
|
|
139
146
|
const useAuth = () => {
|
|
140
147
|
const context = (0, import_react.useContext)(AuthContext);
|
|
141
148
|
if (!context) throw new Error("useAuth must be used within AuthProvider");
|
|
142
149
|
return context;
|
|
143
150
|
};
|
|
144
|
-
return {
|
|
145
|
-
AuthProvider,
|
|
146
|
-
useAuth,
|
|
147
|
-
tokenKey: option?.tokenKey ?? "access_token"
|
|
148
|
-
};
|
|
151
|
+
return { AuthProvider, useAuth };
|
|
149
152
|
}
|
|
150
153
|
|
|
151
154
|
// src/AuthGuard.tsx
|
|
@@ -158,18 +161,16 @@ var AuthGuard = ({
|
|
|
158
161
|
fallback = null
|
|
159
162
|
}) => {
|
|
160
163
|
const router = (0, import_navigation.useRouter)();
|
|
161
|
-
const
|
|
164
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
|
165
|
+
const isAuthChecked = useAuthStore((s) => s.isAuthChecked);
|
|
162
166
|
(0, import_react2.useEffect)(() => {
|
|
163
167
|
if (!isAuthChecked) return;
|
|
164
168
|
if (!isAuthenticated) {
|
|
165
169
|
router.replace(redirectTo);
|
|
166
170
|
}
|
|
167
|
-
}, [isAuthenticated, isAuthChecked
|
|
171
|
+
}, [isAuthenticated, isAuthChecked]);
|
|
168
172
|
if (!isAuthChecked) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: fallback });
|
|
169
|
-
if (!isAuthenticated)
|
|
170
|
-
router.replace(redirectTo);
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
173
|
+
if (!isAuthenticated) return null;
|
|
173
174
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children });
|
|
174
175
|
};
|
|
175
176
|
var AuthGuard_default = AuthGuard;
|
|
@@ -185,19 +186,19 @@ var RoleGuard = ({
|
|
|
185
186
|
fallback = null
|
|
186
187
|
}) => {
|
|
187
188
|
const router = (0, import_navigation2.useRouter)();
|
|
188
|
-
const
|
|
189
|
+
const role = useAuthStore((s) => s.role);
|
|
190
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
|
191
|
+
const isAuthChecked = useAuthStore((s) => s.isAuthChecked);
|
|
189
192
|
(0, import_react3.useEffect)(() => {
|
|
190
|
-
if (!isAuthChecked) return;
|
|
193
|
+
if (!isAuthChecked || !isAuthenticated) return;
|
|
191
194
|
if (!role || !allowedRoles.includes(role)) {
|
|
192
195
|
router.replace(redirectTo);
|
|
193
196
|
}
|
|
194
|
-
}, [role,
|
|
197
|
+
}, [role, isAuthenticated, isAuthChecked]);
|
|
195
198
|
if (!isAuthChecked) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: fallback });
|
|
196
|
-
if (!isAuthenticated)
|
|
197
|
-
router.replace(redirectTo);
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
199
|
+
if (!isAuthenticated) return null;
|
|
200
200
|
if (!role || !allowedRoles.includes(role)) return null;
|
|
201
|
+
console.log(role);
|
|
201
202
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children });
|
|
202
203
|
};
|
|
203
204
|
var RoleGuard_default = RoleGuard;
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/AuthProvider.tsx
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
createContext,
|
|
6
|
+
useContext,
|
|
7
|
+
useEffect,
|
|
8
|
+
useMemo,
|
|
9
|
+
useCallback
|
|
10
|
+
} from "react";
|
|
5
11
|
import { configureTokenManager, useTokenManager } from "react-token-manager";
|
|
6
12
|
|
|
7
13
|
// store/useGuardStore.ts
|
|
@@ -33,92 +39,95 @@ var useAuthStore = create((set) => ({
|
|
|
33
39
|
// src/AuthProvider.tsx
|
|
34
40
|
import { jsx } from "react/jsx-runtime";
|
|
35
41
|
function createAuthContext(option) {
|
|
36
|
-
const AuthContext = createContext(
|
|
42
|
+
const AuthContext = createContext(
|
|
43
|
+
void 0
|
|
44
|
+
);
|
|
37
45
|
const AuthProvider = ({ children }) => {
|
|
38
46
|
const storage = option?.storage ?? "cookie";
|
|
39
47
|
const tokenKey = option?.tokenKey ?? "access_token";
|
|
40
48
|
const rolePath = option?.rolePath ?? "role";
|
|
49
|
+
const manager = useTokenManager();
|
|
50
|
+
const user = useAuthStore((s) => s.user);
|
|
51
|
+
const role = useAuthStore((s) => s.role);
|
|
52
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
|
53
|
+
const isAuthChecked = useAuthStore((s) => s.isAuthChecked);
|
|
54
|
+
const setUser = useAuthStore((s) => s.setUser);
|
|
55
|
+
const setRole = useAuthStore((s) => s.setRole);
|
|
56
|
+
const setAuth = useAuthStore((s) => s.setAuth);
|
|
57
|
+
const setAuthChecked = useAuthStore((s) => s.setAuthChecked);
|
|
58
|
+
const resetAuth = useAuthStore((s) => s.resetAuth);
|
|
41
59
|
useEffect(() => {
|
|
42
60
|
configureTokenManager({ storage });
|
|
43
61
|
}, [storage]);
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
isAuthChecked,
|
|
52
|
-
isAuthenticated,
|
|
53
|
-
setAuth,
|
|
54
|
-
setAuthChecked
|
|
55
|
-
} = useAuthStore();
|
|
56
|
-
const extractRole = (userObj) => {
|
|
57
|
-
if (!userObj || !rolePath) return null;
|
|
58
|
-
return rolePath.split(".").reduce((acc, key) => acc?.[key], userObj) ?? null;
|
|
59
|
-
};
|
|
62
|
+
const extractRole = useCallback(
|
|
63
|
+
(userObj) => {
|
|
64
|
+
if (!userObj) return null;
|
|
65
|
+
return rolePath.split(".").reduce((acc, key) => acc?.[key], userObj) ?? null;
|
|
66
|
+
},
|
|
67
|
+
[rolePath]
|
|
68
|
+
);
|
|
60
69
|
useEffect(() => {
|
|
61
|
-
const storedUser = manager.getSingleToken("user");
|
|
62
70
|
const token = manager.getSingleToken(tokenKey);
|
|
63
71
|
if (token && !manager.isExpired(token)) {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
setAuth(true);
|
|
73
|
+
if (user) {
|
|
74
|
+
try {
|
|
75
|
+
setUser(user);
|
|
76
|
+
setRole(extractRole(user));
|
|
77
|
+
} catch {
|
|
78
|
+
resetAuth();
|
|
70
79
|
}
|
|
71
|
-
} catch {
|
|
72
|
-
resetAuth();
|
|
73
80
|
}
|
|
74
81
|
} else {
|
|
75
82
|
resetAuth();
|
|
76
83
|
}
|
|
77
84
|
setAuthChecked(true);
|
|
78
|
-
}, [tokenKey]);
|
|
79
|
-
const login = (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
85
|
+
}, [tokenKey, manager, user, setAuth, setAuthChecked, setUser, setRole, resetAuth, extractRole]);
|
|
86
|
+
const login = useCallback(
|
|
87
|
+
(tokens, userData) => {
|
|
88
|
+
const tokenValue = tokens[tokenKey] ?? tokens["access_token"] ?? Object.values(tokens)[0];
|
|
89
|
+
manager.setTokens({
|
|
90
|
+
...tokens,
|
|
91
|
+
[tokenKey]: tokenValue,
|
|
92
|
+
user: JSON.stringify(userData ?? null)
|
|
93
|
+
});
|
|
94
|
+
if (userData) {
|
|
95
|
+
setUser(userData);
|
|
96
|
+
setRole(extractRole(userData));
|
|
97
|
+
}
|
|
98
|
+
setAuth(true);
|
|
99
|
+
setAuthChecked(true);
|
|
100
|
+
},
|
|
101
|
+
[tokenKey, manager, setUser, setRole, extractRole, setAuth, setAuthChecked]
|
|
102
|
+
);
|
|
103
|
+
const logout = useCallback(() => {
|
|
92
104
|
manager.clearTokens();
|
|
93
105
|
resetAuth();
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
tokenKey
|
|
106
|
+
}, [manager, resetAuth]);
|
|
107
|
+
const value = useMemo(
|
|
108
|
+
() => ({
|
|
109
|
+
user,
|
|
110
|
+
role,
|
|
111
|
+
isAuthenticated,
|
|
112
|
+
isAuthChecked,
|
|
113
|
+
login,
|
|
114
|
+
logout,
|
|
115
|
+
setUser: (u) => {
|
|
116
|
+
setUser(u);
|
|
117
|
+
setRole(extractRole(u));
|
|
107
118
|
},
|
|
108
|
-
|
|
109
|
-
}
|
|
119
|
+
tokenKey
|
|
120
|
+
}),
|
|
121
|
+
[user, role, isAuthenticated, isAuthChecked, login, logout, setUser, tokenKey, extractRole]
|
|
110
122
|
);
|
|
123
|
+
return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children });
|
|
111
124
|
};
|
|
112
125
|
const useAuth = () => {
|
|
113
126
|
const context = useContext(AuthContext);
|
|
114
127
|
if (!context) throw new Error("useAuth must be used within AuthProvider");
|
|
115
128
|
return context;
|
|
116
129
|
};
|
|
117
|
-
return {
|
|
118
|
-
AuthProvider,
|
|
119
|
-
useAuth,
|
|
120
|
-
tokenKey: option?.tokenKey ?? "access_token"
|
|
121
|
-
};
|
|
130
|
+
return { AuthProvider, useAuth };
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
// src/AuthGuard.tsx
|
|
@@ -131,18 +140,16 @@ var AuthGuard = ({
|
|
|
131
140
|
fallback = null
|
|
132
141
|
}) => {
|
|
133
142
|
const router = useRouter();
|
|
134
|
-
const
|
|
143
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
|
144
|
+
const isAuthChecked = useAuthStore((s) => s.isAuthChecked);
|
|
135
145
|
useEffect2(() => {
|
|
136
146
|
if (!isAuthChecked) return;
|
|
137
147
|
if (!isAuthenticated) {
|
|
138
148
|
router.replace(redirectTo);
|
|
139
149
|
}
|
|
140
|
-
}, [isAuthenticated, isAuthChecked
|
|
150
|
+
}, [isAuthenticated, isAuthChecked]);
|
|
141
151
|
if (!isAuthChecked) return /* @__PURE__ */ jsx2(Fragment, { children: fallback });
|
|
142
|
-
if (!isAuthenticated)
|
|
143
|
-
router.replace(redirectTo);
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
152
|
+
if (!isAuthenticated) return null;
|
|
146
153
|
return /* @__PURE__ */ jsx2(Fragment, { children });
|
|
147
154
|
};
|
|
148
155
|
var AuthGuard_default = AuthGuard;
|
|
@@ -158,19 +165,19 @@ var RoleGuard = ({
|
|
|
158
165
|
fallback = null
|
|
159
166
|
}) => {
|
|
160
167
|
const router = useRouter2();
|
|
161
|
-
const
|
|
168
|
+
const role = useAuthStore((s) => s.role);
|
|
169
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated);
|
|
170
|
+
const isAuthChecked = useAuthStore((s) => s.isAuthChecked);
|
|
162
171
|
useEffect3(() => {
|
|
163
|
-
if (!isAuthChecked) return;
|
|
172
|
+
if (!isAuthChecked || !isAuthenticated) return;
|
|
164
173
|
if (!role || !allowedRoles.includes(role)) {
|
|
165
174
|
router.replace(redirectTo);
|
|
166
175
|
}
|
|
167
|
-
}, [role,
|
|
176
|
+
}, [role, isAuthenticated, isAuthChecked]);
|
|
168
177
|
if (!isAuthChecked) return /* @__PURE__ */ jsx3(Fragment2, { children: fallback });
|
|
169
|
-
if (!isAuthenticated)
|
|
170
|
-
router.replace(redirectTo);
|
|
171
|
-
return null;
|
|
172
|
-
}
|
|
178
|
+
if (!isAuthenticated) return null;
|
|
173
179
|
if (!role || !allowedRoles.includes(role)) return null;
|
|
180
|
+
console.log(role);
|
|
174
181
|
return /* @__PURE__ */ jsx3(Fragment2, { children });
|
|
175
182
|
};
|
|
176
183
|
var RoleGuard_default = RoleGuard;
|
package/package.json
CHANGED
package/readme.md
CHANGED
package/src/AuthGuard.tsx
CHANGED
|
@@ -1,41 +1,34 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { useEffect } from 'react'
|
|
4
4
|
import { useRouter } from 'next/navigation'
|
|
5
5
|
import { useAuthStore } from '../store/useGuardStore'
|
|
6
6
|
|
|
7
|
-
type AuthGuardProps = {
|
|
8
|
-
children: React.ReactNode
|
|
9
|
-
redirectTo?: string
|
|
10
|
-
fallback?: React.ReactNode
|
|
11
|
-
}
|
|
12
|
-
|
|
13
7
|
const AuthGuard = ({
|
|
14
8
|
children,
|
|
15
9
|
redirectTo = '/login',
|
|
16
10
|
fallback = null,
|
|
17
|
-
}:
|
|
11
|
+
}: {
|
|
12
|
+
children: React.ReactNode
|
|
13
|
+
redirectTo?: string
|
|
14
|
+
fallback?: React.ReactNode
|
|
15
|
+
}) => {
|
|
18
16
|
const router = useRouter()
|
|
19
17
|
|
|
20
|
-
const
|
|
18
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated)
|
|
19
|
+
const isAuthChecked = useAuthStore((s) => s.isAuthChecked)
|
|
21
20
|
|
|
22
21
|
useEffect(() => {
|
|
23
22
|
if (!isAuthChecked) return
|
|
24
|
-
|
|
25
23
|
if (!isAuthenticated) {
|
|
26
24
|
router.replace(redirectTo)
|
|
27
25
|
}
|
|
28
|
-
}, [isAuthenticated, isAuthChecked
|
|
26
|
+
}, [isAuthenticated, isAuthChecked])
|
|
29
27
|
|
|
30
28
|
if (!isAuthChecked) return <>{fallback}</>
|
|
31
|
-
|
|
32
|
-
if (!isAuthenticated) {
|
|
33
|
-
router.replace(redirectTo)
|
|
34
|
-
return null
|
|
35
|
-
}
|
|
36
|
-
|
|
29
|
+
if (!isAuthenticated) return null
|
|
37
30
|
|
|
38
31
|
return <>{children}</>
|
|
39
32
|
}
|
|
40
33
|
|
|
41
|
-
export default AuthGuard
|
|
34
|
+
export default AuthGuard
|
package/src/AuthProvider.tsx
CHANGED
|
@@ -1,143 +1,138 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
useContext,
|
|
6
|
+
ReactNode,
|
|
7
|
+
useEffect,
|
|
8
|
+
useMemo,
|
|
9
|
+
useCallback,
|
|
10
|
+
} from 'react'
|
|
4
11
|
import { configureTokenManager, useTokenManager } from 'react-token-manager'
|
|
5
12
|
import { useAuthStore, User } from '../store/useGuardStore'
|
|
6
13
|
|
|
7
|
-
/* ---------------------------------- */
|
|
8
|
-
/* Types */
|
|
9
|
-
/* ---------------------------------- */
|
|
10
|
-
|
|
11
14
|
export type AuthContextType<UserType extends User = User> = {
|
|
12
15
|
user: UserType | null
|
|
13
16
|
role: string | null
|
|
14
17
|
isAuthenticated: boolean
|
|
15
18
|
isAuthChecked: boolean
|
|
16
|
-
login: (tokens: Record<string, string>, userData?: UserType
|
|
19
|
+
login: (tokens: Record<string, string>, userData?: UserType) => void
|
|
17
20
|
logout: () => void
|
|
18
21
|
setUser: (user: UserType | null) => void
|
|
19
22
|
tokenKey: string
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
/* ---------------------------------- */
|
|
23
|
-
/* Factory */
|
|
24
|
-
/* ---------------------------------- */
|
|
25
|
-
|
|
26
25
|
export function createAuthContext<UserType extends User = User>(option?: {
|
|
27
26
|
storage?: 'localStorage' | 'sessionStorage' | 'cookie'
|
|
28
27
|
tokenKey?: string
|
|
29
|
-
rolePath?: string
|
|
28
|
+
rolePath?: string
|
|
30
29
|
}) {
|
|
31
|
-
const AuthContext = createContext<AuthContextType<UserType> | undefined>(
|
|
30
|
+
const AuthContext = createContext<AuthContextType<UserType> | undefined>(
|
|
31
|
+
undefined
|
|
32
|
+
)
|
|
32
33
|
|
|
33
34
|
const AuthProvider = ({ children }: { children: ReactNode }) => {
|
|
34
35
|
const storage = option?.storage ?? 'cookie'
|
|
35
36
|
const tokenKey = option?.tokenKey ?? 'access_token'
|
|
36
37
|
const rolePath = option?.rolePath ?? 'role'
|
|
37
38
|
|
|
39
|
+
const manager = useTokenManager()
|
|
40
|
+
|
|
41
|
+
// ✅ Selectors
|
|
42
|
+
const user = useAuthStore((s) => s.user)
|
|
43
|
+
const role = useAuthStore((s) => s.role)
|
|
44
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated)
|
|
45
|
+
const isAuthChecked = useAuthStore((s) => s.isAuthChecked)
|
|
46
|
+
|
|
47
|
+
const setUser = useAuthStore((s) => s.setUser)
|
|
48
|
+
const setRole = useAuthStore((s) => s.setRole)
|
|
49
|
+
const setAuth = useAuthStore((s) => s.setAuth)
|
|
50
|
+
const setAuthChecked = useAuthStore((s) => s.setAuthChecked)
|
|
51
|
+
const resetAuth = useAuthStore((s) => s.resetAuth)
|
|
52
|
+
|
|
38
53
|
useEffect(() => {
|
|
39
54
|
configureTokenManager({ storage })
|
|
40
55
|
}, [storage])
|
|
41
56
|
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
isAuthenticated,
|
|
51
|
-
setAuth,
|
|
52
|
-
setAuthChecked,
|
|
53
|
-
} = useAuthStore()
|
|
54
|
-
|
|
55
|
-
/* ---------------------------------- */
|
|
56
|
-
/* Helper: get role from path */
|
|
57
|
-
/* ---------------------------------- */
|
|
58
|
-
const extractRole = (userObj: any) => {
|
|
59
|
-
if (!userObj || !rolePath) return null
|
|
60
|
-
return rolePath.split('.').reduce((acc: any, key: string) => acc?.[key], userObj) ?? null
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
/* ---------------------------------- */
|
|
65
|
-
/* Hydrate user from storage */
|
|
66
|
-
/* ---------------------------------- */
|
|
57
|
+
// ✅ Extract role from user
|
|
58
|
+
const extractRole = useCallback(
|
|
59
|
+
(userObj: any) => {
|
|
60
|
+
if (!userObj) return null
|
|
61
|
+
return rolePath.split('.').reduce((acc: any, key: string) => acc?.[key], userObj) ?? null
|
|
62
|
+
},
|
|
63
|
+
[rolePath]
|
|
64
|
+
)
|
|
67
65
|
|
|
66
|
+
// ✅ Hydrate once
|
|
68
67
|
useEffect(() => {
|
|
69
|
-
const storedUser = manager.getSingleToken('user')
|
|
70
68
|
const token = manager.getSingleToken(tokenKey)
|
|
71
69
|
|
|
72
70
|
if (token && !manager.isExpired(token)) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
71
|
+
setAuth(true)
|
|
72
|
+
|
|
73
|
+
if (user) {
|
|
74
|
+
try {
|
|
75
|
+
setUser(user) // ensure user is set in store
|
|
76
|
+
setRole(extractRole(user)) // set role automatically
|
|
77
|
+
} catch {
|
|
78
|
+
resetAuth()
|
|
80
79
|
}
|
|
81
|
-
} catch {
|
|
82
|
-
resetAuth()
|
|
83
80
|
}
|
|
84
81
|
} else {
|
|
85
82
|
resetAuth()
|
|
86
83
|
}
|
|
87
84
|
|
|
88
85
|
setAuthChecked(true)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
setAuth(true)
|
|
108
|
-
setAuthChecked(true)
|
|
109
|
-
}
|
|
86
|
+
}, [tokenKey, manager, user, setAuth, setAuthChecked, setUser, setRole, resetAuth, extractRole])
|
|
87
|
+
|
|
88
|
+
// ✅ Login function
|
|
89
|
+
const login = useCallback(
|
|
90
|
+
(tokens: Record<string, string>, userData?: UserType) => {
|
|
91
|
+
const tokenValue =
|
|
92
|
+
tokens[tokenKey] ?? tokens['access_token'] ?? Object.values(tokens)[0]
|
|
93
|
+
|
|
94
|
+
manager.setTokens({
|
|
95
|
+
...tokens,
|
|
96
|
+
[tokenKey]: tokenValue,
|
|
97
|
+
user: JSON.stringify(userData ?? null),
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
if (userData) {
|
|
101
|
+
setUser(userData)
|
|
102
|
+
setRole(extractRole(userData)) // set role whenever user is logged in
|
|
103
|
+
}
|
|
110
104
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
105
|
+
setAuth(true)
|
|
106
|
+
setAuthChecked(true)
|
|
107
|
+
},
|
|
108
|
+
[tokenKey, manager, setUser, setRole, extractRole, setAuth, setAuthChecked]
|
|
109
|
+
)
|
|
114
110
|
|
|
115
|
-
const logout = () => {
|
|
111
|
+
const logout = useCallback(() => {
|
|
116
112
|
manager.clearTokens()
|
|
117
113
|
resetAuth()
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
114
|
+
}, [manager, resetAuth])
|
|
115
|
+
|
|
116
|
+
// ✅ MEMOIZED CONTEXT VALUE
|
|
117
|
+
const value = useMemo(
|
|
118
|
+
() => ({
|
|
119
|
+
user: user as UserType | null,
|
|
120
|
+
role,
|
|
121
|
+
isAuthenticated,
|
|
122
|
+
isAuthChecked,
|
|
123
|
+
login,
|
|
124
|
+
logout,
|
|
125
|
+
setUser: (u: UserType | null) => {
|
|
126
|
+
setUser(u)
|
|
127
|
+
setRole(extractRole(u))
|
|
128
|
+
},
|
|
129
|
+
tokenKey,
|
|
130
|
+
}),
|
|
131
|
+
[user, role, isAuthenticated, isAuthChecked, login, logout, setUser, tokenKey, extractRole]
|
|
135
132
|
)
|
|
136
|
-
}
|
|
137
133
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
/* ---------------------------------- */
|
|
134
|
+
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
|
135
|
+
}
|
|
141
136
|
|
|
142
137
|
const useAuth = () => {
|
|
143
138
|
const context = useContext(AuthContext)
|
|
@@ -145,9 +140,5 @@ export function createAuthContext<UserType extends User = User>(option?: {
|
|
|
145
140
|
return context
|
|
146
141
|
}
|
|
147
142
|
|
|
148
|
-
return {
|
|
149
|
-
|
|
150
|
-
useAuth,
|
|
151
|
-
tokenKey: option?.tokenKey ?? 'access_token',
|
|
152
|
-
}
|
|
153
|
-
}
|
|
143
|
+
return { AuthProvider, useAuth }
|
|
144
|
+
}
|
package/src/RoleGuard.tsx
CHANGED
|
@@ -1,45 +1,42 @@
|
|
|
1
1
|
'use client'
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { useEffect } from 'react'
|
|
4
4
|
import { useRouter } from 'next/navigation'
|
|
5
5
|
import { useAuthStore } from '../store/useGuardStore'
|
|
6
6
|
|
|
7
|
-
type RoleGuardProps = {
|
|
8
|
-
children: React.ReactNode
|
|
9
|
-
allowedRoles: string[]
|
|
10
|
-
redirectTo?: string
|
|
11
|
-
fallback?: React.ReactNode
|
|
12
|
-
}
|
|
13
|
-
|
|
14
7
|
const RoleGuard = ({
|
|
15
8
|
children,
|
|
16
9
|
allowedRoles,
|
|
17
10
|
redirectTo = '/unauthorized',
|
|
18
11
|
fallback = null,
|
|
19
|
-
}:
|
|
12
|
+
}: {
|
|
13
|
+
children: React.ReactNode
|
|
14
|
+
allowedRoles: string[]
|
|
15
|
+
redirectTo?: string
|
|
16
|
+
fallback?: React.ReactNode
|
|
17
|
+
}) => {
|
|
20
18
|
const router = useRouter()
|
|
21
|
-
|
|
19
|
+
|
|
20
|
+
const role = useAuthStore((s) => s.role)
|
|
21
|
+
const isAuthenticated = useAuthStore((s) => s.isAuthenticated)
|
|
22
|
+
const isAuthChecked = useAuthStore((s) => s.isAuthChecked)
|
|
22
23
|
|
|
23
24
|
useEffect(() => {
|
|
24
|
-
if (!isAuthChecked) return
|
|
25
|
+
if (!isAuthChecked || !isAuthenticated) return
|
|
25
26
|
|
|
26
|
-
// If role not allowed, redirect
|
|
27
27
|
if (!role || !allowedRoles.includes(role)) {
|
|
28
28
|
router.replace(redirectTo)
|
|
29
29
|
}
|
|
30
|
-
}, [role,
|
|
30
|
+
}, [role, isAuthenticated, isAuthChecked])
|
|
31
31
|
|
|
32
32
|
if (!isAuthChecked) return <>{fallback}</>
|
|
33
|
-
|
|
34
|
-
if (!isAuthenticated) {
|
|
35
|
-
router.replace(redirectTo)
|
|
36
|
-
return null
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Block rendering if role is not allowed
|
|
33
|
+
if (!isAuthenticated) return null
|
|
40
34
|
if (!role || !allowedRoles.includes(role)) return null
|
|
41
35
|
|
|
36
|
+
console.log(role);
|
|
37
|
+
|
|
38
|
+
|
|
42
39
|
return <>{children}</>
|
|
43
40
|
}
|
|
44
41
|
|
|
45
|
-
export default RoleGuard
|
|
42
|
+
export default RoleGuard
|