Skip to content

Commit 04f8602

Browse files
committed
Remove lodash and Add default permissionModes
Signed-off-by: Lin Wang <[email protected]>
1 parent e1b0c55 commit 04f8602

File tree

2 files changed

+59
-28
lines changed

2 files changed

+59
-28
lines changed

src/plugins/workspace/server/permission_control/client.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ export class SavedObjectsPermissionControl {
105105
}
106106

107107
/**
108-
* In batch validate case, the logic is a.withPermission && b.withPermission
108+
* In batch validate case, the function will get permissions of all passed saved objects,
109+
* check if has permissions to operate every passed saved objects.
109110
* @param request
110111
* @param savedObjects
111112
* @param permissionModes
@@ -143,7 +144,7 @@ export class SavedObjectsPermissionControl {
143144
permissions?: Permissions;
144145
}
145146
> = [];
146-
const hasAllPermission = savedObjectsGet.every((item) => {
147+
const hasPermissionToAllObjects = savedObjectsGet.every((item) => {
147148
// for object that doesn't contain ACL like config, return true
148149
if (!item.permissions) {
149150
return true;
@@ -160,7 +161,7 @@ export class SavedObjectsPermissionControl {
160161
}
161162
return hasPermission;
162163
});
163-
if (!hasAllPermission) {
164+
if (!hasPermissionToAllObjects) {
164165
this.logger.debug(
165166
`Authorization failed, principals: ${JSON.stringify(
166167
principals
@@ -171,7 +172,7 @@ export class SavedObjectsPermissionControl {
171172
}
172173
return {
173174
success: true,
174-
result: hasAllPermission,
175+
result: hasPermissionToAllObjects,
175176
};
176177
}
177178

src/plugins/workspace/server/saved_objects/workspace_saved_objects_client_wrapper.ts

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55

66
import { i18n } from '@osd/i18n';
7-
import { intersection } from 'lodash';
87

98
import {
109
OpenSearchDashboardsRequest,
@@ -54,6 +53,20 @@ const generateSavedObjectsPermissionError = () =>
5453
)
5554
);
5655

56+
const intersection = <T extends string>(...args: T[][]) => {
57+
const occursCountMap: { [key: string]: number } = {};
58+
for (let i = 0; i < args.length; i++) {
59+
new Set(args[i]).forEach((key) => {
60+
occursCountMap[key] = (occursCountMap[key] || 0) + 1;
61+
});
62+
}
63+
return Object.keys(occursCountMap).filter((key) => occursCountMap[key] === args.length);
64+
};
65+
66+
const getDefaultValuesForEmpty = <T>(values: T[] | undefined, defaultValues: T[]) => {
67+
return !values || values.length === 0 ? defaultValues : values;
68+
};
69+
5770
export class WorkspaceSavedObjectsClientWrapper {
5871
private getScopedClient?: SavedObjectsServiceStart['getScopedClient'];
5972
private formatWorkspacePermissionModeToStringArray(
@@ -145,7 +158,12 @@ export class WorkspaceSavedObjectsClientWrapper {
145158
objectPermissionModes: WorkspacePermissionMode[],
146159
validateAllWorkspaces = true
147160
) {
148-
// Advanced settings have no permissions and workspaces, so we need to skip it.
161+
/**
162+
*
163+
* If savedObject doesn't have workspaces or permissions attributes, we don't know how to
164+
* validate it in current client wrapper. We need to skip it.
165+
*
166+
**/
149167
if (!savedObject.workspaces && !savedObject.permissions) {
150168
return true;
151169
}
@@ -210,7 +228,11 @@ export class WorkspaceSavedObjectsClientWrapper {
210228
return await wrapperOptions.client.delete(type, id, options);
211229
};
212230

213-
// validate `objectToUpdate` if can update with workspace permission, which is used for update and bulkUpdate
231+
/**
232+
* validate if can update`objectToUpdate`, means a user should either
233+
* have `Write` permission on the `objectToUpdate` itself or `LibraryWrite` permission
234+
* to any of the workspaces the `objectToUpdate` associated with.
235+
**/
214236
const validateUpdateWithWorkspacePermission = async <T = unknown>(
215237
objectToUpdate: SavedObject<T>
216238
): Promise<boolean> => {
@@ -272,9 +294,9 @@ export class WorkspaceSavedObjectsClientWrapper {
272294

273295
/**
274296
*
275-
* If target workspaces parameter exists, we don't need to do permission validation again.
276-
* The bulk create method in repository doesn't allow extends workspaces with override.
277-
* If target workspaces parameter doesn't exists, we need to check if has permission to object's workspaces or ACL.
297+
* If target workspaces parameter doesn't exists and `overwrite` is true, we need to check
298+
* if it has permission to the object itself(defined by the object ACL) or it has permission
299+
* to any of the workspaces that the object associates with.
278300
*
279301
*/
280302
if (!hasTargetWorkspaces && options.overwrite) {
@@ -330,9 +352,9 @@ export class WorkspaceSavedObjectsClientWrapper {
330352

331353
/**
332354
*
333-
* If target workspaces parameter exists, we don't need to do permission validation again.
334-
* The create method in repository doesn't allow extends workspaces with override.
335-
* If target workspaces parameter doesn't exists, we need to check if has permission to object's workspaces or ACL.
355+
* If target workspaces parameter doesn't exists, `options.id` was exists and `overwrite` is true,
356+
* we need to check if it has permission to the object itself(defined by the object ACL) or
357+
* it has permission to any of the workspaces that the object associates with.
336358
*
337359
*/
338360
if (
@@ -406,11 +428,16 @@ export class WorkspaceSavedObjectsClientWrapper {
406428
}
407429

408430
if (this.isRelatedToWorkspace(options.type)) {
409-
// Find all "read" saved objects by object's ACL for default
410-
options.ACLSearchParams.permissionModes = options.ACLSearchParams.permissionModes ?? [
411-
WorkspacePermissionMode.Read,
412-
WorkspacePermissionMode.Write,
413-
];
431+
/**
432+
*
433+
* This case is for finding workspace saved objects, will use passed permissionModes
434+
* and override passed principals from request to get all readable workspaces.
435+
*
436+
*/
437+
options.ACLSearchParams.permissionModes = getDefaultValuesForEmpty(
438+
options.ACLSearchParams.permissionModes,
439+
[WorkspacePermissionMode.Read, WorkspacePermissionMode.Write]
440+
);
414441
options.ACLSearchParams.principals = principals;
415442
} else {
416443
/**
@@ -430,12 +457,15 @@ export class WorkspaceSavedObjectsClientWrapper {
430457
* For outside passed permission modes, it may contains other permissions. Add a intersection
431458
* here to make sure only Library related permission modes will be used.
432459
*/
433-
permissionModes: options.ACLSearchParams.permissionModes
434-
? intersection(options.ACLSearchParams.permissionModes, [
435-
WorkspacePermissionMode.LibraryRead,
436-
WorkspacePermissionMode.LibraryWrite,
437-
])
438-
: [WorkspacePermissionMode.LibraryRead, WorkspacePermissionMode.LibraryWrite],
460+
permissionModes: getDefaultValuesForEmpty(
461+
options.ACLSearchParams.permissionModes
462+
? intersection(options.ACLSearchParams.permissionModes, [
463+
WorkspacePermissionMode.LibraryRead,
464+
WorkspacePermissionMode.LibraryWrite,
465+
])
466+
: [],
467+
[WorkspacePermissionMode.LibraryRead, WorkspacePermissionMode.LibraryWrite]
468+
),
439469
},
440470
})
441471
).saved_objects.map((item) => item.id);
@@ -471,10 +501,10 @@ export class WorkspaceSavedObjectsClientWrapper {
471501
*/
472502
options.workspaces = undefined;
473503
options.ACLSearchParams.workspaces = permittedWorkspaceIds;
474-
options.ACLSearchParams.permissionModes = options.ACLSearchParams.permissionModes ?? [
475-
WorkspacePermissionMode.Read,
476-
WorkspacePermissionMode.Write,
477-
];
504+
options.ACLSearchParams.permissionModes = getDefaultValuesForEmpty(
505+
options.ACLSearchParams.permissionModes,
506+
[WorkspacePermissionMode.Read, WorkspacePermissionMode.Write]
507+
);
478508
options.ACLSearchParams.principals = principals;
479509
}
480510
}

0 commit comments

Comments
 (0)