@chemmangat/msal-next 3.1.9 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +141 -2
- package/dist/index.d.ts +141 -2
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -285,6 +285,112 @@ interface MsalAuthProviderProps extends MsalAuthConfig {
|
|
|
285
285
|
declare function getMsalInstance(): PublicClientApplication | null;
|
|
286
286
|
declare function MsalAuthProvider({ children, loadingComponent, onInitialized, ...config }: MsalAuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
287
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Zero-Config Protected Routes - Type Definitions
|
|
290
|
+
* v4.0.0 Killer Feature
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Page-level auth configuration
|
|
295
|
+
* Export this from your page to enable protection
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```tsx
|
|
299
|
+
* // app/dashboard/page.tsx
|
|
300
|
+
* export const auth = { required: true };
|
|
301
|
+
*
|
|
302
|
+
* export default function Dashboard() {
|
|
303
|
+
* return <div>Protected content</div>;
|
|
304
|
+
* }
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
307
|
+
interface PageAuthConfig {
|
|
308
|
+
/**
|
|
309
|
+
* Whether authentication is required for this page
|
|
310
|
+
* @default false
|
|
311
|
+
*/
|
|
312
|
+
required?: boolean;
|
|
313
|
+
/**
|
|
314
|
+
* Required roles for access (checks account.idTokenClaims.roles)
|
|
315
|
+
* User must have at least one of these roles
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* ```tsx
|
|
319
|
+
* export const auth = {
|
|
320
|
+
* required: true,
|
|
321
|
+
* roles: ['admin', 'editor']
|
|
322
|
+
* };
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
roles?: string[];
|
|
326
|
+
/**
|
|
327
|
+
* Custom redirect path when auth fails
|
|
328
|
+
* @default '/login'
|
|
329
|
+
*/
|
|
330
|
+
redirectTo?: string;
|
|
331
|
+
/**
|
|
332
|
+
* Custom loading component while checking auth
|
|
333
|
+
*/
|
|
334
|
+
loading?: ReactNode;
|
|
335
|
+
/**
|
|
336
|
+
* Custom unauthorized component (shown instead of redirect)
|
|
337
|
+
*/
|
|
338
|
+
unauthorized?: ReactNode;
|
|
339
|
+
/**
|
|
340
|
+
* Custom validation function
|
|
341
|
+
* Return true to allow access, false to deny
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```tsx
|
|
345
|
+
* export const auth = {
|
|
346
|
+
* required: true,
|
|
347
|
+
* validate: (account) => account.username.endsWith('@company.com')
|
|
348
|
+
* };
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
validate?: (account: any) => boolean | Promise<boolean>;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Global auth configuration for the provider
|
|
355
|
+
*/
|
|
356
|
+
interface AuthProtectionConfig {
|
|
357
|
+
/**
|
|
358
|
+
* Default redirect path for unauthenticated users
|
|
359
|
+
* @default '/login'
|
|
360
|
+
*/
|
|
361
|
+
defaultRedirectTo?: string;
|
|
362
|
+
/**
|
|
363
|
+
* Default loading component
|
|
364
|
+
*/
|
|
365
|
+
defaultLoading?: ReactNode;
|
|
366
|
+
/**
|
|
367
|
+
* Default unauthorized component
|
|
368
|
+
*/
|
|
369
|
+
defaultUnauthorized?: ReactNode;
|
|
370
|
+
/**
|
|
371
|
+
* Enable debug logging
|
|
372
|
+
* @default false
|
|
373
|
+
*/
|
|
374
|
+
debug?: boolean;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
interface MSALProviderProps extends MsalAuthProviderProps {
|
|
378
|
+
/**
|
|
379
|
+
* Zero-Config Protected Routes configuration (v4.0.0)
|
|
380
|
+
* @example
|
|
381
|
+
* ```tsx
|
|
382
|
+
* <MSALProvider
|
|
383
|
+
* clientId="..."
|
|
384
|
+
* protection={{
|
|
385
|
+
* defaultRedirectTo: '/login',
|
|
386
|
+
* defaultLoading: <Spinner />,
|
|
387
|
+
* debug: true
|
|
388
|
+
* }}
|
|
389
|
+
* >
|
|
390
|
+
* ```
|
|
391
|
+
*/
|
|
392
|
+
protection?: AuthProtectionConfig;
|
|
393
|
+
}
|
|
288
394
|
/**
|
|
289
395
|
* Pre-configured MSALProvider component for Next.js App Router layouts.
|
|
290
396
|
* This component is already marked as 'use client', so you can use it directly
|
|
@@ -311,7 +417,7 @@ declare function MsalAuthProvider({ children, loadingComponent, onInitialized, .
|
|
|
311
417
|
* }
|
|
312
418
|
* ```
|
|
313
419
|
*/
|
|
314
|
-
declare function MSALProvider({ children, ...props }:
|
|
420
|
+
declare function MSALProvider({ children, protection, ...props }: MSALProviderProps): react_jsx_runtime.JSX.Element;
|
|
315
421
|
|
|
316
422
|
interface MicrosoftSignInButtonProps {
|
|
317
423
|
/**
|
|
@@ -1008,6 +1114,39 @@ declare function isValidScope(scope: string): boolean;
|
|
|
1008
1114
|
*/
|
|
1009
1115
|
declare function validateScopes(scopes: string[]): boolean;
|
|
1010
1116
|
|
|
1117
|
+
interface ProtectedPageProps {
|
|
1118
|
+
children: ReactNode;
|
|
1119
|
+
config: PageAuthConfig;
|
|
1120
|
+
defaultRedirectTo?: string;
|
|
1121
|
+
defaultLoading?: ReactNode;
|
|
1122
|
+
defaultUnauthorized?: ReactNode;
|
|
1123
|
+
debug?: boolean;
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Internal component that wraps pages with auth protection
|
|
1127
|
+
* This is automatically used when you export `auth` from your page
|
|
1128
|
+
*/
|
|
1129
|
+
declare function ProtectedPage({ children, config, defaultRedirectTo, defaultLoading, defaultUnauthorized, debug }: ProtectedPageProps): react_jsx_runtime.JSX.Element;
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Higher-order component that adds auth protection to a page
|
|
1133
|
+
*
|
|
1134
|
+
* @example
|
|
1135
|
+
* ```tsx
|
|
1136
|
+
* // Automatic usage (recommended):
|
|
1137
|
+
* export const auth = { required: true };
|
|
1138
|
+
* export default function Dashboard() { ... }
|
|
1139
|
+
*
|
|
1140
|
+
* // Manual usage:
|
|
1141
|
+
* const ProtectedDashboard = withPageAuth(Dashboard, { required: true });
|
|
1142
|
+
* export default ProtectedDashboard;
|
|
1143
|
+
* ```
|
|
1144
|
+
*/
|
|
1145
|
+
declare function withPageAuth<P extends object>(Component: ComponentType<P>, authConfig: PageAuthConfig, globalConfig?: AuthProtectionConfig): {
|
|
1146
|
+
(props: P): react_jsx_runtime.JSX.Element;
|
|
1147
|
+
displayName: string;
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1011
1150
|
interface AuthMiddlewareConfig {
|
|
1012
1151
|
/**
|
|
1013
1152
|
* Routes that require authentication
|
|
@@ -1085,4 +1224,4 @@ interface ServerSession {
|
|
|
1085
1224
|
accessToken?: string;
|
|
1086
1225
|
}
|
|
1087
1226
|
|
|
1088
|
-
export { AuthGuard, type AuthGuardProps, type AuthMiddlewareConfig, AuthStatus, type AuthStatusProps, type CustomTokenClaims, type DebugLoggerConfig, ErrorBoundary, type ErrorBoundaryProps, type GraphApiOptions, MSALProvider, MicrosoftSignInButton, type MicrosoftSignInButtonProps, type MsalAuthConfig, MsalAuthProvider, type MsalAuthProviderProps, type RetryConfig, type ServerSession, SignOutButton, type SignOutButtonProps, type UseGraphApiReturn, type UseMsalAuthReturn, type UseRolesReturn, type UseUserProfileReturn, UserAvatar, type UserAvatarProps, type UserProfile, type ValidatedAccountData, type WithAuthOptions, createAuthMiddleware, createMsalConfig, createRetryWrapper, createScopedLogger, getDebugLogger, getMsalInstance, isValidAccountData, isValidRedirectUri, isValidScope, retryWithBackoff, safeJsonParse, sanitizeError, useGraphApi, useMsalAuth, useRoles, useUserProfile, validateScopes, withAuth };
|
|
1227
|
+
export { AuthGuard, type AuthGuardProps, type AuthMiddlewareConfig, type AuthProtectionConfig, AuthStatus, type AuthStatusProps, type CustomTokenClaims, type DebugLoggerConfig, ErrorBoundary, type ErrorBoundaryProps, type GraphApiOptions, MSALProvider, MicrosoftSignInButton, type MicrosoftSignInButtonProps, type MsalAuthConfig, MsalAuthProvider, type MsalAuthProviderProps, type PageAuthConfig, ProtectedPage, type RetryConfig, type ServerSession, SignOutButton, type SignOutButtonProps, type UseGraphApiReturn, type UseMsalAuthReturn, type UseRolesReturn, type UseUserProfileReturn, UserAvatar, type UserAvatarProps, type UserProfile, type ValidatedAccountData, type WithAuthOptions, createAuthMiddleware, createMsalConfig, createRetryWrapper, createScopedLogger, getDebugLogger, getMsalInstance, isValidAccountData, isValidRedirectUri, isValidScope, retryWithBackoff, safeJsonParse, sanitizeError, useGraphApi, useMsalAuth, useRoles, useUserProfile, validateScopes, withAuth, withPageAuth };
|
package/dist/index.d.ts
CHANGED
|
@@ -285,6 +285,112 @@ interface MsalAuthProviderProps extends MsalAuthConfig {
|
|
|
285
285
|
declare function getMsalInstance(): PublicClientApplication | null;
|
|
286
286
|
declare function MsalAuthProvider({ children, loadingComponent, onInitialized, ...config }: MsalAuthProviderProps): react_jsx_runtime.JSX.Element;
|
|
287
287
|
|
|
288
|
+
/**
|
|
289
|
+
* Zero-Config Protected Routes - Type Definitions
|
|
290
|
+
* v4.0.0 Killer Feature
|
|
291
|
+
*/
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Page-level auth configuration
|
|
295
|
+
* Export this from your page to enable protection
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```tsx
|
|
299
|
+
* // app/dashboard/page.tsx
|
|
300
|
+
* export const auth = { required: true };
|
|
301
|
+
*
|
|
302
|
+
* export default function Dashboard() {
|
|
303
|
+
* return <div>Protected content</div>;
|
|
304
|
+
* }
|
|
305
|
+
* ```
|
|
306
|
+
*/
|
|
307
|
+
interface PageAuthConfig {
|
|
308
|
+
/**
|
|
309
|
+
* Whether authentication is required for this page
|
|
310
|
+
* @default false
|
|
311
|
+
*/
|
|
312
|
+
required?: boolean;
|
|
313
|
+
/**
|
|
314
|
+
* Required roles for access (checks account.idTokenClaims.roles)
|
|
315
|
+
* User must have at least one of these roles
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* ```tsx
|
|
319
|
+
* export const auth = {
|
|
320
|
+
* required: true,
|
|
321
|
+
* roles: ['admin', 'editor']
|
|
322
|
+
* };
|
|
323
|
+
* ```
|
|
324
|
+
*/
|
|
325
|
+
roles?: string[];
|
|
326
|
+
/**
|
|
327
|
+
* Custom redirect path when auth fails
|
|
328
|
+
* @default '/login'
|
|
329
|
+
*/
|
|
330
|
+
redirectTo?: string;
|
|
331
|
+
/**
|
|
332
|
+
* Custom loading component while checking auth
|
|
333
|
+
*/
|
|
334
|
+
loading?: ReactNode;
|
|
335
|
+
/**
|
|
336
|
+
* Custom unauthorized component (shown instead of redirect)
|
|
337
|
+
*/
|
|
338
|
+
unauthorized?: ReactNode;
|
|
339
|
+
/**
|
|
340
|
+
* Custom validation function
|
|
341
|
+
* Return true to allow access, false to deny
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```tsx
|
|
345
|
+
* export const auth = {
|
|
346
|
+
* required: true,
|
|
347
|
+
* validate: (account) => account.username.endsWith('@company.com')
|
|
348
|
+
* };
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
validate?: (account: any) => boolean | Promise<boolean>;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Global auth configuration for the provider
|
|
355
|
+
*/
|
|
356
|
+
interface AuthProtectionConfig {
|
|
357
|
+
/**
|
|
358
|
+
* Default redirect path for unauthenticated users
|
|
359
|
+
* @default '/login'
|
|
360
|
+
*/
|
|
361
|
+
defaultRedirectTo?: string;
|
|
362
|
+
/**
|
|
363
|
+
* Default loading component
|
|
364
|
+
*/
|
|
365
|
+
defaultLoading?: ReactNode;
|
|
366
|
+
/**
|
|
367
|
+
* Default unauthorized component
|
|
368
|
+
*/
|
|
369
|
+
defaultUnauthorized?: ReactNode;
|
|
370
|
+
/**
|
|
371
|
+
* Enable debug logging
|
|
372
|
+
* @default false
|
|
373
|
+
*/
|
|
374
|
+
debug?: boolean;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
interface MSALProviderProps extends MsalAuthProviderProps {
|
|
378
|
+
/**
|
|
379
|
+
* Zero-Config Protected Routes configuration (v4.0.0)
|
|
380
|
+
* @example
|
|
381
|
+
* ```tsx
|
|
382
|
+
* <MSALProvider
|
|
383
|
+
* clientId="..."
|
|
384
|
+
* protection={{
|
|
385
|
+
* defaultRedirectTo: '/login',
|
|
386
|
+
* defaultLoading: <Spinner />,
|
|
387
|
+
* debug: true
|
|
388
|
+
* }}
|
|
389
|
+
* >
|
|
390
|
+
* ```
|
|
391
|
+
*/
|
|
392
|
+
protection?: AuthProtectionConfig;
|
|
393
|
+
}
|
|
288
394
|
/**
|
|
289
395
|
* Pre-configured MSALProvider component for Next.js App Router layouts.
|
|
290
396
|
* This component is already marked as 'use client', so you can use it directly
|
|
@@ -311,7 +417,7 @@ declare function MsalAuthProvider({ children, loadingComponent, onInitialized, .
|
|
|
311
417
|
* }
|
|
312
418
|
* ```
|
|
313
419
|
*/
|
|
314
|
-
declare function MSALProvider({ children, ...props }:
|
|
420
|
+
declare function MSALProvider({ children, protection, ...props }: MSALProviderProps): react_jsx_runtime.JSX.Element;
|
|
315
421
|
|
|
316
422
|
interface MicrosoftSignInButtonProps {
|
|
317
423
|
/**
|
|
@@ -1008,6 +1114,39 @@ declare function isValidScope(scope: string): boolean;
|
|
|
1008
1114
|
*/
|
|
1009
1115
|
declare function validateScopes(scopes: string[]): boolean;
|
|
1010
1116
|
|
|
1117
|
+
interface ProtectedPageProps {
|
|
1118
|
+
children: ReactNode;
|
|
1119
|
+
config: PageAuthConfig;
|
|
1120
|
+
defaultRedirectTo?: string;
|
|
1121
|
+
defaultLoading?: ReactNode;
|
|
1122
|
+
defaultUnauthorized?: ReactNode;
|
|
1123
|
+
debug?: boolean;
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Internal component that wraps pages with auth protection
|
|
1127
|
+
* This is automatically used when you export `auth` from your page
|
|
1128
|
+
*/
|
|
1129
|
+
declare function ProtectedPage({ children, config, defaultRedirectTo, defaultLoading, defaultUnauthorized, debug }: ProtectedPageProps): react_jsx_runtime.JSX.Element;
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Higher-order component that adds auth protection to a page
|
|
1133
|
+
*
|
|
1134
|
+
* @example
|
|
1135
|
+
* ```tsx
|
|
1136
|
+
* // Automatic usage (recommended):
|
|
1137
|
+
* export const auth = { required: true };
|
|
1138
|
+
* export default function Dashboard() { ... }
|
|
1139
|
+
*
|
|
1140
|
+
* // Manual usage:
|
|
1141
|
+
* const ProtectedDashboard = withPageAuth(Dashboard, { required: true });
|
|
1142
|
+
* export default ProtectedDashboard;
|
|
1143
|
+
* ```
|
|
1144
|
+
*/
|
|
1145
|
+
declare function withPageAuth<P extends object>(Component: ComponentType<P>, authConfig: PageAuthConfig, globalConfig?: AuthProtectionConfig): {
|
|
1146
|
+
(props: P): react_jsx_runtime.JSX.Element;
|
|
1147
|
+
displayName: string;
|
|
1148
|
+
};
|
|
1149
|
+
|
|
1011
1150
|
interface AuthMiddlewareConfig {
|
|
1012
1151
|
/**
|
|
1013
1152
|
* Routes that require authentication
|
|
@@ -1085,4 +1224,4 @@ interface ServerSession {
|
|
|
1085
1224
|
accessToken?: string;
|
|
1086
1225
|
}
|
|
1087
1226
|
|
|
1088
|
-
export { AuthGuard, type AuthGuardProps, type AuthMiddlewareConfig, AuthStatus, type AuthStatusProps, type CustomTokenClaims, type DebugLoggerConfig, ErrorBoundary, type ErrorBoundaryProps, type GraphApiOptions, MSALProvider, MicrosoftSignInButton, type MicrosoftSignInButtonProps, type MsalAuthConfig, MsalAuthProvider, type MsalAuthProviderProps, type RetryConfig, type ServerSession, SignOutButton, type SignOutButtonProps, type UseGraphApiReturn, type UseMsalAuthReturn, type UseRolesReturn, type UseUserProfileReturn, UserAvatar, type UserAvatarProps, type UserProfile, type ValidatedAccountData, type WithAuthOptions, createAuthMiddleware, createMsalConfig, createRetryWrapper, createScopedLogger, getDebugLogger, getMsalInstance, isValidAccountData, isValidRedirectUri, isValidScope, retryWithBackoff, safeJsonParse, sanitizeError, useGraphApi, useMsalAuth, useRoles, useUserProfile, validateScopes, withAuth };
|
|
1227
|
+
export { AuthGuard, type AuthGuardProps, type AuthMiddlewareConfig, type AuthProtectionConfig, AuthStatus, type AuthStatusProps, type CustomTokenClaims, type DebugLoggerConfig, ErrorBoundary, type ErrorBoundaryProps, type GraphApiOptions, MSALProvider, MicrosoftSignInButton, type MicrosoftSignInButtonProps, type MsalAuthConfig, MsalAuthProvider, type MsalAuthProviderProps, type PageAuthConfig, ProtectedPage, type RetryConfig, type ServerSession, SignOutButton, type SignOutButtonProps, type UseGraphApiReturn, type UseMsalAuthReturn, type UseRolesReturn, type UseUserProfileReturn, UserAvatar, type UserAvatarProps, type UserProfile, type ValidatedAccountData, type WithAuthOptions, createAuthMiddleware, createMsalConfig, createRetryWrapper, createScopedLogger, getDebugLogger, getMsalInstance, isValidAccountData, isValidRedirectUri, isValidScope, retryWithBackoff, safeJsonParse, sanitizeError, useGraphApi, useMsalAuth, useRoles, useUserProfile, validateScopes, withAuth, withPageAuth };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var msalReact=require('@azure/msal-react'),msalBrowser=require('@azure/msal-browser'),react=require('react'),jsxRuntime=require('react/jsx-runtime'),server=require('next/server');function q(r,e){try{let t=JSON.parse(r);return e(t)?t:(console.warn("[Validation] JSON validation failed"),null)}catch(t){return console.error("[Validation] JSON parse error:",t),null}}function _(r){return typeof r=="object"&&r!==null&&typeof r.homeAccountId=="string"&&r.homeAccountId.length>0&&typeof r.username=="string"&&r.username.length>0&&(r.name===void 0||typeof r.name=="string")}function v(r){return r instanceof Error?r.message.replace(/[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g,"[TOKEN_REDACTED]").replace(/[a-f0-9]{32,}/gi,"[SECRET_REDACTED]").replace(/Bearer\s+[^\s]+/gi,"Bearer [REDACTED]"):"An unexpected error occurred"}function G(r,e){try{let t=new URL(r);return e.some(o=>{let i=new URL(o);return t.origin===i.origin})}catch{return false}}function ne(r){return /^[a-zA-Z0-9._-]+$/.test(r)}function Ae(r){return Array.isArray(r)&&r.every(ne)}function H(r){if(r.msalConfig)return r.msalConfig;let{clientId:e,tenantId:t,authorityType:o="common",redirectUri:i,postLogoutRedirectUri:a,cacheLocation:p="sessionStorage",storeAuthStateInCookie:u=false,navigateToLoginRequestUrl:c=false,enableLogging:n=false,loggerCallback:h,allowedRedirectUris:g}=r;if(!e)throw new Error("@chemmangat/msal-next: clientId is required");let l=()=>{if(o==="tenant"){if(!t)throw new Error('@chemmangat/msal-next: tenantId is required when authorityType is "tenant"');return `https://login.microsoftonline.com/${t}`}return `https://login.microsoftonline.com/${o}`},s=typeof window<"u"?window.location.origin:"http://localhost:3000",m=i||s;if(g&&g.length>0){if(!G(m,g))throw new Error(`@chemmangat/msal-next: redirectUri "${m}" is not in the allowed list`);let d=a||m;if(!G(d,g))throw new Error(`@chemmangat/msal-next: postLogoutRedirectUri "${d}" is not in the allowed list`)}return {auth:{clientId:e,authority:l(),redirectUri:m,postLogoutRedirectUri:a||m,navigateToLoginRequestUrl:c},cache:{cacheLocation:p,storeAuthStateInCookie:u},system:{loggerOptions:{loggerCallback:h||((d,y,R)=>{if(!(R||!n))switch(d){case msalBrowser.LogLevel.Error:console.error("[MSAL]",y);break;case msalBrowser.LogLevel.Warning:console.warn("[MSAL]",y);break;case msalBrowser.LogLevel.Info:console.info("[MSAL]",y);break;case msalBrowser.LogLevel.Verbose:console.debug("[MSAL]",y);break}}),logLevel:n?msalBrowser.LogLevel.Verbose:msalBrowser.LogLevel.Error}}}}var se=null;function Pe(){return se}function V({children:r,loadingComponent:e,onInitialized:t,...o}){let[i,a]=react.useState(null),p=react.useRef(null);return react.useEffect(()=>{if(typeof window>"u"||p.current)return;(async()=>{try{let c=H(o),n=new msalBrowser.PublicClientApplication(c);await n.initialize();try{let l=await n.handleRedirectPromise();l&&(o.enableLogging&&console.log("[MSAL] Redirect authentication successful"),l.account&&n.setActiveAccount(l.account),window.location.hash&&window.history.replaceState(null,"",window.location.pathname+window.location.search));}catch(l){l?.errorCode==="no_token_request_cache_error"?o.enableLogging&&console.log("[MSAL] No pending redirect found (this is normal)"):l?.errorCode==="user_cancelled"?o.enableLogging&&console.log("[MSAL] User cancelled authentication"):console.error("[MSAL] Redirect handling error:",l),window.location.hash&&(window.location.hash.includes("code=")||window.location.hash.includes("error="))&&window.history.replaceState(null,"",window.location.pathname+window.location.search);}let h=n.getAllAccounts();h.length>0&&!n.getActiveAccount()&&n.setActiveAccount(h[0]);let g=o.enableLogging||!1;n.addEventCallback(l=>{if(l.eventType===msalBrowser.EventType.LOGIN_SUCCESS){let s=l.payload;s?.account&&n.setActiveAccount(s.account),g&&console.log("[MSAL] Login successful:",s.account?.username);}if(l.eventType===msalBrowser.EventType.LOGIN_FAILURE&&console.error("[MSAL] Login failed:",l.error),l.eventType===msalBrowser.EventType.LOGOUT_SUCCESS&&(n.setActiveAccount(null),g&&console.log("[MSAL] Logout successful")),l.eventType===msalBrowser.EventType.ACQUIRE_TOKEN_SUCCESS){let s=l.payload;s?.account&&!n.getActiveAccount()&&n.setActiveAccount(s.account);}l.eventType===msalBrowser.EventType.ACQUIRE_TOKEN_FAILURE&&g&&console.error("[MSAL] Token acquisition failed:",l.error);}),p.current=n,se=n,a(n),t&&t(n);}catch(c){throw console.error("[MSAL] Initialization failed:",c),c}})();},[]),typeof window>"u"?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Loading authentication..."})}):i?jsxRuntime.jsx(msalReact.MsalProvider,{instance:i,children:r}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Loading authentication..."})})}function Se({children:r,...e}){return jsxRuntime.jsx(V,{...e,children:r})}var W=new Map;function A(r=["User.Read"]){let{instance:e,accounts:t,inProgress:o}=msalReact.useMsal(),i=msalReact.useAccount(t[0]||null),a=react.useMemo(()=>t.length>0,[t]),p=react.useCallback(async(l=r)=>{if(o!==msalBrowser.InteractionStatus.None){console.warn("[MSAL] Interaction already in progress");return}try{let s={scopes:l,prompt:"select_account"};await e.loginRedirect(s);}catch(s){if(s?.errorCode==="user_cancelled"){console.log("[MSAL] User cancelled login");return}throw console.error("[MSAL] Login redirect failed:",s),s}},[e,r,o]),u=react.useCallback(async()=>{try{await e.logoutRedirect({account:i||void 0});}catch(l){throw console.error("[MSAL] Logout redirect failed:",l),l}},[e,i]),c=react.useCallback(async(l=r)=>{if(!i)throw new Error("[MSAL] No active account. Please login first.");try{let s={scopes:l,account:i,forceRefresh:!1};return (await e.acquireTokenSilent(s)).accessToken}catch(s){throw console.error("[MSAL] Silent token acquisition failed:",s),s}},[e,i,r]),n=react.useCallback(async(l=r)=>{if(!i)throw new Error("[MSAL] No active account. Please login first.");try{let s={scopes:l,account:i};await e.acquireTokenRedirect(s);}catch(s){throw console.error("[MSAL] Token redirect acquisition failed:",s),s}},[e,i,r]),h=react.useCallback(async(l=r)=>{let s=`${i?.homeAccountId||"anonymous"}-${l.sort().join(",")}`,m=W.get(s);if(m)return m;let f=(async()=>{try{return await c(l)}catch{throw console.warn("[MSAL] Silent token acquisition failed, falling back to redirect"),await n(l),new Error("[MSAL] Redirecting for token acquisition")}finally{W.delete(s);}})();return W.set(s,f),f},[c,n,r,i]),g=react.useCallback(async()=>{e.setActiveAccount(null),await e.clearCache();},[e]);return {account:i,accounts:t,isAuthenticated:a,inProgress:o!==msalBrowser.InteractionStatus.None,loginRedirect:p,logoutRedirect:u,acquireToken:h,acquireTokenSilent:c,acquireTokenRedirect:n,clearSession:g}}function Ue({text:r="Sign in with Microsoft",variant:e="dark",size:t="medium",scopes:o,className:i="",style:a,onSuccess:p,onError:u}){let{loginRedirect:c,inProgress:n}=A(),[h,g]=react.useState(false),l=async()=>{g(true);try{await c(o),p?.();}catch(y){u?.(y);}finally{setTimeout(()=>g(false),500);}},s={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},m={dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}},f=n||h,d={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:f?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:f?.6:1,...m[e],...s[t],...a};return jsxRuntime.jsxs("button",{onClick:l,disabled:f,className:i,style:d,"aria-label":r,children:[jsxRuntime.jsx(ke,{}),jsxRuntime.jsx("span",{children:r})]})}function ke(){return jsxRuntime.jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsxRuntime.jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsxRuntime.jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsxRuntime.jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function Fe({text:r="Sign out",variant:e="dark",size:t="medium",className:o="",style:i,onSuccess:a,onError:p}){let{logoutRedirect:u,inProgress:c}=A(),n=async()=>{try{await u(),a?.();}catch(s){p?.(s);}},h={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},l={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:c?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:c?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...h[t],...i};return jsxRuntime.jsxs("button",{onClick:n,disabled:c,className:o,style:l,"aria-label":r,children:[jsxRuntime.jsx(Ne,{}),jsxRuntime.jsx("span",{children:r})]})}function Ne(){return jsxRuntime.jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsxRuntime.jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsxRuntime.jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsxRuntime.jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function k(){let{acquireToken:r}=A(),e=react.useCallback(async(u,c={})=>{let{scopes:n=["User.Read"],version:h="v1.0",debug:g=false,...l}=c;try{let s=await r(n),m=`https://graph.microsoft.com/${h}`,f=u.startsWith("http")?u:`${m}${u.startsWith("/")?u:`/${u}`}`;g&&console.log("[GraphAPI] Request:",{url:f,method:l.method||"GET"});let d=await fetch(f,{...l,headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json",...l.headers}});if(!d.ok){let R=await d.text(),L=`Graph API error (${d.status}): ${R}`;throw new Error(L)}if(d.status===204||d.headers.get("content-length")==="0")return null;let y=await d.json();return g&&console.log("[GraphAPI] Response:",y),y}catch(s){let m=v(s);throw console.error("[GraphAPI] Request failed:",m),new Error(m)}},[r]),t=react.useCallback((u,c={})=>e(u,{...c,method:"GET"}),[e]),o=react.useCallback((u,c,n={})=>e(u,{...n,method:"POST",body:c?JSON.stringify(c):void 0}),[e]),i=react.useCallback((u,c,n={})=>e(u,{...n,method:"PUT",body:c?JSON.stringify(c):void 0}),[e]),a=react.useCallback((u,c,n={})=>e(u,{...n,method:"PATCH",body:c?JSON.stringify(c):void 0}),[e]),p=react.useCallback((u,c={})=>e(u,{...c,method:"DELETE"}),[e]);return {get:t,post:o,put:i,patch:a,delete:p,request:e}}var x=new Map,Ie=300*1e3,pe=100;function Oe(){if(x.size>pe){let r=Array.from(x.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,x.size-pe).forEach(([t])=>{let o=x.get(t);o?.data.photo&&URL.revokeObjectURL(o.data.photo),x.delete(t);});}}function J(){let{isAuthenticated:r,account:e}=A(),t=k(),[o,i]=react.useState(null),[a,p]=react.useState(false),[u,c]=react.useState(null),n=react.useCallback(async()=>{if(!r||!e){i(null);return}let g=e.homeAccountId,l=x.get(g);if(l&&Date.now()-l.timestamp<Ie){i(l.data);return}p(true),c(null);try{let s=await t.get("/me",{scopes:["User.Read"]}),m;try{let d=await t.get("/me/photo/$value",{scopes:["User.Read"],headers:{"Content-Type":"image/jpeg"}});d&&(m=URL.createObjectURL(d));}catch{console.debug("[UserProfile] Photo not available");}let f={id:s.id,displayName:s.displayName,givenName:s.givenName,surname:s.surname,userPrincipalName:s.userPrincipalName,mail:s.mail,jobTitle:s.jobTitle,officeLocation:s.officeLocation,mobilePhone:s.mobilePhone,businessPhones:s.businessPhones,photo:m};x.set(g,{data:f,timestamp:Date.now()}),Oe(),i(f);}catch(s){let f=v(s),d=new Error(f);c(d),console.error("[UserProfile] Failed to fetch profile:",f);}finally{p(false);}},[r,e,t]),h=react.useCallback(()=>{if(e){let g=x.get(e.homeAccountId);g?.data.photo&&URL.revokeObjectURL(g.data.photo),x.delete(e.homeAccountId);}o?.photo&&URL.revokeObjectURL(o.photo),i(null);},[e,o]);return react.useEffect(()=>(n(),()=>{o?.photo&&URL.revokeObjectURL(o.photo);}),[n]),react.useEffect(()=>()=>{o?.photo&&URL.revokeObjectURL(o.photo);},[o?.photo]),{profile:o,loading:a,error:u,refetch:n,clearCache:h}}function Ge({size:r=40,className:e="",style:t,showTooltip:o=true,fallbackImage:i}){let{profile:a,loading:p}=J(),[u,c]=react.useState(null),[n,h]=react.useState(false);react.useEffect(()=>{a?.photo&&c(a.photo);},[a?.photo]);let g=()=>{if(!a)return "?";let{givenName:m,surname:f,displayName:d}=a;if(m&&f)return `${m[0]}${f[0]}`.toUpperCase();if(d){let y=d.split(" ");return y.length>=2?`${y[0][0]}${y[y.length-1][0]}`.toUpperCase():d.substring(0,2).toUpperCase()}return "?"},l={width:`${r}px`,height:`${r}px`,borderRadius:"50%",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:`${r*.4}px`,fontWeight:600,fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',backgroundColor:"#0078D4",color:"#FFFFFF",overflow:"hidden",userSelect:"none",...t},s=a?.displayName||"User";return p?jsxRuntime.jsx("div",{className:e,style:{...l,backgroundColor:"#E1E1E1"},"aria-label":"Loading user avatar",children:jsxRuntime.jsx("span",{style:{fontSize:`${r*.3}px`},children:"..."})}):u&&!n?jsxRuntime.jsx("div",{className:e,style:l,title:o?s:void 0,"aria-label":`${s} avatar`,children:jsxRuntime.jsx("img",{src:u,alt:s,style:{width:"100%",height:"100%",objectFit:"cover"},onError:()=>{h(true),i&&c(i);}})}):jsxRuntime.jsx("div",{className:e,style:l,title:o?s:void 0,"aria-label":`${s} avatar`,children:g()})}function $e({className:r="",style:e,showDetails:t=false,renderLoading:o,renderAuthenticated:i,renderUnauthenticated:a}){let{isAuthenticated:p,inProgress:u,account:c}=A(),n={display:"inline-flex",alignItems:"center",gap:"8px",padding:"8px 12px",borderRadius:"4px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontSize:"14px",fontWeight:500,...e};if(u)return o?jsxRuntime.jsx(jsxRuntime.Fragment,{children:o()}):jsxRuntime.jsxs("div",{className:r,style:{...n,backgroundColor:"#FFF4CE",color:"#8A6D3B"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(K,{color:"#FFA500"}),jsxRuntime.jsx("span",{children:"Loading..."})]});if(p){let h=c?.username||c?.name||"User";return i?jsxRuntime.jsx(jsxRuntime.Fragment,{children:i(h)}):jsxRuntime.jsxs("div",{className:r,style:{...n,backgroundColor:"#D4EDDA",color:"#155724"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(K,{color:"#28A745"}),jsxRuntime.jsx("span",{children:t?`Authenticated as ${h}`:"Authenticated"})]})}return a?jsxRuntime.jsx(jsxRuntime.Fragment,{children:a()}):jsxRuntime.jsxs("div",{className:r,style:{...n,backgroundColor:"#F8D7DA",color:"#721C24"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(K,{color:"#DC3545"}),jsxRuntime.jsx("span",{children:"Not authenticated"})]})}function K({color:r}){return jsxRuntime.jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsxRuntime.jsx("circle",{cx:"4",cy:"4",r:"4",fill:r})})}function Y({children:r,loadingComponent:e,fallbackComponent:t,scopes:o,onAuthRequired:i}){let{isAuthenticated:a,inProgress:p,loginRedirect:u}=A();return react.useEffect(()=>{!a&&!p&&(i?.(),(async()=>{try{await u(o);}catch(n){console.error("[AuthGuard] Authentication failed:",n);}})());},[a,p,o,u,i]),p?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Authenticating..."})}):a?jsxRuntime.jsx(jsxRuntime.Fragment,{children:r}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:t||jsxRuntime.jsx("div",{children:"Redirecting to login..."})})}var re=class extends react.Component{constructor(t){super(t);this.reset=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(t){return {hasError:true,error:t}}componentDidCatch(t,o){let{onError:i,debug:a}=this.props;a&&(console.error("[ErrorBoundary] Caught error:",t),console.error("[ErrorBoundary] Error info:",o)),i?.(t,o);}render(){let{hasError:t,error:o}=this.state,{children:i,fallback:a}=this.props;return t&&o?a?a(o,this.reset):jsxRuntime.jsxs("div",{style:{padding:"20px",margin:"20px",border:"1px solid #DC3545",borderRadius:"4px",backgroundColor:"#F8D7DA",color:"#721C24",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif'},children:[jsxRuntime.jsx("h2",{style:{margin:"0 0 10px 0",fontSize:"18px"},children:"Authentication Error"}),jsxRuntime.jsx("p",{style:{margin:"0 0 10px 0"},children:o.message}),jsxRuntime.jsx("button",{onClick:this.reset,style:{padding:"8px 16px",backgroundColor:"#DC3545",color:"#FFFFFF",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:600},children:"Try Again"})]}):i}};var w=new Map,He=300*1e3,fe=100;function Ve(r){r?w.delete(r):w.clear();}function We(){if(w.size>fe){let r=Array.from(w.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,w.size-fe).forEach(([t])=>w.delete(t));}}function je(){let{isAuthenticated:r,account:e}=A(),t=k(),[o,i]=react.useState([]),[a,p]=react.useState([]),[u,c]=react.useState(false),[n,h]=react.useState(null),g=react.useCallback(async()=>{if(!r||!e){i([]),p([]);return}let d=e.homeAccountId,y=w.get(d);if(y&&Date.now()-y.timestamp<He){i(y.roles),p(y.groups);return}c(true),h(null);try{let L=e.idTokenClaims?.roles||[],D=(await t.get("/me/memberOf",{scopes:["User.Read","Directory.Read.All"]})).value.map(oe=>oe.id);w.set(d,{roles:L,groups:D,timestamp:Date.now()}),We(),i(L),p(D);}catch(R){let B=v(R),D=new Error(B);h(D),console.error("[Roles] Failed to fetch roles/groups:",B);let ye=e.idTokenClaims?.roles||[];i(ye);}finally{c(false);}},[r,e,t]),l=react.useCallback(d=>o.includes(d),[o]),s=react.useCallback(d=>a.includes(d),[a]),m=react.useCallback(d=>d.some(y=>o.includes(y)),[o]),f=react.useCallback(d=>d.every(y=>o.includes(y)),[o]);return react.useEffect(()=>(g(),()=>{e&&Ve(e.homeAccountId);}),[g,e]),{roles:o,groups:a,loading:u,error:n,hasRole:l,hasGroup:s,hasAnyRole:m,hasAllRoles:f,refetch:g}}function Je(r,e={}){let{displayName:t,...o}=e,i=a=>jsxRuntime.jsx(Y,{...o,children:jsxRuntime.jsx(r,{...a})});return i.displayName=t||`withAuth(${r.displayName||r.name||"Component"})`,i}async function me(r,e={}){let{maxRetries:t=3,initialDelay:o=1e3,maxDelay:i=1e4,backoffMultiplier:a=2,debug:p=false}=e,u,c=o;for(let n=0;n<=t;n++)try{return p&&n>0&&console.log(`[TokenRetry] Attempt ${n+1}/${t+1}`),await r()}catch(h){if(u=h,n===t){p&&console.error("[TokenRetry] All retry attempts failed");break}if(!Ke(h))throw p&&console.log("[TokenRetry] Non-retryable error, aborting"),h;p&&console.warn(`[TokenRetry] Attempt ${n+1} failed, retrying in ${c}ms...`),await Ze(c),c=Math.min(c*a,i);}throw u}function Ke(r){let e=r.message.toLowerCase();return !!(e.includes("network")||e.includes("timeout")||e.includes("fetch")||e.includes("connection")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("429")||e.includes("rate limit")||e.includes("token")&&e.includes("expired"))}function Ze(r){return new Promise(e=>setTimeout(e,r))}function Qe(r,e={}){return (...t)=>me(()=>r(...t),e)}var z=class{constructor(e={}){this.logHistory=[];this.performanceTimings=new Map;this.config={enabled:e.enabled??false,prefix:e.prefix??"[MSAL-Next]",showTimestamp:e.showTimestamp??true,level:e.level??"info",enablePerformance:e.enablePerformance??false,enableNetworkLogs:e.enableNetworkLogs??false,maxHistorySize:e.maxHistorySize??100};}shouldLog(e){if(!this.config.enabled)return false;let t=["error","warn","info","debug"],o=t.indexOf(this.config.level);return t.indexOf(e)<=o}formatMessage(e,t,o){let i=this.config.showTimestamp?`[${new Date().toISOString()}]`:"",a=this.config.prefix,p=`[${e.toUpperCase()}]`,u=`${i} ${a} ${p} ${t}`;return o!==void 0&&(u+=`
|
|
2
|
-
`+JSON.stringify(o,null,2)),u}addToHistory(e,t,o){this.logHistory.length>=this.config.maxHistorySize&&this.logHistory.shift(),this.logHistory.push({timestamp:Date.now(),level:e,message:t,data:o});}error(e,t){this.shouldLog("error")&&(console.error(this.formatMessage("error",e,t)),this.addToHistory("error",e,t));}warn(e,t){this.shouldLog("warn")&&(console.warn(this.formatMessage("warn",e,t)),this.addToHistory("warn",e,t));}info(e,t){this.shouldLog("info")&&(console.info(this.formatMessage("info",e,t)),this.addToHistory("info",e,t));}debug(e,t){this.shouldLog("debug")&&(console.debug(this.formatMessage("debug",e,t)),this.addToHistory("debug",e,t));}group(e){this.config.enabled&&console.group(`${this.config.prefix} ${e}`);}groupEnd(){this.config.enabled&&console.groupEnd();}startTiming(e){this.config.enablePerformance&&(this.performanceTimings.set(e,{operation:e,startTime:performance.now()}),this.debug(`\u23F1\uFE0F Started: ${e}`));}endTiming(e){if(this.config.enablePerformance){let t=this.performanceTimings.get(e);if(t)return t.endTime=performance.now(),t.duration=t.endTime-t.startTime,this.info(`\u23F1\uFE0F Completed: ${e} (${t.duration.toFixed(2)}ms)`),t.duration}}logRequest(e,t,o){this.config.enableNetworkLogs&&this.debug(`\u{1F310} ${e} ${t}`,o);}logResponse(e,t,o,i){if(this.config.enableNetworkLogs){let a=o>=200&&o<300?"\u2705":"\u274C";this.debug(`${a} ${e} ${t} - ${o}`,i);}}getHistory(){return [...this.logHistory]}getPerformanceTimings(){return Array.from(this.performanceTimings.values())}clearHistory(){this.logHistory=[];}clearTimings(){this.performanceTimings.clear();}exportLogs(){return JSON.stringify({config:this.config,history:this.logHistory,performanceTimings:Array.from(this.performanceTimings.values()),exportedAt:new Date().toISOString()},null,2)}downloadLogs(e="msal-next-debug-logs.json"){if(typeof window>"u")return;let t=this.exportLogs(),o=new Blob([t],{type:"application/json"}),i=URL.createObjectURL(o),a=document.createElement("a");a.href=i,a.download=e,a.click(),URL.revokeObjectURL(i);}setEnabled(e){this.config.enabled=e;}setLevel(e){e&&(this.config.level=e);}},O=null;function
|
|
1
|
+
'use strict';var msalReact=require('@azure/msal-react'),msalBrowser=require('@azure/msal-browser'),react=require('react'),jsxRuntime=require('react/jsx-runtime'),navigation=require('next/navigation'),server=require('next/server');function H(r,e){try{let t=JSON.parse(r);return e(t)?t:(console.warn("[Validation] JSON validation failed"),null)}catch(t){return console.error("[Validation] JSON parse error:",t),null}}function W(r){return typeof r=="object"&&r!==null&&typeof r.homeAccountId=="string"&&r.homeAccountId.length>0&&typeof r.username=="string"&&r.username.length>0&&(r.name===void 0||typeof r.name=="string")}function w(r){return r instanceof Error?r.message.replace(/[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g,"[TOKEN_REDACTED]").replace(/[a-f0-9]{32,}/gi,"[SECRET_REDACTED]").replace(/Bearer\s+[^\s]+/gi,"Bearer [REDACTED]"):"An unexpected error occurred"}function z(r,e){try{let t=new URL(r);return e.some(o=>{let i=new URL(o);return t.origin===i.origin})}catch{return false}}function ae(r){return /^[a-zA-Z0-9._-]+$/.test(r)}function Ce(r){return Array.isArray(r)&&r.every(ae)}function j(r){if(r.msalConfig)return r.msalConfig;let{clientId:e,tenantId:t,authorityType:o="common",redirectUri:i,postLogoutRedirectUri:a,cacheLocation:g="sessionStorage",storeAuthStateInCookie:u=false,navigateToLoginRequestUrl:l=false,enableLogging:n=false,loggerCallback:h,allowedRedirectUris:f}=r;if(!e)throw new Error("@chemmangat/msal-next: clientId is required");let c=()=>{if(o==="tenant"){if(!t)throw new Error('@chemmangat/msal-next: tenantId is required when authorityType is "tenant"');return `https://login.microsoftonline.com/${t}`}return `https://login.microsoftonline.com/${o}`},s=typeof window<"u"?window.location.origin:"http://localhost:3000",m=i||s;if(f&&f.length>0){if(!z(m,f))throw new Error(`@chemmangat/msal-next: redirectUri "${m}" is not in the allowed list`);let d=a||m;if(!z(d,f))throw new Error(`@chemmangat/msal-next: postLogoutRedirectUri "${d}" is not in the allowed list`)}return {auth:{clientId:e,authority:c(),redirectUri:m,postLogoutRedirectUri:a||m,navigateToLoginRequestUrl:l},cache:{cacheLocation:g,storeAuthStateInCookie:u},system:{loggerOptions:{loggerCallback:h||((d,y,R)=>{if(!(R||!n))switch(d){case msalBrowser.LogLevel.Error:console.error("[MSAL]",y);break;case msalBrowser.LogLevel.Warning:console.warn("[MSAL]",y);break;case msalBrowser.LogLevel.Info:console.info("[MSAL]",y);break;case msalBrowser.LogLevel.Verbose:console.debug("[MSAL]",y);break}}),logLevel:n?msalBrowser.LogLevel.Verbose:msalBrowser.LogLevel.Error}}}}var ce=null;function Ue(){return ce}function J({children:r,loadingComponent:e,onInitialized:t,...o}){let[i,a]=react.useState(null),g=react.useRef(null);return react.useEffect(()=>{if(typeof window>"u"||g.current)return;(async()=>{try{let l=j(o),n=new msalBrowser.PublicClientApplication(l);await n.initialize();try{let c=await n.handleRedirectPromise();c&&(o.enableLogging&&console.log("[MSAL] Redirect authentication successful"),c.account&&n.setActiveAccount(c.account),window.location.hash&&window.history.replaceState(null,"",window.location.pathname+window.location.search));}catch(c){c?.errorCode==="no_token_request_cache_error"?o.enableLogging&&console.log("[MSAL] No pending redirect found (this is normal)"):c?.errorCode==="user_cancelled"?o.enableLogging&&console.log("[MSAL] User cancelled authentication"):console.error("[MSAL] Redirect handling error:",c),window.location.hash&&(window.location.hash.includes("code=")||window.location.hash.includes("error="))&&window.history.replaceState(null,"",window.location.pathname+window.location.search);}let h=n.getAllAccounts();h.length>0&&!n.getActiveAccount()&&n.setActiveAccount(h[0]);let f=o.enableLogging||!1;n.addEventCallback(c=>{if(c.eventType===msalBrowser.EventType.LOGIN_SUCCESS){let s=c.payload;s?.account&&n.setActiveAccount(s.account),f&&console.log("[MSAL] Login successful:",s.account?.username);}if(c.eventType===msalBrowser.EventType.LOGIN_FAILURE&&console.error("[MSAL] Login failed:",c.error),c.eventType===msalBrowser.EventType.LOGOUT_SUCCESS&&(n.setActiveAccount(null),f&&console.log("[MSAL] Logout successful")),c.eventType===msalBrowser.EventType.ACQUIRE_TOKEN_SUCCESS){let s=c.payload;s?.account&&!n.getActiveAccount()&&n.setActiveAccount(s.account);}c.eventType===msalBrowser.EventType.ACQUIRE_TOKEN_FAILURE&&f&&console.error("[MSAL] Token acquisition failed:",c.error);}),g.current=n,ce=n,a(n),t&&t(n);}catch(l){throw console.error("[MSAL] Initialization failed:",l),l}})();},[]),typeof window>"u"?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Loading authentication..."})}):i?jsxRuntime.jsx(msalReact.MsalProvider,{instance:i,children:r}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Loading authentication..."})})}var Ne=react.createContext(void 0);function Fe({children:r,protection:e,...t}){return jsxRuntime.jsx(Ne.Provider,{value:e,children:jsxRuntime.jsx(J,{...t,children:r})})}var K=new Map;function A(r=["User.Read"]){let{instance:e,accounts:t,inProgress:o}=msalReact.useMsal(),i=msalReact.useAccount(t[0]||null),a=react.useMemo(()=>t.length>0,[t]),g=react.useCallback(async(c=r)=>{if(o!==msalBrowser.InteractionStatus.None){console.warn("[MSAL] Interaction already in progress");return}try{let s={scopes:c,prompt:"select_account"};await e.loginRedirect(s);}catch(s){if(s?.errorCode==="user_cancelled"){console.log("[MSAL] User cancelled login");return}throw console.error("[MSAL] Login redirect failed:",s),s}},[e,r,o]),u=react.useCallback(async()=>{try{await e.logoutRedirect({account:i||void 0});}catch(c){throw console.error("[MSAL] Logout redirect failed:",c),c}},[e,i]),l=react.useCallback(async(c=r)=>{if(!i)throw new Error("[MSAL] No active account. Please login first.");try{let s={scopes:c,account:i,forceRefresh:!1};return (await e.acquireTokenSilent(s)).accessToken}catch(s){throw console.error("[MSAL] Silent token acquisition failed:",s),s}},[e,i,r]),n=react.useCallback(async(c=r)=>{if(!i)throw new Error("[MSAL] No active account. Please login first.");try{let s={scopes:c,account:i};await e.acquireTokenRedirect(s);}catch(s){throw console.error("[MSAL] Token redirect acquisition failed:",s),s}},[e,i,r]),h=react.useCallback(async(c=r)=>{let s=`${i?.homeAccountId||"anonymous"}-${c.sort().join(",")}`,m=K.get(s);if(m)return m;let p=(async()=>{try{return await l(c)}catch{throw console.warn("[MSAL] Silent token acquisition failed, falling back to redirect"),await n(c),new Error("[MSAL] Redirecting for token acquisition")}finally{K.delete(s);}})();return K.set(s,p),p},[l,n,r,i]),f=react.useCallback(async()=>{e.setActiveAccount(null),await e.clearCache();},[e]);return {account:i,accounts:t,isAuthenticated:a,inProgress:o!==msalBrowser.InteractionStatus.None,loginRedirect:g,logoutRedirect:u,acquireToken:h,acquireTokenSilent:l,acquireTokenRedirect:n,clearSession:f}}function $e({text:r="Sign in with Microsoft",variant:e="dark",size:t="medium",scopes:o,className:i="",style:a,onSuccess:g,onError:u}){let{loginRedirect:l,inProgress:n}=A(),[h,f]=react.useState(false),c=async()=>{f(true);try{await l(o),g?.();}catch(y){u?.(y);}finally{setTimeout(()=>f(false),500);}},s={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},m={dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}},p=n||h,d={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:p?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:p?.6:1,...m[e],...s[t],...a};return jsxRuntime.jsxs("button",{onClick:c,disabled:p,className:i,style:d,"aria-label":r,children:[jsxRuntime.jsx(ze,{}),jsxRuntime.jsx("span",{children:r})]})}function ze(){return jsxRuntime.jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsxRuntime.jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsxRuntime.jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsxRuntime.jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function qe({text:r="Sign out",variant:e="dark",size:t="medium",className:o="",style:i,onSuccess:a,onError:g}){let{logoutRedirect:u,inProgress:l}=A(),n=async()=>{try{await u(),a?.();}catch(s){g?.(s);}},h={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},c={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:l?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:l?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...h[t],...i};return jsxRuntime.jsxs("button",{onClick:n,disabled:l,className:o,style:c,"aria-label":r,children:[jsxRuntime.jsx(Be,{}),jsxRuntime.jsx("span",{children:r})]})}function Be(){return jsxRuntime.jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsxRuntime.jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsxRuntime.jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsxRuntime.jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsxRuntime.jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function N(){let{acquireToken:r}=A(),e=react.useCallback(async(u,l={})=>{let{scopes:n=["User.Read"],version:h="v1.0",debug:f=false,...c}=l;try{let s=await r(n),m=`https://graph.microsoft.com/${h}`,p=u.startsWith("http")?u:`${m}${u.startsWith("/")?u:`/${u}`}`;f&&console.log("[GraphAPI] Request:",{url:p,method:c.method||"GET"});let d=await fetch(p,{...c,headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json",...c.headers}});if(!d.ok){let R=await d.text(),M=`Graph API error (${d.status}): ${R}`;throw new Error(M)}if(d.status===204||d.headers.get("content-length")==="0")return null;let y=await d.json();return f&&console.log("[GraphAPI] Response:",y),y}catch(s){let m=w(s);throw console.error("[GraphAPI] Request failed:",m),new Error(m)}},[r]),t=react.useCallback((u,l={})=>e(u,{...l,method:"GET"}),[e]),o=react.useCallback((u,l,n={})=>e(u,{...n,method:"POST",body:l?JSON.stringify(l):void 0}),[e]),i=react.useCallback((u,l,n={})=>e(u,{...n,method:"PUT",body:l?JSON.stringify(l):void 0}),[e]),a=react.useCallback((u,l,n={})=>e(u,{...n,method:"PATCH",body:l?JSON.stringify(l):void 0}),[e]),g=react.useCallback((u,l={})=>e(u,{...l,method:"DELETE"}),[e]);return {get:t,post:o,put:i,patch:a,delete:g,request:e}}var x=new Map,_e=300*1e3,me=100;function Ve(){if(x.size>me){let r=Array.from(x.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,x.size-me).forEach(([t])=>{let o=x.get(t);o?.data.photo&&URL.revokeObjectURL(o.data.photo),x.delete(t);});}}function Q(){let{isAuthenticated:r,account:e}=A(),t=N(),[o,i]=react.useState(null),[a,g]=react.useState(false),[u,l]=react.useState(null),n=react.useCallback(async()=>{if(!r||!e){i(null);return}let f=e.homeAccountId,c=x.get(f);if(c&&Date.now()-c.timestamp<_e){i(c.data);return}g(true),l(null);try{let s=await t.get("/me",{scopes:["User.Read"]}),m;try{let d=await t.get("/me/photo/$value",{scopes:["User.Read"],headers:{"Content-Type":"image/jpeg"}});d&&(m=URL.createObjectURL(d));}catch{console.debug("[UserProfile] Photo not available");}let p={id:s.id,displayName:s.displayName,givenName:s.givenName,surname:s.surname,userPrincipalName:s.userPrincipalName,mail:s.mail,jobTitle:s.jobTitle,officeLocation:s.officeLocation,mobilePhone:s.mobilePhone,businessPhones:s.businessPhones,photo:m};x.set(f,{data:p,timestamp:Date.now()}),Ve(),i(p);}catch(s){let p=w(s),d=new Error(p);l(d),console.error("[UserProfile] Failed to fetch profile:",p);}finally{g(false);}},[r,e,t]),h=react.useCallback(()=>{if(e){let f=x.get(e.homeAccountId);f?.data.photo&&URL.revokeObjectURL(f.data.photo),x.delete(e.homeAccountId);}o?.photo&&URL.revokeObjectURL(o.photo),i(null);},[e,o]);return react.useEffect(()=>(n(),()=>{o?.photo&&URL.revokeObjectURL(o.photo);}),[n]),react.useEffect(()=>()=>{o?.photo&&URL.revokeObjectURL(o.photo);},[o?.photo]),{profile:o,loading:a,error:u,refetch:n,clearCache:h}}function We({size:r=40,className:e="",style:t,showTooltip:o=true,fallbackImage:i}){let{profile:a,loading:g}=Q(),[u,l]=react.useState(null),[n,h]=react.useState(false);react.useEffect(()=>{a?.photo&&l(a.photo);},[a?.photo]);let f=()=>{if(!a)return "?";let{givenName:m,surname:p,displayName:d}=a;if(m&&p)return `${m[0]}${p[0]}`.toUpperCase();if(d){let y=d.split(" ");return y.length>=2?`${y[0][0]}${y[y.length-1][0]}`.toUpperCase():d.substring(0,2).toUpperCase()}return "?"},c={width:`${r}px`,height:`${r}px`,borderRadius:"50%",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:`${r*.4}px`,fontWeight:600,fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',backgroundColor:"#0078D4",color:"#FFFFFF",overflow:"hidden",userSelect:"none",...t},s=a?.displayName||"User";return g?jsxRuntime.jsx("div",{className:e,style:{...c,backgroundColor:"#E1E1E1"},"aria-label":"Loading user avatar",children:jsxRuntime.jsx("span",{style:{fontSize:`${r*.3}px`},children:"..."})}):u&&!n?jsxRuntime.jsx("div",{className:e,style:c,title:o?s:void 0,"aria-label":`${s} avatar`,children:jsxRuntime.jsx("img",{src:u,alt:s,style:{width:"100%",height:"100%",objectFit:"cover"},onError:()=>{h(true),i&&l(i);}})}):jsxRuntime.jsx("div",{className:e,style:c,title:o?s:void 0,"aria-label":`${s} avatar`,children:f()})}function je({className:r="",style:e,showDetails:t=false,renderLoading:o,renderAuthenticated:i,renderUnauthenticated:a}){let{isAuthenticated:g,inProgress:u,account:l}=A(),n={display:"inline-flex",alignItems:"center",gap:"8px",padding:"8px 12px",borderRadius:"4px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontSize:"14px",fontWeight:500,...e};if(u)return o?jsxRuntime.jsx(jsxRuntime.Fragment,{children:o()}):jsxRuntime.jsxs("div",{className:r,style:{...n,backgroundColor:"#FFF4CE",color:"#8A6D3B"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(X,{color:"#FFA500"}),jsxRuntime.jsx("span",{children:"Loading..."})]});if(g){let h=l?.username||l?.name||"User";return i?jsxRuntime.jsx(jsxRuntime.Fragment,{children:i(h)}):jsxRuntime.jsxs("div",{className:r,style:{...n,backgroundColor:"#D4EDDA",color:"#155724"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(X,{color:"#28A745"}),jsxRuntime.jsx("span",{children:t?`Authenticated as ${h}`:"Authenticated"})]})}return a?jsxRuntime.jsx(jsxRuntime.Fragment,{children:a()}):jsxRuntime.jsxs("div",{className:r,style:{...n,backgroundColor:"#F8D7DA",color:"#721C24"},role:"status","aria-live":"polite",children:[jsxRuntime.jsx(X,{color:"#DC3545"}),jsxRuntime.jsx("span",{children:"Not authenticated"})]})}function X({color:r}){return jsxRuntime.jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsxRuntime.jsx("circle",{cx:"4",cy:"4",r:"4",fill:r})})}function re({children:r,loadingComponent:e,fallbackComponent:t,scopes:o,onAuthRequired:i}){let{isAuthenticated:a,inProgress:g,loginRedirect:u}=A();return react.useEffect(()=>{!a&&!g&&(i?.(),(async()=>{try{await u(o);}catch(n){console.error("[AuthGuard] Authentication failed:",n);}})());},[a,g,o,u,i]),g?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e||jsxRuntime.jsx("div",{children:"Authenticating..."})}):a?jsxRuntime.jsx(jsxRuntime.Fragment,{children:r}):jsxRuntime.jsx(jsxRuntime.Fragment,{children:t||jsxRuntime.jsx("div",{children:"Redirecting to login..."})})}var ne=class extends react.Component{constructor(t){super(t);this.reset=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(t){return {hasError:true,error:t}}componentDidCatch(t,o){let{onError:i,debug:a}=this.props;a&&(console.error("[ErrorBoundary] Caught error:",t),console.error("[ErrorBoundary] Error info:",o)),i?.(t,o);}render(){let{hasError:t,error:o}=this.state,{children:i,fallback:a}=this.props;return t&&o?a?a(o,this.reset):jsxRuntime.jsxs("div",{style:{padding:"20px",margin:"20px",border:"1px solid #DC3545",borderRadius:"4px",backgroundColor:"#F8D7DA",color:"#721C24",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif'},children:[jsxRuntime.jsx("h2",{style:{margin:"0 0 10px 0",fontSize:"18px"},children:"Authentication Error"}),jsxRuntime.jsx("p",{style:{margin:"0 0 10px 0"},children:o.message}),jsxRuntime.jsx("button",{onClick:this.reset,style:{padding:"8px 16px",backgroundColor:"#DC3545",color:"#FFFFFF",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:600},children:"Try Again"})]}):i}};var v=new Map,Xe=300*1e3,Ae=100;function Ye(r){r?v.delete(r):v.clear();}function et(){if(v.size>Ae){let r=Array.from(v.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,v.size-Ae).forEach(([t])=>v.delete(t));}}function tt(){let{isAuthenticated:r,account:e}=A(),t=N(),[o,i]=react.useState([]),[a,g]=react.useState([]),[u,l]=react.useState(false),[n,h]=react.useState(null),f=react.useCallback(async()=>{if(!r||!e){i([]),g([]);return}let d=e.homeAccountId,y=v.get(d);if(y&&Date.now()-y.timestamp<Xe){i(y.roles),g(y.groups);return}l(true),h(null);try{let M=e.idTokenClaims?.roles||[],$=(await t.get("/me/memberOf",{scopes:["User.Read","Directory.Read.All"]})).value.map(se=>se.id);v.set(d,{roles:M,groups:$,timestamp:Date.now()}),et(),i(M),g($);}catch(R){let V=w(R),$=new Error(V);h($),console.error("[Roles] Failed to fetch roles/groups:",V);let Re=e.idTokenClaims?.roles||[];i(Re);}finally{l(false);}},[r,e,t]),c=react.useCallback(d=>o.includes(d),[o]),s=react.useCallback(d=>a.includes(d),[a]),m=react.useCallback(d=>d.some(y=>o.includes(y)),[o]),p=react.useCallback(d=>d.every(y=>o.includes(y)),[o]);return react.useEffect(()=>(f(),()=>{e&&Ye(e.homeAccountId);}),[f,e]),{roles:o,groups:a,loading:u,error:n,hasRole:c,hasGroup:s,hasAnyRole:m,hasAllRoles:p,refetch:f}}function rt(r,e={}){let{displayName:t,...o}=e,i=a=>jsxRuntime.jsx(re,{...o,children:jsxRuntime.jsx(r,{...a})});return i.displayName=t||`withAuth(${r.displayName||r.name||"Component"})`,i}async function Pe(r,e={}){let{maxRetries:t=3,initialDelay:o=1e3,maxDelay:i=1e4,backoffMultiplier:a=2,debug:g=false}=e,u,l=o;for(let n=0;n<=t;n++)try{return g&&n>0&&console.log(`[TokenRetry] Attempt ${n+1}/${t+1}`),await r()}catch(h){if(u=h,n===t){g&&console.error("[TokenRetry] All retry attempts failed");break}if(!ot(h))throw g&&console.log("[TokenRetry] Non-retryable error, aborting"),h;g&&console.warn(`[TokenRetry] Attempt ${n+1} failed, retrying in ${l}ms...`),await nt(l),l=Math.min(l*a,i);}throw u}function ot(r){let e=r.message.toLowerCase();return !!(e.includes("network")||e.includes("timeout")||e.includes("fetch")||e.includes("connection")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("429")||e.includes("rate limit")||e.includes("token")&&e.includes("expired"))}function nt(r){return new Promise(e=>setTimeout(e,r))}function it(r,e={}){return (...t)=>Pe(()=>r(...t),e)}var B=class{constructor(e={}){this.logHistory=[];this.performanceTimings=new Map;this.config={enabled:e.enabled??false,prefix:e.prefix??"[MSAL-Next]",showTimestamp:e.showTimestamp??true,level:e.level??"info",enablePerformance:e.enablePerformance??false,enableNetworkLogs:e.enableNetworkLogs??false,maxHistorySize:e.maxHistorySize??100};}shouldLog(e){if(!this.config.enabled)return false;let t=["error","warn","info","debug"],o=t.indexOf(this.config.level);return t.indexOf(e)<=o}formatMessage(e,t,o){let i=this.config.showTimestamp?`[${new Date().toISOString()}]`:"",a=this.config.prefix,g=`[${e.toUpperCase()}]`,u=`${i} ${a} ${g} ${t}`;return o!==void 0&&(u+=`
|
|
2
|
+
`+JSON.stringify(o,null,2)),u}addToHistory(e,t,o){this.logHistory.length>=this.config.maxHistorySize&&this.logHistory.shift(),this.logHistory.push({timestamp:Date.now(),level:e,message:t,data:o});}error(e,t){this.shouldLog("error")&&(console.error(this.formatMessage("error",e,t)),this.addToHistory("error",e,t));}warn(e,t){this.shouldLog("warn")&&(console.warn(this.formatMessage("warn",e,t)),this.addToHistory("warn",e,t));}info(e,t){this.shouldLog("info")&&(console.info(this.formatMessage("info",e,t)),this.addToHistory("info",e,t));}debug(e,t){this.shouldLog("debug")&&(console.debug(this.formatMessage("debug",e,t)),this.addToHistory("debug",e,t));}group(e){this.config.enabled&&console.group(`${this.config.prefix} ${e}`);}groupEnd(){this.config.enabled&&console.groupEnd();}startTiming(e){this.config.enablePerformance&&(this.performanceTimings.set(e,{operation:e,startTime:performance.now()}),this.debug(`\u23F1\uFE0F Started: ${e}`));}endTiming(e){if(this.config.enablePerformance){let t=this.performanceTimings.get(e);if(t)return t.endTime=performance.now(),t.duration=t.endTime-t.startTime,this.info(`\u23F1\uFE0F Completed: ${e} (${t.duration.toFixed(2)}ms)`),t.duration}}logRequest(e,t,o){this.config.enableNetworkLogs&&this.debug(`\u{1F310} ${e} ${t}`,o);}logResponse(e,t,o,i){if(this.config.enableNetworkLogs){let a=o>=200&&o<300?"\u2705":"\u274C";this.debug(`${a} ${e} ${t} - ${o}`,i);}}getHistory(){return [...this.logHistory]}getPerformanceTimings(){return Array.from(this.performanceTimings.values())}clearHistory(){this.logHistory=[];}clearTimings(){this.performanceTimings.clear();}exportLogs(){return JSON.stringify({config:this.config,history:this.logHistory,performanceTimings:Array.from(this.performanceTimings.values()),exportedAt:new Date().toISOString()},null,2)}downloadLogs(e="msal-next-debug-logs.json"){if(typeof window>"u")return;let t=this.exportLogs(),o=new Blob([t],{type:"application/json"}),i=URL.createObjectURL(o),a=document.createElement("a");a.href=i,a.download=e,a.click(),URL.revokeObjectURL(i);}setEnabled(e){this.config.enabled=e;}setLevel(e){e&&(this.config.level=e);}},O=null;function st(r){return O?r&&(r.enabled!==void 0&&O.setEnabled(r.enabled),r.level&&O.setLevel(r.level)):O=new B(r),O}function at(r,e){return new B({...e,prefix:`[MSAL-Next:${r}]`})}function _({children:r,config:e,defaultRedirectTo:t="/login",defaultLoading:o,defaultUnauthorized:i,debug:a=false}){let g=navigation.useRouter(),{isAuthenticated:u,account:l,inProgress:n}=A(),[h,f]=react.useState(true),[c,s]=react.useState(false);return react.useEffect(()=>{async function m(){if(a&&console.log("[ProtectedPage] Checking auth...",{isAuthenticated:u,inProgress:n,config:e}),!n){if(!e.required){s(true),f(false);return}if(!u||!l){a&&console.log("[ProtectedPage] Not authenticated, redirecting...");let p=e.redirectTo||t,d=encodeURIComponent(window.location.pathname+window.location.search);g.push(`${p}?returnUrl=${d}`);return}if(e.roles&&e.roles.length>0){let p=l.idTokenClaims?.roles||[];if(!e.roles.some(y=>p.includes(y))){a&&console.log("[ProtectedPage] Missing required role",{required:e.roles,user:p}),s(false),f(false);return}}if(e.validate)try{if(!await e.validate(l)){a&&console.log("[ProtectedPage] Custom validation failed"),s(!1),f(!1);return}}catch(p){console.error("[ProtectedPage] Validation error:",p),s(false),f(false);return}a&&console.log("[ProtectedPage] Authorization successful"),s(true),f(false);}}m();},[u,l,n,e,g,t,a]),h||n?e.loading?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e.loading}):o?jsxRuntime.jsx(jsxRuntime.Fragment,{children:o}):jsxRuntime.jsx("div",{className:"flex items-center justify-center min-h-screen",children:jsxRuntime.jsx("div",{className:"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"})}):c?jsxRuntime.jsx(jsxRuntime.Fragment,{children:r}):e.unauthorized?jsxRuntime.jsx(jsxRuntime.Fragment,{children:e.unauthorized}):i?jsxRuntime.jsx(jsxRuntime.Fragment,{children:i}):jsxRuntime.jsx("div",{className:"flex items-center justify-center min-h-screen",children:jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-2",children:"Access Denied"}),jsxRuntime.jsx("p",{className:"text-gray-600",children:"You don't have permission to access this page."})]})})}function we(r,e,t){let o=i=>jsxRuntime.jsx(_,{config:e,defaultRedirectTo:t?.defaultRedirectTo,defaultLoading:t?.defaultLoading,defaultUnauthorized:t?.defaultUnauthorized,debug:t?.debug,children:jsxRuntime.jsx(r,{...i})});return o.displayName=`withPageAuth(${r.displayName||r.name||"Component"})`,o}function dt(r={}){let{protectedRoutes:e=[],publicOnlyRoutes:t=[],loginPath:o="/login",redirectAfterLogin:i="/",sessionCookie:a="msal.account",isAuthenticated:g,debug:u=false}=r;return async function(n){let{pathname:h}=n.nextUrl;u&&console.log("[AuthMiddleware] Processing:",h);let f=false;g?f=await g(n):f=!!n.cookies.get(a)?.value,u&&console.log("[AuthMiddleware] Authenticated:",f);let c=e.some(p=>h.startsWith(p)),s=t.some(p=>h.startsWith(p));if(c&&!f){u&&console.log("[AuthMiddleware] Redirecting to login");let p=n.nextUrl.clone();return p.pathname=o,p.searchParams.set("returnUrl",h),server.NextResponse.redirect(p)}if(s&&f){u&&console.log("[AuthMiddleware] Redirecting to home");let p=n.nextUrl.searchParams.get("returnUrl"),d=n.nextUrl.clone();return d.pathname=p||i,d.searchParams.delete("returnUrl"),server.NextResponse.redirect(d)}let m=server.NextResponse.next();if(f){m.headers.set("x-msal-authenticated","true");try{let p=n.cookies.get(a);if(p?.value){let d=H(p.value,W);d?.username&&m.headers.set("x-msal-username",d.username);}}catch{u&&console.warn("[AuthMiddleware] Failed to parse session data");}}return m}}Object.defineProperty(exports,"useAccount",{enumerable:true,get:function(){return msalReact.useAccount}});Object.defineProperty(exports,"useIsAuthenticated",{enumerable:true,get:function(){return msalReact.useIsAuthenticated}});Object.defineProperty(exports,"useMsal",{enumerable:true,get:function(){return msalReact.useMsal}});exports.AuthGuard=re;exports.AuthStatus=je;exports.ErrorBoundary=ne;exports.MSALProvider=Fe;exports.MicrosoftSignInButton=$e;exports.MsalAuthProvider=J;exports.ProtectedPage=_;exports.SignOutButton=qe;exports.UserAvatar=We;exports.createAuthMiddleware=dt;exports.createMsalConfig=j;exports.createRetryWrapper=it;exports.createScopedLogger=at;exports.getDebugLogger=st;exports.getMsalInstance=Ue;exports.isValidAccountData=W;exports.isValidRedirectUri=z;exports.isValidScope=ae;exports.retryWithBackoff=Pe;exports.safeJsonParse=H;exports.sanitizeError=w;exports.useGraphApi=N;exports.useMsalAuth=A;exports.useRoles=tt;exports.useUserProfile=Q;exports.validateScopes=Ce;exports.withAuth=rt;exports.withPageAuth=we;
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {MsalProvider,useMsal,useAccount}from'@azure/msal-react';export{useAccount,useIsAuthenticated,useMsal}from'@azure/msal-react';import {LogLevel,PublicClientApplication,EventType,InteractionStatus}from'@azure/msal-browser';import {useState,useRef,useEffect,useMemo,useCallback,Component}from'react';import {jsx,Fragment,jsxs}from'react/jsx-runtime';import {NextResponse}from'next/server';function q(r,e){try{let t=JSON.parse(r);return e(t)?t:(console.warn("[Validation] JSON validation failed"),null)}catch(t){return console.error("[Validation] JSON parse error:",t),null}}function _(r){return typeof r=="object"&&r!==null&&typeof r.homeAccountId=="string"&&r.homeAccountId.length>0&&typeof r.username=="string"&&r.username.length>0&&(r.name===void 0||typeof r.name=="string")}function v(r){return r instanceof Error?r.message.replace(/[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g,"[TOKEN_REDACTED]").replace(/[a-f0-9]{32,}/gi,"[SECRET_REDACTED]").replace(/Bearer\s+[^\s]+/gi,"Bearer [REDACTED]"):"An unexpected error occurred"}function G(r,e){try{let t=new URL(r);return e.some(o=>{let i=new URL(o);return t.origin===i.origin})}catch{return false}}function ne(r){return /^[a-zA-Z0-9._-]+$/.test(r)}function Ae(r){return Array.isArray(r)&&r.every(ne)}function H(r){if(r.msalConfig)return r.msalConfig;let{clientId:e,tenantId:t,authorityType:o="common",redirectUri:i,postLogoutRedirectUri:a,cacheLocation:p="sessionStorage",storeAuthStateInCookie:u=false,navigateToLoginRequestUrl:c=false,enableLogging:n=false,loggerCallback:h,allowedRedirectUris:g}=r;if(!e)throw new Error("@chemmangat/msal-next: clientId is required");let l=()=>{if(o==="tenant"){if(!t)throw new Error('@chemmangat/msal-next: tenantId is required when authorityType is "tenant"');return `https://login.microsoftonline.com/${t}`}return `https://login.microsoftonline.com/${o}`},s=typeof window<"u"?window.location.origin:"http://localhost:3000",m=i||s;if(g&&g.length>0){if(!G(m,g))throw new Error(`@chemmangat/msal-next: redirectUri "${m}" is not in the allowed list`);let d=a||m;if(!G(d,g))throw new Error(`@chemmangat/msal-next: postLogoutRedirectUri "${d}" is not in the allowed list`)}return {auth:{clientId:e,authority:l(),redirectUri:m,postLogoutRedirectUri:a||m,navigateToLoginRequestUrl:c},cache:{cacheLocation:p,storeAuthStateInCookie:u},system:{loggerOptions:{loggerCallback:h||((d,y,R)=>{if(!(R||!n))switch(d){case LogLevel.Error:console.error("[MSAL]",y);break;case LogLevel.Warning:console.warn("[MSAL]",y);break;case LogLevel.Info:console.info("[MSAL]",y);break;case LogLevel.Verbose:console.debug("[MSAL]",y);break}}),logLevel:n?LogLevel.Verbose:LogLevel.Error}}}}var se=null;function Pe(){return se}function V({children:r,loadingComponent:e,onInitialized:t,...o}){let[i,a]=useState(null),p=useRef(null);return useEffect(()=>{if(typeof window>"u"||p.current)return;(async()=>{try{let c=H(o),n=new PublicClientApplication(c);await n.initialize();try{let l=await n.handleRedirectPromise();l&&(o.enableLogging&&console.log("[MSAL] Redirect authentication successful"),l.account&&n.setActiveAccount(l.account),window.location.hash&&window.history.replaceState(null,"",window.location.pathname+window.location.search));}catch(l){l?.errorCode==="no_token_request_cache_error"?o.enableLogging&&console.log("[MSAL] No pending redirect found (this is normal)"):l?.errorCode==="user_cancelled"?o.enableLogging&&console.log("[MSAL] User cancelled authentication"):console.error("[MSAL] Redirect handling error:",l),window.location.hash&&(window.location.hash.includes("code=")||window.location.hash.includes("error="))&&window.history.replaceState(null,"",window.location.pathname+window.location.search);}let h=n.getAllAccounts();h.length>0&&!n.getActiveAccount()&&n.setActiveAccount(h[0]);let g=o.enableLogging||!1;n.addEventCallback(l=>{if(l.eventType===EventType.LOGIN_SUCCESS){let s=l.payload;s?.account&&n.setActiveAccount(s.account),g&&console.log("[MSAL] Login successful:",s.account?.username);}if(l.eventType===EventType.LOGIN_FAILURE&&console.error("[MSAL] Login failed:",l.error),l.eventType===EventType.LOGOUT_SUCCESS&&(n.setActiveAccount(null),g&&console.log("[MSAL] Logout successful")),l.eventType===EventType.ACQUIRE_TOKEN_SUCCESS){let s=l.payload;s?.account&&!n.getActiveAccount()&&n.setActiveAccount(s.account);}l.eventType===EventType.ACQUIRE_TOKEN_FAILURE&&g&&console.error("[MSAL] Token acquisition failed:",l.error);}),p.current=n,se=n,a(n),t&&t(n);}catch(c){throw console.error("[MSAL] Initialization failed:",c),c}})();},[]),typeof window>"u"?jsx(Fragment,{children:e||jsx("div",{children:"Loading authentication..."})}):i?jsx(MsalProvider,{instance:i,children:r}):jsx(Fragment,{children:e||jsx("div",{children:"Loading authentication..."})})}function Se({children:r,...e}){return jsx(V,{...e,children:r})}var W=new Map;function A(r=["User.Read"]){let{instance:e,accounts:t,inProgress:o}=useMsal(),i=useAccount(t[0]||null),a=useMemo(()=>t.length>0,[t]),p=useCallback(async(l=r)=>{if(o!==InteractionStatus.None){console.warn("[MSAL] Interaction already in progress");return}try{let s={scopes:l,prompt:"select_account"};await e.loginRedirect(s);}catch(s){if(s?.errorCode==="user_cancelled"){console.log("[MSAL] User cancelled login");return}throw console.error("[MSAL] Login redirect failed:",s),s}},[e,r,o]),u=useCallback(async()=>{try{await e.logoutRedirect({account:i||void 0});}catch(l){throw console.error("[MSAL] Logout redirect failed:",l),l}},[e,i]),c=useCallback(async(l=r)=>{if(!i)throw new Error("[MSAL] No active account. Please login first.");try{let s={scopes:l,account:i,forceRefresh:!1};return (await e.acquireTokenSilent(s)).accessToken}catch(s){throw console.error("[MSAL] Silent token acquisition failed:",s),s}},[e,i,r]),n=useCallback(async(l=r)=>{if(!i)throw new Error("[MSAL] No active account. Please login first.");try{let s={scopes:l,account:i};await e.acquireTokenRedirect(s);}catch(s){throw console.error("[MSAL] Token redirect acquisition failed:",s),s}},[e,i,r]),h=useCallback(async(l=r)=>{let s=`${i?.homeAccountId||"anonymous"}-${l.sort().join(",")}`,m=W.get(s);if(m)return m;let f=(async()=>{try{return await c(l)}catch{throw console.warn("[MSAL] Silent token acquisition failed, falling back to redirect"),await n(l),new Error("[MSAL] Redirecting for token acquisition")}finally{W.delete(s);}})();return W.set(s,f),f},[c,n,r,i]),g=useCallback(async()=>{e.setActiveAccount(null),await e.clearCache();},[e]);return {account:i,accounts:t,isAuthenticated:a,inProgress:o!==InteractionStatus.None,loginRedirect:p,logoutRedirect:u,acquireToken:h,acquireTokenSilent:c,acquireTokenRedirect:n,clearSession:g}}function Ue({text:r="Sign in with Microsoft",variant:e="dark",size:t="medium",scopes:o,className:i="",style:a,onSuccess:p,onError:u}){let{loginRedirect:c,inProgress:n}=A(),[h,g]=useState(false),l=async()=>{g(true);try{await c(o),p?.();}catch(y){u?.(y);}finally{setTimeout(()=>g(false),500);}},s={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},m={dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}},f=n||h,d={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:f?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:f?.6:1,...m[e],...s[t],...a};return jsxs("button",{onClick:l,disabled:f,className:i,style:d,"aria-label":r,children:[jsx(ke,{}),jsx("span",{children:r})]})}function ke(){return jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function Fe({text:r="Sign out",variant:e="dark",size:t="medium",className:o="",style:i,onSuccess:a,onError:p}){let{logoutRedirect:u,inProgress:c}=A(),n=async()=>{try{await u(),a?.();}catch(s){p?.(s);}},h={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},l={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:c?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:c?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...h[t],...i};return jsxs("button",{onClick:n,disabled:c,className:o,style:l,"aria-label":r,children:[jsx(Ne,{}),jsx("span",{children:r})]})}function Ne(){return jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function k(){let{acquireToken:r}=A(),e=useCallback(async(u,c={})=>{let{scopes:n=["User.Read"],version:h="v1.0",debug:g=false,...l}=c;try{let s=await r(n),m=`https://graph.microsoft.com/${h}`,f=u.startsWith("http")?u:`${m}${u.startsWith("/")?u:`/${u}`}`;g&&console.log("[GraphAPI] Request:",{url:f,method:l.method||"GET"});let d=await fetch(f,{...l,headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json",...l.headers}});if(!d.ok){let R=await d.text(),L=`Graph API error (${d.status}): ${R}`;throw new Error(L)}if(d.status===204||d.headers.get("content-length")==="0")return null;let y=await d.json();return g&&console.log("[GraphAPI] Response:",y),y}catch(s){let m=v(s);throw console.error("[GraphAPI] Request failed:",m),new Error(m)}},[r]),t=useCallback((u,c={})=>e(u,{...c,method:"GET"}),[e]),o=useCallback((u,c,n={})=>e(u,{...n,method:"POST",body:c?JSON.stringify(c):void 0}),[e]),i=useCallback((u,c,n={})=>e(u,{...n,method:"PUT",body:c?JSON.stringify(c):void 0}),[e]),a=useCallback((u,c,n={})=>e(u,{...n,method:"PATCH",body:c?JSON.stringify(c):void 0}),[e]),p=useCallback((u,c={})=>e(u,{...c,method:"DELETE"}),[e]);return {get:t,post:o,put:i,patch:a,delete:p,request:e}}var x=new Map,Ie=300*1e3,pe=100;function Oe(){if(x.size>pe){let r=Array.from(x.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,x.size-pe).forEach(([t])=>{let o=x.get(t);o?.data.photo&&URL.revokeObjectURL(o.data.photo),x.delete(t);});}}function J(){let{isAuthenticated:r,account:e}=A(),t=k(),[o,i]=useState(null),[a,p]=useState(false),[u,c]=useState(null),n=useCallback(async()=>{if(!r||!e){i(null);return}let g=e.homeAccountId,l=x.get(g);if(l&&Date.now()-l.timestamp<Ie){i(l.data);return}p(true),c(null);try{let s=await t.get("/me",{scopes:["User.Read"]}),m;try{let d=await t.get("/me/photo/$value",{scopes:["User.Read"],headers:{"Content-Type":"image/jpeg"}});d&&(m=URL.createObjectURL(d));}catch{console.debug("[UserProfile] Photo not available");}let f={id:s.id,displayName:s.displayName,givenName:s.givenName,surname:s.surname,userPrincipalName:s.userPrincipalName,mail:s.mail,jobTitle:s.jobTitle,officeLocation:s.officeLocation,mobilePhone:s.mobilePhone,businessPhones:s.businessPhones,photo:m};x.set(g,{data:f,timestamp:Date.now()}),Oe(),i(f);}catch(s){let f=v(s),d=new Error(f);c(d),console.error("[UserProfile] Failed to fetch profile:",f);}finally{p(false);}},[r,e,t]),h=useCallback(()=>{if(e){let g=x.get(e.homeAccountId);g?.data.photo&&URL.revokeObjectURL(g.data.photo),x.delete(e.homeAccountId);}o?.photo&&URL.revokeObjectURL(o.photo),i(null);},[e,o]);return useEffect(()=>(n(),()=>{o?.photo&&URL.revokeObjectURL(o.photo);}),[n]),useEffect(()=>()=>{o?.photo&&URL.revokeObjectURL(o.photo);},[o?.photo]),{profile:o,loading:a,error:u,refetch:n,clearCache:h}}function Ge({size:r=40,className:e="",style:t,showTooltip:o=true,fallbackImage:i}){let{profile:a,loading:p}=J(),[u,c]=useState(null),[n,h]=useState(false);useEffect(()=>{a?.photo&&c(a.photo);},[a?.photo]);let g=()=>{if(!a)return "?";let{givenName:m,surname:f,displayName:d}=a;if(m&&f)return `${m[0]}${f[0]}`.toUpperCase();if(d){let y=d.split(" ");return y.length>=2?`${y[0][0]}${y[y.length-1][0]}`.toUpperCase():d.substring(0,2).toUpperCase()}return "?"},l={width:`${r}px`,height:`${r}px`,borderRadius:"50%",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:`${r*.4}px`,fontWeight:600,fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',backgroundColor:"#0078D4",color:"#FFFFFF",overflow:"hidden",userSelect:"none",...t},s=a?.displayName||"User";return p?jsx("div",{className:e,style:{...l,backgroundColor:"#E1E1E1"},"aria-label":"Loading user avatar",children:jsx("span",{style:{fontSize:`${r*.3}px`},children:"..."})}):u&&!n?jsx("div",{className:e,style:l,title:o?s:void 0,"aria-label":`${s} avatar`,children:jsx("img",{src:u,alt:s,style:{width:"100%",height:"100%",objectFit:"cover"},onError:()=>{h(true),i&&c(i);}})}):jsx("div",{className:e,style:l,title:o?s:void 0,"aria-label":`${s} avatar`,children:g()})}function $e({className:r="",style:e,showDetails:t=false,renderLoading:o,renderAuthenticated:i,renderUnauthenticated:a}){let{isAuthenticated:p,inProgress:u,account:c}=A(),n={display:"inline-flex",alignItems:"center",gap:"8px",padding:"8px 12px",borderRadius:"4px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontSize:"14px",fontWeight:500,...e};if(u)return o?jsx(Fragment,{children:o()}):jsxs("div",{className:r,style:{...n,backgroundColor:"#FFF4CE",color:"#8A6D3B"},role:"status","aria-live":"polite",children:[jsx(K,{color:"#FFA500"}),jsx("span",{children:"Loading..."})]});if(p){let h=c?.username||c?.name||"User";return i?jsx(Fragment,{children:i(h)}):jsxs("div",{className:r,style:{...n,backgroundColor:"#D4EDDA",color:"#155724"},role:"status","aria-live":"polite",children:[jsx(K,{color:"#28A745"}),jsx("span",{children:t?`Authenticated as ${h}`:"Authenticated"})]})}return a?jsx(Fragment,{children:a()}):jsxs("div",{className:r,style:{...n,backgroundColor:"#F8D7DA",color:"#721C24"},role:"status","aria-live":"polite",children:[jsx(K,{color:"#DC3545"}),jsx("span",{children:"Not authenticated"})]})}function K({color:r}){return jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsx("circle",{cx:"4",cy:"4",r:"4",fill:r})})}function Y({children:r,loadingComponent:e,fallbackComponent:t,scopes:o,onAuthRequired:i}){let{isAuthenticated:a,inProgress:p,loginRedirect:u}=A();return useEffect(()=>{!a&&!p&&(i?.(),(async()=>{try{await u(o);}catch(n){console.error("[AuthGuard] Authentication failed:",n);}})());},[a,p,o,u,i]),p?jsx(Fragment,{children:e||jsx("div",{children:"Authenticating..."})}):a?jsx(Fragment,{children:r}):jsx(Fragment,{children:t||jsx("div",{children:"Redirecting to login..."})})}var re=class extends Component{constructor(t){super(t);this.reset=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(t){return {hasError:true,error:t}}componentDidCatch(t,o){let{onError:i,debug:a}=this.props;a&&(console.error("[ErrorBoundary] Caught error:",t),console.error("[ErrorBoundary] Error info:",o)),i?.(t,o);}render(){let{hasError:t,error:o}=this.state,{children:i,fallback:a}=this.props;return t&&o?a?a(o,this.reset):jsxs("div",{style:{padding:"20px",margin:"20px",border:"1px solid #DC3545",borderRadius:"4px",backgroundColor:"#F8D7DA",color:"#721C24",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif'},children:[jsx("h2",{style:{margin:"0 0 10px 0",fontSize:"18px"},children:"Authentication Error"}),jsx("p",{style:{margin:"0 0 10px 0"},children:o.message}),jsx("button",{onClick:this.reset,style:{padding:"8px 16px",backgroundColor:"#DC3545",color:"#FFFFFF",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:600},children:"Try Again"})]}):i}};var w=new Map,He=300*1e3,fe=100;function Ve(r){r?w.delete(r):w.clear();}function We(){if(w.size>fe){let r=Array.from(w.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,w.size-fe).forEach(([t])=>w.delete(t));}}function je(){let{isAuthenticated:r,account:e}=A(),t=k(),[o,i]=useState([]),[a,p]=useState([]),[u,c]=useState(false),[n,h]=useState(null),g=useCallback(async()=>{if(!r||!e){i([]),p([]);return}let d=e.homeAccountId,y=w.get(d);if(y&&Date.now()-y.timestamp<He){i(y.roles),p(y.groups);return}c(true),h(null);try{let L=e.idTokenClaims?.roles||[],D=(await t.get("/me/memberOf",{scopes:["User.Read","Directory.Read.All"]})).value.map(oe=>oe.id);w.set(d,{roles:L,groups:D,timestamp:Date.now()}),We(),i(L),p(D);}catch(R){let B=v(R),D=new Error(B);h(D),console.error("[Roles] Failed to fetch roles/groups:",B);let ye=e.idTokenClaims?.roles||[];i(ye);}finally{c(false);}},[r,e,t]),l=useCallback(d=>o.includes(d),[o]),s=useCallback(d=>a.includes(d),[a]),m=useCallback(d=>d.some(y=>o.includes(y)),[o]),f=useCallback(d=>d.every(y=>o.includes(y)),[o]);return useEffect(()=>(g(),()=>{e&&Ve(e.homeAccountId);}),[g,e]),{roles:o,groups:a,loading:u,error:n,hasRole:l,hasGroup:s,hasAnyRole:m,hasAllRoles:f,refetch:g}}function Je(r,e={}){let{displayName:t,...o}=e,i=a=>jsx(Y,{...o,children:jsx(r,{...a})});return i.displayName=t||`withAuth(${r.displayName||r.name||"Component"})`,i}async function me(r,e={}){let{maxRetries:t=3,initialDelay:o=1e3,maxDelay:i=1e4,backoffMultiplier:a=2,debug:p=false}=e,u,c=o;for(let n=0;n<=t;n++)try{return p&&n>0&&console.log(`[TokenRetry] Attempt ${n+1}/${t+1}`),await r()}catch(h){if(u=h,n===t){p&&console.error("[TokenRetry] All retry attempts failed");break}if(!Ke(h))throw p&&console.log("[TokenRetry] Non-retryable error, aborting"),h;p&&console.warn(`[TokenRetry] Attempt ${n+1} failed, retrying in ${c}ms...`),await Ze(c),c=Math.min(c*a,i);}throw u}function Ke(r){let e=r.message.toLowerCase();return !!(e.includes("network")||e.includes("timeout")||e.includes("fetch")||e.includes("connection")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("429")||e.includes("rate limit")||e.includes("token")&&e.includes("expired"))}function Ze(r){return new Promise(e=>setTimeout(e,r))}function Qe(r,e={}){return (...t)=>me(()=>r(...t),e)}var z=class{constructor(e={}){this.logHistory=[];this.performanceTimings=new Map;this.config={enabled:e.enabled??false,prefix:e.prefix??"[MSAL-Next]",showTimestamp:e.showTimestamp??true,level:e.level??"info",enablePerformance:e.enablePerformance??false,enableNetworkLogs:e.enableNetworkLogs??false,maxHistorySize:e.maxHistorySize??100};}shouldLog(e){if(!this.config.enabled)return false;let t=["error","warn","info","debug"],o=t.indexOf(this.config.level);return t.indexOf(e)<=o}formatMessage(e,t,o){let i=this.config.showTimestamp?`[${new Date().toISOString()}]`:"",a=this.config.prefix,p=`[${e.toUpperCase()}]`,u=`${i} ${a} ${p} ${t}`;return o!==void 0&&(u+=`
|
|
2
|
-
`+JSON.stringify(o,null,2)),u}addToHistory(e,t,o){this.logHistory.length>=this.config.maxHistorySize&&this.logHistory.shift(),this.logHistory.push({timestamp:Date.now(),level:e,message:t,data:o});}error(e,t){this.shouldLog("error")&&(console.error(this.formatMessage("error",e,t)),this.addToHistory("error",e,t));}warn(e,t){this.shouldLog("warn")&&(console.warn(this.formatMessage("warn",e,t)),this.addToHistory("warn",e,t));}info(e,t){this.shouldLog("info")&&(console.info(this.formatMessage("info",e,t)),this.addToHistory("info",e,t));}debug(e,t){this.shouldLog("debug")&&(console.debug(this.formatMessage("debug",e,t)),this.addToHistory("debug",e,t));}group(e){this.config.enabled&&console.group(`${this.config.prefix} ${e}`);}groupEnd(){this.config.enabled&&console.groupEnd();}startTiming(e){this.config.enablePerformance&&(this.performanceTimings.set(e,{operation:e,startTime:performance.now()}),this.debug(`\u23F1\uFE0F Started: ${e}`));}endTiming(e){if(this.config.enablePerformance){let t=this.performanceTimings.get(e);if(t)return t.endTime=performance.now(),t.duration=t.endTime-t.startTime,this.info(`\u23F1\uFE0F Completed: ${e} (${t.duration.toFixed(2)}ms)`),t.duration}}logRequest(e,t,o){this.config.enableNetworkLogs&&this.debug(`\u{1F310} ${e} ${t}`,o);}logResponse(e,t,o,i){if(this.config.enableNetworkLogs){let a=o>=200&&o<300?"\u2705":"\u274C";this.debug(`${a} ${e} ${t} - ${o}`,i);}}getHistory(){return [...this.logHistory]}getPerformanceTimings(){return Array.from(this.performanceTimings.values())}clearHistory(){this.logHistory=[];}clearTimings(){this.performanceTimings.clear();}exportLogs(){return JSON.stringify({config:this.config,history:this.logHistory,performanceTimings:Array.from(this.performanceTimings.values()),exportedAt:new Date().toISOString()},null,2)}downloadLogs(e="msal-next-debug-logs.json"){if(typeof window>"u")return;let t=this.exportLogs(),o=new Blob([t],{type:"application/json"}),i=URL.createObjectURL(o),a=document.createElement("a");a.href=i,a.download=e,a.click(),URL.revokeObjectURL(i);}setEnabled(e){this.config.enabled=e;}setLevel(e){e&&(this.config.level=e);}},O=null;function
|
|
1
|
+
import {MsalProvider,useMsal,useAccount}from'@azure/msal-react';export{useAccount,useIsAuthenticated,useMsal}from'@azure/msal-react';import {LogLevel,PublicClientApplication,EventType,InteractionStatus}from'@azure/msal-browser';import {createContext,useState,useRef,useEffect,useMemo,useCallback,Component}from'react';import {jsx,Fragment,jsxs}from'react/jsx-runtime';import {useRouter}from'next/navigation';import {NextResponse}from'next/server';function H(r,e){try{let t=JSON.parse(r);return e(t)?t:(console.warn("[Validation] JSON validation failed"),null)}catch(t){return console.error("[Validation] JSON parse error:",t),null}}function W(r){return typeof r=="object"&&r!==null&&typeof r.homeAccountId=="string"&&r.homeAccountId.length>0&&typeof r.username=="string"&&r.username.length>0&&(r.name===void 0||typeof r.name=="string")}function w(r){return r instanceof Error?r.message.replace(/[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}/g,"[TOKEN_REDACTED]").replace(/[a-f0-9]{32,}/gi,"[SECRET_REDACTED]").replace(/Bearer\s+[^\s]+/gi,"Bearer [REDACTED]"):"An unexpected error occurred"}function z(r,e){try{let t=new URL(r);return e.some(o=>{let i=new URL(o);return t.origin===i.origin})}catch{return false}}function ae(r){return /^[a-zA-Z0-9._-]+$/.test(r)}function Ce(r){return Array.isArray(r)&&r.every(ae)}function j(r){if(r.msalConfig)return r.msalConfig;let{clientId:e,tenantId:t,authorityType:o="common",redirectUri:i,postLogoutRedirectUri:a,cacheLocation:g="sessionStorage",storeAuthStateInCookie:u=false,navigateToLoginRequestUrl:l=false,enableLogging:n=false,loggerCallback:h,allowedRedirectUris:f}=r;if(!e)throw new Error("@chemmangat/msal-next: clientId is required");let c=()=>{if(o==="tenant"){if(!t)throw new Error('@chemmangat/msal-next: tenantId is required when authorityType is "tenant"');return `https://login.microsoftonline.com/${t}`}return `https://login.microsoftonline.com/${o}`},s=typeof window<"u"?window.location.origin:"http://localhost:3000",m=i||s;if(f&&f.length>0){if(!z(m,f))throw new Error(`@chemmangat/msal-next: redirectUri "${m}" is not in the allowed list`);let d=a||m;if(!z(d,f))throw new Error(`@chemmangat/msal-next: postLogoutRedirectUri "${d}" is not in the allowed list`)}return {auth:{clientId:e,authority:c(),redirectUri:m,postLogoutRedirectUri:a||m,navigateToLoginRequestUrl:l},cache:{cacheLocation:g,storeAuthStateInCookie:u},system:{loggerOptions:{loggerCallback:h||((d,y,R)=>{if(!(R||!n))switch(d){case LogLevel.Error:console.error("[MSAL]",y);break;case LogLevel.Warning:console.warn("[MSAL]",y);break;case LogLevel.Info:console.info("[MSAL]",y);break;case LogLevel.Verbose:console.debug("[MSAL]",y);break}}),logLevel:n?LogLevel.Verbose:LogLevel.Error}}}}var ce=null;function Ue(){return ce}function J({children:r,loadingComponent:e,onInitialized:t,...o}){let[i,a]=useState(null),g=useRef(null);return useEffect(()=>{if(typeof window>"u"||g.current)return;(async()=>{try{let l=j(o),n=new PublicClientApplication(l);await n.initialize();try{let c=await n.handleRedirectPromise();c&&(o.enableLogging&&console.log("[MSAL] Redirect authentication successful"),c.account&&n.setActiveAccount(c.account),window.location.hash&&window.history.replaceState(null,"",window.location.pathname+window.location.search));}catch(c){c?.errorCode==="no_token_request_cache_error"?o.enableLogging&&console.log("[MSAL] No pending redirect found (this is normal)"):c?.errorCode==="user_cancelled"?o.enableLogging&&console.log("[MSAL] User cancelled authentication"):console.error("[MSAL] Redirect handling error:",c),window.location.hash&&(window.location.hash.includes("code=")||window.location.hash.includes("error="))&&window.history.replaceState(null,"",window.location.pathname+window.location.search);}let h=n.getAllAccounts();h.length>0&&!n.getActiveAccount()&&n.setActiveAccount(h[0]);let f=o.enableLogging||!1;n.addEventCallback(c=>{if(c.eventType===EventType.LOGIN_SUCCESS){let s=c.payload;s?.account&&n.setActiveAccount(s.account),f&&console.log("[MSAL] Login successful:",s.account?.username);}if(c.eventType===EventType.LOGIN_FAILURE&&console.error("[MSAL] Login failed:",c.error),c.eventType===EventType.LOGOUT_SUCCESS&&(n.setActiveAccount(null),f&&console.log("[MSAL] Logout successful")),c.eventType===EventType.ACQUIRE_TOKEN_SUCCESS){let s=c.payload;s?.account&&!n.getActiveAccount()&&n.setActiveAccount(s.account);}c.eventType===EventType.ACQUIRE_TOKEN_FAILURE&&f&&console.error("[MSAL] Token acquisition failed:",c.error);}),g.current=n,ce=n,a(n),t&&t(n);}catch(l){throw console.error("[MSAL] Initialization failed:",l),l}})();},[]),typeof window>"u"?jsx(Fragment,{children:e||jsx("div",{children:"Loading authentication..."})}):i?jsx(MsalProvider,{instance:i,children:r}):jsx(Fragment,{children:e||jsx("div",{children:"Loading authentication..."})})}var Ne=createContext(void 0);function Fe({children:r,protection:e,...t}){return jsx(Ne.Provider,{value:e,children:jsx(J,{...t,children:r})})}var K=new Map;function A(r=["User.Read"]){let{instance:e,accounts:t,inProgress:o}=useMsal(),i=useAccount(t[0]||null),a=useMemo(()=>t.length>0,[t]),g=useCallback(async(c=r)=>{if(o!==InteractionStatus.None){console.warn("[MSAL] Interaction already in progress");return}try{let s={scopes:c,prompt:"select_account"};await e.loginRedirect(s);}catch(s){if(s?.errorCode==="user_cancelled"){console.log("[MSAL] User cancelled login");return}throw console.error("[MSAL] Login redirect failed:",s),s}},[e,r,o]),u=useCallback(async()=>{try{await e.logoutRedirect({account:i||void 0});}catch(c){throw console.error("[MSAL] Logout redirect failed:",c),c}},[e,i]),l=useCallback(async(c=r)=>{if(!i)throw new Error("[MSAL] No active account. Please login first.");try{let s={scopes:c,account:i,forceRefresh:!1};return (await e.acquireTokenSilent(s)).accessToken}catch(s){throw console.error("[MSAL] Silent token acquisition failed:",s),s}},[e,i,r]),n=useCallback(async(c=r)=>{if(!i)throw new Error("[MSAL] No active account. Please login first.");try{let s={scopes:c,account:i};await e.acquireTokenRedirect(s);}catch(s){throw console.error("[MSAL] Token redirect acquisition failed:",s),s}},[e,i,r]),h=useCallback(async(c=r)=>{let s=`${i?.homeAccountId||"anonymous"}-${c.sort().join(",")}`,m=K.get(s);if(m)return m;let p=(async()=>{try{return await l(c)}catch{throw console.warn("[MSAL] Silent token acquisition failed, falling back to redirect"),await n(c),new Error("[MSAL] Redirecting for token acquisition")}finally{K.delete(s);}})();return K.set(s,p),p},[l,n,r,i]),f=useCallback(async()=>{e.setActiveAccount(null),await e.clearCache();},[e]);return {account:i,accounts:t,isAuthenticated:a,inProgress:o!==InteractionStatus.None,loginRedirect:g,logoutRedirect:u,acquireToken:h,acquireTokenSilent:l,acquireTokenRedirect:n,clearSession:f}}function $e({text:r="Sign in with Microsoft",variant:e="dark",size:t="medium",scopes:o,className:i="",style:a,onSuccess:g,onError:u}){let{loginRedirect:l,inProgress:n}=A(),[h,f]=useState(false),c=async()=>{f(true);try{await l(o),g?.();}catch(y){u?.(y);}finally{setTimeout(()=>f(false),500);}},s={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},m={dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}},p=n||h,d={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:p?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:p?.6:1,...m[e],...s[t],...a};return jsxs("button",{onClick:c,disabled:p,className:i,style:d,"aria-label":r,children:[jsx(ze,{}),jsx("span",{children:r})]})}function ze(){return jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function qe({text:r="Sign out",variant:e="dark",size:t="medium",className:o="",style:i,onSuccess:a,onError:g}){let{logoutRedirect:u,inProgress:l}=A(),n=async()=>{try{await u(),a?.();}catch(s){g?.(s);}},h={small:{padding:"8px 16px",fontSize:"14px",height:"36px"},medium:{padding:"10px 20px",fontSize:"15px",height:"41px"},large:{padding:"12px 24px",fontSize:"16px",height:"48px"}},c={display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"12px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontWeight:600,borderRadius:"2px",cursor:l?"not-allowed":"pointer",transition:"all 0.2s ease",opacity:l?.6:1,...{dark:{backgroundColor:"#2F2F2F",color:"#FFFFFF",border:"1px solid #8C8C8C"},light:{backgroundColor:"#FFFFFF",color:"#5E5E5E",border:"1px solid #8C8C8C"}}[e],...h[t],...i};return jsxs("button",{onClick:n,disabled:l,className:o,style:c,"aria-label":r,children:[jsx(Be,{}),jsx("span",{children:r})]})}function Be(){return jsxs("svg",{width:"21",height:"21",viewBox:"0 0 21 21",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{width:"10",height:"10",fill:"#F25022"}),jsx("rect",{x:"11",width:"10",height:"10",fill:"#7FBA00"}),jsx("rect",{y:"11",width:"10",height:"10",fill:"#00A4EF"}),jsx("rect",{x:"11",y:"11",width:"10",height:"10",fill:"#FFB900"})]})}function N(){let{acquireToken:r}=A(),e=useCallback(async(u,l={})=>{let{scopes:n=["User.Read"],version:h="v1.0",debug:f=false,...c}=l;try{let s=await r(n),m=`https://graph.microsoft.com/${h}`,p=u.startsWith("http")?u:`${m}${u.startsWith("/")?u:`/${u}`}`;f&&console.log("[GraphAPI] Request:",{url:p,method:c.method||"GET"});let d=await fetch(p,{...c,headers:{Authorization:`Bearer ${s}`,"Content-Type":"application/json",...c.headers}});if(!d.ok){let R=await d.text(),M=`Graph API error (${d.status}): ${R}`;throw new Error(M)}if(d.status===204||d.headers.get("content-length")==="0")return null;let y=await d.json();return f&&console.log("[GraphAPI] Response:",y),y}catch(s){let m=w(s);throw console.error("[GraphAPI] Request failed:",m),new Error(m)}},[r]),t=useCallback((u,l={})=>e(u,{...l,method:"GET"}),[e]),o=useCallback((u,l,n={})=>e(u,{...n,method:"POST",body:l?JSON.stringify(l):void 0}),[e]),i=useCallback((u,l,n={})=>e(u,{...n,method:"PUT",body:l?JSON.stringify(l):void 0}),[e]),a=useCallback((u,l,n={})=>e(u,{...n,method:"PATCH",body:l?JSON.stringify(l):void 0}),[e]),g=useCallback((u,l={})=>e(u,{...l,method:"DELETE"}),[e]);return {get:t,post:o,put:i,patch:a,delete:g,request:e}}var x=new Map,_e=300*1e3,me=100;function Ve(){if(x.size>me){let r=Array.from(x.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,x.size-me).forEach(([t])=>{let o=x.get(t);o?.data.photo&&URL.revokeObjectURL(o.data.photo),x.delete(t);});}}function Q(){let{isAuthenticated:r,account:e}=A(),t=N(),[o,i]=useState(null),[a,g]=useState(false),[u,l]=useState(null),n=useCallback(async()=>{if(!r||!e){i(null);return}let f=e.homeAccountId,c=x.get(f);if(c&&Date.now()-c.timestamp<_e){i(c.data);return}g(true),l(null);try{let s=await t.get("/me",{scopes:["User.Read"]}),m;try{let d=await t.get("/me/photo/$value",{scopes:["User.Read"],headers:{"Content-Type":"image/jpeg"}});d&&(m=URL.createObjectURL(d));}catch{console.debug("[UserProfile] Photo not available");}let p={id:s.id,displayName:s.displayName,givenName:s.givenName,surname:s.surname,userPrincipalName:s.userPrincipalName,mail:s.mail,jobTitle:s.jobTitle,officeLocation:s.officeLocation,mobilePhone:s.mobilePhone,businessPhones:s.businessPhones,photo:m};x.set(f,{data:p,timestamp:Date.now()}),Ve(),i(p);}catch(s){let p=w(s),d=new Error(p);l(d),console.error("[UserProfile] Failed to fetch profile:",p);}finally{g(false);}},[r,e,t]),h=useCallback(()=>{if(e){let f=x.get(e.homeAccountId);f?.data.photo&&URL.revokeObjectURL(f.data.photo),x.delete(e.homeAccountId);}o?.photo&&URL.revokeObjectURL(o.photo),i(null);},[e,o]);return useEffect(()=>(n(),()=>{o?.photo&&URL.revokeObjectURL(o.photo);}),[n]),useEffect(()=>()=>{o?.photo&&URL.revokeObjectURL(o.photo);},[o?.photo]),{profile:o,loading:a,error:u,refetch:n,clearCache:h}}function We({size:r=40,className:e="",style:t,showTooltip:o=true,fallbackImage:i}){let{profile:a,loading:g}=Q(),[u,l]=useState(null),[n,h]=useState(false);useEffect(()=>{a?.photo&&l(a.photo);},[a?.photo]);let f=()=>{if(!a)return "?";let{givenName:m,surname:p,displayName:d}=a;if(m&&p)return `${m[0]}${p[0]}`.toUpperCase();if(d){let y=d.split(" ");return y.length>=2?`${y[0][0]}${y[y.length-1][0]}`.toUpperCase():d.substring(0,2).toUpperCase()}return "?"},c={width:`${r}px`,height:`${r}px`,borderRadius:"50%",display:"inline-flex",alignItems:"center",justifyContent:"center",fontSize:`${r*.4}px`,fontWeight:600,fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',backgroundColor:"#0078D4",color:"#FFFFFF",overflow:"hidden",userSelect:"none",...t},s=a?.displayName||"User";return g?jsx("div",{className:e,style:{...c,backgroundColor:"#E1E1E1"},"aria-label":"Loading user avatar",children:jsx("span",{style:{fontSize:`${r*.3}px`},children:"..."})}):u&&!n?jsx("div",{className:e,style:c,title:o?s:void 0,"aria-label":`${s} avatar`,children:jsx("img",{src:u,alt:s,style:{width:"100%",height:"100%",objectFit:"cover"},onError:()=>{h(true),i&&l(i);}})}):jsx("div",{className:e,style:c,title:o?s:void 0,"aria-label":`${s} avatar`,children:f()})}function je({className:r="",style:e,showDetails:t=false,renderLoading:o,renderAuthenticated:i,renderUnauthenticated:a}){let{isAuthenticated:g,inProgress:u,account:l}=A(),n={display:"inline-flex",alignItems:"center",gap:"8px",padding:"8px 12px",borderRadius:"4px",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',fontSize:"14px",fontWeight:500,...e};if(u)return o?jsx(Fragment,{children:o()}):jsxs("div",{className:r,style:{...n,backgroundColor:"#FFF4CE",color:"#8A6D3B"},role:"status","aria-live":"polite",children:[jsx(X,{color:"#FFA500"}),jsx("span",{children:"Loading..."})]});if(g){let h=l?.username||l?.name||"User";return i?jsx(Fragment,{children:i(h)}):jsxs("div",{className:r,style:{...n,backgroundColor:"#D4EDDA",color:"#155724"},role:"status","aria-live":"polite",children:[jsx(X,{color:"#28A745"}),jsx("span",{children:t?`Authenticated as ${h}`:"Authenticated"})]})}return a?jsx(Fragment,{children:a()}):jsxs("div",{className:r,style:{...n,backgroundColor:"#F8D7DA",color:"#721C24"},role:"status","aria-live":"polite",children:[jsx(X,{color:"#DC3545"}),jsx("span",{children:"Not authenticated"})]})}function X({color:r}){return jsx("svg",{width:"8",height:"8",viewBox:"0 0 8 8",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:jsx("circle",{cx:"4",cy:"4",r:"4",fill:r})})}function re({children:r,loadingComponent:e,fallbackComponent:t,scopes:o,onAuthRequired:i}){let{isAuthenticated:a,inProgress:g,loginRedirect:u}=A();return useEffect(()=>{!a&&!g&&(i?.(),(async()=>{try{await u(o);}catch(n){console.error("[AuthGuard] Authentication failed:",n);}})());},[a,g,o,u,i]),g?jsx(Fragment,{children:e||jsx("div",{children:"Authenticating..."})}):a?jsx(Fragment,{children:r}):jsx(Fragment,{children:t||jsx("div",{children:"Redirecting to login..."})})}var ne=class extends Component{constructor(t){super(t);this.reset=()=>{this.setState({hasError:false,error:null});};this.state={hasError:false,error:null};}static getDerivedStateFromError(t){return {hasError:true,error:t}}componentDidCatch(t,o){let{onError:i,debug:a}=this.props;a&&(console.error("[ErrorBoundary] Caught error:",t),console.error("[ErrorBoundary] Error info:",o)),i?.(t,o);}render(){let{hasError:t,error:o}=this.state,{children:i,fallback:a}=this.props;return t&&o?a?a(o,this.reset):jsxs("div",{style:{padding:"20px",margin:"20px",border:"1px solid #DC3545",borderRadius:"4px",backgroundColor:"#F8D7DA",color:"#721C24",fontFamily:'"Segoe UI", Tahoma, Geneva, Verdana, sans-serif'},children:[jsx("h2",{style:{margin:"0 0 10px 0",fontSize:"18px"},children:"Authentication Error"}),jsx("p",{style:{margin:"0 0 10px 0"},children:o.message}),jsx("button",{onClick:this.reset,style:{padding:"8px 16px",backgroundColor:"#DC3545",color:"#FFFFFF",border:"none",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:600},children:"Try Again"})]}):i}};var v=new Map,Xe=300*1e3,Ae=100;function Ye(r){r?v.delete(r):v.clear();}function et(){if(v.size>Ae){let r=Array.from(v.entries());r.sort((t,o)=>t[1].timestamp-o[1].timestamp),r.slice(0,v.size-Ae).forEach(([t])=>v.delete(t));}}function tt(){let{isAuthenticated:r,account:e}=A(),t=N(),[o,i]=useState([]),[a,g]=useState([]),[u,l]=useState(false),[n,h]=useState(null),f=useCallback(async()=>{if(!r||!e){i([]),g([]);return}let d=e.homeAccountId,y=v.get(d);if(y&&Date.now()-y.timestamp<Xe){i(y.roles),g(y.groups);return}l(true),h(null);try{let M=e.idTokenClaims?.roles||[],$=(await t.get("/me/memberOf",{scopes:["User.Read","Directory.Read.All"]})).value.map(se=>se.id);v.set(d,{roles:M,groups:$,timestamp:Date.now()}),et(),i(M),g($);}catch(R){let V=w(R),$=new Error(V);h($),console.error("[Roles] Failed to fetch roles/groups:",V);let Re=e.idTokenClaims?.roles||[];i(Re);}finally{l(false);}},[r,e,t]),c=useCallback(d=>o.includes(d),[o]),s=useCallback(d=>a.includes(d),[a]),m=useCallback(d=>d.some(y=>o.includes(y)),[o]),p=useCallback(d=>d.every(y=>o.includes(y)),[o]);return useEffect(()=>(f(),()=>{e&&Ye(e.homeAccountId);}),[f,e]),{roles:o,groups:a,loading:u,error:n,hasRole:c,hasGroup:s,hasAnyRole:m,hasAllRoles:p,refetch:f}}function rt(r,e={}){let{displayName:t,...o}=e,i=a=>jsx(re,{...o,children:jsx(r,{...a})});return i.displayName=t||`withAuth(${r.displayName||r.name||"Component"})`,i}async function Pe(r,e={}){let{maxRetries:t=3,initialDelay:o=1e3,maxDelay:i=1e4,backoffMultiplier:a=2,debug:g=false}=e,u,l=o;for(let n=0;n<=t;n++)try{return g&&n>0&&console.log(`[TokenRetry] Attempt ${n+1}/${t+1}`),await r()}catch(h){if(u=h,n===t){g&&console.error("[TokenRetry] All retry attempts failed");break}if(!ot(h))throw g&&console.log("[TokenRetry] Non-retryable error, aborting"),h;g&&console.warn(`[TokenRetry] Attempt ${n+1} failed, retrying in ${l}ms...`),await nt(l),l=Math.min(l*a,i);}throw u}function ot(r){let e=r.message.toLowerCase();return !!(e.includes("network")||e.includes("timeout")||e.includes("fetch")||e.includes("connection")||e.includes("500")||e.includes("502")||e.includes("503")||e.includes("429")||e.includes("rate limit")||e.includes("token")&&e.includes("expired"))}function nt(r){return new Promise(e=>setTimeout(e,r))}function it(r,e={}){return (...t)=>Pe(()=>r(...t),e)}var B=class{constructor(e={}){this.logHistory=[];this.performanceTimings=new Map;this.config={enabled:e.enabled??false,prefix:e.prefix??"[MSAL-Next]",showTimestamp:e.showTimestamp??true,level:e.level??"info",enablePerformance:e.enablePerformance??false,enableNetworkLogs:e.enableNetworkLogs??false,maxHistorySize:e.maxHistorySize??100};}shouldLog(e){if(!this.config.enabled)return false;let t=["error","warn","info","debug"],o=t.indexOf(this.config.level);return t.indexOf(e)<=o}formatMessage(e,t,o){let i=this.config.showTimestamp?`[${new Date().toISOString()}]`:"",a=this.config.prefix,g=`[${e.toUpperCase()}]`,u=`${i} ${a} ${g} ${t}`;return o!==void 0&&(u+=`
|
|
2
|
+
`+JSON.stringify(o,null,2)),u}addToHistory(e,t,o){this.logHistory.length>=this.config.maxHistorySize&&this.logHistory.shift(),this.logHistory.push({timestamp:Date.now(),level:e,message:t,data:o});}error(e,t){this.shouldLog("error")&&(console.error(this.formatMessage("error",e,t)),this.addToHistory("error",e,t));}warn(e,t){this.shouldLog("warn")&&(console.warn(this.formatMessage("warn",e,t)),this.addToHistory("warn",e,t));}info(e,t){this.shouldLog("info")&&(console.info(this.formatMessage("info",e,t)),this.addToHistory("info",e,t));}debug(e,t){this.shouldLog("debug")&&(console.debug(this.formatMessage("debug",e,t)),this.addToHistory("debug",e,t));}group(e){this.config.enabled&&console.group(`${this.config.prefix} ${e}`);}groupEnd(){this.config.enabled&&console.groupEnd();}startTiming(e){this.config.enablePerformance&&(this.performanceTimings.set(e,{operation:e,startTime:performance.now()}),this.debug(`\u23F1\uFE0F Started: ${e}`));}endTiming(e){if(this.config.enablePerformance){let t=this.performanceTimings.get(e);if(t)return t.endTime=performance.now(),t.duration=t.endTime-t.startTime,this.info(`\u23F1\uFE0F Completed: ${e} (${t.duration.toFixed(2)}ms)`),t.duration}}logRequest(e,t,o){this.config.enableNetworkLogs&&this.debug(`\u{1F310} ${e} ${t}`,o);}logResponse(e,t,o,i){if(this.config.enableNetworkLogs){let a=o>=200&&o<300?"\u2705":"\u274C";this.debug(`${a} ${e} ${t} - ${o}`,i);}}getHistory(){return [...this.logHistory]}getPerformanceTimings(){return Array.from(this.performanceTimings.values())}clearHistory(){this.logHistory=[];}clearTimings(){this.performanceTimings.clear();}exportLogs(){return JSON.stringify({config:this.config,history:this.logHistory,performanceTimings:Array.from(this.performanceTimings.values()),exportedAt:new Date().toISOString()},null,2)}downloadLogs(e="msal-next-debug-logs.json"){if(typeof window>"u")return;let t=this.exportLogs(),o=new Blob([t],{type:"application/json"}),i=URL.createObjectURL(o),a=document.createElement("a");a.href=i,a.download=e,a.click(),URL.revokeObjectURL(i);}setEnabled(e){this.config.enabled=e;}setLevel(e){e&&(this.config.level=e);}},O=null;function st(r){return O?r&&(r.enabled!==void 0&&O.setEnabled(r.enabled),r.level&&O.setLevel(r.level)):O=new B(r),O}function at(r,e){return new B({...e,prefix:`[MSAL-Next:${r}]`})}function _({children:r,config:e,defaultRedirectTo:t="/login",defaultLoading:o,defaultUnauthorized:i,debug:a=false}){let g=useRouter(),{isAuthenticated:u,account:l,inProgress:n}=A(),[h,f]=useState(true),[c,s]=useState(false);return useEffect(()=>{async function m(){if(a&&console.log("[ProtectedPage] Checking auth...",{isAuthenticated:u,inProgress:n,config:e}),!n){if(!e.required){s(true),f(false);return}if(!u||!l){a&&console.log("[ProtectedPage] Not authenticated, redirecting...");let p=e.redirectTo||t,d=encodeURIComponent(window.location.pathname+window.location.search);g.push(`${p}?returnUrl=${d}`);return}if(e.roles&&e.roles.length>0){let p=l.idTokenClaims?.roles||[];if(!e.roles.some(y=>p.includes(y))){a&&console.log("[ProtectedPage] Missing required role",{required:e.roles,user:p}),s(false),f(false);return}}if(e.validate)try{if(!await e.validate(l)){a&&console.log("[ProtectedPage] Custom validation failed"),s(!1),f(!1);return}}catch(p){console.error("[ProtectedPage] Validation error:",p),s(false),f(false);return}a&&console.log("[ProtectedPage] Authorization successful"),s(true),f(false);}}m();},[u,l,n,e,g,t,a]),h||n?e.loading?jsx(Fragment,{children:e.loading}):o?jsx(Fragment,{children:o}):jsx("div",{className:"flex items-center justify-center min-h-screen",children:jsx("div",{className:"animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"})}):c?jsx(Fragment,{children:r}):e.unauthorized?jsx(Fragment,{children:e.unauthorized}):i?jsx(Fragment,{children:i}):jsx("div",{className:"flex items-center justify-center min-h-screen",children:jsxs("div",{className:"text-center",children:[jsx("h1",{className:"text-2xl font-bold text-gray-900 mb-2",children:"Access Denied"}),jsx("p",{className:"text-gray-600",children:"You don't have permission to access this page."})]})})}function we(r,e,t){let o=i=>jsx(_,{config:e,defaultRedirectTo:t?.defaultRedirectTo,defaultLoading:t?.defaultLoading,defaultUnauthorized:t?.defaultUnauthorized,debug:t?.debug,children:jsx(r,{...i})});return o.displayName=`withPageAuth(${r.displayName||r.name||"Component"})`,o}function dt(r={}){let{protectedRoutes:e=[],publicOnlyRoutes:t=[],loginPath:o="/login",redirectAfterLogin:i="/",sessionCookie:a="msal.account",isAuthenticated:g,debug:u=false}=r;return async function(n){let{pathname:h}=n.nextUrl;u&&console.log("[AuthMiddleware] Processing:",h);let f=false;g?f=await g(n):f=!!n.cookies.get(a)?.value,u&&console.log("[AuthMiddleware] Authenticated:",f);let c=e.some(p=>h.startsWith(p)),s=t.some(p=>h.startsWith(p));if(c&&!f){u&&console.log("[AuthMiddleware] Redirecting to login");let p=n.nextUrl.clone();return p.pathname=o,p.searchParams.set("returnUrl",h),NextResponse.redirect(p)}if(s&&f){u&&console.log("[AuthMiddleware] Redirecting to home");let p=n.nextUrl.searchParams.get("returnUrl"),d=n.nextUrl.clone();return d.pathname=p||i,d.searchParams.delete("returnUrl"),NextResponse.redirect(d)}let m=NextResponse.next();if(f){m.headers.set("x-msal-authenticated","true");try{let p=n.cookies.get(a);if(p?.value){let d=H(p.value,W);d?.username&&m.headers.set("x-msal-username",d.username);}}catch{u&&console.warn("[AuthMiddleware] Failed to parse session data");}}return m}}export{re as AuthGuard,je as AuthStatus,ne as ErrorBoundary,Fe as MSALProvider,$e as MicrosoftSignInButton,J as MsalAuthProvider,_ as ProtectedPage,qe as SignOutButton,We as UserAvatar,dt as createAuthMiddleware,j as createMsalConfig,it as createRetryWrapper,at as createScopedLogger,st as getDebugLogger,Ue as getMsalInstance,W as isValidAccountData,z as isValidRedirectUri,ae as isValidScope,Pe as retryWithBackoff,H as safeJsonParse,w as sanitizeError,N as useGraphApi,A as useMsalAuth,tt as useRoles,Q as useUserProfile,Ce as validateScopes,rt as withAuth,we as withPageAuth};
|
package/package.json
CHANGED