{"version":3,"file":"rbac-context.mjs","sources":["../../../../src/lib/auth/rbac/rbac-context.tsx"],"sourcesContent":["/**\n * RBAC React Context\n *\n * React context provider for RBAC functionality.\n * Integrates with the auth system to provide permission checking.\n *\n * @module auth/rbac/rbac-context\n */\n\nimport React, {\n  createContext,\n  useCallback,\n  useEffect,\n  useMemo,\n  useState,\n  type ReactNode,\n} from 'react';\nimport { useFeatureFlag } from '@/lib/flags';\nimport type {\n  RBACConfig,\n  RBACState,\n  RBACContextValue,\n  RoleDefinition,\n  Permission,\n  PermissionAction,\n  AccessRequest,\n  EvaluationResult,\n} from './types';\nimport type { User } from '../types';\nimport { createRBACEngine } from './rbac-engine';\n\n// =============================================================================\n// Context\n// =============================================================================\n\n/**\n * RBAC Context for React applications.\n */\n// @refresh reset\n// eslint-disable-next-line react-refresh/only-export-components\nexport const RBACContext = createContext<RBACContextValue | null>(null);\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/**\n * RBAC Provider props.\n */\nexport interface RBACProviderProps {\n  /** RBAC configuration */\n  config: RBACConfig;\n  /** Child components */\n  children: ReactNode;\n  /** Current user */\n  user?: User | null;\n  /** User's assigned roles */\n  userRoles?: string[];\n  /** User's direct permissions */\n  userPermissions?: Permission[];\n  /** Callback to fetch permissions from server */\n  fetchPermissions?: () => Promise<{\n    roles: string[];\n    permissions: Permission[];\n  }>;\n  /** Loading component */\n  loadingComponent?: ReactNode;\n  /** Callback when permission check occurs */\n  onPermissionCheck?: (permission: Permission, granted: boolean) => void;\n  /** Callback when access check occurs */\n  onAccessCheck?: (resource: string, action: PermissionAction, granted: boolean) => void;\n}\n\n// =============================================================================\n// Provider Component\n// =============================================================================\n\n/**\n * RBAC Provider Component.\n *\n * Provides RBAC functionality to child components through React context.\n *\n * @example\n * ```tsx\n * import { RBACProvider } from '@/lib/auth/rbac';\n *\n * const rbacConfig = {\n *   roles: [\n *     { id: 'admin', name: 'Admin', permissions: ['*'], priority: 100 },\n *     { id: 'user', name: 'User', permissions: ['read:*'], priority: 10 },\n *   ],\n *   defaultDecision: 'deny',\n *   enableCaching: true,\n * };\n *\n * function App() {\n *   const { user } = useAuth();\n *\n *   return (\n *     <RBACProvider\n *       config={rbacConfig}\n *       user={user}\n *       userRoles={user?.roles}\n *     >\n *       <MyApplication />\n *     </RBACProvider>\n *   );\n * }\n * ```\n */\nexport function RBACProvider({\n  config,\n  children,\n  user,\n  userRoles = [],\n  userPermissions = [],\n  fetchPermissions,\n  loadingComponent,\n  onPermissionCheck,\n  onAccessCheck,\n}: RBACProviderProps): React.ReactElement {\n  // Check feature flag\n  const isRBACEnabled = useFeatureFlag(config.featureFlag ?? 'rbac');\n\n  // State\n  const [state, setState] = useState<RBACState>({\n    initialized: false,\n    loading: true,\n    userRoles: [],\n    userPermissions: [],\n    evaluationCache: new Map(),\n    lastRefresh: null,\n    error: null,\n  });\n\n  // Create RBAC engine\n  const engine = useMemo(() => createRBACEngine(config), [config]);\n\n  // ===========================================================================\n  // Initialization\n  // ===========================================================================\n\n  useEffect(() => {\n    if (!isRBACEnabled) {\n      setState((prev) => ({ ...prev, initialized: true, loading: false }));\n      return;\n    }\n\n    const initialize = async (): Promise<void> => {\n      setState((prev) => ({ ...prev, loading: true, error: null }));\n\n      try {\n        let roles = userRoles;\n        let permissions = userPermissions;\n\n        // Fetch permissions from server if callback provided\n        if (fetchPermissions) {\n          const fetched = await fetchPermissions();\n          const { roles: fetchedRoles, permissions: fetchedPermissions } = fetched;\n          roles = fetchedRoles;\n          permissions = fetchedPermissions;\n        }\n\n        // Set user context on engine\n        engine.setUserContext(roles, {\n          id: user?.id,\n          email: user?.email,\n          ...user?.metadata,\n        });\n\n        setState((prev) => ({\n          ...prev,\n          initialized: true,\n          loading: false,\n          userRoles: roles,\n          userPermissions: permissions,\n          lastRefresh: Date.now(),\n        }));\n      } catch (error) {\n        setState((prev) => ({\n          ...prev,\n          loading: false,\n          error: error instanceof Error ? error.message : 'Failed to initialize RBAC',\n        }));\n      }\n    };\n\n    void initialize();\n  }, [isRBACEnabled, user, userRoles, userPermissions, fetchPermissions, engine]);\n\n  // Update engine when roles change\n  useEffect(() => {\n    if (state.initialized && state.userRoles.length > 0) {\n      engine.setUserContext(state.userRoles, {\n        id: user?.id,\n        email: user?.email,\n        ...user?.metadata,\n      });\n    }\n  }, [state.initialized, state.userRoles, user, engine]);\n\n  // ===========================================================================\n  // Permission Checking Methods\n  // ===========================================================================\n\n  const hasPermission = useCallback(\n    (permission: Permission): boolean => {\n      if (!isRBACEnabled) return true;\n\n      const granted = engine.hasPermission(permission);\n      onPermissionCheck?.(permission, granted);\n\n      return granted;\n    },\n    [isRBACEnabled, engine, onPermissionCheck]\n  );\n\n  const hasAnyPermission = useCallback(\n    (permissions: Permission[]): boolean => {\n      if (!isRBACEnabled) return true;\n      return engine.hasAnyPermission(permissions);\n    },\n    [isRBACEnabled, engine]\n  );\n\n  const hasAllPermissions = useCallback(\n    (permissions: Permission[]): boolean => {\n      if (!isRBACEnabled) return true;\n      return engine.hasAllPermissions(permissions);\n    },\n    [isRBACEnabled, engine]\n  );\n\n  // ===========================================================================\n  // Role Checking Methods\n  // ===========================================================================\n\n  const hasRole = useCallback(\n    (role: string): boolean => {\n      if (!isRBACEnabled) return true;\n      return engine.hasRole(role);\n    },\n    [isRBACEnabled, engine]\n  );\n\n  const hasAnyRole = useCallback(\n    (roles: string[]): boolean => {\n      if (!isRBACEnabled) return true;\n      return engine.hasAnyRole(roles);\n    },\n    [isRBACEnabled, engine]\n  );\n\n  const hasAllRoles = useCallback(\n    (roles: string[]): boolean => {\n      if (!isRBACEnabled) return true;\n      return engine.hasAllRoles(roles);\n    },\n    [isRBACEnabled, engine]\n  );\n\n  // ===========================================================================\n  // Access Checking Methods\n  // ===========================================================================\n\n  const canAccess = useCallback(\n    (resource: string, action: PermissionAction, resourceId?: string): boolean => {\n      if (!isRBACEnabled) return true;\n\n      const granted =\n        resourceId !== null && resourceId !== undefined && resourceId !== ''\n          ? engine.checkResourcePermission(resource, resourceId, action)\n          : engine.canAccess(resource, action);\n\n      onAccessCheck?.(resource, action, granted);\n\n      return granted;\n    },\n    [isRBACEnabled, engine, onAccessCheck]\n  );\n\n  const evaluate = useCallback(\n    (request: AccessRequest): EvaluationResult => {\n      if (!isRBACEnabled) {\n        return {\n          allowed: true,\n          decision: 'allow',\n          reason: 'RBAC disabled',\n          evaluatedAt: Date.now(),\n        };\n      }\n\n      return engine.evaluate(request);\n    },\n    [isRBACEnabled, engine]\n  );\n\n  const checkResourcePermission = useCallback(\n    (resourceType: string, resourceId: string, action: PermissionAction): boolean => {\n      if (!isRBACEnabled) return true;\n      return engine.checkResourcePermission(resourceType, resourceId, action);\n    },\n    [isRBACEnabled, engine]\n  );\n\n  // ===========================================================================\n  // Utility Methods\n  // ===========================================================================\n\n  const getEffectivePermissions = useCallback((): Permission[] => {\n    return engine.getResolvedPermissions();\n  }, [engine]);\n\n  const getRoleDefinitions = useCallback((): RoleDefinition[] => {\n    return state.userRoles\n      .map((roleId) => config.roles.find((r) => r.id === roleId))\n      .filter((r): r is RoleDefinition => r !== undefined);\n  }, [state.userRoles, config.roles]);\n\n  const refreshPermissions = useCallback(async (): Promise<void> => {\n    if (!fetchPermissions) return;\n\n    setState((prev) => ({ ...prev, loading: true }));\n\n    try {\n      const { roles, permissions } = await fetchPermissions();\n\n      engine.setUserContext(roles, {\n        id: user?.id,\n        email: user?.email,\n        ...user?.metadata,\n      });\n\n      setState((prev) => ({\n        ...prev,\n        loading: false,\n        userRoles: roles,\n        userPermissions: permissions,\n        lastRefresh: Date.now(),\n      }));\n    } catch (error) {\n      setState((prev) => ({\n        ...prev,\n        loading: false,\n        error: error instanceof Error ? error.message : 'Failed to refresh permissions',\n      }));\n    }\n  }, [fetchPermissions, user, engine]);\n\n  const clearCache = useCallback((): void => {\n    engine.clearCache();\n    setState((prev) => ({\n      ...prev,\n      evaluationCache: new Map(),\n    }));\n  }, [engine]);\n\n  // ===========================================================================\n  // Context Value\n  // ===========================================================================\n\n  const contextValue: RBACContextValue = useMemo(\n    () => ({\n      ...state,\n      config,\n      hasPermission,\n      hasAnyPermission,\n      hasAllPermissions,\n      hasRole,\n      hasAnyRole,\n      hasAllRoles,\n      canAccess,\n      evaluate,\n      getEffectivePermissions,\n      getRoleDefinitions,\n      refreshPermissions,\n      clearCache,\n      checkResourcePermission,\n    }),\n    [\n      state,\n      config,\n      hasPermission,\n      hasAnyPermission,\n      hasAllPermissions,\n      hasRole,\n      hasAnyRole,\n      hasAllRoles,\n      canAccess,\n      evaluate,\n      getEffectivePermissions,\n      getRoleDefinitions,\n      refreshPermissions,\n      clearCache,\n      checkResourcePermission,\n    ]\n  );\n\n  // ===========================================================================\n  // Render\n  // ===========================================================================\n\n  // Show loading during initialization\n  if (state.loading && loadingComponent !== null && loadingComponent !== undefined) {\n    return <>{loadingComponent}</>;\n  }\n\n  // Feature flag disabled - render children without RBAC\n  if (!isRBACEnabled) {\n    return <>{children}</>;\n  }\n\n  return <RBACContext.Provider value={contextValue}>{children}</RBACContext.Provider>;\n}\n"],"names":["RBACContext","createContext","RBACProvider","config","children","user","userRoles","userPermissions","fetchPermissions","loadingComponent","onPermissionCheck","onAccessCheck","isRBACEnabled","useFeatureFlag","state","setState","useState","engine","useMemo","createRBACEngine","useEffect","prev","roles","permissions","fetched","fetchedRoles","fetchedPermissions","error","hasPermission","useCallback","permission","granted","hasAnyPermission","hasAllPermissions","hasRole","role","hasAnyRole","hasAllRoles","canAccess","resource","action","resourceId","evaluate","request","checkResourcePermission","resourceType","getEffectivePermissions","getRoleDefinitions","roleId","r","refreshPermissions","clearCache","contextValue"],"mappings":";;;;AAwCO,MAAMA,IAAcC,EAAuC,IAAI;AAsE/D,SAASC,EAAa;AAAA,EAC3B,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAC,IAAY,CAAA;AAAA,EACZ,iBAAAC,IAAkB,CAAA;AAAA,EAClB,kBAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,eAAAC;AACF,GAA0C;AAExC,QAAMC,IAAgBC,EAAeV,EAAO,eAAe,MAAM,GAG3D,CAACW,GAAOC,CAAQ,IAAIC,EAAoB;AAAA,IAC5C,aAAa;AAAA,IACb,SAAS;AAAA,IACT,WAAW,CAAA;AAAA,IACX,iBAAiB,CAAA;AAAA,IACjB,qCAAqB,IAAA;AAAA,IACrB,aAAa;AAAA,IACb,OAAO;AAAA,EAAA,CACR,GAGKC,IAASC,EAAQ,MAAMC,EAAiBhB,CAAM,GAAG,CAACA,CAAM,CAAC;AAM/D,EAAAiB,EAAU,MAAM;AACd,QAAI,CAACR,GAAe;AAClB,MAAAG,EAAS,CAACM,OAAU,EAAE,GAAGA,GAAM,aAAa,IAAM,SAAS,GAAA,EAAQ;AACnE;AAAA,IACF;AAyCA,KAvCmB,YAA2B;AAC5C,MAAAN,EAAS,CAACM,OAAU,EAAE,GAAGA,GAAM,SAAS,IAAM,OAAO,KAAA,EAAO;AAE5D,UAAI;AACF,YAAIC,IAAQhB,GACRiB,IAAchB;AAGlB,YAAIC,GAAkB;AACpB,gBAAMgB,IAAU,MAAMhB,EAAA,GAChB,EAAE,OAAOiB,GAAc,aAAaC,MAAuBF;AACjE,UAAAF,IAAQG,GACRF,IAAcG;AAAA,QAChB;AAGA,QAAAT,EAAO,eAAeK,GAAO;AAAA,UAC3B,IAAIjB,GAAM;AAAA,UACV,OAAOA,GAAM;AAAA,UACb,GAAGA,GAAM;AAAA,QAAA,CACV,GAEDU,EAAS,CAACM,OAAU;AAAA,UAClB,GAAGA;AAAA,UACH,aAAa;AAAA,UACb,SAAS;AAAA,UACT,WAAWC;AAAA,UACX,iBAAiBC;AAAA,UACjB,aAAa,KAAK,IAAA;AAAA,QAAI,EACtB;AAAA,MACJ,SAASI,GAAO;AACd,QAAAZ,EAAS,CAACM,OAAU;AAAA,UAClB,GAAGA;AAAA,UACH,SAAS;AAAA,UACT,OAAOM,aAAiB,QAAQA,EAAM,UAAU;AAAA,QAAA,EAChD;AAAA,MACJ;AAAA,IACF,GAEK;AAAA,EACP,GAAG,CAACf,GAAeP,GAAMC,GAAWC,GAAiBC,GAAkBS,CAAM,CAAC,GAG9EG,EAAU,MAAM;AACd,IAAIN,EAAM,eAAeA,EAAM,UAAU,SAAS,KAChDG,EAAO,eAAeH,EAAM,WAAW;AAAA,MACrC,IAAIT,GAAM;AAAA,MACV,OAAOA,GAAM;AAAA,MACb,GAAGA,GAAM;AAAA,IAAA,CACV;AAAA,EAEL,GAAG,CAACS,EAAM,aAAaA,EAAM,WAAWT,GAAMY,CAAM,CAAC;AAMrD,QAAMW,IAAgBC;AAAA,IACpB,CAACC,MAAoC;AACnC,UAAI,CAAClB,EAAe,QAAO;AAE3B,YAAMmB,IAAUd,EAAO,cAAca,CAAU;AAC/C,aAAApB,IAAoBoB,GAAYC,CAAO,GAEhCA;AAAA,IACT;AAAA,IACA,CAACnB,GAAeK,GAAQP,CAAiB;AAAA,EAAA,GAGrCsB,IAAmBH;AAAA,IACvB,CAACN,MACMX,IACEK,EAAO,iBAAiBM,CAAW,IADf;AAAA,IAG7B,CAACX,GAAeK,CAAM;AAAA,EAAA,GAGlBgB,IAAoBJ;AAAA,IACxB,CAACN,MACMX,IACEK,EAAO,kBAAkBM,CAAW,IADhB;AAAA,IAG7B,CAACX,GAAeK,CAAM;AAAA,EAAA,GAOlBiB,IAAUL;AAAA,IACd,CAACM,MACMvB,IACEK,EAAO,QAAQkB,CAAI,IADC;AAAA,IAG7B,CAACvB,GAAeK,CAAM;AAAA,EAAA,GAGlBmB,IAAaP;AAAA,IACjB,CAACP,MACMV,IACEK,EAAO,WAAWK,CAAK,IADH;AAAA,IAG7B,CAACV,GAAeK,CAAM;AAAA,EAAA,GAGlBoB,IAAcR;AAAA,IAClB,CAACP,MACMV,IACEK,EAAO,YAAYK,CAAK,IADJ;AAAA,IAG7B,CAACV,GAAeK,CAAM;AAAA,EAAA,GAOlBqB,IAAYT;AAAA,IAChB,CAACU,GAAkBC,GAA0BC,MAAiC;AAC5E,UAAI,CAAC7B,EAAe,QAAO;AAE3B,YAAMmB,IACJU,KAAe,QAAoCA,MAAe,KAC9DxB,EAAO,wBAAwBsB,GAAUE,GAAYD,CAAM,IAC3DvB,EAAO,UAAUsB,GAAUC,CAAM;AAEvC,aAAA7B,IAAgB4B,GAAUC,GAAQT,CAAO,GAElCA;AAAA,IACT;AAAA,IACA,CAACnB,GAAeK,GAAQN,CAAa;AAAA,EAAA,GAGjC+B,IAAWb;AAAA,IACf,CAACc,MACM/B,IASEK,EAAO,SAAS0B,CAAO,IARrB;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,aAAa,KAAK,IAAA;AAAA,IAAI;AAAA,IAM5B,CAAC/B,GAAeK,CAAM;AAAA,EAAA,GAGlB2B,IAA0Bf;AAAA,IAC9B,CAACgB,GAAsBJ,GAAoBD,MACpC5B,IACEK,EAAO,wBAAwB4B,GAAcJ,GAAYD,CAAM,IAD3C;AAAA,IAG7B,CAAC5B,GAAeK,CAAM;AAAA,EAAA,GAOlB6B,IAA0BjB,EAAY,MACnCZ,EAAO,uBAAA,GACb,CAACA,CAAM,CAAC,GAEL8B,IAAqBlB,EAAY,MAC9Bf,EAAM,UACV,IAAI,CAACkC,MAAW7C,EAAO,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO6C,CAAM,CAAC,EACzD,OAAO,CAACC,MAA2BA,MAAM,MAAS,GACpD,CAACnC,EAAM,WAAWX,EAAO,KAAK,CAAC,GAE5B+C,IAAqBrB,EAAY,YAA2B;AAChE,QAAKrB,GAEL;AAAA,MAAAO,EAAS,CAACM,OAAU,EAAE,GAAGA,GAAM,SAAS,KAAO;AAE/C,UAAI;AACF,cAAM,EAAE,OAAAC,GAAO,aAAAC,EAAA,IAAgB,MAAMf,EAAA;AAErC,QAAAS,EAAO,eAAeK,GAAO;AAAA,UAC3B,IAAIjB,GAAM;AAAA,UACV,OAAOA,GAAM;AAAA,UACb,GAAGA,GAAM;AAAA,QAAA,CACV,GAEDU,EAAS,CAACM,OAAU;AAAA,UAClB,GAAGA;AAAA,UACH,SAAS;AAAA,UACT,WAAWC;AAAA,UACX,iBAAiBC;AAAA,UACjB,aAAa,KAAK,IAAA;AAAA,QAAI,EACtB;AAAA,MACJ,SAASI,GAAO;AACd,QAAAZ,EAAS,CAACM,OAAU;AAAA,UAClB,GAAGA;AAAA,UACH,SAAS;AAAA,UACT,OAAOM,aAAiB,QAAQA,EAAM,UAAU;AAAA,QAAA,EAChD;AAAA,MACJ;AAAA;AAAA,EACF,GAAG,CAACnB,GAAkBH,GAAMY,CAAM,CAAC,GAE7BkC,IAAatB,EAAY,MAAY;AACzC,IAAAZ,EAAO,WAAA,GACPF,EAAS,CAACM,OAAU;AAAA,MAClB,GAAGA;AAAA,MACH,qCAAqB,IAAA;AAAA,IAAI,EACzB;AAAA,EACJ,GAAG,CAACJ,CAAM,CAAC,GAMLmC,IAAiClC;AAAA,IACrC,OAAO;AAAA,MACL,GAAGJ;AAAA,MACH,QAAAX;AAAA,MACA,eAAAyB;AAAA,MACA,kBAAAI;AAAA,MACA,mBAAAC;AAAA,MACA,SAAAC;AAAA,MACA,YAAAE;AAAA,MACA,aAAAC;AAAA,MACA,WAAAC;AAAA,MACA,UAAAI;AAAA,MACA,yBAAAI;AAAA,MACA,oBAAAC;AAAA,MACA,oBAAAG;AAAA,MACA,YAAAC;AAAA,MACA,yBAAAP;AAAA,IAAA;AAAA,IAEF;AAAA,MACE9B;AAAA,MACAX;AAAA,MACAyB;AAAA,MACAI;AAAA,MACAC;AAAA,MACAC;AAAA,MACAE;AAAA,MACAC;AAAA,MACAC;AAAA,MACAI;AAAA,MACAI;AAAA,MACAC;AAAA,MACAG;AAAA,MACAC;AAAA,MACAP;AAAA,IAAA;AAAA,EACF;AAQF,SAAI9B,EAAM,WAAWL,MAAqB,QAAQA,MAAqB,gCAC3D,UAAAA,EAAA,CAAiB,IAIxBG,sBAIGZ,EAAY,UAAZ,EAAqB,OAAOoD,GAAe,UAAAhD,GAAS,2BAHhD,UAAAA,GAAS;AAIvB;"}