44 */
55
66import { i18n } from '@osd/i18n' ;
7- import { intersection } from 'lodash' ;
87
98import {
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+
5770export 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