@jmruthers/pace-core 0.5.42 → 0.5.44

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.
Files changed (142) hide show
  1. package/dist/{DataTable-DCW3J4YX.js → DataTable-GU72TTL6.js} +5 -5
  2. package/dist/{UnifiedAuthProvider-DGQsy-vY.d.ts → UnifiedAuthProvider-CQNiemcB.d.ts} +2 -2
  3. package/dist/{chunk-P27KH7XF.js → chunk-6CGBO4IS.js} +126 -192
  4. package/dist/chunk-6CGBO4IS.js.map +1 -0
  5. package/dist/{chunk-RL267HOF.js → chunk-7NAMQC3W.js} +2 -2
  6. package/dist/{chunk-BLZBTCBT.js → chunk-D4ZF5QUY.js} +2 -2
  7. package/dist/{chunk-APHGXR2D.js → chunk-DWA6SCGM.js} +3 -3
  8. package/dist/{chunk-CL2MCHIO.js → chunk-DZSLRIE2.js} +3 -3
  9. package/dist/{chunk-XC6XWRP6.js → chunk-HEYEDETJ.js} +6 -58
  10. package/dist/chunk-HEYEDETJ.js.map +1 -0
  11. package/dist/{chunk-ZSXH6L7D.js → chunk-KVMIO3BU.js} +3 -3
  12. package/dist/{chunk-YXTIVGX3.js → chunk-OTQBUB66.js} +4 -4
  13. package/dist/{chunk-ZRWNGBDJ.js → chunk-SFXM5VTP.js} +3 -3
  14. package/dist/{chunk-2DUJJPO2.js → chunk-U7EDXJBG.js} +5 -5
  15. package/dist/components.d.ts +1 -1
  16. package/dist/components.js +7 -7
  17. package/dist/hooks.js +4 -4
  18. package/dist/index.d.ts +1 -1
  19. package/dist/index.js +10 -10
  20. package/dist/providers.d.ts +1 -1
  21. package/dist/providers.js +3 -3
  22. package/dist/rbac/index.js +5 -5
  23. package/dist/utils.js +1 -1
  24. package/docs/api/classes/ErrorBoundary.md +1 -1
  25. package/docs/api/classes/InvalidScopeError.md +1 -1
  26. package/docs/api/classes/MissingUserContextError.md +1 -1
  27. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  28. package/docs/api/classes/PermissionDeniedError.md +1 -1
  29. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  30. package/docs/api/classes/RBACAuditManager.md +1 -1
  31. package/docs/api/classes/RBACCache.md +1 -1
  32. package/docs/api/classes/RBACEngine.md +1 -1
  33. package/docs/api/classes/RBACError.md +1 -1
  34. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  35. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  36. package/docs/api/interfaces/AggregateConfig.md +1 -1
  37. package/docs/api/interfaces/ButtonProps.md +1 -1
  38. package/docs/api/interfaces/CardProps.md +1 -1
  39. package/docs/api/interfaces/ColorPalette.md +1 -1
  40. package/docs/api/interfaces/ColorShade.md +1 -1
  41. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  42. package/docs/api/interfaces/DataTableAction.md +1 -1
  43. package/docs/api/interfaces/DataTableColumn.md +1 -1
  44. package/docs/api/interfaces/DataTableProps.md +1 -1
  45. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  46. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  47. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  48. package/docs/api/interfaces/EventContextType.md +7 -7
  49. package/docs/api/interfaces/EventLogoProps.md +1 -1
  50. package/docs/api/interfaces/EventProviderProps.md +2 -2
  51. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  52. package/docs/api/interfaces/FileUploadProps.md +1 -1
  53. package/docs/api/interfaces/FooterProps.md +1 -1
  54. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  55. package/docs/api/interfaces/InputProps.md +1 -1
  56. package/docs/api/interfaces/LabelProps.md +1 -1
  57. package/docs/api/interfaces/LoginFormProps.md +1 -1
  58. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  59. package/docs/api/interfaces/NavigationContextType.md +1 -1
  60. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  61. package/docs/api/interfaces/NavigationItem.md +1 -1
  62. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  63. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  64. package/docs/api/interfaces/Organisation.md +1 -1
  65. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  66. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  67. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  68. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  69. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  70. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  71. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  72. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  73. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  74. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  75. package/docs/api/interfaces/PaletteData.md +1 -1
  76. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  77. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  78. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  79. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  80. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  81. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  82. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  83. package/docs/api/interfaces/RBACConfig.md +1 -1
  84. package/docs/api/interfaces/RBACContextType.md +1 -1
  85. package/docs/api/interfaces/RBACLogger.md +1 -1
  86. package/docs/api/interfaces/RBACProviderProps.md +1 -1
  87. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  88. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  89. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  90. package/docs/api/interfaces/RouteConfig.md +1 -1
  91. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  92. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  93. package/docs/api/interfaces/StorageConfig.md +1 -1
  94. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  95. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  96. package/docs/api/interfaces/StorageListOptions.md +1 -1
  97. package/docs/api/interfaces/StorageListResult.md +1 -1
  98. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  99. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  100. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  101. package/docs/api/interfaces/StyleImport.md +1 -1
  102. package/docs/api/interfaces/ToastActionElement.md +1 -1
  103. package/docs/api/interfaces/ToastProps.md +1 -1
  104. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  105. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  106. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  107. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  108. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  109. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  110. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  111. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  112. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  113. package/docs/api/interfaces/UserEventAccess.md +1 -1
  114. package/docs/api/interfaces/UserMenuProps.md +1 -1
  115. package/docs/api/interfaces/UserProfile.md +1 -1
  116. package/docs/api/modules.md +5 -5
  117. package/package.json +1 -1
  118. package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +756 -0
  119. package/src/components/DataTable/__tests__/DataTable.test.tsx +880 -0
  120. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +702 -0
  121. package/src/components/PrintButton/__tests__/PrintButton.test.tsx +271 -0
  122. package/src/providers/AuthProvider.tsx +131 -230
  123. package/src/providers/EventProvider.tsx +5 -14
  124. package/src/providers/OrganisationProvider.tsx +37 -6
  125. package/src/providers/__tests__/AuthProvider.test.tsx +619 -0
  126. package/src/providers/__tests__/EventProvider.test.tsx +190 -0
  127. package/src/providers/__tests__/InactivityProvider.test.tsx +645 -0
  128. package/src/providers/__tests__/OrganisationProvider.test.tsx +343 -0
  129. package/src/providers/__tests__/README.md +167 -0
  130. package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +581 -0
  131. package/src/rbac/__tests__/rbac-core.test.tsx +277 -0
  132. package/dist/chunk-P27KH7XF.js.map +0 -1
  133. package/dist/chunk-XC6XWRP6.js.map +0 -1
  134. /package/dist/{DataTable-DCW3J4YX.js.map → DataTable-GU72TTL6.js.map} +0 -0
  135. /package/dist/{chunk-RL267HOF.js.map → chunk-7NAMQC3W.js.map} +0 -0
  136. /package/dist/{chunk-BLZBTCBT.js.map → chunk-D4ZF5QUY.js.map} +0 -0
  137. /package/dist/{chunk-APHGXR2D.js.map → chunk-DWA6SCGM.js.map} +0 -0
  138. /package/dist/{chunk-CL2MCHIO.js.map → chunk-DZSLRIE2.js.map} +0 -0
  139. /package/dist/{chunk-ZSXH6L7D.js.map → chunk-KVMIO3BU.js.map} +0 -0
  140. /package/dist/{chunk-YXTIVGX3.js.map → chunk-OTQBUB66.js.map} +0 -0
  141. /package/dist/{chunk-ZRWNGBDJ.js.map → chunk-SFXM5VTP.js.map} +0 -0
  142. /package/dist/{chunk-2DUJJPO2.js.map → chunk-U7EDXJBG.js.map} +0 -0
@@ -0,0 +1,277 @@
1
+ /**
2
+ * @file RBAC Core Tests
3
+ * @package @jmruthers/pace-core
4
+ * @module RBAC/__tests__
5
+ * @since 0.4.0
6
+ *
7
+ * Comprehensive test suite for RBAC core functionality.
8
+ * Follows testing guidelines with proper structure, naming, and best practices.
9
+ */
10
+
11
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
12
+ import { setupRBAC, hasPermission, isPermitted, getAccessLevel } from '../api';
13
+ import { Operation, Permission, AccessLevel } from '../types';
14
+
15
+ // Mock Supabase client
16
+ const mockSupabaseClient = {
17
+ from: vi.fn(),
18
+ rpc: vi.fn(),
19
+ };
20
+
21
+ describe('RBAC Core Functionality', () => {
22
+ beforeEach(() => {
23
+ vi.clearAllMocks();
24
+ });
25
+
26
+ afterEach(() => {
27
+ vi.restoreAllMocks();
28
+ });
29
+
30
+ describe('Permission Types', () => {
31
+ it('has all required operation types', () => {
32
+ // Check that the Operation type includes the expected values
33
+ const operations: Operation[] = ['read', 'create', 'update', 'delete', 'manage'];
34
+ operations.forEach(op => {
35
+ expect(['read', 'create', 'update', 'delete', 'manage']).toContain(op);
36
+ });
37
+ });
38
+
39
+ it('has all required access levels', () => {
40
+ // Check that the AccessLevel type includes the expected values
41
+ const accessLevels: AccessLevel[] = ['viewer', 'participant', 'planner', 'admin', 'super'];
42
+ accessLevels.forEach(level => {
43
+ expect(['viewer', 'participant', 'planner', 'admin', 'super']).toContain(level);
44
+ });
45
+ });
46
+ });
47
+
48
+ describe('RBAC Setup', () => {
49
+ it('initializes RBAC system', () => {
50
+ expect(() => {
51
+ setupRBAC(mockSupabaseClient as any);
52
+ }).not.toThrow();
53
+ });
54
+
55
+ it('initializes RBAC system with config', () => {
56
+ const config = {
57
+ debug: true,
58
+ logLevel: 'info' as const,
59
+ };
60
+
61
+ expect(() => {
62
+ setupRBAC(mockSupabaseClient as any, config);
63
+ }).not.toThrow();
64
+ });
65
+ });
66
+
67
+ describe('Permission Checking', () => {
68
+ it('validates permission strings', () => {
69
+ const validPermissions: Permission[] = [
70
+ 'read:users',
71
+ 'create:user-profiles',
72
+ 'update:events',
73
+ 'delete:organisations',
74
+ 'manage:base',
75
+ ];
76
+
77
+ validPermissions.forEach(permission => {
78
+ expect(permission).toMatch(/^(read|create|update|delete|manage):/);
79
+ });
80
+ });
81
+
82
+ it('handles invalid permission formats', () => {
83
+ const invalidPermissions = ['invalid', '', 'read', 'manage'];
84
+
85
+ invalidPermissions.forEach(permission => {
86
+ expect(permission).not.toMatch(/^(read|create|update|delete|manage):/);
87
+ });
88
+ });
89
+ });
90
+
91
+ describe('Permission Validation', () => {
92
+ it('validates permission strings correctly', () => {
93
+ const permission: Permission = 'read:users';
94
+ expect(permission).toMatch(/^(read|create|update|delete|manage):/);
95
+ });
96
+
97
+ it('validates complex resource names', () => {
98
+ const permission: Permission = 'create:user-profiles';
99
+ expect(permission).toMatch(/^(read|create|update|delete|manage):/);
100
+ });
101
+
102
+ it('handles invalid permission formats', () => {
103
+ const invalidPermissions = ['invalid', '', 'read'];
104
+
105
+ invalidPermissions.forEach(permission => {
106
+ expect(permission).not.toMatch(/^(read|create|update|delete|manage):/);
107
+ });
108
+ });
109
+ });
110
+
111
+ describe('Access Level Validation', () => {
112
+ it('validates access level hierarchy', () => {
113
+ const levels: AccessLevel[] = ['viewer', 'participant', 'planner', 'admin', 'super'];
114
+
115
+ // Check that all levels are valid
116
+ levels.forEach(level => {
117
+ expect(['viewer', 'participant', 'planner', 'admin', 'super']).toContain(level);
118
+ });
119
+ });
120
+
121
+ it('handles access level comparisons', () => {
122
+ const levels: AccessLevel[] = ['viewer', 'participant', 'planner', 'admin', 'super'];
123
+
124
+ // viewer < participant < planner < admin < super
125
+ const levelHierarchy = {
126
+ viewer: 0,
127
+ participant: 1,
128
+ planner: 2,
129
+ admin: 3,
130
+ super: 4,
131
+ };
132
+
133
+ levels.forEach(level => {
134
+ expect(levelHierarchy[level]).toBeGreaterThanOrEqual(0);
135
+ expect(levelHierarchy[level]).toBeLessThanOrEqual(4);
136
+ });
137
+ });
138
+ });
139
+
140
+ describe('Permission String Parsing', () => {
141
+ it('parses valid permission strings', () => {
142
+ const parsePermission = (permission: string) => {
143
+ const match = permission.match(/^(\w+):(.+)$/);
144
+ if (!match) return null;
145
+ return {
146
+ operation: match[1],
147
+ resource: match[2],
148
+ };
149
+ };
150
+
151
+ const permission = parsePermission('read:users');
152
+ expect(permission).toEqual({
153
+ operation: 'read',
154
+ resource: 'users',
155
+ });
156
+ });
157
+
158
+ it('parses complex resource names', () => {
159
+ const parsePermission = (permission: string) => {
160
+ const match = permission.match(/^(\w+):(.+)$/);
161
+ if (!match) return null;
162
+ return {
163
+ operation: match[1],
164
+ resource: match[2],
165
+ };
166
+ };
167
+
168
+ const permission = parsePermission('write:user-profiles');
169
+ expect(permission).toEqual({
170
+ operation: 'write',
171
+ resource: 'user-profiles',
172
+ });
173
+ });
174
+
175
+ it('returns null for invalid permissions', () => {
176
+ const parsePermission = (permission: string) => {
177
+ const match = permission.match(/^(\w+):(.+)$/);
178
+ if (!match) return null;
179
+ return {
180
+ operation: match[1],
181
+ resource: match[2],
182
+ };
183
+ };
184
+
185
+ expect(parsePermission('invalid')).toBeNull();
186
+ expect(parsePermission('')).toBeNull();
187
+ expect(parsePermission('read')).toBeNull();
188
+ });
189
+ });
190
+
191
+ describe('Error Handling', () => {
192
+ it('handles missing Supabase client gracefully', () => {
193
+ // The setupRBAC function doesn't throw on null client, it just logs
194
+ expect(() => {
195
+ setupRBAC(null as any);
196
+ }).not.toThrow();
197
+ });
198
+
199
+ it('handles invalid configuration', () => {
200
+ const invalidConfig = {
201
+ debug: 'invalid' as any,
202
+ logLevel: 'invalid' as any,
203
+ };
204
+
205
+ // Should not throw during setup, but may log warnings
206
+ expect(() => {
207
+ setupRBAC(mockSupabaseClient as any, invalidConfig);
208
+ }).not.toThrow();
209
+ });
210
+ });
211
+
212
+ describe('Type Safety', () => {
213
+ it('ensures Permission type safety', () => {
214
+ const validPermissions: Permission[] = [
215
+ 'read:users',
216
+ 'create:events',
217
+ 'update:profiles',
218
+ 'delete:comments',
219
+ 'manage:organisations',
220
+ ];
221
+
222
+ validPermissions.forEach(permission => {
223
+ expect(typeof permission).toBe('string');
224
+ expect(permission).toMatch(/^(read|create|update|delete|manage):/);
225
+ });
226
+ });
227
+
228
+ it('ensures AccessLevel type safety', () => {
229
+ const validAccessLevels: AccessLevel[] = [
230
+ 'viewer',
231
+ 'participant',
232
+ 'planner',
233
+ 'admin',
234
+ 'super',
235
+ ];
236
+
237
+ validAccessLevels.forEach(level => {
238
+ expect(typeof level).toBe('string');
239
+ expect(['viewer', 'participant', 'planner', 'admin', 'super']).toContain(level);
240
+ });
241
+ });
242
+ });
243
+
244
+ describe('Permission Logic', () => {
245
+ it('validates permission hierarchy', () => {
246
+ const permissionHierarchy = {
247
+ 'read': 1,
248
+ 'create': 2,
249
+ 'update': 3,
250
+ 'delete': 4,
251
+ 'manage': 5,
252
+ };
253
+
254
+ const operations: Operation[] = ['read', 'create', 'update', 'delete', 'manage'];
255
+
256
+ operations.forEach(operation => {
257
+ expect(permissionHierarchy[operation]).toBeGreaterThan(0);
258
+ });
259
+ });
260
+
261
+ it('validates access level hierarchy', () => {
262
+ const accessLevelHierarchy = {
263
+ 'viewer': 1,
264
+ 'participant': 2,
265
+ 'planner': 3,
266
+ 'admin': 4,
267
+ 'super': 5,
268
+ };
269
+
270
+ const levels: AccessLevel[] = ['viewer', 'participant', 'planner', 'admin', 'super'];
271
+
272
+ levels.forEach(level => {
273
+ expect(accessLevelHierarchy[level]).toBeGreaterThan(0);
274
+ });
275
+ });
276
+ });
277
+ });