@pubflow/react 0.2.0 → 0.3.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/index.cjs +276 -238
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +276 -239
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createStorageKey, initConfig, ApiClient, AuthService, BridgeApiService, validateWithSchema, FilterOperator } from '@pubflow/core';
|
|
2
2
|
export * from '@pubflow/core';
|
|
3
3
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
4
|
-
import React, { createContext, useState,
|
|
4
|
+
import React, { createContext, useState, useCallback, useEffect, useContext } from 'react';
|
|
5
5
|
import useSWR, { SWRConfig, useSWRConfig } from 'swr';
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -208,64 +208,36 @@ const PubflowContext = createContext({
|
|
|
208
208
|
defaultInstance: 'default'
|
|
209
209
|
});
|
|
210
210
|
/**
|
|
211
|
-
* Pubflow
|
|
211
|
+
* Pubflow Provider Component
|
|
212
212
|
*/
|
|
213
|
-
function PubflowProvider({ children, config, instances, defaultInstance = 'default',
|
|
214
|
-
const [isInitialized, setIsInitialized] = useState(false);
|
|
213
|
+
function PubflowProvider({ children, config, instances, defaultInstance = 'default', enableDebugTools = false, showSessionAlerts = false, persistentCache = { enabled: false }, theme = {}, loginRedirectPath = '/login', publicPaths = [] }) {
|
|
215
214
|
const [contextValue, setContextValue] = useState({
|
|
216
215
|
instances: {},
|
|
217
216
|
defaultInstance
|
|
218
217
|
});
|
|
219
|
-
//
|
|
220
|
-
useEffect(() => {
|
|
221
|
-
if (enableDebugTools) {
|
|
222
|
-
console.log('Pubflow debug tools enabled');
|
|
223
|
-
// Add debug utilities to window object
|
|
224
|
-
if (typeof window !== 'undefined') {
|
|
225
|
-
window.pubflowDebug = {
|
|
226
|
-
getInstances: () => contextValue.instances,
|
|
227
|
-
getDefaultInstance: () => contextValue.defaultInstance,
|
|
228
|
-
clearStorage: async () => {
|
|
229
|
-
const storage = new BrowserStorageAdapter();
|
|
230
|
-
await storage.removeItem('pubflow_session_id');
|
|
231
|
-
await storage.removeItem('pubflow_user_data');
|
|
232
|
-
console.log('Pubflow storage cleared');
|
|
233
|
-
},
|
|
234
|
-
loginRedirectPath,
|
|
235
|
-
publicPaths,
|
|
236
|
-
theme
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}, [enableDebugTools, contextValue, loginRedirectPath, publicPaths, theme]);
|
|
241
|
-
// Handle session expiration
|
|
218
|
+
// Session handlers
|
|
242
219
|
const handleSessionExpired = useCallback(() => {
|
|
243
|
-
if (showSessionAlerts) {
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
if (onSessionExpired) {
|
|
247
|
-
onSessionExpired();
|
|
220
|
+
if (showSessionAlerts && typeof window !== 'undefined') {
|
|
221
|
+
console.warn('Session expired');
|
|
248
222
|
}
|
|
249
|
-
}, [
|
|
250
|
-
// Handle session refresh
|
|
223
|
+
}, [showSessionAlerts]);
|
|
251
224
|
const handleSessionRefreshed = useCallback(() => {
|
|
252
|
-
if (showSessionAlerts) {
|
|
253
|
-
|
|
254
|
-
}
|
|
255
|
-
if (onSessionRefreshed) {
|
|
256
|
-
onSessionRefreshed();
|
|
225
|
+
if (showSessionAlerts && typeof window !== 'undefined') {
|
|
226
|
+
console.log('Session refreshed');
|
|
257
227
|
}
|
|
258
|
-
}, [
|
|
228
|
+
}, [showSessionAlerts]);
|
|
229
|
+
// Initialize instances
|
|
259
230
|
useEffect(() => {
|
|
231
|
+
let isMounted = true;
|
|
260
232
|
const initialize = async () => {
|
|
261
233
|
var _a, _b;
|
|
262
234
|
try {
|
|
263
|
-
// Initialize instances
|
|
264
235
|
const instancesMap = {};
|
|
265
236
|
if (instances && instances.length > 0) {
|
|
266
237
|
// Initialize multiple instances
|
|
267
238
|
for (const instanceConfig of instances) {
|
|
268
|
-
|
|
239
|
+
if (!isMounted)
|
|
240
|
+
return;
|
|
269
241
|
const fullConfig = initConfig({
|
|
270
242
|
...instanceConfig,
|
|
271
243
|
sessionConfig: {
|
|
@@ -274,36 +246,24 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
274
246
|
onSessionRefreshed: handleSessionRefreshed
|
|
275
247
|
}
|
|
276
248
|
}, instanceConfig.id);
|
|
277
|
-
// Create storage adapter
|
|
278
249
|
const storage = new BrowserStorageAdapter({
|
|
279
250
|
prefix: (_a = fullConfig.storageConfig) === null || _a === void 0 ? void 0 : _a.prefix
|
|
280
251
|
});
|
|
281
|
-
// Create API client
|
|
282
252
|
const apiClient = new ApiClient(fullConfig, storage);
|
|
283
|
-
// Create auth service
|
|
284
253
|
const authService = new AuthService(apiClient, storage, fullConfig);
|
|
285
|
-
// Get current user
|
|
254
|
+
// Get current user (non-blocking)
|
|
286
255
|
let user = null;
|
|
287
256
|
let isAuthenticated = false;
|
|
288
|
-
try {
|
|
289
|
-
user = await authService.getCurrentUser();
|
|
290
|
-
isAuthenticated = !!user;
|
|
291
|
-
}
|
|
292
|
-
catch (error) {
|
|
293
|
-
console.error(`Error getting current user for instance ${instanceConfig.id}:`, error);
|
|
294
|
-
}
|
|
295
|
-
// Create instance
|
|
296
257
|
instancesMap[instanceConfig.id] = {
|
|
297
258
|
config: fullConfig,
|
|
298
259
|
apiClient,
|
|
299
260
|
authService,
|
|
300
261
|
user,
|
|
301
262
|
isAuthenticated,
|
|
302
|
-
isLoading:
|
|
263
|
+
isLoading: true,
|
|
303
264
|
login: async (credentials) => {
|
|
304
265
|
const result = await authService.login(credentials);
|
|
305
|
-
if (result.success && result.user) {
|
|
306
|
-
// Update instance
|
|
266
|
+
if (result.success && result.user && isMounted) {
|
|
307
267
|
setContextValue(prev => ({
|
|
308
268
|
...prev,
|
|
309
269
|
instances: {
|
|
@@ -311,7 +271,8 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
311
271
|
[instanceConfig.id]: {
|
|
312
272
|
...prev.instances[instanceConfig.id],
|
|
313
273
|
user: result.user,
|
|
314
|
-
isAuthenticated: true
|
|
274
|
+
isAuthenticated: true,
|
|
275
|
+
isLoading: false
|
|
315
276
|
}
|
|
316
277
|
}
|
|
317
278
|
}));
|
|
@@ -320,41 +281,74 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
320
281
|
},
|
|
321
282
|
logout: async () => {
|
|
322
283
|
await authService.logout();
|
|
323
|
-
|
|
284
|
+
if (isMounted) {
|
|
285
|
+
setContextValue(prev => ({
|
|
286
|
+
...prev,
|
|
287
|
+
instances: {
|
|
288
|
+
...prev.instances,
|
|
289
|
+
[instanceConfig.id]: {
|
|
290
|
+
...prev.instances[instanceConfig.id],
|
|
291
|
+
user: null,
|
|
292
|
+
isAuthenticated: false,
|
|
293
|
+
isLoading: false
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}));
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
validateSession: async () => {
|
|
300
|
+
const result = await authService.validateSession();
|
|
301
|
+
if (isMounted) {
|
|
302
|
+
setContextValue(prev => ({
|
|
303
|
+
...prev,
|
|
304
|
+
instances: {
|
|
305
|
+
...prev.instances,
|
|
306
|
+
[instanceConfig.id]: {
|
|
307
|
+
...prev.instances[instanceConfig.id],
|
|
308
|
+
user: result.user || null,
|
|
309
|
+
isAuthenticated: result.isValid,
|
|
310
|
+
isLoading: false
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}));
|
|
314
|
+
}
|
|
315
|
+
return result;
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
// Load user asynchronously
|
|
319
|
+
authService.getCurrentUser().then(currentUser => {
|
|
320
|
+
if (isMounted) {
|
|
324
321
|
setContextValue(prev => ({
|
|
325
322
|
...prev,
|
|
326
323
|
instances: {
|
|
327
324
|
...prev.instances,
|
|
328
325
|
[instanceConfig.id]: {
|
|
329
326
|
...prev.instances[instanceConfig.id],
|
|
330
|
-
user:
|
|
331
|
-
isAuthenticated:
|
|
327
|
+
user: currentUser,
|
|
328
|
+
isAuthenticated: !!currentUser,
|
|
329
|
+
isLoading: false
|
|
332
330
|
}
|
|
333
331
|
}
|
|
334
332
|
}));
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
// Update instance
|
|
333
|
+
}
|
|
334
|
+
}).catch(() => {
|
|
335
|
+
if (isMounted) {
|
|
339
336
|
setContextValue(prev => ({
|
|
340
337
|
...prev,
|
|
341
338
|
instances: {
|
|
342
339
|
...prev.instances,
|
|
343
340
|
[instanceConfig.id]: {
|
|
344
341
|
...prev.instances[instanceConfig.id],
|
|
345
|
-
|
|
346
|
-
isAuthenticated: result.isValid
|
|
342
|
+
isLoading: false
|
|
347
343
|
}
|
|
348
344
|
}
|
|
349
345
|
}));
|
|
350
|
-
return result;
|
|
351
346
|
}
|
|
352
|
-
};
|
|
347
|
+
});
|
|
353
348
|
}
|
|
354
349
|
}
|
|
355
350
|
else if (config) {
|
|
356
|
-
//
|
|
357
|
-
// Initialize configuration
|
|
351
|
+
// Single instance mode (simplified)
|
|
358
352
|
const fullConfig = initConfig({
|
|
359
353
|
...config,
|
|
360
354
|
sessionConfig: {
|
|
@@ -362,37 +356,22 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
362
356
|
onSessionExpired: handleSessionExpired,
|
|
363
357
|
onSessionRefreshed: handleSessionRefreshed
|
|
364
358
|
}
|
|
365
|
-
}, defaultInstance);
|
|
366
|
-
// Create storage adapter
|
|
359
|
+
}, config.id || defaultInstance);
|
|
367
360
|
const storage = new BrowserStorageAdapter({
|
|
368
361
|
prefix: (_b = fullConfig.storageConfig) === null || _b === void 0 ? void 0 : _b.prefix
|
|
369
362
|
});
|
|
370
|
-
// Create API client
|
|
371
363
|
const apiClient = new ApiClient(fullConfig, storage);
|
|
372
|
-
// Create auth service
|
|
373
364
|
const authService = new AuthService(apiClient, storage, fullConfig);
|
|
374
|
-
// Get current user
|
|
375
|
-
let user = null;
|
|
376
|
-
let isAuthenticated = false;
|
|
377
|
-
try {
|
|
378
|
-
user = await authService.getCurrentUser();
|
|
379
|
-
isAuthenticated = !!user;
|
|
380
|
-
}
|
|
381
|
-
catch (error) {
|
|
382
|
-
console.error('Error getting current user:', error);
|
|
383
|
-
}
|
|
384
|
-
// Create instance
|
|
385
365
|
instancesMap[defaultInstance] = {
|
|
386
366
|
config: fullConfig,
|
|
387
367
|
apiClient,
|
|
388
368
|
authService,
|
|
389
|
-
user,
|
|
390
|
-
isAuthenticated,
|
|
391
|
-
isLoading:
|
|
369
|
+
user: null,
|
|
370
|
+
isAuthenticated: false,
|
|
371
|
+
isLoading: true,
|
|
392
372
|
login: async (credentials) => {
|
|
393
373
|
const result = await authService.login(credentials);
|
|
394
|
-
if (result.success && result.user) {
|
|
395
|
-
// Update instance
|
|
374
|
+
if (result.success && result.user && isMounted) {
|
|
396
375
|
setContextValue(prev => ({
|
|
397
376
|
...prev,
|
|
398
377
|
instances: {
|
|
@@ -400,7 +379,8 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
400
379
|
[defaultInstance]: {
|
|
401
380
|
...prev.instances[defaultInstance],
|
|
402
381
|
user: result.user,
|
|
403
|
-
isAuthenticated: true
|
|
382
|
+
isAuthenticated: true,
|
|
383
|
+
isLoading: false
|
|
404
384
|
}
|
|
405
385
|
}
|
|
406
386
|
}));
|
|
@@ -409,61 +389,107 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
409
389
|
},
|
|
410
390
|
logout: async () => {
|
|
411
391
|
await authService.logout();
|
|
412
|
-
|
|
392
|
+
if (isMounted) {
|
|
393
|
+
setContextValue(prev => ({
|
|
394
|
+
...prev,
|
|
395
|
+
instances: {
|
|
396
|
+
...prev.instances,
|
|
397
|
+
[defaultInstance]: {
|
|
398
|
+
...prev.instances[defaultInstance],
|
|
399
|
+
user: null,
|
|
400
|
+
isAuthenticated: false,
|
|
401
|
+
isLoading: false
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}));
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
validateSession: async () => {
|
|
408
|
+
const result = await authService.validateSession();
|
|
409
|
+
if (isMounted) {
|
|
410
|
+
setContextValue(prev => ({
|
|
411
|
+
...prev,
|
|
412
|
+
instances: {
|
|
413
|
+
...prev.instances,
|
|
414
|
+
[defaultInstance]: {
|
|
415
|
+
...prev.instances[defaultInstance],
|
|
416
|
+
user: result.user || null,
|
|
417
|
+
isAuthenticated: result.isValid,
|
|
418
|
+
isLoading: false
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}));
|
|
422
|
+
}
|
|
423
|
+
return result;
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
// Load user asynchronously
|
|
427
|
+
authService.getCurrentUser().then(currentUser => {
|
|
428
|
+
if (isMounted) {
|
|
413
429
|
setContextValue(prev => ({
|
|
414
430
|
...prev,
|
|
415
431
|
instances: {
|
|
416
432
|
...prev.instances,
|
|
417
433
|
[defaultInstance]: {
|
|
418
434
|
...prev.instances[defaultInstance],
|
|
419
|
-
user:
|
|
420
|
-
isAuthenticated:
|
|
435
|
+
user: currentUser,
|
|
436
|
+
isAuthenticated: !!currentUser,
|
|
437
|
+
isLoading: false
|
|
421
438
|
}
|
|
422
439
|
}
|
|
423
440
|
}));
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
// Update instance
|
|
441
|
+
}
|
|
442
|
+
}).catch(() => {
|
|
443
|
+
if (isMounted) {
|
|
428
444
|
setContextValue(prev => ({
|
|
429
445
|
...prev,
|
|
430
446
|
instances: {
|
|
431
447
|
...prev.instances,
|
|
432
448
|
[defaultInstance]: {
|
|
433
449
|
...prev.instances[defaultInstance],
|
|
434
|
-
|
|
435
|
-
isAuthenticated: result.isValid
|
|
450
|
+
isLoading: false
|
|
436
451
|
}
|
|
437
452
|
}
|
|
438
453
|
}));
|
|
439
|
-
return result;
|
|
440
454
|
}
|
|
441
|
-
};
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
if (isMounted) {
|
|
458
|
+
setContextValue({
|
|
459
|
+
instances: instancesMap,
|
|
460
|
+
defaultInstance
|
|
461
|
+
});
|
|
442
462
|
}
|
|
443
|
-
// Set context value
|
|
444
|
-
setContextValue({
|
|
445
|
-
instances: instancesMap,
|
|
446
|
-
defaultInstance
|
|
447
|
-
});
|
|
448
|
-
// Set initialized
|
|
449
|
-
setIsInitialized(true);
|
|
450
463
|
}
|
|
451
464
|
catch (error) {
|
|
452
465
|
console.error('Error initializing Pubflow:', error);
|
|
453
466
|
}
|
|
454
467
|
};
|
|
455
468
|
initialize();
|
|
469
|
+
return () => {
|
|
470
|
+
isMounted = false;
|
|
471
|
+
};
|
|
456
472
|
}, [config, instances, defaultInstance, handleSessionExpired, handleSessionRefreshed]);
|
|
457
|
-
//
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
473
|
+
// Debug tools (simplified)
|
|
474
|
+
useEffect(() => {
|
|
475
|
+
if (enableDebugTools && typeof window !== 'undefined') {
|
|
476
|
+
window.pubflowDebug = {
|
|
477
|
+
getInstances: () => contextValue.instances,
|
|
478
|
+
getDefaultInstance: () => contextValue.defaultInstance
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
}, [enableDebugTools]);
|
|
482
|
+
// SWR configuration
|
|
483
|
+
const swrConfig = {
|
|
484
|
+
revalidateOnFocus: false,
|
|
485
|
+
revalidateOnReconnect: true,
|
|
486
|
+
...(persistentCache.enabled && {
|
|
487
|
+
provider: () => new Map(),
|
|
488
|
+
isOnline: () => true,
|
|
489
|
+
isVisible: () => true
|
|
490
|
+
})
|
|
491
|
+
};
|
|
492
|
+
return (jsx(PubflowContext.Provider, { value: contextValue, children: jsx(SWRConfig, { value: swrConfig, children: children }) }));
|
|
467
493
|
}
|
|
468
494
|
|
|
469
495
|
/**
|
|
@@ -479,7 +505,6 @@ function PubflowProvider({ children, config, instances, defaultInstance = 'defau
|
|
|
479
505
|
*/
|
|
480
506
|
function useAuth(instanceId) {
|
|
481
507
|
const context = useContext(PubflowContext);
|
|
482
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
483
508
|
if (!context) {
|
|
484
509
|
throw new Error('useAuth must be used within a PubflowProvider');
|
|
485
510
|
}
|
|
@@ -488,68 +513,14 @@ function useAuth(instanceId) {
|
|
|
488
513
|
if (!pubflowInstance) {
|
|
489
514
|
throw new Error(`Pubflow instance '${instance}' not found`);
|
|
490
515
|
}
|
|
491
|
-
// Wrap login to handle loading state
|
|
492
|
-
const login = useCallback(async (credentials) => {
|
|
493
|
-
setIsLoading(true);
|
|
494
|
-
try {
|
|
495
|
-
return await pubflowInstance.login(credentials);
|
|
496
|
-
}
|
|
497
|
-
finally {
|
|
498
|
-
setIsLoading(false);
|
|
499
|
-
}
|
|
500
|
-
}, [pubflowInstance]);
|
|
501
|
-
// Wrap logout to handle loading state
|
|
502
|
-
const logout = useCallback(async () => {
|
|
503
|
-
setIsLoading(true);
|
|
504
|
-
try {
|
|
505
|
-
await pubflowInstance.logout();
|
|
506
|
-
}
|
|
507
|
-
finally {
|
|
508
|
-
setIsLoading(false);
|
|
509
|
-
}
|
|
510
|
-
}, [pubflowInstance]);
|
|
511
|
-
// Wrap validateSession to handle loading state
|
|
512
|
-
const validateSession = useCallback(async () => {
|
|
513
|
-
setIsLoading(true);
|
|
514
|
-
try {
|
|
515
|
-
return await pubflowInstance.validateSession();
|
|
516
|
-
}
|
|
517
|
-
finally {
|
|
518
|
-
setIsLoading(false);
|
|
519
|
-
}
|
|
520
|
-
}, [pubflowInstance]);
|
|
521
|
-
// Add refreshUser function to manually refresh user data
|
|
522
|
-
const refreshUser = useCallback(async () => {
|
|
523
|
-
setIsLoading(true);
|
|
524
|
-
try {
|
|
525
|
-
const result = await pubflowInstance.validateSession();
|
|
526
|
-
return result.user || null;
|
|
527
|
-
}
|
|
528
|
-
finally {
|
|
529
|
-
setIsLoading(false);
|
|
530
|
-
}
|
|
531
|
-
}, [pubflowInstance]);
|
|
532
|
-
// Validate session on mount
|
|
533
|
-
useEffect(() => {
|
|
534
|
-
const validate = async () => {
|
|
535
|
-
try {
|
|
536
|
-
await validateSession();
|
|
537
|
-
}
|
|
538
|
-
catch (error) {
|
|
539
|
-
console.error('Error validating session:', error);
|
|
540
|
-
}
|
|
541
|
-
};
|
|
542
|
-
validate();
|
|
543
|
-
}, [validateSession]);
|
|
544
516
|
return {
|
|
545
517
|
// Ensure user is never undefined
|
|
546
518
|
user: pubflowInstance.user || null,
|
|
547
519
|
isAuthenticated: pubflowInstance.isAuthenticated,
|
|
548
|
-
isLoading,
|
|
549
|
-
login,
|
|
550
|
-
logout,
|
|
551
|
-
validateSession
|
|
552
|
-
refreshUser
|
|
520
|
+
isLoading: pubflowInstance.isLoading,
|
|
521
|
+
login: pubflowInstance.login,
|
|
522
|
+
logout: pubflowInstance.logout,
|
|
523
|
+
validateSession: pubflowInstance.validateSession
|
|
553
524
|
};
|
|
554
525
|
}
|
|
555
526
|
|
|
@@ -9559,6 +9530,131 @@ function createStyles(theme) {
|
|
|
9559
9530
|
};
|
|
9560
9531
|
}
|
|
9561
9532
|
|
|
9533
|
+
/**
|
|
9534
|
+
* Authentication Guard Hook for React
|
|
9535
|
+
*
|
|
9536
|
+
* Framework-agnostic hook for handling authentication validation and redirects
|
|
9537
|
+
*/
|
|
9538
|
+
/**
|
|
9539
|
+
* Hook for handling authentication validation and redirects
|
|
9540
|
+
*
|
|
9541
|
+
* This hook is framework-agnostic and requires the user to provide
|
|
9542
|
+
* their own redirect function (e.g., Next.js router, React Router, etc.)
|
|
9543
|
+
*
|
|
9544
|
+
* @param options Hook options
|
|
9545
|
+
* @returns Authentication guard result
|
|
9546
|
+
*/
|
|
9547
|
+
function useAuthGuard({ validateOnMount = true, allowedTypes = ['authenticated'], instanceId, onRedirect, onSessionExpired, loginRedirectPath = '/login', accessDeniedPath = '/access-denied', enableLogging = false } = {}) {
|
|
9548
|
+
const { user, isAuthenticated, isLoading, validateSession } = useAuth(instanceId);
|
|
9549
|
+
// Check if user is authorized based on user type
|
|
9550
|
+
const isAuthorized = useCallback(() => {
|
|
9551
|
+
if (!isAuthenticated || !user) {
|
|
9552
|
+
return false;
|
|
9553
|
+
}
|
|
9554
|
+
// If allowedTypes includes 'authenticated', any authenticated user is allowed
|
|
9555
|
+
if (allowedTypes.includes('authenticated')) {
|
|
9556
|
+
return true;
|
|
9557
|
+
}
|
|
9558
|
+
// Check specific user types
|
|
9559
|
+
const userType = user.userType || user.user_type || '';
|
|
9560
|
+
return allowedTypes.some(type => type.toLowerCase() === userType.toLowerCase());
|
|
9561
|
+
}, [isAuthenticated, user, allowedTypes]);
|
|
9562
|
+
const authorized = isAuthorized();
|
|
9563
|
+
// Determine redirect reason
|
|
9564
|
+
const getRedirectReason = useCallback(() => {
|
|
9565
|
+
if (isLoading) {
|
|
9566
|
+
return null;
|
|
9567
|
+
}
|
|
9568
|
+
if (!isAuthenticated) {
|
|
9569
|
+
return 'unauthenticated';
|
|
9570
|
+
}
|
|
9571
|
+
if (!authorized) {
|
|
9572
|
+
return 'unauthorized';
|
|
9573
|
+
}
|
|
9574
|
+
return null;
|
|
9575
|
+
}, [isLoading, isAuthenticated, authorized]);
|
|
9576
|
+
const redirectReason = getRedirectReason();
|
|
9577
|
+
// Validate session on mount
|
|
9578
|
+
useEffect(() => {
|
|
9579
|
+
if (validateOnMount && isAuthenticated) {
|
|
9580
|
+
validateSession().then(({ isValid }) => {
|
|
9581
|
+
if (!isValid) {
|
|
9582
|
+
if (enableLogging) {
|
|
9583
|
+
console.warn('useAuthGuard: Session validation failed');
|
|
9584
|
+
}
|
|
9585
|
+
// Call session expired handler
|
|
9586
|
+
if (onSessionExpired) {
|
|
9587
|
+
onSessionExpired();
|
|
9588
|
+
}
|
|
9589
|
+
// Redirect to login
|
|
9590
|
+
if (onRedirect) {
|
|
9591
|
+
onRedirect(loginRedirectPath, 'session-expired');
|
|
9592
|
+
}
|
|
9593
|
+
}
|
|
9594
|
+
}).catch(error => {
|
|
9595
|
+
if (enableLogging) {
|
|
9596
|
+
console.error('useAuthGuard: Session validation error:', error);
|
|
9597
|
+
}
|
|
9598
|
+
});
|
|
9599
|
+
}
|
|
9600
|
+
}, [validateOnMount, isAuthenticated, validateSession, onSessionExpired, onRedirect, loginRedirectPath, enableLogging]);
|
|
9601
|
+
// Handle authentication redirects
|
|
9602
|
+
useEffect(() => {
|
|
9603
|
+
if (isLoading || !onRedirect) {
|
|
9604
|
+
return;
|
|
9605
|
+
}
|
|
9606
|
+
if (!isAuthenticated) {
|
|
9607
|
+
if (enableLogging) {
|
|
9608
|
+
console.warn('useAuthGuard: User not authenticated, redirecting to login');
|
|
9609
|
+
}
|
|
9610
|
+
onRedirect(loginRedirectPath, 'unauthenticated');
|
|
9611
|
+
return;
|
|
9612
|
+
}
|
|
9613
|
+
if (!authorized) {
|
|
9614
|
+
if (enableLogging) {
|
|
9615
|
+
console.warn('useAuthGuard: User not authorized for this page, redirecting to access denied');
|
|
9616
|
+
}
|
|
9617
|
+
onRedirect(accessDeniedPath, 'unauthorized');
|
|
9618
|
+
return;
|
|
9619
|
+
}
|
|
9620
|
+
}, [isLoading, isAuthenticated, authorized, onRedirect, loginRedirectPath, accessDeniedPath, enableLogging]);
|
|
9621
|
+
return {
|
|
9622
|
+
user,
|
|
9623
|
+
isAuthenticated,
|
|
9624
|
+
isLoading,
|
|
9625
|
+
isAuthorized: authorized,
|
|
9626
|
+
validateSession,
|
|
9627
|
+
redirectReason
|
|
9628
|
+
};
|
|
9629
|
+
}
|
|
9630
|
+
/**
|
|
9631
|
+
* Simple authentication guard hook with automatic redirects
|
|
9632
|
+
*
|
|
9633
|
+
* This is a simplified version that uses window.location for redirects
|
|
9634
|
+
* Suitable for simple React apps without complex routing
|
|
9635
|
+
*
|
|
9636
|
+
* @param options Hook options
|
|
9637
|
+
* @returns Authentication guard result
|
|
9638
|
+
*/
|
|
9639
|
+
function useSimpleAuthGuard(options = {}) {
|
|
9640
|
+
var _a;
|
|
9641
|
+
const handleRedirect = useCallback((path, reason) => {
|
|
9642
|
+
if (typeof window !== 'undefined') {
|
|
9643
|
+
// Add current path as redirect parameter
|
|
9644
|
+
const currentPath = window.location.pathname + window.location.search;
|
|
9645
|
+
const redirectUrl = reason === 'unauthenticated'
|
|
9646
|
+
? `${path}?redirect=${encodeURIComponent(currentPath)}`
|
|
9647
|
+
: path;
|
|
9648
|
+
window.location.href = redirectUrl;
|
|
9649
|
+
}
|
|
9650
|
+
}, []);
|
|
9651
|
+
return useAuthGuard({
|
|
9652
|
+
...options,
|
|
9653
|
+
onRedirect: handleRedirect,
|
|
9654
|
+
enableLogging: (_a = options.enableLogging) !== null && _a !== void 0 ? _a : true
|
|
9655
|
+
});
|
|
9656
|
+
}
|
|
9657
|
+
|
|
9562
9658
|
/**
|
|
9563
9659
|
* Bridge API Raw Hook for React
|
|
9564
9660
|
*
|
|
@@ -9638,65 +9734,6 @@ function useBridgeApiRaw(instanceId) {
|
|
|
9638
9734
|
};
|
|
9639
9735
|
}
|
|
9640
9736
|
|
|
9641
|
-
/**
|
|
9642
|
-
* Server Authentication Hook for React
|
|
9643
|
-
*
|
|
9644
|
-
* Provides a hook for handling authentication with automatic redirects
|
|
9645
|
-
*/
|
|
9646
|
-
/**
|
|
9647
|
-
* Hook for handling authentication with automatic redirects
|
|
9648
|
-
*
|
|
9649
|
-
* @param options Hook options
|
|
9650
|
-
* @returns Authentication hook result
|
|
9651
|
-
*/
|
|
9652
|
-
function useServerAuth({ loginRedirectPath = '/login', allowedTypes = ['authenticated'], validateOnMount = true, instanceId, onRedirect } = {}) {
|
|
9653
|
-
const { user, isAuthenticated, isLoading, validateSession } = useAuth(instanceId);
|
|
9654
|
-
// Default redirect function
|
|
9655
|
-
const defaultRedirect = (path) => {
|
|
9656
|
-
if (typeof window !== 'undefined') {
|
|
9657
|
-
const currentPath = window.location.pathname;
|
|
9658
|
-
const redirectUrl = `${path}?redirect=${encodeURIComponent(currentPath)}`;
|
|
9659
|
-
window.location.href = redirectUrl;
|
|
9660
|
-
}
|
|
9661
|
-
};
|
|
9662
|
-
const redirect = onRedirect || defaultRedirect;
|
|
9663
|
-
useEffect(() => {
|
|
9664
|
-
// Validate session on mount if configured
|
|
9665
|
-
if (validateOnMount) {
|
|
9666
|
-
validateSession().then(({ isValid }) => {
|
|
9667
|
-
if (!isValid) {
|
|
9668
|
-
redirect(loginRedirectPath);
|
|
9669
|
-
}
|
|
9670
|
-
});
|
|
9671
|
-
}
|
|
9672
|
-
}, [validateOnMount, loginRedirectPath, validateSession, redirect]);
|
|
9673
|
-
useEffect(() => {
|
|
9674
|
-
// Skip if still loading
|
|
9675
|
-
if (isLoading) {
|
|
9676
|
-
return;
|
|
9677
|
-
}
|
|
9678
|
-
// Redirect if not authenticated
|
|
9679
|
-
if (!isAuthenticated) {
|
|
9680
|
-
redirect(loginRedirectPath);
|
|
9681
|
-
return;
|
|
9682
|
-
}
|
|
9683
|
-
// Check user type if allowedTypes doesn't include 'authenticated'
|
|
9684
|
-
if (!allowedTypes.includes('authenticated') && user) {
|
|
9685
|
-
const userType = user.userType || '';
|
|
9686
|
-
const isAllowed = allowedTypes.some(type => type.toLowerCase() === userType.toLowerCase());
|
|
9687
|
-
if (!isAllowed) {
|
|
9688
|
-
redirect('/access-denied');
|
|
9689
|
-
}
|
|
9690
|
-
}
|
|
9691
|
-
}, [isLoading, isAuthenticated, user, allowedTypes, loginRedirectPath, redirect]);
|
|
9692
|
-
return {
|
|
9693
|
-
user,
|
|
9694
|
-
isAuthenticated,
|
|
9695
|
-
isLoading,
|
|
9696
|
-
validateSession
|
|
9697
|
-
};
|
|
9698
|
-
}
|
|
9699
|
-
|
|
9700
9737
|
/**
|
|
9701
9738
|
* Search Query Builder Hook for React
|
|
9702
9739
|
*
|
|
@@ -9918,5 +9955,5 @@ function useRequireAuth(options = {}) {
|
|
|
9918
9955
|
};
|
|
9919
9956
|
}
|
|
9920
9957
|
|
|
9921
|
-
export { AccountCreationForm, AdvancedFilter, BridgeForm, BridgeList, BridgeTable, BridgeView, BrowserStorageAdapter, LoginForm, OfflineIndicator, PasswordResetForm, PubflowContext, PubflowProvider, ThemeProvider, createStyles, generateCSSVariables, useAuth, useBridgeApi, useBridgeApiRaw, useBridgeCrud, useBridgeMutation, useBridgeQuery, useNetworkStatus, useRequireAuth, useSearchQueryBuilder,
|
|
9958
|
+
export { AccountCreationForm, AdvancedFilter, BridgeForm, BridgeList, BridgeTable, BridgeView, BrowserStorageAdapter, LoginForm, OfflineIndicator, PasswordResetForm, PubflowContext, PubflowProvider, ThemeProvider, createStyles, generateCSSVariables, useAuth, useAuthGuard, useBridgeApi, useBridgeApiRaw, useBridgeCrud, useBridgeMutation, useBridgeQuery, useNetworkStatus, useRequireAuth, useSearchQueryBuilder, useSimpleAuthGuard, useTheme };
|
|
9922
9959
|
//# sourceMappingURL=index.esm.js.map
|