@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.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var axios = require('axios');
|
|
5
|
+
var socket_ioClient = require('socket.io-client');
|
|
5
6
|
var upfiles = require('@thetechfossil/upfiles');
|
|
6
7
|
var React = require('react');
|
|
7
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -22,6 +23,16 @@ var __export = (target, all) => {
|
|
|
22
23
|
for (var name in all)
|
|
23
24
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
24
25
|
};
|
|
26
|
+
var ERROR_MESSAGES = {
|
|
27
|
+
NETWORK_ERROR: "Unable to connect to the server. Please check your internet connection and try again.",
|
|
28
|
+
TIMEOUT: "The request took too long. Please try again.",
|
|
29
|
+
SERVER_ERROR: "Something went wrong on our end. Please try again later.",
|
|
30
|
+
UNAUTHORIZED: "Your session has expired. Please log in again.",
|
|
31
|
+
FORBIDDEN: "You do not have permission to perform this action.",
|
|
32
|
+
NOT_FOUND: "The requested resource was not found.",
|
|
33
|
+
RATE_LIMITED: "Too many requests. Please wait a moment and try again.",
|
|
34
|
+
UNKNOWN: "An unexpected error occurred. Please try again."
|
|
35
|
+
};
|
|
25
36
|
var HttpClient = class {
|
|
26
37
|
constructor(baseUrl, defaultHeaders = {}) {
|
|
27
38
|
this.csrfToken = null;
|
|
@@ -56,7 +67,7 @@ var HttpClient = class {
|
|
|
56
67
|
}
|
|
57
68
|
return config;
|
|
58
69
|
},
|
|
59
|
-
(error) => Promise.reject(error)
|
|
70
|
+
(error) => Promise.reject(this.createUserFriendlyError(error))
|
|
60
71
|
);
|
|
61
72
|
this.axiosInstance.interceptors.response.use(
|
|
62
73
|
(response) => response,
|
|
@@ -71,18 +82,71 @@ var HttpClient = class {
|
|
|
71
82
|
}
|
|
72
83
|
return this.axiosInstance(originalRequest);
|
|
73
84
|
} catch (refreshError) {
|
|
74
|
-
return Promise.reject(refreshError);
|
|
85
|
+
return Promise.reject(this.createUserFriendlyError(refreshError));
|
|
75
86
|
}
|
|
76
87
|
}
|
|
77
|
-
|
|
78
|
-
const customError = new Error(error.response.data.message);
|
|
79
|
-
customError.response = error.response;
|
|
80
|
-
return Promise.reject(customError);
|
|
81
|
-
}
|
|
82
|
-
return Promise.reject(error);
|
|
88
|
+
return Promise.reject(this.createUserFriendlyError(error));
|
|
83
89
|
}
|
|
84
90
|
);
|
|
85
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Creates a user-friendly error message from an Axios error
|
|
94
|
+
*/
|
|
95
|
+
createUserFriendlyError(error) {
|
|
96
|
+
if (error instanceof Error && !error.isAxiosError) {
|
|
97
|
+
return error;
|
|
98
|
+
}
|
|
99
|
+
let message;
|
|
100
|
+
let statusCode;
|
|
101
|
+
if (axios__default.default.isAxiosError(error)) {
|
|
102
|
+
statusCode = error.response?.status;
|
|
103
|
+
const responseData = error.response?.data;
|
|
104
|
+
if (responseData?.message) {
|
|
105
|
+
message = responseData.message;
|
|
106
|
+
} else if (!error.response) {
|
|
107
|
+
if (error.code === "ECONNABORTED" || error.message.includes("timeout")) {
|
|
108
|
+
message = ERROR_MESSAGES.TIMEOUT;
|
|
109
|
+
} else if (error.code === "ERR_NETWORK" || error.message === "Network Error") {
|
|
110
|
+
message = ERROR_MESSAGES.NETWORK_ERROR;
|
|
111
|
+
} else {
|
|
112
|
+
message = ERROR_MESSAGES.NETWORK_ERROR;
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
switch (statusCode) {
|
|
116
|
+
case 400:
|
|
117
|
+
message = responseData?.message || "Invalid request. Please check your input.";
|
|
118
|
+
break;
|
|
119
|
+
case 401:
|
|
120
|
+
message = responseData?.message || ERROR_MESSAGES.UNAUTHORIZED;
|
|
121
|
+
break;
|
|
122
|
+
case 403:
|
|
123
|
+
message = responseData?.message || ERROR_MESSAGES.FORBIDDEN;
|
|
124
|
+
break;
|
|
125
|
+
case 404:
|
|
126
|
+
message = responseData?.message || ERROR_MESSAGES.NOT_FOUND;
|
|
127
|
+
break;
|
|
128
|
+
case 429:
|
|
129
|
+
message = ERROR_MESSAGES.RATE_LIMITED;
|
|
130
|
+
break;
|
|
131
|
+
case 500:
|
|
132
|
+
case 502:
|
|
133
|
+
case 503:
|
|
134
|
+
case 504:
|
|
135
|
+
message = ERROR_MESSAGES.SERVER_ERROR;
|
|
136
|
+
break;
|
|
137
|
+
default:
|
|
138
|
+
message = responseData?.message || ERROR_MESSAGES.UNKNOWN;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
} else {
|
|
142
|
+
message = error?.message || ERROR_MESSAGES.UNKNOWN;
|
|
143
|
+
}
|
|
144
|
+
const customError = new Error(message);
|
|
145
|
+
customError.response = error?.response;
|
|
146
|
+
customError.statusCode = statusCode;
|
|
147
|
+
customError.originalError = error;
|
|
148
|
+
return customError;
|
|
149
|
+
}
|
|
86
150
|
async get(endpoint, headers) {
|
|
87
151
|
const response = await this.axiosInstance.get(endpoint, { headers });
|
|
88
152
|
return response.data;
|
|
@@ -133,16 +197,134 @@ var HttpClient = class {
|
|
|
133
197
|
}
|
|
134
198
|
}
|
|
135
199
|
};
|
|
200
|
+
var SocketService = class {
|
|
201
|
+
constructor(config) {
|
|
202
|
+
this.socket = null;
|
|
203
|
+
this.token = null;
|
|
204
|
+
this.eventHandlers = /* @__PURE__ */ new Map();
|
|
205
|
+
this.isConnecting = false;
|
|
206
|
+
this.config = {
|
|
207
|
+
autoConnect: false,
|
|
208
|
+
reconnection: true,
|
|
209
|
+
reconnectionAttempts: 5,
|
|
210
|
+
reconnectionDelay: 1e3,
|
|
211
|
+
...config
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
connect(token) {
|
|
215
|
+
if (this.socket?.connected || this.isConnecting) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
this.token = token;
|
|
219
|
+
this.isConnecting = true;
|
|
220
|
+
this.socket = socket_ioClient.io(this.config.baseUrl, {
|
|
221
|
+
auth: { token },
|
|
222
|
+
autoConnect: true,
|
|
223
|
+
reconnection: this.config.reconnection,
|
|
224
|
+
reconnectionAttempts: this.config.reconnectionAttempts,
|
|
225
|
+
reconnectionDelay: this.config.reconnectionDelay,
|
|
226
|
+
transports: ["websocket", "polling"]
|
|
227
|
+
});
|
|
228
|
+
this.setupEventListeners();
|
|
229
|
+
}
|
|
230
|
+
setupEventListeners() {
|
|
231
|
+
if (!this.socket) return;
|
|
232
|
+
this.socket.on("connect", () => {
|
|
233
|
+
this.isConnecting = false;
|
|
234
|
+
console.log("[Auth SDK] Socket connected");
|
|
235
|
+
this.emit("connected", {});
|
|
236
|
+
});
|
|
237
|
+
this.socket.on("disconnect", (reason) => {
|
|
238
|
+
console.log("[Auth SDK] Socket disconnected:", reason);
|
|
239
|
+
this.emit("disconnected", { reason });
|
|
240
|
+
});
|
|
241
|
+
this.socket.on("connect_error", (error) => {
|
|
242
|
+
this.isConnecting = false;
|
|
243
|
+
console.error("[Auth SDK] Socket connection error:", error.message);
|
|
244
|
+
this.emit("error", { error: error.message });
|
|
245
|
+
});
|
|
246
|
+
this.socket.on("user:updated", (data) => {
|
|
247
|
+
this.emit("user:updated", data);
|
|
248
|
+
});
|
|
249
|
+
this.socket.on("session:revoked", (data) => {
|
|
250
|
+
this.emit("session:revoked", data);
|
|
251
|
+
});
|
|
252
|
+
this.socket.on("session:all-revoked", () => {
|
|
253
|
+
this.emit("session:all-revoked", {});
|
|
254
|
+
});
|
|
255
|
+
this.socket.on("auth:password-changed", () => {
|
|
256
|
+
this.emit("auth:password-changed", {});
|
|
257
|
+
});
|
|
258
|
+
this.socket.on("auth:2fa-changed", (data) => {
|
|
259
|
+
this.emit("auth:2fa-changed", data);
|
|
260
|
+
});
|
|
261
|
+
this.socket.on("user:refresh", () => {
|
|
262
|
+
this.emit("user:refresh", {});
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
disconnect() {
|
|
266
|
+
if (this.socket) {
|
|
267
|
+
this.socket.disconnect();
|
|
268
|
+
this.socket = null;
|
|
269
|
+
this.token = null;
|
|
270
|
+
this.isConnecting = false;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
isConnected() {
|
|
274
|
+
return this.socket?.connected ?? false;
|
|
275
|
+
}
|
|
276
|
+
// Event subscription
|
|
277
|
+
on(event, handler) {
|
|
278
|
+
if (!this.eventHandlers.has(event)) {
|
|
279
|
+
this.eventHandlers.set(event, /* @__PURE__ */ new Set());
|
|
280
|
+
}
|
|
281
|
+
this.eventHandlers.get(event).add(handler);
|
|
282
|
+
return () => {
|
|
283
|
+
this.eventHandlers.get(event)?.delete(handler);
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
off(event, handler) {
|
|
287
|
+
if (handler) {
|
|
288
|
+
this.eventHandlers.get(event)?.delete(handler);
|
|
289
|
+
} else {
|
|
290
|
+
this.eventHandlers.delete(event);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
emit(event, data) {
|
|
294
|
+
const handlers = this.eventHandlers.get(event);
|
|
295
|
+
if (handlers) {
|
|
296
|
+
handlers.forEach((handler) => {
|
|
297
|
+
try {
|
|
298
|
+
handler(data);
|
|
299
|
+
} catch (error) {
|
|
300
|
+
console.error(`[Auth SDK] Error in event handler for ${event}:`, error);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// Request fresh user data from server
|
|
306
|
+
requestUserRefresh() {
|
|
307
|
+
if (this.socket?.connected) {
|
|
308
|
+
this.socket.emit("request:user");
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
};
|
|
136
312
|
var AuthService = class {
|
|
313
|
+
// 5 minutes cache
|
|
137
314
|
constructor(config) {
|
|
138
315
|
this.token = null;
|
|
139
316
|
this.upfilesClient = null;
|
|
317
|
+
this.cachedUser = null;
|
|
318
|
+
this.userCacheTimestamp = 0;
|
|
319
|
+
this.USER_CACHE_TTL = 5 * 60 * 1e3;
|
|
140
320
|
this.config = {
|
|
141
321
|
localStorageKey: "auth_token",
|
|
142
322
|
csrfEnabled: true,
|
|
323
|
+
enableSocket: true,
|
|
143
324
|
...config
|
|
144
325
|
};
|
|
145
326
|
this.httpClient = new HttpClient(this.config.baseUrl);
|
|
327
|
+
this.socketService = new SocketService({ baseUrl: this.config.baseUrl });
|
|
146
328
|
this.loadTokenFromStorage();
|
|
147
329
|
if (this.config.upfilesConfig) {
|
|
148
330
|
this.upfilesClient = new upfiles.UpfilesClient({
|
|
@@ -159,6 +341,9 @@ var AuthService = class {
|
|
|
159
341
|
this.httpClient.setFrontendBaseUrl(frontendBaseUrl);
|
|
160
342
|
}
|
|
161
343
|
}
|
|
344
|
+
if (this.token && this.config.enableSocket !== false) {
|
|
345
|
+
this.connectSocket();
|
|
346
|
+
}
|
|
162
347
|
}
|
|
163
348
|
loadTokenFromStorage() {
|
|
164
349
|
if (typeof window !== "undefined" && this.config.localStorageKey) {
|
|
@@ -191,6 +376,57 @@ var AuthService = class {
|
|
|
191
376
|
}
|
|
192
377
|
}
|
|
193
378
|
}
|
|
379
|
+
// Socket connection management
|
|
380
|
+
connectSocket() {
|
|
381
|
+
if (this.token && this.config.enableSocket !== false && typeof window !== "undefined") {
|
|
382
|
+
this.socketService.connect(this.token);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
disconnectSocket() {
|
|
386
|
+
this.socketService.disconnect();
|
|
387
|
+
}
|
|
388
|
+
// Socket event subscription
|
|
389
|
+
onUserUpdated(handler) {
|
|
390
|
+
return this.socketService.on("user:updated", (data) => {
|
|
391
|
+
if (data.user) {
|
|
392
|
+
this.cachedUser = data.user;
|
|
393
|
+
this.userCacheTimestamp = Date.now();
|
|
394
|
+
}
|
|
395
|
+
handler(data);
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
onSessionRevoked(handler) {
|
|
399
|
+
return this.socketService.on("session:revoked", handler);
|
|
400
|
+
}
|
|
401
|
+
onAllSessionsRevoked(handler) {
|
|
402
|
+
return this.socketService.on("session:all-revoked", handler);
|
|
403
|
+
}
|
|
404
|
+
onPasswordChanged(handler) {
|
|
405
|
+
return this.socketService.on("auth:password-changed", handler);
|
|
406
|
+
}
|
|
407
|
+
on2FAChanged(handler) {
|
|
408
|
+
return this.socketService.on("auth:2fa-changed", handler);
|
|
409
|
+
}
|
|
410
|
+
onSocketConnected(handler) {
|
|
411
|
+
return this.socketService.on("connected", handler);
|
|
412
|
+
}
|
|
413
|
+
onSocketDisconnected(handler) {
|
|
414
|
+
return this.socketService.on("disconnected", handler);
|
|
415
|
+
}
|
|
416
|
+
onSocketError(handler) {
|
|
417
|
+
return this.socketService.on("error", handler);
|
|
418
|
+
}
|
|
419
|
+
isSocketConnected() {
|
|
420
|
+
return this.socketService.isConnected();
|
|
421
|
+
}
|
|
422
|
+
// Cache management
|
|
423
|
+
clearUserCache() {
|
|
424
|
+
this.cachedUser = null;
|
|
425
|
+
this.userCacheTimestamp = 0;
|
|
426
|
+
}
|
|
427
|
+
isCacheValid() {
|
|
428
|
+
return this.cachedUser !== null && Date.now() - this.userCacheTimestamp < this.USER_CACHE_TTL;
|
|
429
|
+
}
|
|
194
430
|
isAuthenticated() {
|
|
195
431
|
return !!this.token;
|
|
196
432
|
}
|
|
@@ -256,6 +492,11 @@ var AuthService = class {
|
|
|
256
492
|
this.token = response.token;
|
|
257
493
|
this.httpClient.setAuthToken(response.token);
|
|
258
494
|
this.saveTokenToStorage(response.token);
|
|
495
|
+
if (response.user) {
|
|
496
|
+
this.cachedUser = response.user;
|
|
497
|
+
this.userCacheTimestamp = Date.now();
|
|
498
|
+
}
|
|
499
|
+
this.connectSocket();
|
|
259
500
|
return response;
|
|
260
501
|
}
|
|
261
502
|
if (response.success && (response.message === "OTP sent to your email." || response.message === "OTP sent to your phone number.")) {
|
|
@@ -265,6 +506,11 @@ var AuthService = class {
|
|
|
265
506
|
this.token = response.token;
|
|
266
507
|
this.httpClient.setAuthToken(response.token);
|
|
267
508
|
this.saveTokenToStorage(response.token);
|
|
509
|
+
if (response.user) {
|
|
510
|
+
this.cachedUser = response.user;
|
|
511
|
+
this.userCacheTimestamp = Date.now();
|
|
512
|
+
}
|
|
513
|
+
this.connectSocket();
|
|
268
514
|
return response;
|
|
269
515
|
}
|
|
270
516
|
throw new Error(response.message || "Login failed");
|
|
@@ -308,21 +554,29 @@ var AuthService = class {
|
|
|
308
554
|
}
|
|
309
555
|
}
|
|
310
556
|
async logout() {
|
|
557
|
+
this.disconnectSocket();
|
|
311
558
|
try {
|
|
312
559
|
await this.httpClient.post("/api/v1/auth/logout", {});
|
|
313
560
|
} catch (error) {
|
|
314
561
|
console.warn("Failed to call logout endpoint:", error);
|
|
315
562
|
}
|
|
316
563
|
this.token = null;
|
|
564
|
+
this.cachedUser = null;
|
|
565
|
+
this.userCacheTimestamp = 0;
|
|
317
566
|
this.httpClient.removeAuthToken();
|
|
318
567
|
this.httpClient.removeCsrfToken();
|
|
319
568
|
this.removeTokenFromStorage();
|
|
320
569
|
}
|
|
321
|
-
async getProfile() {
|
|
570
|
+
async getProfile(forceRefresh = false) {
|
|
322
571
|
if (!this.token) {
|
|
323
572
|
throw new Error("Not authenticated");
|
|
324
573
|
}
|
|
574
|
+
if (!forceRefresh && this.isCacheValid() && this.cachedUser) {
|
|
575
|
+
return this.cachedUser;
|
|
576
|
+
}
|
|
325
577
|
const response = await this.httpClient.get("/api/v1/user/me");
|
|
578
|
+
this.cachedUser = response.user;
|
|
579
|
+
this.userCacheTimestamp = Date.now();
|
|
326
580
|
return response.user;
|
|
327
581
|
}
|
|
328
582
|
async updateProfile(data) {
|
|
@@ -486,6 +740,16 @@ var AuthService = class {
|
|
|
486
740
|
);
|
|
487
741
|
return response;
|
|
488
742
|
}
|
|
743
|
+
async adminCreateUser(data) {
|
|
744
|
+
if (!this.token) {
|
|
745
|
+
throw new Error("Not authenticated");
|
|
746
|
+
}
|
|
747
|
+
const response = await this.httpClient.post(
|
|
748
|
+
"/api/v1/admin/create-user",
|
|
749
|
+
data
|
|
750
|
+
);
|
|
751
|
+
return response;
|
|
752
|
+
}
|
|
489
753
|
async adminVerifyUser(userId) {
|
|
490
754
|
if (!this.token) {
|
|
491
755
|
throw new Error("Not authenticated");
|
|
@@ -578,21 +842,49 @@ var AuthProvider = ({ children, config }) => {
|
|
|
578
842
|
const [user, setUser] = React.useState(null);
|
|
579
843
|
const [isLoaded, setIsLoaded] = React.useState(false);
|
|
580
844
|
const [loading, setLoading] = React.useState(false);
|
|
581
|
-
const
|
|
845
|
+
const [isSocketConnected, setIsSocketConnected] = React.useState(false);
|
|
846
|
+
React.useEffect(() => {
|
|
847
|
+
const unsubUserUpdated = authService.onUserUpdated(({ user: updatedUser }) => {
|
|
848
|
+
if (updatedUser) {
|
|
849
|
+
setUser(updatedUser);
|
|
850
|
+
}
|
|
851
|
+
});
|
|
852
|
+
const unsubSessionRevoked = authService.onSessionRevoked(() => {
|
|
853
|
+
authService.logout().then(() => {
|
|
854
|
+
setUser(null);
|
|
855
|
+
});
|
|
856
|
+
});
|
|
857
|
+
const unsubAllSessionsRevoked = authService.onAllSessionsRevoked(() => {
|
|
858
|
+
authService.logout().then(() => {
|
|
859
|
+
setUser(null);
|
|
860
|
+
});
|
|
861
|
+
});
|
|
862
|
+
const unsubPasswordChanged = authService.onPasswordChanged(() => {
|
|
863
|
+
authService.logout().then(() => {
|
|
864
|
+
setUser(null);
|
|
865
|
+
});
|
|
866
|
+
});
|
|
867
|
+
const unsubConnected = authService.onSocketConnected(() => {
|
|
868
|
+
setIsSocketConnected(true);
|
|
869
|
+
});
|
|
870
|
+
const unsubDisconnected = authService.onSocketDisconnected(() => {
|
|
871
|
+
setIsSocketConnected(false);
|
|
872
|
+
});
|
|
873
|
+
return () => {
|
|
874
|
+
unsubUserUpdated();
|
|
875
|
+
unsubSessionRevoked();
|
|
876
|
+
unsubAllSessionsRevoked();
|
|
877
|
+
unsubPasswordChanged();
|
|
878
|
+
unsubConnected();
|
|
879
|
+
unsubDisconnected();
|
|
880
|
+
};
|
|
881
|
+
}, [authService]);
|
|
882
|
+
React.useEffect(() => {
|
|
582
883
|
const authenticated = authService.isAuthenticated();
|
|
583
884
|
if (authenticated) {
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
setUser(
|
|
587
|
-
} catch (error) {
|
|
588
|
-
console.error("Failed to fetch fresh user profile, falling back to token:", error);
|
|
589
|
-
try {
|
|
590
|
-
const currentUser = authService.getCurrentUser();
|
|
591
|
-
setUser(currentUser);
|
|
592
|
-
} catch (fallbackError) {
|
|
593
|
-
console.error("Failed to get current user from token:", fallbackError);
|
|
594
|
-
setUser(null);
|
|
595
|
-
}
|
|
885
|
+
const currentUser = authService.getCurrentUser();
|
|
886
|
+
if (currentUser) {
|
|
887
|
+
setUser(currentUser);
|
|
596
888
|
}
|
|
597
889
|
} else {
|
|
598
890
|
setUser(null);
|
|
@@ -600,8 +892,21 @@ var AuthProvider = ({ children, config }) => {
|
|
|
600
892
|
setIsLoaded(true);
|
|
601
893
|
}, [authService]);
|
|
602
894
|
React.useEffect(() => {
|
|
603
|
-
|
|
604
|
-
|
|
895
|
+
if (!isLoaded) return;
|
|
896
|
+
const authenticated = authService.isAuthenticated();
|
|
897
|
+
if (!authenticated) return;
|
|
898
|
+
const fetchFreshUser = async () => {
|
|
899
|
+
try {
|
|
900
|
+
const freshUser = await authService.getProfile();
|
|
901
|
+
setUser(freshUser);
|
|
902
|
+
} catch (error) {
|
|
903
|
+
console.warn("[Auth SDK] Failed to fetch fresh user profile:", error);
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
if (isSocketConnected) {
|
|
907
|
+
fetchFreshUser();
|
|
908
|
+
}
|
|
909
|
+
}, [authService, isLoaded, isSocketConnected]);
|
|
605
910
|
const signIn = React.useCallback(async (data) => {
|
|
606
911
|
setLoading(true);
|
|
607
912
|
try {
|
|
@@ -823,6 +1128,7 @@ var AuthProvider = ({ children, config }) => {
|
|
|
823
1128
|
isLoaded,
|
|
824
1129
|
isSignedIn: !!user,
|
|
825
1130
|
loading,
|
|
1131
|
+
isSocketConnected,
|
|
826
1132
|
signIn,
|
|
827
1133
|
signUp,
|
|
828
1134
|
signOut,
|
|
@@ -3707,15 +4013,15 @@ var VerifyEmail = ({ token, onSuccess, onError }) => {
|
|
|
3707
4013
|
const [message, setMessage] = React.useState("");
|
|
3708
4014
|
React.useEffect(() => {
|
|
3709
4015
|
const verify = async () => {
|
|
3710
|
-
const
|
|
3711
|
-
if (!
|
|
4016
|
+
const verifyToken2 = token || (typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null);
|
|
4017
|
+
if (!verifyToken2) {
|
|
3712
4018
|
setStatus("error");
|
|
3713
4019
|
setMessage("No verification token provided");
|
|
3714
4020
|
onError?.("No verification token provided");
|
|
3715
4021
|
return;
|
|
3716
4022
|
}
|
|
3717
4023
|
try {
|
|
3718
|
-
const response = await verifyEmailToken(
|
|
4024
|
+
const response = await verifyEmailToken(verifyToken2);
|
|
3719
4025
|
if (response.success) {
|
|
3720
4026
|
setStatus("success");
|
|
3721
4027
|
setMessage("Email verified successfully! Redirecting...");
|
|
@@ -4474,11 +4780,11 @@ var ChangePassword = ({ onSuccess, appearance }) => {
|
|
|
4474
4780
|
|
|
4475
4781
|
// src/react/components/utils/injectModalStyles.ts
|
|
4476
4782
|
var injectModalStyles = () => {
|
|
4477
|
-
if (document.getElementById("
|
|
4783
|
+
if (document.getElementById("ktw-auth-modal-styles")) {
|
|
4478
4784
|
return;
|
|
4479
4785
|
}
|
|
4480
4786
|
const styleElement = document.createElement("style");
|
|
4481
|
-
styleElement.id = "
|
|
4787
|
+
styleElement.id = "ktw-auth-modal-styles";
|
|
4482
4788
|
styleElement.textContent = `
|
|
4483
4789
|
/* ImageManager Modal Styles - Critical for proper modal display */
|
|
4484
4790
|
/* Radix UI Dialog styles - Force visibility */
|
|
@@ -5016,7 +5322,11 @@ __export(react_exports, {
|
|
|
5016
5322
|
// src/node/index.ts
|
|
5017
5323
|
var node_exports = {};
|
|
5018
5324
|
__export(node_exports, {
|
|
5019
|
-
AuthClient: () => AuthClient
|
|
5325
|
+
AuthClient: () => AuthClient,
|
|
5326
|
+
TokenVerifier: () => TokenVerifier,
|
|
5327
|
+
createTokenVerifier: () => createTokenVerifier,
|
|
5328
|
+
getTokenVerifier: () => getTokenVerifier,
|
|
5329
|
+
verifyToken: () => verifyToken
|
|
5020
5330
|
});
|
|
5021
5331
|
|
|
5022
5332
|
// src/node/auth-client.ts
|
|
@@ -5097,6 +5407,135 @@ var AuthClient = class extends AuthService {
|
|
|
5097
5407
|
}
|
|
5098
5408
|
};
|
|
5099
5409
|
|
|
5410
|
+
// src/node/token-verifier.ts
|
|
5411
|
+
var TokenVerifier = class {
|
|
5412
|
+
constructor(config) {
|
|
5413
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
5414
|
+
this.cleanupInterval = null;
|
|
5415
|
+
this.config = {
|
|
5416
|
+
cacheTTL: 6e4,
|
|
5417
|
+
// 1 minute default
|
|
5418
|
+
cacheEnabled: true,
|
|
5419
|
+
...config
|
|
5420
|
+
};
|
|
5421
|
+
if (this.config.cacheEnabled) {
|
|
5422
|
+
this.startCleanup();
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5425
|
+
/**
|
|
5426
|
+
* Verify a JWT token and get user data
|
|
5427
|
+
* Returns cached user if available and valid
|
|
5428
|
+
*/
|
|
5429
|
+
async verifyToken(token) {
|
|
5430
|
+
if (!token) {
|
|
5431
|
+
return null;
|
|
5432
|
+
}
|
|
5433
|
+
if (this.config.cacheEnabled) {
|
|
5434
|
+
const cached = this.getFromCache(token);
|
|
5435
|
+
if (cached) {
|
|
5436
|
+
return cached;
|
|
5437
|
+
}
|
|
5438
|
+
}
|
|
5439
|
+
try {
|
|
5440
|
+
const response = await fetch(`${this.config.authServiceUrl}/api/v1/user/me`, {
|
|
5441
|
+
headers: {
|
|
5442
|
+
"Authorization": `Bearer ${token}`,
|
|
5443
|
+
"Content-Type": "application/json"
|
|
5444
|
+
}
|
|
5445
|
+
});
|
|
5446
|
+
if (!response.ok) {
|
|
5447
|
+
this.cache.delete(token);
|
|
5448
|
+
return null;
|
|
5449
|
+
}
|
|
5450
|
+
const data = await response.json();
|
|
5451
|
+
const user = data.user || null;
|
|
5452
|
+
if (user && this.config.cacheEnabled) {
|
|
5453
|
+
this.setCache(token, user);
|
|
5454
|
+
}
|
|
5455
|
+
return user;
|
|
5456
|
+
} catch (error) {
|
|
5457
|
+
console.error("[TokenVerifier] Auth service verification failed:", error);
|
|
5458
|
+
return null;
|
|
5459
|
+
}
|
|
5460
|
+
}
|
|
5461
|
+
/**
|
|
5462
|
+
* Invalidate cache for a specific token
|
|
5463
|
+
*/
|
|
5464
|
+
invalidateToken(token) {
|
|
5465
|
+
this.cache.delete(token);
|
|
5466
|
+
}
|
|
5467
|
+
/**
|
|
5468
|
+
* Clear all cached tokens
|
|
5469
|
+
*/
|
|
5470
|
+
clearCache() {
|
|
5471
|
+
this.cache.clear();
|
|
5472
|
+
}
|
|
5473
|
+
/**
|
|
5474
|
+
* Get cache statistics
|
|
5475
|
+
*/
|
|
5476
|
+
getCacheStats() {
|
|
5477
|
+
return {
|
|
5478
|
+
size: this.cache.size,
|
|
5479
|
+
enabled: this.config.cacheEnabled,
|
|
5480
|
+
ttl: this.config.cacheTTL
|
|
5481
|
+
};
|
|
5482
|
+
}
|
|
5483
|
+
/**
|
|
5484
|
+
* Stop the cleanup interval (call when shutting down)
|
|
5485
|
+
*/
|
|
5486
|
+
destroy() {
|
|
5487
|
+
if (this.cleanupInterval) {
|
|
5488
|
+
clearInterval(this.cleanupInterval);
|
|
5489
|
+
this.cleanupInterval = null;
|
|
5490
|
+
}
|
|
5491
|
+
this.cache.clear();
|
|
5492
|
+
}
|
|
5493
|
+
getFromCache(token) {
|
|
5494
|
+
const entry = this.cache.get(token);
|
|
5495
|
+
if (!entry) {
|
|
5496
|
+
return null;
|
|
5497
|
+
}
|
|
5498
|
+
if (Date.now() > entry.expiresAt) {
|
|
5499
|
+
this.cache.delete(token);
|
|
5500
|
+
return null;
|
|
5501
|
+
}
|
|
5502
|
+
return entry.user;
|
|
5503
|
+
}
|
|
5504
|
+
setCache(token, user) {
|
|
5505
|
+
this.cache.set(token, {
|
|
5506
|
+
user,
|
|
5507
|
+
expiresAt: Date.now() + this.config.cacheTTL
|
|
5508
|
+
});
|
|
5509
|
+
}
|
|
5510
|
+
startCleanup() {
|
|
5511
|
+
this.cleanupInterval = setInterval(() => {
|
|
5512
|
+
const now = Date.now();
|
|
5513
|
+
for (const [token, entry] of this.cache.entries()) {
|
|
5514
|
+
if (now > entry.expiresAt) {
|
|
5515
|
+
this.cache.delete(token);
|
|
5516
|
+
}
|
|
5517
|
+
}
|
|
5518
|
+
}, 6e4);
|
|
5519
|
+
if (this.cleanupInterval && this.cleanupInterval.unref) {
|
|
5520
|
+
this.cleanupInterval.unref();
|
|
5521
|
+
}
|
|
5522
|
+
}
|
|
5523
|
+
};
|
|
5524
|
+
var defaultVerifier = null;
|
|
5525
|
+
function createTokenVerifier(config) {
|
|
5526
|
+
defaultVerifier = new TokenVerifier(config);
|
|
5527
|
+
return defaultVerifier;
|
|
5528
|
+
}
|
|
5529
|
+
function getTokenVerifier() {
|
|
5530
|
+
if (!defaultVerifier) {
|
|
5531
|
+
throw new Error("TokenVerifier not initialized. Call createTokenVerifier() first.");
|
|
5532
|
+
}
|
|
5533
|
+
return defaultVerifier;
|
|
5534
|
+
}
|
|
5535
|
+
async function verifyToken(token) {
|
|
5536
|
+
return getTokenVerifier().verifyToken(token);
|
|
5537
|
+
}
|
|
5538
|
+
|
|
5100
5539
|
Object.defineProperty(exports, "ConnectProjectDialog", {
|
|
5101
5540
|
enumerable: true,
|
|
5102
5541
|
get: function () { return upfiles.ConnectProjectDialog; }
|
|
@@ -5135,6 +5574,7 @@ exports.ResetPassword = ResetPassword;
|
|
|
5135
5574
|
exports.SignIn = SignIn;
|
|
5136
5575
|
exports.SignOut = SignOut;
|
|
5137
5576
|
exports.SignUp = SignUp;
|
|
5577
|
+
exports.SocketService = SocketService;
|
|
5138
5578
|
exports.UserButton = UserButton;
|
|
5139
5579
|
exports.UserProfile = UserProfile;
|
|
5140
5580
|
exports.VerifyEmail = VerifyEmail;
|