@thetechfossil/auth2 1.2.19 → 1.2.21
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/README.md +1 -1
- package/dist/index.components.d.mts +1 -0
- package/dist/index.components.d.ts +1 -0
- package/dist/index.components.js +275 -11
- package/dist/index.components.js.map +1 -1
- package/dist/index.components.mjs +275 -11
- package/dist/index.components.mjs.map +1 -1
- package/dist/index.d.mts +111 -3
- package/dist/index.d.ts +111 -3
- package/dist/index.js +470 -30
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +471 -32
- package/dist/index.mjs.map +1 -1
- package/dist/index.next.d.mts +54 -1
- package/dist/index.next.d.ts +54 -1
- package/dist/index.next.js +332 -26
- package/dist/index.next.js.map +1 -1
- package/dist/index.next.mjs +332 -26
- package/dist/index.next.mjs.map +1 -1
- package/dist/index.next.server.d.mts +81 -2
- package/dist/index.next.server.d.ts +81 -2
- package/dist/index.next.server.js +406 -9
- package/dist/index.next.server.js.map +1 -1
- package/dist/index.next.server.mjs +403 -10
- package/dist/index.next.server.mjs.map +1 -1
- package/dist/index.node.d.mts +81 -2
- package/dist/index.node.d.ts +81 -2
- package/dist/index.node.js +406 -9
- package/dist/index.node.js.map +1 -1
- package/dist/index.node.mjs +403 -10
- package/dist/index.node.mjs.map +1 -1
- package/dist/index.react-native.d.mts +227 -0
- package/dist/index.react-native.d.ts +227 -0
- package/dist/index.react-native.js +1684 -0
- package/dist/index.react-native.js.map +1 -0
- package/dist/index.react-native.mjs +1648 -0
- package/dist/index.react-native.mjs.map +1 -0
- package/package.json +119 -102
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import axios from 'axios';
|
|
3
|
+
import { io } from 'socket.io-client';
|
|
3
4
|
import { UpfilesClient, ImageManager } from '@thetechfossil/upfiles';
|
|
4
5
|
export { ConnectProjectDialog, ImageManager, ProjectFilesWidget, UpfilesClient, Uploader } from '@thetechfossil/upfiles';
|
|
5
|
-
import React, { createContext, forwardRef, useContext, useState,
|
|
6
|
+
import React, { createContext, forwardRef, useContext, useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
|
6
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
8
|
|
|
8
9
|
var __defProp = Object.defineProperty;
|
|
@@ -16,6 +17,16 @@ var __export = (target, all) => {
|
|
|
16
17
|
for (var name in all)
|
|
17
18
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
18
19
|
};
|
|
20
|
+
var ERROR_MESSAGES = {
|
|
21
|
+
NETWORK_ERROR: "Unable to connect to the server. Please check your internet connection and try again.",
|
|
22
|
+
TIMEOUT: "The request took too long. Please try again.",
|
|
23
|
+
SERVER_ERROR: "Something went wrong on our end. Please try again later.",
|
|
24
|
+
UNAUTHORIZED: "Your session has expired. Please log in again.",
|
|
25
|
+
FORBIDDEN: "You do not have permission to perform this action.",
|
|
26
|
+
NOT_FOUND: "The requested resource was not found.",
|
|
27
|
+
RATE_LIMITED: "Too many requests. Please wait a moment and try again.",
|
|
28
|
+
UNKNOWN: "An unexpected error occurred. Please try again."
|
|
29
|
+
};
|
|
19
30
|
var HttpClient = class {
|
|
20
31
|
constructor(baseUrl, defaultHeaders = {}) {
|
|
21
32
|
this.csrfToken = null;
|
|
@@ -50,7 +61,7 @@ var HttpClient = class {
|
|
|
50
61
|
}
|
|
51
62
|
return config;
|
|
52
63
|
},
|
|
53
|
-
(error) => Promise.reject(error)
|
|
64
|
+
(error) => Promise.reject(this.createUserFriendlyError(error))
|
|
54
65
|
);
|
|
55
66
|
this.axiosInstance.interceptors.response.use(
|
|
56
67
|
(response) => response,
|
|
@@ -65,18 +76,71 @@ var HttpClient = class {
|
|
|
65
76
|
}
|
|
66
77
|
return this.axiosInstance(originalRequest);
|
|
67
78
|
} catch (refreshError) {
|
|
68
|
-
return Promise.reject(refreshError);
|
|
79
|
+
return Promise.reject(this.createUserFriendlyError(refreshError));
|
|
69
80
|
}
|
|
70
81
|
}
|
|
71
|
-
|
|
72
|
-
const customError = new Error(error.response.data.message);
|
|
73
|
-
customError.response = error.response;
|
|
74
|
-
return Promise.reject(customError);
|
|
75
|
-
}
|
|
76
|
-
return Promise.reject(error);
|
|
82
|
+
return Promise.reject(this.createUserFriendlyError(error));
|
|
77
83
|
}
|
|
78
84
|
);
|
|
79
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Creates a user-friendly error message from an Axios error
|
|
88
|
+
*/
|
|
89
|
+
createUserFriendlyError(error) {
|
|
90
|
+
if (error instanceof Error && !error.isAxiosError) {
|
|
91
|
+
return error;
|
|
92
|
+
}
|
|
93
|
+
let message;
|
|
94
|
+
let statusCode;
|
|
95
|
+
if (axios.isAxiosError(error)) {
|
|
96
|
+
statusCode = error.response?.status;
|
|
97
|
+
const responseData = error.response?.data;
|
|
98
|
+
if (responseData?.message) {
|
|
99
|
+
message = responseData.message;
|
|
100
|
+
} else if (!error.response) {
|
|
101
|
+
if (error.code === "ECONNABORTED" || error.message.includes("timeout")) {
|
|
102
|
+
message = ERROR_MESSAGES.TIMEOUT;
|
|
103
|
+
} else if (error.code === "ERR_NETWORK" || error.message === "Network Error") {
|
|
104
|
+
message = ERROR_MESSAGES.NETWORK_ERROR;
|
|
105
|
+
} else {
|
|
106
|
+
message = ERROR_MESSAGES.NETWORK_ERROR;
|
|
107
|
+
}
|
|
108
|
+
} else {
|
|
109
|
+
switch (statusCode) {
|
|
110
|
+
case 400:
|
|
111
|
+
message = responseData?.message || "Invalid request. Please check your input.";
|
|
112
|
+
break;
|
|
113
|
+
case 401:
|
|
114
|
+
message = responseData?.message || ERROR_MESSAGES.UNAUTHORIZED;
|
|
115
|
+
break;
|
|
116
|
+
case 403:
|
|
117
|
+
message = responseData?.message || ERROR_MESSAGES.FORBIDDEN;
|
|
118
|
+
break;
|
|
119
|
+
case 404:
|
|
120
|
+
message = responseData?.message || ERROR_MESSAGES.NOT_FOUND;
|
|
121
|
+
break;
|
|
122
|
+
case 429:
|
|
123
|
+
message = ERROR_MESSAGES.RATE_LIMITED;
|
|
124
|
+
break;
|
|
125
|
+
case 500:
|
|
126
|
+
case 502:
|
|
127
|
+
case 503:
|
|
128
|
+
case 504:
|
|
129
|
+
message = ERROR_MESSAGES.SERVER_ERROR;
|
|
130
|
+
break;
|
|
131
|
+
default:
|
|
132
|
+
message = responseData?.message || ERROR_MESSAGES.UNKNOWN;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
message = error?.message || ERROR_MESSAGES.UNKNOWN;
|
|
137
|
+
}
|
|
138
|
+
const customError = new Error(message);
|
|
139
|
+
customError.response = error?.response;
|
|
140
|
+
customError.statusCode = statusCode;
|
|
141
|
+
customError.originalError = error;
|
|
142
|
+
return customError;
|
|
143
|
+
}
|
|
80
144
|
async get(endpoint, headers) {
|
|
81
145
|
const response = await this.axiosInstance.get(endpoint, { headers });
|
|
82
146
|
return response.data;
|
|
@@ -127,16 +191,134 @@ var HttpClient = class {
|
|
|
127
191
|
}
|
|
128
192
|
}
|
|
129
193
|
};
|
|
194
|
+
var SocketService = class {
|
|
195
|
+
constructor(config) {
|
|
196
|
+
this.socket = null;
|
|
197
|
+
this.token = null;
|
|
198
|
+
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
199
|
+
this.isConnecting = false;
|
|
200
|
+
this.config = {
|
|
201
|
+
autoConnect: false,
|
|
202
|
+
reconnection: true,
|
|
203
|
+
reconnectionAttempts: 5,
|
|
204
|
+
reconnectionDelay: 1e3,
|
|
205
|
+
...config
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
connect(token) {
|
|
209
|
+
if (this.socket?.connected || this.isConnecting) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
this.token = token;
|
|
213
|
+
this.isConnecting = true;
|
|
214
|
+
this.socket = io(this.config.baseUrl, {
|
|
215
|
+
auth: { token },
|
|
216
|
+
autoConnect: true,
|
|
217
|
+
reconnection: this.config.reconnection,
|
|
218
|
+
reconnectionAttempts: this.config.reconnectionAttempts,
|
|
219
|
+
reconnectionDelay: this.config.reconnectionDelay,
|
|
220
|
+
transports: ["websocket", "polling"]
|
|
221
|
+
});
|
|
222
|
+
this.setupEventListeners();
|
|
223
|
+
}
|
|
224
|
+
setupEventListeners() {
|
|
225
|
+
if (!this.socket) return;
|
|
226
|
+
this.socket.on("connect", () => {
|
|
227
|
+
this.isConnecting = false;
|
|
228
|
+
console.log("[Auth SDK] Socket connected");
|
|
229
|
+
this.emit("connected", {});
|
|
230
|
+
});
|
|
231
|
+
this.socket.on("disconnect", (reason) => {
|
|
232
|
+
console.log("[Auth SDK] Socket disconnected:", reason);
|
|
233
|
+
this.emit("disconnected", { reason });
|
|
234
|
+
});
|
|
235
|
+
this.socket.on("connect_error", (error) => {
|
|
236
|
+
this.isConnecting = false;
|
|
237
|
+
console.error("[Auth SDK] Socket connection error:", error.message);
|
|
238
|
+
this.emit("error", { error: error.message });
|
|
239
|
+
});
|
|
240
|
+
this.socket.on("user:updated", (data) => {
|
|
241
|
+
this.emit("user:updated", data);
|
|
242
|
+
});
|
|
243
|
+
this.socket.on("session:revoked", (data) => {
|
|
244
|
+
this.emit("session:revoked", data);
|
|
245
|
+
});
|
|
246
|
+
this.socket.on("session:all-revoked", () => {
|
|
247
|
+
this.emit("session:all-revoked", {});
|
|
248
|
+
});
|
|
249
|
+
this.socket.on("auth:password-changed", () => {
|
|
250
|
+
this.emit("auth:password-changed", {});
|
|
251
|
+
});
|
|
252
|
+
this.socket.on("auth:2fa-changed", (data) => {
|
|
253
|
+
this.emit("auth:2fa-changed", data);
|
|
254
|
+
});
|
|
255
|
+
this.socket.on("user:refresh", () => {
|
|
256
|
+
this.emit("user:refresh", {});
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
disconnect() {
|
|
260
|
+
if (this.socket) {
|
|
261
|
+
this.socket.disconnect();
|
|
262
|
+
this.socket = null;
|
|
263
|
+
this.token = null;
|
|
264
|
+
this.isConnecting = false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
isConnected() {
|
|
268
|
+
return this.socket?.connected ?? false;
|
|
269
|
+
}
|
|
270
|
+
// Event subscription
|
|
271
|
+
on(event, handler) {
|
|
272
|
+
if (!this.eventHandlers.has(event)) {
|
|
273
|
+
this.eventHandlers.set(event, /* @__PURE__ */ new Set());
|
|
274
|
+
}
|
|
275
|
+
this.eventHandlers.get(event).add(handler);
|
|
276
|
+
return () => {
|
|
277
|
+
this.eventHandlers.get(event)?.delete(handler);
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
off(event, handler) {
|
|
281
|
+
if (handler) {
|
|
282
|
+
this.eventHandlers.get(event)?.delete(handler);
|
|
283
|
+
} else {
|
|
284
|
+
this.eventHandlers.delete(event);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
emit(event, data) {
|
|
288
|
+
const handlers = this.eventHandlers.get(event);
|
|
289
|
+
if (handlers) {
|
|
290
|
+
handlers.forEach((handler) => {
|
|
291
|
+
try {
|
|
292
|
+
handler(data);
|
|
293
|
+
} catch (error) {
|
|
294
|
+
console.error(`[Auth SDK] Error in event handler for ${event}:`, error);
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
// Request fresh user data from server
|
|
300
|
+
requestUserRefresh() {
|
|
301
|
+
if (this.socket?.connected) {
|
|
302
|
+
this.socket.emit("request:user");
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
};
|
|
130
306
|
var AuthService = class {
|
|
307
|
+
// 5 minutes cache
|
|
131
308
|
constructor(config) {
|
|
132
309
|
this.token = null;
|
|
133
310
|
this.upfilesClient = null;
|
|
311
|
+
this.cachedUser = null;
|
|
312
|
+
this.userCacheTimestamp = 0;
|
|
313
|
+
this.USER_CACHE_TTL = 5 * 60 * 1e3;
|
|
134
314
|
this.config = {
|
|
135
315
|
localStorageKey: "auth_token",
|
|
136
316
|
csrfEnabled: true,
|
|
317
|
+
enableSocket: true,
|
|
137
318
|
...config
|
|
138
319
|
};
|
|
139
320
|
this.httpClient = new HttpClient(this.config.baseUrl);
|
|
321
|
+
this.socketService = new SocketService({ baseUrl: this.config.baseUrl });
|
|
140
322
|
this.loadTokenFromStorage();
|
|
141
323
|
if (this.config.upfilesConfig) {
|
|
142
324
|
this.upfilesClient = new UpfilesClient({
|
|
@@ -153,6 +335,9 @@ var AuthService = class {
|
|
|
153
335
|
this.httpClient.setFrontendBaseUrl(frontendBaseUrl);
|
|
154
336
|
}
|
|
155
337
|
}
|
|
338
|
+
if (this.token && this.config.enableSocket !== false) {
|
|
339
|
+
this.connectSocket();
|
|
340
|
+
}
|
|
156
341
|
}
|
|
157
342
|
loadTokenFromStorage() {
|
|
158
343
|
if (typeof window !== "undefined" && this.config.localStorageKey) {
|
|
@@ -185,6 +370,57 @@ var AuthService = class {
|
|
|
185
370
|
}
|
|
186
371
|
}
|
|
187
372
|
}
|
|
373
|
+
// Socket connection management
|
|
374
|
+
connectSocket() {
|
|
375
|
+
if (this.token && this.config.enableSocket !== false && typeof window !== "undefined") {
|
|
376
|
+
this.socketService.connect(this.token);
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
disconnectSocket() {
|
|
380
|
+
this.socketService.disconnect();
|
|
381
|
+
}
|
|
382
|
+
// Socket event subscription
|
|
383
|
+
onUserUpdated(handler) {
|
|
384
|
+
return this.socketService.on("user:updated", (data) => {
|
|
385
|
+
if (data.user) {
|
|
386
|
+
this.cachedUser = data.user;
|
|
387
|
+
this.userCacheTimestamp = Date.now();
|
|
388
|
+
}
|
|
389
|
+
handler(data);
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
onSessionRevoked(handler) {
|
|
393
|
+
return this.socketService.on("session:revoked", handler);
|
|
394
|
+
}
|
|
395
|
+
onAllSessionsRevoked(handler) {
|
|
396
|
+
return this.socketService.on("session:all-revoked", handler);
|
|
397
|
+
}
|
|
398
|
+
onPasswordChanged(handler) {
|
|
399
|
+
return this.socketService.on("auth:password-changed", handler);
|
|
400
|
+
}
|
|
401
|
+
on2FAChanged(handler) {
|
|
402
|
+
return this.socketService.on("auth:2fa-changed", handler);
|
|
403
|
+
}
|
|
404
|
+
onSocketConnected(handler) {
|
|
405
|
+
return this.socketService.on("connected", handler);
|
|
406
|
+
}
|
|
407
|
+
onSocketDisconnected(handler) {
|
|
408
|
+
return this.socketService.on("disconnected", handler);
|
|
409
|
+
}
|
|
410
|
+
onSocketError(handler) {
|
|
411
|
+
return this.socketService.on("error", handler);
|
|
412
|
+
}
|
|
413
|
+
isSocketConnected() {
|
|
414
|
+
return this.socketService.isConnected();
|
|
415
|
+
}
|
|
416
|
+
// Cache management
|
|
417
|
+
clearUserCache() {
|
|
418
|
+
this.cachedUser = null;
|
|
419
|
+
this.userCacheTimestamp = 0;
|
|
420
|
+
}
|
|
421
|
+
isCacheValid() {
|
|
422
|
+
return this.cachedUser !== null && Date.now() - this.userCacheTimestamp < this.USER_CACHE_TTL;
|
|
423
|
+
}
|
|
188
424
|
isAuthenticated() {
|
|
189
425
|
return !!this.token;
|
|
190
426
|
}
|
|
@@ -250,6 +486,11 @@ var AuthService = class {
|
|
|
250
486
|
this.token = response.token;
|
|
251
487
|
this.httpClient.setAuthToken(response.token);
|
|
252
488
|
this.saveTokenToStorage(response.token);
|
|
489
|
+
if (response.user) {
|
|
490
|
+
this.cachedUser = response.user;
|
|
491
|
+
this.userCacheTimestamp = Date.now();
|
|
492
|
+
}
|
|
493
|
+
this.connectSocket();
|
|
253
494
|
return response;
|
|
254
495
|
}
|
|
255
496
|
if (response.success && (response.message === "OTP sent to your email." || response.message === "OTP sent to your phone number.")) {
|
|
@@ -259,6 +500,11 @@ var AuthService = class {
|
|
|
259
500
|
this.token = response.token;
|
|
260
501
|
this.httpClient.setAuthToken(response.token);
|
|
261
502
|
this.saveTokenToStorage(response.token);
|
|
503
|
+
if (response.user) {
|
|
504
|
+
this.cachedUser = response.user;
|
|
505
|
+
this.userCacheTimestamp = Date.now();
|
|
506
|
+
}
|
|
507
|
+
this.connectSocket();
|
|
262
508
|
return response;
|
|
263
509
|
}
|
|
264
510
|
throw new Error(response.message || "Login failed");
|
|
@@ -302,21 +548,29 @@ var AuthService = class {
|
|
|
302
548
|
}
|
|
303
549
|
}
|
|
304
550
|
async logout() {
|
|
551
|
+
this.disconnectSocket();
|
|
305
552
|
try {
|
|
306
553
|
await this.httpClient.post("/api/v1/auth/logout", {});
|
|
307
554
|
} catch (error) {
|
|
308
555
|
console.warn("Failed to call logout endpoint:", error);
|
|
309
556
|
}
|
|
310
557
|
this.token = null;
|
|
558
|
+
this.cachedUser = null;
|
|
559
|
+
this.userCacheTimestamp = 0;
|
|
311
560
|
this.httpClient.removeAuthToken();
|
|
312
561
|
this.httpClient.removeCsrfToken();
|
|
313
562
|
this.removeTokenFromStorage();
|
|
314
563
|
}
|
|
315
|
-
async getProfile() {
|
|
564
|
+
async getProfile(forceRefresh = false) {
|
|
316
565
|
if (!this.token) {
|
|
317
566
|
throw new Error("Not authenticated");
|
|
318
567
|
}
|
|
568
|
+
if (!forceRefresh && this.isCacheValid() && this.cachedUser) {
|
|
569
|
+
return this.cachedUser;
|
|
570
|
+
}
|
|
319
571
|
const response = await this.httpClient.get("/api/v1/user/me");
|
|
572
|
+
this.cachedUser = response.user;
|
|
573
|
+
this.userCacheTimestamp = Date.now();
|
|
320
574
|
return response.user;
|
|
321
575
|
}
|
|
322
576
|
async updateProfile(data) {
|
|
@@ -480,6 +734,16 @@ var AuthService = class {
|
|
|
480
734
|
);
|
|
481
735
|
return response;
|
|
482
736
|
}
|
|
737
|
+
async adminCreateUser(data) {
|
|
738
|
+
if (!this.token) {
|
|
739
|
+
throw new Error("Not authenticated");
|
|
740
|
+
}
|
|
741
|
+
const response = await this.httpClient.post(
|
|
742
|
+
"/api/v1/admin/create-user",
|
|
743
|
+
data
|
|
744
|
+
);
|
|
745
|
+
return response;
|
|
746
|
+
}
|
|
483
747
|
async adminVerifyUser(userId) {
|
|
484
748
|
if (!this.token) {
|
|
485
749
|
throw new Error("Not authenticated");
|
|
@@ -572,21 +836,49 @@ var AuthProvider = ({ children, config }) => {
|
|
|
572
836
|
const [user, setUser] = useState(null);
|
|
573
837
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
574
838
|
const [loading, setLoading] = useState(false);
|
|
575
|
-
const
|
|
839
|
+
const [isSocketConnected, setIsSocketConnected] = useState(false);
|
|
840
|
+
useEffect(() => {
|
|
841
|
+
const unsubUserUpdated = authService.onUserUpdated(({ user: updatedUser }) => {
|
|
842
|
+
if (updatedUser) {
|
|
843
|
+
setUser(updatedUser);
|
|
844
|
+
}
|
|
845
|
+
});
|
|
846
|
+
const unsubSessionRevoked = authService.onSessionRevoked(() => {
|
|
847
|
+
authService.logout().then(() => {
|
|
848
|
+
setUser(null);
|
|
849
|
+
});
|
|
850
|
+
});
|
|
851
|
+
const unsubAllSessionsRevoked = authService.onAllSessionsRevoked(() => {
|
|
852
|
+
authService.logout().then(() => {
|
|
853
|
+
setUser(null);
|
|
854
|
+
});
|
|
855
|
+
});
|
|
856
|
+
const unsubPasswordChanged = authService.onPasswordChanged(() => {
|
|
857
|
+
authService.logout().then(() => {
|
|
858
|
+
setUser(null);
|
|
859
|
+
});
|
|
860
|
+
});
|
|
861
|
+
const unsubConnected = authService.onSocketConnected(() => {
|
|
862
|
+
setIsSocketConnected(true);
|
|
863
|
+
});
|
|
864
|
+
const unsubDisconnected = authService.onSocketDisconnected(() => {
|
|
865
|
+
setIsSocketConnected(false);
|
|
866
|
+
});
|
|
867
|
+
return () => {
|
|
868
|
+
unsubUserUpdated();
|
|
869
|
+
unsubSessionRevoked();
|
|
870
|
+
unsubAllSessionsRevoked();
|
|
871
|
+
unsubPasswordChanged();
|
|
872
|
+
unsubConnected();
|
|
873
|
+
unsubDisconnected();
|
|
874
|
+
};
|
|
875
|
+
}, [authService]);
|
|
876
|
+
useEffect(() => {
|
|
576
877
|
const authenticated = authService.isAuthenticated();
|
|
577
878
|
if (authenticated) {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
setUser(
|
|
581
|
-
} catch (error) {
|
|
582
|
-
console.error("Failed to fetch fresh user profile, falling back to token:", error);
|
|
583
|
-
try {
|
|
584
|
-
const currentUser = authService.getCurrentUser();
|
|
585
|
-
setUser(currentUser);
|
|
586
|
-
} catch (fallbackError) {
|
|
587
|
-
console.error("Failed to get current user from token:", fallbackError);
|
|
588
|
-
setUser(null);
|
|
589
|
-
}
|
|
879
|
+
const currentUser = authService.getCurrentUser();
|
|
880
|
+
if (currentUser) {
|
|
881
|
+
setUser(currentUser);
|
|
590
882
|
}
|
|
591
883
|
} else {
|
|
592
884
|
setUser(null);
|
|
@@ -594,8 +886,21 @@ var AuthProvider = ({ children, config }) => {
|
|
|
594
886
|
setIsLoaded(true);
|
|
595
887
|
}, [authService]);
|
|
596
888
|
useEffect(() => {
|
|
597
|
-
|
|
598
|
-
|
|
889
|
+
if (!isLoaded) return;
|
|
890
|
+
const authenticated = authService.isAuthenticated();
|
|
891
|
+
if (!authenticated) return;
|
|
892
|
+
const fetchFreshUser = async () => {
|
|
893
|
+
try {
|
|
894
|
+
const freshUser = await authService.getProfile();
|
|
895
|
+
setUser(freshUser);
|
|
896
|
+
} catch (error) {
|
|
897
|
+
console.warn("[Auth SDK] Failed to fetch fresh user profile:", error);
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
if (isSocketConnected) {
|
|
901
|
+
fetchFreshUser();
|
|
902
|
+
}
|
|
903
|
+
}, [authService, isLoaded, isSocketConnected]);
|
|
599
904
|
const signIn = useCallback(async (data) => {
|
|
600
905
|
setLoading(true);
|
|
601
906
|
try {
|
|
@@ -817,6 +1122,7 @@ var AuthProvider = ({ children, config }) => {
|
|
|
817
1122
|
isLoaded,
|
|
818
1123
|
isSignedIn: !!user,
|
|
819
1124
|
loading,
|
|
1125
|
+
isSocketConnected,
|
|
820
1126
|
signIn,
|
|
821
1127
|
signUp,
|
|
822
1128
|
signOut,
|
|
@@ -3701,15 +4007,15 @@ var VerifyEmail = ({ token, onSuccess, onError }) => {
|
|
|
3701
4007
|
const [message, setMessage] = useState("");
|
|
3702
4008
|
useEffect(() => {
|
|
3703
4009
|
const verify = async () => {
|
|
3704
|
-
const
|
|
3705
|
-
if (!
|
|
4010
|
+
const verifyToken2 = token || (typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null);
|
|
4011
|
+
if (!verifyToken2) {
|
|
3706
4012
|
setStatus("error");
|
|
3707
4013
|
setMessage("No verification token provided");
|
|
3708
4014
|
onError?.("No verification token provided");
|
|
3709
4015
|
return;
|
|
3710
4016
|
}
|
|
3711
4017
|
try {
|
|
3712
|
-
const response = await verifyEmailToken(
|
|
4018
|
+
const response = await verifyEmailToken(verifyToken2);
|
|
3713
4019
|
if (response.success) {
|
|
3714
4020
|
setStatus("success");
|
|
3715
4021
|
setMessage("Email verified successfully! Redirecting...");
|
|
@@ -4468,11 +4774,11 @@ var ChangePassword = ({ onSuccess, appearance }) => {
|
|
|
4468
4774
|
|
|
4469
4775
|
// src/react/components/utils/injectModalStyles.ts
|
|
4470
4776
|
var injectModalStyles = () => {
|
|
4471
|
-
if (document.getElementById("
|
|
4777
|
+
if (document.getElementById("ktw-auth-modal-styles")) {
|
|
4472
4778
|
return;
|
|
4473
4779
|
}
|
|
4474
4780
|
const styleElement = document.createElement("style");
|
|
4475
|
-
styleElement.id = "
|
|
4781
|
+
styleElement.id = "ktw-auth-modal-styles";
|
|
4476
4782
|
styleElement.textContent = `
|
|
4477
4783
|
/* ImageManager Modal Styles - Critical for proper modal display */
|
|
4478
4784
|
/* Radix UI Dialog styles - Force visibility */
|
|
@@ -5010,7 +5316,11 @@ __export(react_exports, {
|
|
|
5010
5316
|
// src/node/index.ts
|
|
5011
5317
|
var node_exports = {};
|
|
5012
5318
|
__export(node_exports, {
|
|
5013
|
-
AuthClient: () => AuthClient
|
|
5319
|
+
AuthClient: () => AuthClient,
|
|
5320
|
+
TokenVerifier: () => TokenVerifier,
|
|
5321
|
+
createTokenVerifier: () => createTokenVerifier,
|
|
5322
|
+
getTokenVerifier: () => getTokenVerifier,
|
|
5323
|
+
verifyToken: () => verifyToken
|
|
5014
5324
|
});
|
|
5015
5325
|
|
|
5016
5326
|
// src/node/auth-client.ts
|
|
@@ -5091,6 +5401,135 @@ var AuthClient = class extends AuthService {
|
|
|
5091
5401
|
}
|
|
5092
5402
|
};
|
|
5093
5403
|
|
|
5094
|
-
|
|
5404
|
+
// src/node/token-verifier.ts
|
|
5405
|
+
var TokenVerifier = class {
|
|
5406
|
+
constructor(config) {
|
|
5407
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
5408
|
+
this.cleanupInterval = null;
|
|
5409
|
+
this.config = {
|
|
5410
|
+
cacheTTL: 6e4,
|
|
5411
|
+
// 1 minute default
|
|
5412
|
+
cacheEnabled: true,
|
|
5413
|
+
...config
|
|
5414
|
+
};
|
|
5415
|
+
if (this.config.cacheEnabled) {
|
|
5416
|
+
this.startCleanup();
|
|
5417
|
+
}
|
|
5418
|
+
}
|
|
5419
|
+
/**
|
|
5420
|
+
* Verify a JWT token and get user data
|
|
5421
|
+
* Returns cached user if available and valid
|
|
5422
|
+
*/
|
|
5423
|
+
async verifyToken(token) {
|
|
5424
|
+
if (!token) {
|
|
5425
|
+
return null;
|
|
5426
|
+
}
|
|
5427
|
+
if (this.config.cacheEnabled) {
|
|
5428
|
+
const cached = this.getFromCache(token);
|
|
5429
|
+
if (cached) {
|
|
5430
|
+
return cached;
|
|
5431
|
+
}
|
|
5432
|
+
}
|
|
5433
|
+
try {
|
|
5434
|
+
const response = await fetch(`${this.config.authServiceUrl}/api/v1/user/me`, {
|
|
5435
|
+
headers: {
|
|
5436
|
+
"Authorization": `Bearer ${token}`,
|
|
5437
|
+
"Content-Type": "application/json"
|
|
5438
|
+
}
|
|
5439
|
+
});
|
|
5440
|
+
if (!response.ok) {
|
|
5441
|
+
this.cache.delete(token);
|
|
5442
|
+
return null;
|
|
5443
|
+
}
|
|
5444
|
+
const data = await response.json();
|
|
5445
|
+
const user = data.user || null;
|
|
5446
|
+
if (user && this.config.cacheEnabled) {
|
|
5447
|
+
this.setCache(token, user);
|
|
5448
|
+
}
|
|
5449
|
+
return user;
|
|
5450
|
+
} catch (error) {
|
|
5451
|
+
console.error("[TokenVerifier] Auth service verification failed:", error);
|
|
5452
|
+
return null;
|
|
5453
|
+
}
|
|
5454
|
+
}
|
|
5455
|
+
/**
|
|
5456
|
+
* Invalidate cache for a specific token
|
|
5457
|
+
*/
|
|
5458
|
+
invalidateToken(token) {
|
|
5459
|
+
this.cache.delete(token);
|
|
5460
|
+
}
|
|
5461
|
+
/**
|
|
5462
|
+
* Clear all cached tokens
|
|
5463
|
+
*/
|
|
5464
|
+
clearCache() {
|
|
5465
|
+
this.cache.clear();
|
|
5466
|
+
}
|
|
5467
|
+
/**
|
|
5468
|
+
* Get cache statistics
|
|
5469
|
+
*/
|
|
5470
|
+
getCacheStats() {
|
|
5471
|
+
return {
|
|
5472
|
+
size: this.cache.size,
|
|
5473
|
+
enabled: this.config.cacheEnabled,
|
|
5474
|
+
ttl: this.config.cacheTTL
|
|
5475
|
+
};
|
|
5476
|
+
}
|
|
5477
|
+
/**
|
|
5478
|
+
* Stop the cleanup interval (call when shutting down)
|
|
5479
|
+
*/
|
|
5480
|
+
destroy() {
|
|
5481
|
+
if (this.cleanupInterval) {
|
|
5482
|
+
clearInterval(this.cleanupInterval);
|
|
5483
|
+
this.cleanupInterval = null;
|
|
5484
|
+
}
|
|
5485
|
+
this.cache.clear();
|
|
5486
|
+
}
|
|
5487
|
+
getFromCache(token) {
|
|
5488
|
+
const entry = this.cache.get(token);
|
|
5489
|
+
if (!entry) {
|
|
5490
|
+
return null;
|
|
5491
|
+
}
|
|
5492
|
+
if (Date.now() > entry.expiresAt) {
|
|
5493
|
+
this.cache.delete(token);
|
|
5494
|
+
return null;
|
|
5495
|
+
}
|
|
5496
|
+
return entry.user;
|
|
5497
|
+
}
|
|
5498
|
+
setCache(token, user) {
|
|
5499
|
+
this.cache.set(token, {
|
|
5500
|
+
user,
|
|
5501
|
+
expiresAt: Date.now() + this.config.cacheTTL
|
|
5502
|
+
});
|
|
5503
|
+
}
|
|
5504
|
+
startCleanup() {
|
|
5505
|
+
this.cleanupInterval = setInterval(() => {
|
|
5506
|
+
const now = Date.now();
|
|
5507
|
+
for (const [token, entry] of this.cache.entries()) {
|
|
5508
|
+
if (now > entry.expiresAt) {
|
|
5509
|
+
this.cache.delete(token);
|
|
5510
|
+
}
|
|
5511
|
+
}
|
|
5512
|
+
}, 6e4);
|
|
5513
|
+
if (this.cleanupInterval && this.cleanupInterval.unref) {
|
|
5514
|
+
this.cleanupInterval.unref();
|
|
5515
|
+
}
|
|
5516
|
+
}
|
|
5517
|
+
};
|
|
5518
|
+
var defaultVerifier = null;
|
|
5519
|
+
function createTokenVerifier(config) {
|
|
5520
|
+
defaultVerifier = new TokenVerifier(config);
|
|
5521
|
+
return defaultVerifier;
|
|
5522
|
+
}
|
|
5523
|
+
function getTokenVerifier() {
|
|
5524
|
+
if (!defaultVerifier) {
|
|
5525
|
+
throw new Error("TokenVerifier not initialized. Call createTokenVerifier() first.");
|
|
5526
|
+
}
|
|
5527
|
+
return defaultVerifier;
|
|
5528
|
+
}
|
|
5529
|
+
async function verifyToken(token) {
|
|
5530
|
+
return getTokenVerifier().verifyToken(token);
|
|
5531
|
+
}
|
|
5532
|
+
|
|
5533
|
+
export { AuthFlow, AuthProvider, AuthService, AvatarManager, AvatarUploader, ChangePassword, EmailVerificationPage, ForgotPassword, HttpClient, LoginForm, OtpForm, ProtectedRoute, PublicRoute, RegisterForm, ResetPassword, SignIn, SignOut, SignUp, SocketService, UserButton, UserProfile, VerifyEmail, node_exports as node, react_exports as react, useAuth };
|
|
5095
5534
|
//# sourceMappingURL=index.mjs.map
|
|
5096
5535
|
//# sourceMappingURL=index.mjs.map
|