@explita/cloud-auth-client 0.1.3 → 0.2.1
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/components/login-form.js +1 -2
- package/dist/components/reset-password.js +1 -1
- package/dist/components/signup-form.js +1 -1
- package/dist/contexts/auth-provider.js +37 -36
- package/dist/lib/api-server.js +1 -0
- package/dist/lib/utils.d.ts +2 -2
- package/dist/lib/utils.js +3 -3
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/server-session.d.ts +2 -8
- package/dist/server/server-session.js +16 -15
- package/dist/server/token-session.d.ts +7 -0
- package/dist/server/token-session.js +36 -0
- package/dist/styles.css +2603 -2645
- package/dist/types.d.ts +23 -0
- package/package.json +2 -1
|
@@ -77,7 +77,6 @@ function Login({ className, logo, ...props }) {
|
|
|
77
77
|
setIsAuthenticated(true);
|
|
78
78
|
}
|
|
79
79
|
setIsPending(false);
|
|
80
|
-
// return { email: formData.get("email") as string };
|
|
81
80
|
}
|
|
82
81
|
return (react_1.default.createElement("div", { className: (0, utils_1.cn)("ecpauth:relative ecpauth:flex ecpauth:flex-col ecpauth:items-center ecpauth:justify-center ecpauth:w-full ecpauth:mx-auto ecpauth:px-4", className), ...props },
|
|
83
82
|
isAuthenticated && react_1.default.createElement(loader_1.Loader, null),
|
|
@@ -91,7 +90,7 @@ function Login({ className, logo, ...props }) {
|
|
|
91
90
|
react_1.default.createElement(card_1.CardTitle, { className: "ecpauth:text-2xl ecpauth:font-black ecpauth:tracking-tight ecpauth:text-gray-900 ecpauth:dark:text-white" }, "Welcome Back"),
|
|
92
91
|
react_1.default.createElement(card_1.CardDescription, { className: "ecpauth:text-sm ecpauth:text-gray-500 ecpauth:dark:text-gray-400" }, "Enter your credentials to access the dashboard.")),
|
|
93
92
|
error?.message && (react_1.default.createElement("p", { className: "ecpauth:text-red-500 ecpauth:mt-3 ecpauth:text-sm ecpauth:font-medium" }, error.message))),
|
|
94
|
-
react_1.default.createElement(card_1.CardContent, { className: "ecpauth:space-y-6 ecpauth:p-8 ecpauth:px-12" },
|
|
93
|
+
react_1.default.createElement(card_1.CardContent, { className: "ecpauth:space-y-6 ecpauth:p-8 ecpauth:lg:px-12" },
|
|
95
94
|
react_1.default.createElement("form", { onSubmit: handleSubmit, className: "ecpauth:space-y-6" },
|
|
96
95
|
react_1.default.createElement("div", { className: "ecpauth:space-y-4" },
|
|
97
96
|
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
@@ -96,7 +96,7 @@ function ResetPassword({ className, onChangePassword, logo, ...props }) {
|
|
|
96
96
|
state?.status === "success" ? (react_1.default.createElement("div", { className: "ecpauth:mt-3" },
|
|
97
97
|
react_1.default.createElement(message_1.Message, { message: state?.message, variant: "success" }))) : state?.message ? (react_1.default.createElement("div", { className: "ecpauth:mt-3" },
|
|
98
98
|
react_1.default.createElement(message_1.Message, { message: state?.message }))) : null),
|
|
99
|
-
react_1.default.createElement(card_1.CardContent, { className: "ecpauth:space-y-6 ecpauth:p-8 ecpauth:px-12" },
|
|
99
|
+
react_1.default.createElement(card_1.CardContent, { className: "ecpauth:space-y-6 ecpauth:p-8 ecpauth:lg:px-12" },
|
|
100
100
|
!token ? (react_1.default.createElement("form", { onSubmit: handleSubmit, className: "ecpauth:space-y-6" },
|
|
101
101
|
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
102
102
|
react_1.default.createElement(label_1.Label, { htmlFor: "email", className: "ecpauth:text-sm ecpauth:font-medium ecpauth:text-gray-700 ecpauth:dark:text-gray-300" }, "Email Address"),
|
|
@@ -108,7 +108,7 @@ function Signup({ className, onSubmit, groupId, metadata, acceptUsername = true,
|
|
|
108
108
|
state?.status === "success" ? (react_1.default.createElement("div", { className: "ecpauth:mt-3" },
|
|
109
109
|
react_1.default.createElement(message_1.Message, { message: state?.message, variant: "success" }))) : state?.message ? (react_1.default.createElement("div", { className: "ecpauth:mt-3" },
|
|
110
110
|
react_1.default.createElement(message_1.Message, { message: state?.message }))) : null),
|
|
111
|
-
react_1.default.createElement(card_1.CardContent, { className: "ecpauth:space-y-6 ecpauth:p-8 ecpauth:px-12" },
|
|
111
|
+
react_1.default.createElement(card_1.CardContent, { className: "ecpauth:space-y-6 ecpauth:p-8 ecpauth:lg:px-12" },
|
|
112
112
|
react_1.default.createElement("form", { onSubmit: handleSubmit, className: "ecpauth:space-y-6" },
|
|
113
113
|
react_1.default.createElement("div", { className: "ecpauth:grid ecpauth:grid-cols-1 ecpauth:md:grid-cols-2 ecpauth:gap-4" },
|
|
114
114
|
react_1.default.createElement("div", { className: "ecpauth:space-y-2" },
|
|
@@ -49,8 +49,7 @@ function AuthProvider({ children, config }) {
|
|
|
49
49
|
const [user, setUser] = (0, react_1.useState)(null);
|
|
50
50
|
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
51
51
|
const [error, setError] = (0, react_1.useState)(null);
|
|
52
|
-
const [
|
|
53
|
-
const [transition, startTransition] = (0, react_1.useTransition)();
|
|
52
|
+
const [_, startTransition] = (0, react_1.useTransition)();
|
|
54
53
|
const withFullObject = (0, utils_1.shouldPassFullUserObject)();
|
|
55
54
|
const computedRouteContext = (0, utils_1.buildRouteContext)(config);
|
|
56
55
|
const { loginUrl, resetPasswordUrl, dashboardUrl, returnPathRaw, isExcluded, } = computedRouteContext;
|
|
@@ -69,14 +68,6 @@ function AuthProvider({ children, config }) {
|
|
|
69
68
|
if (!token)
|
|
70
69
|
return;
|
|
71
70
|
if (!navigator.onLine) {
|
|
72
|
-
try {
|
|
73
|
-
const payload = (0, utils_1.parseJwt)(token);
|
|
74
|
-
setUser(payload?.user);
|
|
75
|
-
setIsAuthenticated(true);
|
|
76
|
-
}
|
|
77
|
-
catch (e) {
|
|
78
|
-
console.warn("[ecp-auth] Invalid token format:", e);
|
|
79
|
-
}
|
|
80
71
|
console.warn("[ecp-auth] Offline — skipping fetchCurrentUser()");
|
|
81
72
|
return;
|
|
82
73
|
}
|
|
@@ -84,10 +75,8 @@ function AuthProvider({ children, config }) {
|
|
|
84
75
|
try {
|
|
85
76
|
const res = await (0, api_1.apiFactory)("/me", { method: "GET" });
|
|
86
77
|
setUser(res.user);
|
|
87
|
-
setIsAuthenticated(true);
|
|
88
78
|
}
|
|
89
79
|
catch (err) {
|
|
90
|
-
console.warn("[ecp-auth] Failed to fetch user:", err);
|
|
91
80
|
await logout("server_unavailable");
|
|
92
81
|
}
|
|
93
82
|
finally {
|
|
@@ -97,7 +86,7 @@ function AuthProvider({ children, config }) {
|
|
|
97
86
|
(0, react_1.useEffect)(() => {
|
|
98
87
|
fetchCurrentUser();
|
|
99
88
|
}, []);
|
|
100
|
-
|
|
89
|
+
const login = (0, react_1.useCallback)(async (credentials) => {
|
|
101
90
|
setError(null);
|
|
102
91
|
setLoading(true);
|
|
103
92
|
try {
|
|
@@ -109,7 +98,6 @@ function AuthProvider({ children, config }) {
|
|
|
109
98
|
});
|
|
110
99
|
const { authToken, user, with2fa } = res;
|
|
111
100
|
if (authToken && !with2fa) {
|
|
112
|
-
setIsAuthenticated(true);
|
|
113
101
|
await redirectAfterLogin(authToken, res.tempRefreshToken);
|
|
114
102
|
return null;
|
|
115
103
|
}
|
|
@@ -126,8 +114,8 @@ function AuthProvider({ children, config }) {
|
|
|
126
114
|
finally {
|
|
127
115
|
setLoading(false);
|
|
128
116
|
}
|
|
129
|
-
}
|
|
130
|
-
|
|
117
|
+
}, []);
|
|
118
|
+
const sendPasswordResetRequest = (0, react_1.useCallback)(async (email) => {
|
|
131
119
|
try {
|
|
132
120
|
const res = await (0, api_1.apiFactory)("/reset-password", {
|
|
133
121
|
body: { email, passwordResetLink: resetPasswordUrl },
|
|
@@ -140,8 +128,8 @@ function AuthProvider({ children, config }) {
|
|
|
140
128
|
}
|
|
141
129
|
return { message: err.message, status: "failure" };
|
|
142
130
|
}
|
|
143
|
-
}
|
|
144
|
-
|
|
131
|
+
}, []);
|
|
132
|
+
const logout = (0, react_1.useCallback)(async (reason = "", params) => {
|
|
145
133
|
let logoutSucceeded = false;
|
|
146
134
|
try {
|
|
147
135
|
await (0, api_1.apiFactory)("/logout");
|
|
@@ -151,7 +139,6 @@ function AuthProvider({ children, config }) {
|
|
|
151
139
|
if ([401, 403].includes(err.status)) {
|
|
152
140
|
logoutSucceeded = true;
|
|
153
141
|
}
|
|
154
|
-
console.error("Logout failed:", err);
|
|
155
142
|
}
|
|
156
143
|
const forceLogout = ["user_logout", "server_unavailable"].includes(reason);
|
|
157
144
|
if (logoutSucceeded || forceLogout) {
|
|
@@ -168,42 +155,56 @@ function AuthProvider({ children, config }) {
|
|
|
168
155
|
window.location.href = `${loginUrl}?${fullParams}`;
|
|
169
156
|
}
|
|
170
157
|
}
|
|
171
|
-
}
|
|
158
|
+
}, [loginUrl, returnPathRaw, config]);
|
|
172
159
|
(0, use_token_refresher_1.useTokenRefresher)({
|
|
173
160
|
config,
|
|
174
161
|
refreshTokenRequest: async () => {
|
|
175
|
-
|
|
162
|
+
return await (0, api_1.apiFactory)("/refresh", {
|
|
176
163
|
body: {
|
|
177
164
|
withFullObject,
|
|
178
165
|
},
|
|
179
166
|
});
|
|
180
|
-
return res;
|
|
181
167
|
},
|
|
182
168
|
onTokenRefreshed: (authToken, tempRefreshToken) => {
|
|
183
169
|
localStorage.setItem(constants_1.AUTH_TOKEN_KEY, authToken);
|
|
184
170
|
config?.cookieOverride?.(tempRefreshToken);
|
|
185
171
|
},
|
|
186
|
-
revalidateUserWhenOnline: fetchCurrentUser,
|
|
172
|
+
// revalidateUserWhenOnline: fetchCurrentUser,
|
|
187
173
|
onRefreshFailed: async () => await logout("session_expired"),
|
|
188
174
|
});
|
|
175
|
+
const userLogout = (0, react_1.useCallback)((params) => logout("user_logout", params), [logout]);
|
|
176
|
+
const revalidate = (0, react_1.useCallback)(() => startTransition(fetchCurrentUser), [fetchCurrentUser]);
|
|
177
|
+
const contextValue = (0, react_1.useMemo)(() => {
|
|
178
|
+
return {
|
|
179
|
+
user,
|
|
180
|
+
isLoading: loading,
|
|
181
|
+
isAuthenticated: !!user,
|
|
182
|
+
error,
|
|
183
|
+
computedRouteContext,
|
|
184
|
+
login,
|
|
185
|
+
sendPasswordResetRequest,
|
|
186
|
+
logout: userLogout,
|
|
187
|
+
hasPermission: (permission) => (0, utils_1.hasPermission)(user, permission),
|
|
188
|
+
revalidate,
|
|
189
|
+
getToken: () => (0, utils_1.getClientToken)(),
|
|
190
|
+
};
|
|
191
|
+
}, [
|
|
192
|
+
user,
|
|
193
|
+
loading,
|
|
194
|
+
error,
|
|
195
|
+
computedRouteContext,
|
|
196
|
+
login,
|
|
197
|
+
sendPasswordResetRequest,
|
|
198
|
+
fetchCurrentUser,
|
|
199
|
+
userLogout,
|
|
200
|
+
revalidate,
|
|
201
|
+
]);
|
|
189
202
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
190
203
|
react_1.default.createElement(optional_otp_wrapper_1.OptionalOTPWrapper, { user: twoFAData, onVerified: redirectAfterLogin, onCanceled: () => {
|
|
191
204
|
setTwoFAData(null);
|
|
192
205
|
} }),
|
|
193
206
|
!disableLoading && loading && react_1.default.createElement(loader_1.Loader, null),
|
|
194
|
-
react_1.default.createElement(AuthContext.Provider, { value:
|
|
195
|
-
user,
|
|
196
|
-
isLoading: loading,
|
|
197
|
-
isAuthenticated,
|
|
198
|
-
error,
|
|
199
|
-
computedRouteContext,
|
|
200
|
-
login,
|
|
201
|
-
sendPasswordResetRequest,
|
|
202
|
-
logout: (params) => logout("user_logout", params),
|
|
203
|
-
hasPermission: (permission) => (0, utils_1.hasPermission)(user, permission),
|
|
204
|
-
revalidate: () => startTransition(fetchCurrentUser),
|
|
205
|
-
getToken: () => (0, utils_1.getClientToken)(),
|
|
206
|
-
} }, children)));
|
|
207
|
+
react_1.default.createElement(AuthContext.Provider, { value: contextValue }, children)));
|
|
207
208
|
}
|
|
208
209
|
function useAuth() {
|
|
209
210
|
const ctx = (0, react_1.useContext)(AuthContext);
|
package/dist/lib/api-server.js
CHANGED
package/dist/lib/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AuthConfig, QueryOpts, User } from "../types";
|
|
1
|
+
import { AuthConfig, QueryOpts, TokenSession, User } from "../types";
|
|
2
2
|
export declare function cn(...classes: (string | false | null | undefined)[]): string;
|
|
3
3
|
export declare function unstuckPointerEvents(): void;
|
|
4
4
|
export declare function buildRouteContext(config?: AuthConfig, currentPath?: string): {
|
|
@@ -13,7 +13,7 @@ export declare function buildRouteContext(config?: AuthConfig, currentPath?: str
|
|
|
13
13
|
isExcluded: boolean;
|
|
14
14
|
};
|
|
15
15
|
export declare function getClientToken(): string;
|
|
16
|
-
export declare function hasPermission(
|
|
16
|
+
export declare function hasPermission(session: User | TokenSession | null, permission: string): boolean;
|
|
17
17
|
export declare function parseMessage(message: string): string;
|
|
18
18
|
export declare function parseGroupId(data?: QueryOpts["groupIds"]): string;
|
|
19
19
|
export declare function parseJwt(token: string): any;
|
package/dist/lib/utils.js
CHANGED
|
@@ -102,10 +102,10 @@ function getClientToken() {
|
|
|
102
102
|
? localStorage.getItem(constants_1.AUTH_TOKEN_KEY) || ""
|
|
103
103
|
: "";
|
|
104
104
|
}
|
|
105
|
-
function hasPermission(
|
|
106
|
-
if (!
|
|
105
|
+
function hasPermission(session, permission) {
|
|
106
|
+
if (!session)
|
|
107
107
|
return false;
|
|
108
|
-
return
|
|
108
|
+
return session.role.permissions?.includes(permission) || session.isSuperAdmin;
|
|
109
109
|
}
|
|
110
110
|
function parseMessage(message) {
|
|
111
111
|
return message == "fetch failed" || message == "Failed to fetch"
|
package/dist/server/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export * from "./reset-password";
|
|
|
3
3
|
export * from "./user";
|
|
4
4
|
export * from "./next-cookie-override";
|
|
5
5
|
export * from "./server-session";
|
|
6
|
+
export * from "./token-session";
|
|
6
7
|
export * from "./server-token";
|
|
7
8
|
export * from "./role";
|
|
8
9
|
export { hasPermission } from "../lib/utils";
|
package/dist/server/index.js
CHANGED
|
@@ -20,6 +20,7 @@ __exportStar(require("./reset-password"), exports);
|
|
|
20
20
|
__exportStar(require("./user"), exports);
|
|
21
21
|
__exportStar(require("./next-cookie-override"), exports);
|
|
22
22
|
__exportStar(require("./server-session"), exports);
|
|
23
|
+
__exportStar(require("./token-session"), exports);
|
|
23
24
|
__exportStar(require("./server-token"), exports);
|
|
24
25
|
__exportStar(require("./role"), exports);
|
|
25
26
|
var utils_1 = require("../lib/utils");
|
|
@@ -1,8 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare
|
|
3
|
-
meta: {
|
|
4
|
-
sessionId: string;
|
|
5
|
-
exp: number;
|
|
6
|
-
iat: number;
|
|
7
|
-
};
|
|
8
|
-
}) | null>;
|
|
1
|
+
import { ServerSession } from "../types";
|
|
2
|
+
export declare const getServerSession: () => Promise<ServerSession | null>;
|
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.getServerSession =
|
|
4
|
+
exports.getServerSession = void 0;
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const api_1 = require("../lib/api");
|
|
5
7
|
const utils_1 = require("../lib/utils");
|
|
6
8
|
const server_token_1 = require("./server-token");
|
|
7
|
-
async function
|
|
9
|
+
exports.getServerSession = (0, react_1.cache)(async function () {
|
|
8
10
|
try {
|
|
9
11
|
const token = await (0, server_token_1.getServerToken)();
|
|
10
12
|
if (!token)
|
|
11
13
|
return null;
|
|
12
14
|
const session = (0, utils_1.parseJwt)(token);
|
|
13
|
-
|
|
14
|
-
const now = Date.now();
|
|
15
|
-
if (now > expiresAt) {
|
|
15
|
+
if (!session)
|
|
16
16
|
return null;
|
|
17
|
-
|
|
17
|
+
const now = Date.now();
|
|
18
|
+
if (now > session.exp * 1000 - 1000)
|
|
19
|
+
return null; // 1s buffer
|
|
20
|
+
const res = await (0, api_1.apiFactory)("/me-server", {
|
|
21
|
+
method: "GET",
|
|
22
|
+
cache: "no-store",
|
|
23
|
+
});
|
|
18
24
|
return {
|
|
19
|
-
...
|
|
25
|
+
...res.user,
|
|
20
26
|
meta: {
|
|
21
27
|
sessionId: session.sessionId,
|
|
22
28
|
exp: session.exp,
|
|
23
29
|
iat: session.iat,
|
|
24
30
|
},
|
|
25
31
|
};
|
|
26
|
-
// const res = await apiFactory("/me-server", {
|
|
27
|
-
// method: "GET",
|
|
28
|
-
// cache: "no-store",
|
|
29
|
-
// });
|
|
30
|
-
// return res.user;
|
|
31
32
|
}
|
|
32
|
-
catch (
|
|
33
|
-
console.
|
|
33
|
+
catch (err) {
|
|
34
|
+
console.error("[getServerSession] Failed to fetch user:", err);
|
|
34
35
|
return null;
|
|
35
36
|
}
|
|
36
|
-
}
|
|
37
|
+
});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { TokenSession } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Reads session from JWT in cookies.
|
|
4
|
+
* No network call. No server validation.
|
|
5
|
+
* Intended for middleware / edge usage.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getTokenSession<T extends Record<string, any>>(): Promise<TokenSession<T> | null>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.getTokenSession = getTokenSession;
|
|
5
|
+
const utils_1 = require("../lib/utils");
|
|
6
|
+
const server_token_1 = require("./server-token");
|
|
7
|
+
/**
|
|
8
|
+
* Reads session from JWT in cookies.
|
|
9
|
+
* No network call. No server validation.
|
|
10
|
+
* Intended for middleware / edge usage.
|
|
11
|
+
*/
|
|
12
|
+
async function getTokenSession() {
|
|
13
|
+
try {
|
|
14
|
+
const token = await (0, server_token_1.getServerToken)();
|
|
15
|
+
if (!token)
|
|
16
|
+
return null;
|
|
17
|
+
const session = (0, utils_1.parseJwt)(token);
|
|
18
|
+
if (!session)
|
|
19
|
+
return null;
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
if (now > session.exp * 1000 - 5000)
|
|
22
|
+
return null; // 5s buffer
|
|
23
|
+
return {
|
|
24
|
+
...session.user,
|
|
25
|
+
meta: {
|
|
26
|
+
sessionId: session.sessionId,
|
|
27
|
+
exp: session.exp,
|
|
28
|
+
iat: session.iat,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
console.error("[getTokenSession] Failed:", err);
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|