34b62f7516
* feat: implement generalized navigation permission system with PBAC - Create NavigationPermissionsProvider context for server-side permission data - Add checkNavigationPermissions utility using PermissionCheckService - Update main navigation layout to check permissions server-side - Enhance useShouldDisplayNavigationItem for generalized permission filtering - Support permission mapping for insights, workflows, routing, teams, members - Use unstable_cache for performance optimization - Replace insights-specific logic with scalable PBAC-based system Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: correct flag check logic in useShouldDisplayNavigationItem - Only return false when flag is explicitly false - Allow navigation permission checks to run when flags are truthy - Fixes bug where truthy flags would short-circuit permission checks Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: resolve linting errors in embed-core files - Replace forbidden non-null assertion with null check in embed.ts - Replace 'any' type with 'unknown' in embed.test.ts - Replace non-null assertion with proper null check in EmbedElement.test.ts - Remove unused variable declaration These are pre-existing linting issues unrelated to navigation permissions feature. Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: resolve server-client boundary issue in NavigationPermissionsProvider - Add 'use client' directive to NavigationPermissionsProvider.ts - Replace JSX syntax with React.createElement to fix TypeScript compilation - Create NavigationPermissionsWrapper.tsx as client component bridge - Update layout.tsx to use wrapper instead of provider directly - Ensure proper separation between server-side permission checking and client-side context consumption This fixes the architectural issue where useContext was being used in server components. Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * Revert "fix: resolve linting errors in embed-core files" This reverts commit 4f481bae576376c9f9177215f7872c8bf7132894. * refactor: simplify NavigationPermissionsProvider approach - Remove NavigationPermissionsWrapper.tsx (revert to simpler approach) - Rename NavigationPermissionsProvider.ts to .tsx for JSX support - Update layout.tsx to use NavigationPermissionsProvider directly - Keep 'use client' directive for proper server-client boundary handling - Maintain all navigation permission functionality with cleaner architecture Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * clean up * return true for no team situation * fix: prevent hidden navigation items from reappearing via stored expansion state - Modified usePersistedExpansionState hook to accept shouldDisplay parameter - Clear stored expansion state for items that shouldn't be displayed - Prevent state persistence for items without permissions - Updated both NavigationItem and MobileNavigationMoreItem components - Use safe sessionStorage import from @calcom/lib/webstorage Fixes bug where clicking 'Workflows' would restore 'Insights' menu visibility even when user lacks insights permissions due to sessionStorage state restoration. Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix: add sessionStorage to webstorage module and export NavigationItemName type - Added sessionStorage wrapper to @calcom/lib/webstorage with safe error handling - Export NavigationItemName type from NavigationPermissionsProvider for proper type access - Resolves TypeScript compilation errors in navigation permission system These changes enable the collapsible menu state bug fix to compile properly. Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: improve separation of concerns in usePersistedExpansionState hook - Remove shouldDisplay parameter from usePersistedExpansionState hook - Move state clearing logic for hidden items to NavigationItem component level - Add setIsExpanded to useEffect dependency arrays to fix ESLint warnings - Maintain bug fix functionality while improving code design - Better separation between expansion state management and display permissions This addresses user feedback about inappropriate coupling between concerns. Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix provider * fix unstable_cache * refactor: move navigation permission checks to client-side with tRPC - Replace server-side unstable_cache permission checks with client-side tRPC query - Add getNavigationPermissions query to PBAC router - Update NavigationPermissionsProvider to use tRPC with loading states - Remove server-side checkNavigationPermissions function - Improve initial page load performance by deferring permission checks Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * refactor: centralize navigation item definitions to eliminate repetition - Create NAVIGATION_ITEMS_CONFIG as single source of truth for navigation items - Auto-generate NAVIGATION_PERMISSION_MAP from centralized config - Update Navigation.tsx to use centralized definitions for teams, routing, workflows, insights - Fix import issues in NavigationPermissionsProvider.tsx - Eliminate hardcoded repetition of navigation item properties across codebase Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * clean up * clean up permissions --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
69 lines
2.0 KiB
TypeScript
69 lines
2.0 KiB
TypeScript
/**
|
|
* Provides a wrapper around localStorage(and sessionStorage(TODO when needed)) to avoid errors in case of restricted storage access.
|
|
*
|
|
* TODO: In case of an embed if localStorage is not available(third party), use localStorage of parent(first party) that contains the iframe.
|
|
*/
|
|
export const localStorage = {
|
|
getItem(key: string) {
|
|
try {
|
|
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
|
|
return window.localStorage.getItem(key);
|
|
} catch (e) {
|
|
// In case storage is restricted. Possible reasons
|
|
// 1. Third Party Context in Chrome Incognito mode.
|
|
return null;
|
|
}
|
|
},
|
|
setItem(key: string, value: string) {
|
|
try {
|
|
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
|
|
window.localStorage.setItem(key, value);
|
|
} catch (e) {
|
|
// In case storage is restricted. Possible reasons
|
|
// 1. Third Party Context in Chrome Incognito mode.
|
|
// 2. Storage limit reached
|
|
return;
|
|
}
|
|
},
|
|
removeItem: (key: string) => {
|
|
try {
|
|
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
|
|
window.localStorage.removeItem(key);
|
|
} catch (e) {
|
|
return;
|
|
}
|
|
},
|
|
};
|
|
|
|
export const sessionStorage = {
|
|
getItem(key: string) {
|
|
try {
|
|
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
|
|
return window.sessionStorage.getItem(key);
|
|
} catch (e) {
|
|
// In case storage is restricted. Possible reasons
|
|
// 1. Third Party Context in Chrome Incognito mode.
|
|
return null;
|
|
}
|
|
},
|
|
setItem(key: string, value: string) {
|
|
try {
|
|
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
|
|
window.sessionStorage.setItem(key, value);
|
|
} catch (e) {
|
|
// In case storage is restricted. Possible reasons
|
|
// 1. Third Party Context in Chrome Incognito mode.
|
|
// 2. Storage limit reached
|
|
return;
|
|
}
|
|
},
|
|
removeItem: (key: string) => {
|
|
try {
|
|
// eslint-disable-next-line @calcom/eslint/avoid-web-storage
|
|
window.sessionStorage.removeItem(key);
|
|
} catch (e) {
|
|
return;
|
|
}
|
|
},
|
|
};
|