@lightdash/common 0.1937.0 → 0.1938.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.
Files changed (129) hide show
  1. package/dist/cjs/authorization/index.d.ts +8 -4
  2. package/dist/cjs/authorization/index.d.ts.map +1 -1
  3. package/dist/cjs/authorization/index.js +26 -3
  4. package/dist/cjs/authorization/index.js.map +1 -1
  5. package/dist/cjs/authorization/index.mock.d.ts +2 -0
  6. package/dist/cjs/authorization/index.mock.d.ts.map +1 -1
  7. package/dist/cjs/authorization/index.mock.js +2 -0
  8. package/dist/cjs/authorization/index.mock.js.map +1 -1
  9. package/dist/cjs/authorization/organizationMemberAbility.mock.d.ts.map +1 -1
  10. package/dist/cjs/authorization/organizationMemberAbility.mock.js +1 -0
  11. package/dist/cjs/authorization/organizationMemberAbility.mock.js.map +1 -1
  12. package/dist/cjs/authorization/parseScopes.d.ts +3 -2
  13. package/dist/cjs/authorization/parseScopes.d.ts.map +1 -1
  14. package/dist/cjs/authorization/parseScopes.js +17 -8
  15. package/dist/cjs/authorization/parseScopes.js.map +1 -1
  16. package/dist/cjs/authorization/parseScopes.test.js +9 -14
  17. package/dist/cjs/authorization/parseScopes.test.js.map +1 -1
  18. package/dist/cjs/authorization/projectMemberAbility.mock.d.ts.map +1 -1
  19. package/dist/cjs/authorization/projectMemberAbility.mock.js +1 -0
  20. package/dist/cjs/authorization/projectMemberAbility.mock.js.map +1 -1
  21. package/dist/cjs/authorization/roleToScopeMapping.d.ts +19 -0
  22. package/dist/cjs/authorization/roleToScopeMapping.d.ts.map +1 -0
  23. package/dist/cjs/authorization/roleToScopeMapping.js +163 -0
  24. package/dist/cjs/authorization/roleToScopeMapping.js.map +1 -0
  25. package/dist/cjs/authorization/roleToScopeMapping.test.d.ts +2 -0
  26. package/dist/cjs/authorization/roleToScopeMapping.test.d.ts.map +1 -0
  27. package/dist/cjs/authorization/roleToScopeMapping.test.js +549 -0
  28. package/dist/cjs/authorization/roleToScopeMapping.test.js.map +1 -0
  29. package/dist/cjs/authorization/roleToScopeMapping.testUtils.d.ts +1393 -0
  30. package/dist/cjs/authorization/roleToScopeMapping.testUtils.d.ts.map +1 -0
  31. package/dist/cjs/authorization/roleToScopeMapping.testUtils.js +329 -0
  32. package/dist/cjs/authorization/roleToScopeMapping.testUtils.js.map +1 -0
  33. package/dist/cjs/authorization/scopeAbilityBuilder.d.ts +14 -8
  34. package/dist/cjs/authorization/scopeAbilityBuilder.d.ts.map +1 -1
  35. package/dist/cjs/authorization/scopeAbilityBuilder.js +7 -7
  36. package/dist/cjs/authorization/scopeAbilityBuilder.js.map +1 -1
  37. package/dist/cjs/authorization/scopeAbilityBuilder.test.js +258 -185
  38. package/dist/cjs/authorization/scopeAbilityBuilder.test.js.map +1 -1
  39. package/dist/cjs/authorization/scopes.d.ts.map +1 -1
  40. package/dist/cjs/authorization/scopes.js +132 -187
  41. package/dist/cjs/authorization/scopes.js.map +1 -1
  42. package/dist/cjs/types/organizationMemberProfile.d.ts +1 -0
  43. package/dist/cjs/types/organizationMemberProfile.d.ts.map +1 -1
  44. package/dist/cjs/types/organizationMemberProfile.js.map +1 -1
  45. package/dist/cjs/types/projectMemberProfile.d.ts +1 -0
  46. package/dist/cjs/types/projectMemberProfile.d.ts.map +1 -1
  47. package/dist/cjs/types/scopes.d.ts +19 -9
  48. package/dist/cjs/types/scopes.d.ts.map +1 -1
  49. package/dist/cjs/types/user.d.ts +1 -0
  50. package/dist/cjs/types/user.d.ts.map +1 -1
  51. package/dist/cjs/types/user.js.map +1 -1
  52. package/dist/esm/authorization/index.d.ts +8 -4
  53. package/dist/esm/authorization/index.d.ts.map +1 -1
  54. package/dist/esm/authorization/index.js +26 -3
  55. package/dist/esm/authorization/index.js.map +1 -1
  56. package/dist/esm/authorization/index.mock.d.ts +2 -0
  57. package/dist/esm/authorization/index.mock.d.ts.map +1 -1
  58. package/dist/esm/authorization/index.mock.js +2 -0
  59. package/dist/esm/authorization/index.mock.js.map +1 -1
  60. package/dist/esm/authorization/organizationMemberAbility.mock.d.ts.map +1 -1
  61. package/dist/esm/authorization/organizationMemberAbility.mock.js +1 -0
  62. package/dist/esm/authorization/organizationMemberAbility.mock.js.map +1 -1
  63. package/dist/esm/authorization/parseScopes.d.ts +3 -2
  64. package/dist/esm/authorization/parseScopes.d.ts.map +1 -1
  65. package/dist/esm/authorization/parseScopes.js +15 -7
  66. package/dist/esm/authorization/parseScopes.js.map +1 -1
  67. package/dist/esm/authorization/parseScopes.test.js +9 -14
  68. package/dist/esm/authorization/parseScopes.test.js.map +1 -1
  69. package/dist/esm/authorization/projectMemberAbility.mock.d.ts.map +1 -1
  70. package/dist/esm/authorization/projectMemberAbility.mock.js +1 -0
  71. package/dist/esm/authorization/projectMemberAbility.mock.js.map +1 -1
  72. package/dist/esm/authorization/roleToScopeMapping.d.ts +19 -0
  73. package/dist/esm/authorization/roleToScopeMapping.d.ts.map +1 -0
  74. package/dist/esm/authorization/roleToScopeMapping.js +157 -0
  75. package/dist/esm/authorization/roleToScopeMapping.js.map +1 -0
  76. package/dist/esm/authorization/roleToScopeMapping.test.d.ts +2 -0
  77. package/dist/esm/authorization/roleToScopeMapping.test.d.ts.map +1 -0
  78. package/dist/esm/authorization/roleToScopeMapping.test.js +547 -0
  79. package/dist/esm/authorization/roleToScopeMapping.test.js.map +1 -0
  80. package/dist/esm/authorization/roleToScopeMapping.testUtils.d.ts +1393 -0
  81. package/dist/esm/authorization/roleToScopeMapping.testUtils.d.ts.map +1 -0
  82. package/dist/esm/authorization/roleToScopeMapping.testUtils.js +319 -0
  83. package/dist/esm/authorization/roleToScopeMapping.testUtils.js.map +1 -0
  84. package/dist/esm/authorization/scopeAbilityBuilder.d.ts +14 -8
  85. package/dist/esm/authorization/scopeAbilityBuilder.d.ts.map +1 -1
  86. package/dist/esm/authorization/scopeAbilityBuilder.js +7 -7
  87. package/dist/esm/authorization/scopeAbilityBuilder.js.map +1 -1
  88. package/dist/esm/authorization/scopeAbilityBuilder.test.js +259 -186
  89. package/dist/esm/authorization/scopeAbilityBuilder.test.js.map +1 -1
  90. package/dist/esm/authorization/scopes.d.ts.map +1 -1
  91. package/dist/esm/authorization/scopes.js +132 -187
  92. package/dist/esm/authorization/scopes.js.map +1 -1
  93. package/dist/esm/types/organizationMemberProfile.d.ts +1 -0
  94. package/dist/esm/types/organizationMemberProfile.d.ts.map +1 -1
  95. package/dist/esm/types/organizationMemberProfile.js.map +1 -1
  96. package/dist/esm/types/projectMemberProfile.d.ts +1 -0
  97. package/dist/esm/types/projectMemberProfile.d.ts.map +1 -1
  98. package/dist/esm/types/scopes.d.ts +19 -9
  99. package/dist/esm/types/scopes.d.ts.map +1 -1
  100. package/dist/esm/types/user.d.ts +1 -0
  101. package/dist/esm/types/user.d.ts.map +1 -1
  102. package/dist/esm/types/user.js.map +1 -1
  103. package/dist/tsconfig.types.tsbuildinfo +1 -1
  104. package/dist/types/authorization/index.d.ts +8 -4
  105. package/dist/types/authorization/index.d.ts.map +1 -1
  106. package/dist/types/authorization/index.mock.d.ts +2 -0
  107. package/dist/types/authorization/index.mock.d.ts.map +1 -1
  108. package/dist/types/authorization/organizationMemberAbility.mock.d.ts.map +1 -1
  109. package/dist/types/authorization/parseScopes.d.ts +3 -2
  110. package/dist/types/authorization/parseScopes.d.ts.map +1 -1
  111. package/dist/types/authorization/projectMemberAbility.mock.d.ts.map +1 -1
  112. package/dist/types/authorization/roleToScopeMapping.d.ts +19 -0
  113. package/dist/types/authorization/roleToScopeMapping.d.ts.map +1 -0
  114. package/dist/types/authorization/roleToScopeMapping.test.d.ts +2 -0
  115. package/dist/types/authorization/roleToScopeMapping.test.d.ts.map +1 -0
  116. package/dist/types/authorization/roleToScopeMapping.testUtils.d.ts +1393 -0
  117. package/dist/types/authorization/roleToScopeMapping.testUtils.d.ts.map +1 -0
  118. package/dist/types/authorization/scopeAbilityBuilder.d.ts +14 -8
  119. package/dist/types/authorization/scopeAbilityBuilder.d.ts.map +1 -1
  120. package/dist/types/authorization/scopes.d.ts.map +1 -1
  121. package/dist/types/types/organizationMemberProfile.d.ts +1 -0
  122. package/dist/types/types/organizationMemberProfile.d.ts.map +1 -1
  123. package/dist/types/types/projectMemberProfile.d.ts +1 -0
  124. package/dist/types/types/projectMemberProfile.d.ts.map +1 -1
  125. package/dist/types/types/scopes.d.ts +19 -9
  126. package/dist/types/types/scopes.d.ts.map +1 -1
  127. package/dist/types/types/user.d.ts +1 -0
  128. package/dist/types/types/user.d.ts.map +1 -1
  129. package/package.json +1 -1
@@ -0,0 +1,547 @@
1
+ /* eslint-disable no-console */
2
+ import { Ability, AbilityBuilder, subject } from '@casl/ability';
3
+ import { OrganizationMemberRole } from '../types/organizationMemberProfile';
4
+ import { ProjectMemberRole } from '../types/projectMemberRole';
5
+ import { getUserAbilityBuilder } from './index';
6
+ import { projectMemberAbilities } from './projectMemberAbility';
7
+ import { PROJECT_EDITOR } from './projectMemberAbility.mock';
8
+ import { getIncrementalScopesForRole, getNonEnterpriseScopesForRole, getScopesForRole, } from './roleToScopeMapping';
9
+ import { debugRoleScopeMapping, validateRoleInheritance, } from './roleToScopeMapping.testUtils';
10
+ import { buildAbilityFromScopes } from './scopeAbilityBuilder';
11
+ describe('roleToScopeMapping', () => {
12
+ describe('getScopesForRole', () => {
13
+ it('should return scopes for viewer role', () => {
14
+ const scopes = getScopesForRole(ProjectMemberRole.VIEWER);
15
+ expect(scopes).toContain('view:Dashboard');
16
+ expect(scopes).toContain('view:SavedChart');
17
+ expect(scopes).toContain('view:Space');
18
+ expect(scopes).toContain('view:Project');
19
+ });
20
+ it('should include inherited scopes for editor role', () => {
21
+ const scopes = getScopesForRole(ProjectMemberRole.EDITOR);
22
+ // Should have viewer scopes
23
+ expect(scopes).toContain('view:Dashboard');
24
+ expect(scopes).toContain('view:SavedChart');
25
+ // Should have interactive viewer scopes
26
+ expect(scopes).toContain('view:UnderlyingData');
27
+ expect(scopes).toContain('manage:Explore');
28
+ // Should have editor-specific scopes
29
+ expect(scopes).toContain('create:Space');
30
+ expect(scopes).toContain('manage:DashboardComments');
31
+ expect(scopes).toContain('manage:ScheduledDeliveries');
32
+ });
33
+ it('should have more scopes for higher roles', () => {
34
+ const viewerScopes = getScopesForRole(ProjectMemberRole.VIEWER);
35
+ const editorScopes = getScopesForRole(ProjectMemberRole.EDITOR);
36
+ const adminScopes = getScopesForRole(ProjectMemberRole.ADMIN);
37
+ expect(editorScopes.length).toBeGreaterThan(viewerScopes.length);
38
+ expect(adminScopes.length).toBeGreaterThan(editorScopes.length);
39
+ });
40
+ });
41
+ describe('getIncrementalScopesForRole', () => {
42
+ it('should return all scopes for viewer (base role)', () => {
43
+ const incrementalScopes = getIncrementalScopesForRole(ProjectMemberRole.VIEWER);
44
+ const allScopes = getScopesForRole(ProjectMemberRole.VIEWER);
45
+ expect(incrementalScopes.sort()).toEqual(allScopes.sort());
46
+ });
47
+ it('should return only new scopes for editor role', () => {
48
+ const incrementalScopes = getIncrementalScopesForRole(ProjectMemberRole.EDITOR);
49
+ const interactiveViewerScopes = getScopesForRole(ProjectMemberRole.INTERACTIVE_VIEWER);
50
+ // Should not contain any interactive viewer scopes
51
+ incrementalScopes.forEach((scope) => {
52
+ expect(interactiveViewerScopes).not.toContain(scope);
53
+ });
54
+ // Should contain editor-specific scopes
55
+ expect(incrementalScopes).toContain('create:Space');
56
+ expect(incrementalScopes).toContain('manage:DashboardComments');
57
+ expect(incrementalScopes).toContain('manage:ScheduledDeliveries');
58
+ });
59
+ });
60
+ describe('validateRoleInheritance', () => {
61
+ it('should validate that roles properly inherit permissions', () => {
62
+ const validation = validateRoleInheritance();
63
+ if (!validation.valid) {
64
+ console.debug('Validation errors:', validation.errors);
65
+ }
66
+ expect(validation.valid).toBe(true);
67
+ expect(validation.errors).toHaveLength(0);
68
+ });
69
+ });
70
+ describe('debugRoleScopeMapping', () => {
71
+ it('should not throw when debugging editor role', () => {
72
+ expect(() => {
73
+ debugRoleScopeMapping(ProjectMemberRole.EDITOR);
74
+ }).not.toThrow();
75
+ });
76
+ });
77
+ describe('AbilityBuilderCompatibility', () => { });
78
+ describe('Ability builder compatibility', () => {
79
+ it('should build equivalent abilities using scopes vs role-based builder', () => {
80
+ // Build ability using the old role-based system
81
+ const roleBuilder = new AbilityBuilder(Ability);
82
+ projectMemberAbilities[ProjectMemberRole.EDITOR](PROJECT_EDITOR, roleBuilder);
83
+ const roleAbility = roleBuilder.build();
84
+ // Define scopes that should be equivalent to an editor role
85
+ // Based on projectMemberAbility.ts, an editor can:
86
+ // - Do everything interactive_viewer can do (view content, export, create deliveries)
87
+ // - Create spaces
88
+ // - Manage non-private spaces, jobs, pinned items, scheduled deliveries, dashboard comments, tags
89
+ // NOTE: Adding manage:Project to enable managing non-private spaces
90
+ const editorScopes = [
91
+ // Interactive viewer scopes (inherited)
92
+ 'view:Dashboard',
93
+ 'view:SavedChart',
94
+ 'view:Space',
95
+ 'view:Project',
96
+ 'create:ScheduledDeliveries',
97
+ 'view:Job',
98
+ 'create:Job',
99
+ 'manage:Explore',
100
+ 'create:DashboardComments',
101
+ // Editor-specific scopes
102
+ 'create:Space',
103
+ 'manage:Space',
104
+ 'manage:Project', // Required for managing non-private spaces
105
+ 'manage:Job',
106
+ 'manage:PinnedItems',
107
+ 'manage:ScheduledDeliveries',
108
+ 'manage:DashboardComments',
109
+ 'manage:Tags',
110
+ ];
111
+ // Build ability using the new scope-based system
112
+ const scopeBuilder = new AbilityBuilder(Ability);
113
+ buildAbilityFromScopes({
114
+ projectUuid: PROJECT_EDITOR.projectUuid,
115
+ userUuid: PROJECT_EDITOR.userUuid,
116
+ scopes: editorScopes,
117
+ isEnterprise: false,
118
+ organizationRole: 'editor',
119
+ permissionsConfig: {
120
+ pat: {
121
+ enabled: false,
122
+ allowedOrgRoles: [],
123
+ },
124
+ },
125
+ }, scopeBuilder);
126
+ const scopeAbility = scopeBuilder.build();
127
+ // Test cases that should be equivalent for both abilities
128
+ const testCases = [
129
+ // View permissions (inherited from interactive_viewer)
130
+ {
131
+ action: 'view',
132
+ subject: 'Dashboard',
133
+ resource: {
134
+ organizationUuid: 'org-uuid-test',
135
+ projectUuid: PROJECT_EDITOR.projectUuid,
136
+ isPrivate: false,
137
+ },
138
+ },
139
+ {
140
+ action: 'view',
141
+ subject: 'SavedChart',
142
+ resource: {
143
+ organizationUuid: 'org-uuid-test',
144
+ projectUuid: PROJECT_EDITOR.projectUuid,
145
+ isPrivate: false,
146
+ },
147
+ },
148
+ {
149
+ action: 'view',
150
+ subject: 'Space',
151
+ resource: {
152
+ organizationUuid: 'org-uuid-test',
153
+ projectUuid: PROJECT_EDITOR.projectUuid,
154
+ isPrivate: false,
155
+ },
156
+ },
157
+ // Create permissions (editor-specific)
158
+ {
159
+ action: 'create',
160
+ subject: 'Space',
161
+ resource: {
162
+ organizationUuid: 'org-uuid-test',
163
+ projectUuid: PROJECT_EDITOR.projectUuid,
164
+ },
165
+ },
166
+ // Manage permissions (editor-specific)
167
+ {
168
+ action: 'manage',
169
+ subject: 'Space',
170
+ resource: {
171
+ organizationUuid: 'org-uuid-test',
172
+ projectUuid: PROJECT_EDITOR.projectUuid,
173
+ isPrivate: false,
174
+ },
175
+ },
176
+ {
177
+ action: 'manage',
178
+ subject: 'Job',
179
+ resource: {},
180
+ },
181
+ {
182
+ action: 'manage',
183
+ subject: 'PinnedItems',
184
+ resource: {
185
+ organizationUuid: 'org-uuid-test',
186
+ projectUuid: PROJECT_EDITOR.projectUuid,
187
+ },
188
+ },
189
+ {
190
+ action: 'manage',
191
+ subject: 'ScheduledDeliveries',
192
+ resource: {
193
+ organizationUuid: 'org-uuid-test',
194
+ projectUuid: PROJECT_EDITOR.projectUuid,
195
+ },
196
+ },
197
+ {
198
+ action: 'manage',
199
+ subject: 'DashboardComments',
200
+ resource: {
201
+ organizationUuid: 'org-uuid-test',
202
+ projectUuid: PROJECT_EDITOR.projectUuid,
203
+ },
204
+ },
205
+ {
206
+ action: 'manage',
207
+ subject: 'Tags',
208
+ resource: {
209
+ organizationUuid: 'org-uuid-test',
210
+ projectUuid: PROJECT_EDITOR.projectUuid,
211
+ },
212
+ },
213
+ ];
214
+ // Verify that both ability builders produce the same results
215
+ testCases.forEach(({ action, subject: subjectType, resource }) => {
216
+ const subjectWithResource = subject(subjectType, resource);
217
+ const roleResult = roleAbility.can(action, subjectWithResource);
218
+ const scopeResult = scopeAbility.can(action, subjectWithResource);
219
+ expect(scopeResult).toBe(roleResult);
220
+ });
221
+ });
222
+ it('should deny the same permissions for both abilities', () => {
223
+ // Build abilities
224
+ const roleBuilder = new AbilityBuilder(Ability);
225
+ projectMemberAbilities[ProjectMemberRole.EDITOR](PROJECT_EDITOR, roleBuilder);
226
+ const roleAbility = roleBuilder.build();
227
+ const editorScopes = [
228
+ 'view:Dashboard',
229
+ 'view:SavedChart',
230
+ 'view:Space',
231
+ 'view:Project',
232
+ 'create:ScheduledDeliveries',
233
+ 'view:Job',
234
+ 'create:Job',
235
+ 'manage:Explore',
236
+ 'create:DashboardComments',
237
+ 'create:Space',
238
+ 'manage:Job',
239
+ 'manage:PinnedItems',
240
+ 'manage:ScheduledDeliveries',
241
+ 'manage:DashboardComments',
242
+ 'manage:Tags',
243
+ ];
244
+ const scopeBuilder = new AbilityBuilder(Ability);
245
+ buildAbilityFromScopes({
246
+ projectUuid: PROJECT_EDITOR.projectUuid,
247
+ userUuid: PROJECT_EDITOR.userUuid,
248
+ scopes: editorScopes,
249
+ isEnterprise: false,
250
+ organizationRole: 'editor',
251
+ permissionsConfig: {
252
+ pat: {
253
+ enabled: false,
254
+ allowedOrgRoles: [],
255
+ },
256
+ },
257
+ }, scopeBuilder);
258
+ const scopeAbility = scopeBuilder.build();
259
+ // Test cases that should be denied for both abilities (editor limitations)
260
+ const deniedTestCases = [
261
+ // Cannot manage project (developer+ only)
262
+ {
263
+ action: 'manage',
264
+ subject: 'Project',
265
+ resource: { projectUuid: PROJECT_EDITOR.projectUuid },
266
+ },
267
+ // Cannot manage validations (developer+ only)
268
+ {
269
+ action: 'manage',
270
+ subject: 'Validation',
271
+ resource: { projectUuid: PROJECT_EDITOR.projectUuid },
272
+ },
273
+ // Cannot manage virtual views (developer+ only)
274
+ {
275
+ action: 'manage',
276
+ subject: 'VirtualView',
277
+ resource: { projectUuid: PROJECT_EDITOR.projectUuid },
278
+ },
279
+ ];
280
+ // Verify that both ability builders deny the same permissions
281
+ deniedTestCases.forEach(({ action, subject: subjectType, resource }) => {
282
+ const subjectWithResource = subject(subjectType, resource);
283
+ const roleResult = roleAbility.can(action, subjectWithResource);
284
+ const scopeResult = scopeAbility.can(action, subjectWithResource);
285
+ expect(scopeResult).toBe(roleResult);
286
+ expect(roleResult).toBe(false); // Ensure they're both false
287
+ });
288
+ });
289
+ });
290
+ describe('Convert all project member roles to scopes', () => {
291
+ const testCases = [
292
+ {
293
+ action: 'view',
294
+ subject: 'Dashboard',
295
+ resource: {
296
+ organizationUuid: 'org-uuid-test',
297
+ projectUuid: 'test-project-uuid',
298
+ isPrivate: false,
299
+ },
300
+ },
301
+ {
302
+ action: 'create',
303
+ subject: 'Space',
304
+ resource: {
305
+ organizationUuid: 'org-uuid-test',
306
+ projectUuid: 'test-project-uuid',
307
+ },
308
+ },
309
+ {
310
+ action: 'manage',
311
+ subject: 'Space',
312
+ resource: {
313
+ organizationUuid: 'org-uuid-test',
314
+ projectUuid: 'test-project-uuid',
315
+ isPrivate: false,
316
+ },
317
+ },
318
+ {
319
+ action: 'manage',
320
+ subject: 'Project',
321
+ resource: { projectUuid: 'test-project-uuid' },
322
+ },
323
+ {
324
+ action: 'view',
325
+ subject: 'Analytics',
326
+ resource: { projectUuid: 'test-project-uuid' },
327
+ },
328
+ ];
329
+ const roles = [
330
+ ProjectMemberRole.VIEWER,
331
+ ProjectMemberRole.INTERACTIVE_VIEWER,
332
+ ProjectMemberRole.EDITOR,
333
+ ProjectMemberRole.DEVELOPER,
334
+ ProjectMemberRole.ADMIN,
335
+ ];
336
+ roles.forEach((role) => {
337
+ it(`should have equivalent CASL abilities for ${role} role`, () => {
338
+ // Build role-based ability
339
+ const roleBuilder = new AbilityBuilder(Ability);
340
+ const testMember = {
341
+ role,
342
+ projectUuid: PROJECT_EDITOR.projectUuid,
343
+ userUuid: PROJECT_EDITOR.userUuid,
344
+ };
345
+ projectMemberAbilities[role](testMember, roleBuilder);
346
+ const roleAbility = roleBuilder.build();
347
+ // Build scope-based ability
348
+ const scopes = getNonEnterpriseScopesForRole(role);
349
+ const scopeBuilder = new AbilityBuilder(Ability);
350
+ buildAbilityFromScopes({
351
+ projectUuid: PROJECT_EDITOR.projectUuid,
352
+ userUuid: PROJECT_EDITOR.userUuid,
353
+ scopes,
354
+ isEnterprise: false,
355
+ organizationRole: 'editor',
356
+ permissionsConfig: {
357
+ pat: {
358
+ enabled: false,
359
+ allowedOrgRoles: [],
360
+ },
361
+ },
362
+ }, scopeBuilder);
363
+ const scopeAbility = scopeBuilder.build();
364
+ // Test key permissions for each role - assert strict equivalence
365
+ testCases.forEach((testCase) => {
366
+ const subjectWithResource = subject(testCase.subject, testCase.resource);
367
+ const roleResult = roleAbility.can(testCase.action, subjectWithResource);
368
+ const scopeResult = scopeAbility.can(testCase.action, subjectWithResource);
369
+ // Assert that both systems return the same result with detailed context
370
+ if (scopeResult !== roleResult) {
371
+ throw new Error(`Permission mismatch for ${role} role:\n` +
372
+ ` Action: ${testCase.action}\n` +
373
+ ` Subject: ${testCase.subject}\n` +
374
+ ` Resource: ${JSON.stringify(testCase.resource, null, 2)}\n` +
375
+ ` Role-based result: ${roleResult}\n` +
376
+ ` Scope-based result: ${scopeResult}\n` +
377
+ ` Expected: Both systems should return ${roleResult}`);
378
+ }
379
+ expect(scopeResult).toBe(roleResult);
380
+ });
381
+ });
382
+ });
383
+ });
384
+ describe('Combined Organization and Project Roles', () => {
385
+ const testCases = [
386
+ {
387
+ action: 'view',
388
+ subject: 'Dashboard',
389
+ resource: {
390
+ organizationUuid: 'org-uuid-test',
391
+ projectUuid: 'project-uuid-test',
392
+ isPrivate: false,
393
+ },
394
+ },
395
+ {
396
+ action: 'create',
397
+ subject: 'Space',
398
+ resource: {
399
+ organizationUuid: 'org-uuid-test',
400
+ projectUuid: 'project-uuid-test',
401
+ },
402
+ },
403
+ {
404
+ action: 'manage',
405
+ subject: 'Space',
406
+ resource: {
407
+ organizationUuid: 'org-uuid-test',
408
+ projectUuid: 'project-uuid-test',
409
+ isPrivate: false,
410
+ },
411
+ },
412
+ {
413
+ action: 'manage',
414
+ subject: 'Project',
415
+ resource: { projectUuid: 'project-uuid-test' },
416
+ },
417
+ {
418
+ action: 'manage',
419
+ subject: 'Validation',
420
+ resource: { projectUuid: 'project-uuid-test' },
421
+ },
422
+ {
423
+ action: 'view',
424
+ subject: 'Analytics',
425
+ resource: { projectUuid: 'project-uuid-test' },
426
+ },
427
+ ];
428
+ const roleCombinations = [
429
+ {
430
+ description: 'viewer org + viewer project',
431
+ orgRole: OrganizationMemberRole.VIEWER,
432
+ projectRole: ProjectMemberRole.VIEWER,
433
+ },
434
+ {
435
+ description: 'viewer org + developer project',
436
+ orgRole: OrganizationMemberRole.VIEWER,
437
+ projectRole: ProjectMemberRole.DEVELOPER,
438
+ },
439
+ {
440
+ description: 'editor org + developer project',
441
+ orgRole: OrganizationMemberRole.EDITOR,
442
+ projectRole: ProjectMemberRole.DEVELOPER,
443
+ },
444
+ {
445
+ description: 'developer org + admin project',
446
+ orgRole: OrganizationMemberRole.DEVELOPER,
447
+ projectRole: ProjectMemberRole.ADMIN,
448
+ },
449
+ {
450
+ description: 'viewer org + admin project',
451
+ orgRole: OrganizationMemberRole.VIEWER,
452
+ projectRole: ProjectMemberRole.ADMIN,
453
+ },
454
+ ];
455
+ roleCombinations.forEach(({ description, orgRole, projectRole }) => {
456
+ it(`should have equivalent abilities for ${description}`, () => {
457
+ const user = {
458
+ role: orgRole,
459
+ organizationUuid: 'org-uuid-test',
460
+ userUuid: 'user-uuid-test',
461
+ roleUuid: undefined,
462
+ };
463
+ const projectProfiles = [
464
+ {
465
+ projectUuid: 'project-uuid-test',
466
+ role: projectRole,
467
+ userUuid: 'user-uuid-test',
468
+ roleUuid: undefined,
469
+ },
470
+ ];
471
+ // Build ability using the combined role-based system
472
+ const roleBasedBuilder = getUserAbilityBuilder({
473
+ user,
474
+ projectProfiles,
475
+ permissionsConfig: {
476
+ pat: {
477
+ enabled: false,
478
+ allowedOrgRoles: [],
479
+ },
480
+ },
481
+ customRoleScopes: {},
482
+ customRolesEnabled: false,
483
+ isEnterprise: false,
484
+ });
485
+ const roleBasedAbility = roleBasedBuilder.build();
486
+ // Build equivalent scope-based ability
487
+ // Convert OrganizationMemberRole to ProjectMemberRole for scope mapping
488
+ // Note: This is a simplification - in reality, org roles may have different scope mappings
489
+ const orgRoleAsProjectRole = orgRole;
490
+ const orgScopes = getNonEnterpriseScopesForRole(orgRoleAsProjectRole);
491
+ const projectScopes = getNonEnterpriseScopesForRole(projectRole);
492
+ const allScopes = [
493
+ ...new Set([...orgScopes, ...projectScopes]),
494
+ ]; // Remove duplicates
495
+ const scopeBuilder = new AbilityBuilder(Ability);
496
+ buildAbilityFromScopes({
497
+ organizationUuid: 'org-uuid-test',
498
+ userUuid: 'user-uuid-test',
499
+ scopes: orgScopes,
500
+ isEnterprise: false,
501
+ organizationRole: orgRole,
502
+ permissionsConfig: {
503
+ pat: {
504
+ enabled: false,
505
+ allowedOrgRoles: [],
506
+ },
507
+ },
508
+ }, scopeBuilder);
509
+ buildAbilityFromScopes({
510
+ projectUuid: projectProfiles[0].projectUuid,
511
+ userUuid: 'user-uuid-test',
512
+ scopes: projectScopes,
513
+ isEnterprise: false,
514
+ organizationRole: orgRole,
515
+ permissionsConfig: {
516
+ pat: {
517
+ enabled: false,
518
+ allowedOrgRoles: [],
519
+ },
520
+ },
521
+ }, scopeBuilder);
522
+ const scopeBasedAbility = scopeBuilder.build();
523
+ // Test each permission combination
524
+ testCases.forEach((testCase) => {
525
+ const subjectWithResource = subject(testCase.subject, testCase.resource);
526
+ const roleBasedResult = roleBasedAbility.can(testCase.action, subjectWithResource);
527
+ const scopeBasedResult = scopeBasedAbility.can(testCase.action, subjectWithResource);
528
+ // Provide detailed error information for mismatches
529
+ if (roleBasedResult !== scopeBasedResult) {
530
+ throw new Error(`Permission mismatch for ${description}:\n` +
531
+ ` Action: ${testCase.action}\n` +
532
+ ` Subject: ${testCase.subject}\n` +
533
+ ` Resource: ${JSON.stringify(testCase.resource, null, 2)}\n` +
534
+ ` Role-based result: ${roleBasedResult}\n` +
535
+ ` Scope-based result: ${scopeBasedResult}\n` +
536
+ ` Organization role: ${orgRole}\n` +
537
+ ` Project role: ${projectRole}\n` +
538
+ ` Combined scopes: ${allScopes.length} scopes\n` +
539
+ ` Expected: Both systems should return ${roleBasedResult}`);
540
+ }
541
+ expect(scopeBasedResult).toBe(roleBasedResult);
542
+ });
543
+ });
544
+ });
545
+ });
546
+ });
547
+ //# sourceMappingURL=roleToScopeMapping.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"roleToScopeMapping.test.js","sourceRoot":"","sources":["../../../src/authorization/roleToScopeMapping.test.ts"],"names":[],"mappings":"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"}