@@ -400,39 +400,103 @@ export const isOnlyOrgaAdmin = (user: AuthUser) => {
400
400
return ! isUserHasCapability ( user , SETTINGS_SET_ACCESSES ) && isUserHasCapability ( user , VIRTUAL_ORGANIZATION_ADMIN ) ;
401
401
} ;
402
402
403
- export const isOrganizationAllowed = ( element : BasicStoreCommon , user : AuthUser , settings :BasicStoreSettings ) => {
404
- const elementOrganizations = element [ RELATION_GRANTED_TO ] ?? [ ] ;
403
+ // returns all user member access ids : his id, his organizations ids (and parent organizations), his groups ids
404
+ export const computeUserMemberAccessIds = ( user : AuthUser ) => {
405
+ const memberAccessIds = [ user . id ] ;
406
+ if ( user . organizations ) {
407
+ const userOrganizationsIds = user . organizations . map ( ( org ) => org . internal_id ) ;
408
+ memberAccessIds . push ( ...userOrganizationsIds ) ;
409
+ }
410
+ if ( user . groups ) {
411
+ const userGroupsIds = user . groups . map ( ( group ) => group . internal_id ) ;
412
+ memberAccessIds . push ( ...userGroupsIds ) ;
413
+ }
414
+ if ( user . roles ) {
415
+ const userRolesIds = user . roles . map ( ( role ) => role . internal_id ) ;
416
+ memberAccessIds . push ( ...userRolesIds ) ;
417
+ }
418
+ return memberAccessIds ;
419
+ } ;
405
420
421
+ // region entity access by user
422
+
423
+ export const getUserAccessRight = ( user : AuthUser , element : any ) => {
424
+ if ( ! element . authorized_members || element . authorized_members . length === 0 ) { // no restricted user access on element
425
+ return MEMBER_ACCESS_RIGHT_ADMIN ;
426
+ }
427
+ const accessMembers = [ ...element . authorized_members ] ;
428
+ const userMemberAccessIds = computeUserMemberAccessIds ( user ) ;
429
+ const foundAccessMembers = accessMembers . filter ( ( u ) => u . id === MEMBER_ACCESS_ALL || userMemberAccessIds . includes ( u . id ) ) ;
430
+ // If user have extended capabilities, is an admin
431
+ if ( ( element . authorized_authorities ?? [ ] ) . some ( ( c : string ) => userMemberAccessIds . includes ( c ) || isUserHasCapability ( user , c ) ) ) {
432
+ return MEMBER_ACCESS_RIGHT_ADMIN ;
433
+ }
434
+ // if user is bypass, user has admin access (needed for data management usage)
435
+ if ( isBypassUser ( user ) ) {
436
+ return MEMBER_ACCESS_RIGHT_ADMIN ;
437
+ }
438
+ if ( ! foundAccessMembers . length ) { // user has no access
439
+ return null ;
440
+ }
441
+ if ( foundAccessMembers . some ( ( m ) => m . access_right === MEMBER_ACCESS_RIGHT_ADMIN ) ) {
442
+ return MEMBER_ACCESS_RIGHT_ADMIN ;
443
+ }
444
+ if ( foundAccessMembers . some ( ( m ) => m . access_right === MEMBER_ACCESS_RIGHT_EDIT ) ) {
445
+ return MEMBER_ACCESS_RIGHT_EDIT ;
446
+ }
447
+ return MEMBER_ACCESS_RIGHT_VIEW ;
448
+ } ;
449
+ export const hasAuthorizedMemberAccess = ( user : AuthUser , element : { authorized_members ?: AuthorizedMember [ ] , authorized_authorities ?: string [ ] } ) => {
450
+ const userAccessRight = getUserAccessRight ( user , element ) ;
451
+ return ! ! userAccessRight ;
452
+ } ;
453
+
454
+ const isEntityOrganizationsAllowed = (
455
+ entityInternalId : string ,
456
+ entityOrganizations : string [ ] ,
457
+ user : AuthUser ,
458
+ settings : BasicStoreSettings ,
459
+ opts : { useStandardId ?: boolean } = { }
460
+ ) => {
461
+ const { useStandardId = false } = opts ;
406
462
// If platform organization is set
407
463
if ( settings . platform_organization ) {
408
- const userOrganizations = user . organizations . map ( ( o ) => o . internal_id ) ;
464
+ const userOrganizations = user . organizations . map ( ( o ) => ( useStandardId ? o . standard_id : o . internal_id ) ) ;
409
465
410
466
// If user part of platform organization, is granted by default
411
467
if ( user . inside_platform_organization ) {
412
468
return true ;
413
469
}
414
470
// Grant access to the user individual
415
- if ( element . internal_id === user . individual_id ) {
471
+ if ( entityInternalId === user . individual_id ) {
416
472
return true ;
417
473
}
418
474
// If not, user is by design inside an organization
419
475
// If element has no current sharing organization, it can be accessed (secure by default)
420
476
// If element is shared, user must have a matching sharing organization
421
- return elementOrganizations . some ( ( r ) => userOrganizations . includes ( r ) ) ;
477
+ return entityOrganizations . some ( ( r ) => userOrganizations . includes ( r ) ) ;
422
478
}
423
479
return true ;
424
480
} ;
425
481
482
+ export const isOrganizationAllowed = ( element : BasicStoreCommon , user : AuthUser , settings : BasicStoreSettings ) => {
483
+ const elementOrganizations = element [ RELATION_GRANTED_TO ] ?? [ ] ;
484
+ return isEntityOrganizationsAllowed ( element . internal_id , elementOrganizations , user , settings ) ;
485
+ } ;
486
+
487
+ const isOrganizationUnrestrictedForEntityType = ( entityType : string ) => {
488
+ const types = [ entityType , ...getParentTypes ( entityType ) ] ;
489
+ if ( STIX_ORGANIZATIONS_UNRESTRICTED . some ( ( r ) => types . includes ( r ) ) ) {
490
+ return true ;
491
+ }
492
+ return false ;
493
+ } ;
426
494
/**
427
495
* Organization unrestricted mean that this element is visible whatever the organization the user belongs to.
428
496
* @param element
429
497
*/
430
498
export const isOrganizationUnrestricted = ( element : BasicStoreCommon ) => {
431
- const types = [ element . entity_type , ...getParentTypes ( element . entity_type ) ] ;
432
- if ( STIX_ORGANIZATIONS_UNRESTRICTED . some ( ( r ) => types . includes ( r ) ) ) {
433
- return true ;
434
- }
435
- return false ;
499
+ return isOrganizationUnrestrictedForEntityType ( element . entity_type ) ;
436
500
} ;
437
501
438
502
export const isMarkingAllowed = ( element : BasicStoreCommon , userAuthorizedMarkings : string [ ] ) => {
@@ -469,13 +533,19 @@ export const userFilterStoreElements = async (context: AuthContext, user: AuthUs
469
533
if ( ! isMarkingAllowed ( element , authorizedMarkings ) ) {
470
534
return false ;
471
535
}
472
- // 2. Check organizations
536
+ // 2. check authorized members
537
+ if ( ! hasAuthorizedMemberAccess ( user , element ) ) {
538
+ return false ;
539
+ }
540
+ // 3. Check organizations
473
541
// Allow unrestricted entities
474
542
if ( isOrganizationUnrestricted ( element ) ) {
475
543
return true ;
476
544
}
477
545
// Check restricted elements
478
- return isOrganizationAllowed ( element , user , settings ) ;
546
+ // either allowed by orga sharing or has authorized members access if authorized_members are defined (bypass orga sharing)
547
+ return isOrganizationAllowed ( element , user , settings )
548
+ || ( element . authorized_members && element . authorized_members . length > 0 && hasAuthorizedMemberAccess ( user , element ) ) ;
479
549
} ) ;
480
550
} ;
481
551
return telemetry ( context , user , 'FILTERING store filter' , {
@@ -503,52 +573,29 @@ export const isUserCanAccessStixElement = async (context: AuthContext, user: Aut
503
573
return false ;
504
574
}
505
575
}
506
- // 2. Check organizations
576
+ const authorized_members = instance . extensions ?. [ STIX_EXT_OCTI ] ?. authorized_members ?? [ ] ;
577
+ const authorizedMemberAllowed = hasAuthorizedMemberAccess ( user , { authorized_members } ) ;
578
+ // 2. check authorized members
579
+ if ( ! authorizedMemberAllowed ) {
580
+ return false ;
581
+ }
582
+ // 3. Check organizations
507
583
// Allow unrestricted entities
508
584
const entityType = instance . extensions ?. [ STIX_EXT_OCTI ] ?. type ?? generateInternalType ( instance ) ;
509
- const types = [ entityType , ...getParentTypes ( entityType ) ] ;
510
- if ( STIX_ORGANIZATIONS_UNRESTRICTED . some ( ( r ) => types . includes ( r ) ) ) {
585
+ if ( isOrganizationUnrestrictedForEntityType ( entityType ) ) {
511
586
return true ;
512
587
}
513
588
// Check restricted elements
514
589
const settings = await getEntityFromCache < BasicStoreSettings > ( context , user , ENTITY_TYPE_SETTINGS ) ;
515
590
const elementOrganizations = instance . extensions ?. [ STIX_EXT_OCTI ] ?. granted_refs ?? [ ] ;
516
- const userOrganizations = user . organizations . map ( ( o ) => o . standard_id ) ;
517
- // If platform organization is set
518
- if ( settings . platform_organization ) {
519
- // If user part of platform organization, is granted by default
520
- if ( user . inside_platform_organization ) {
521
- return true ;
522
- }
523
- // If not, user is by design inside an organization
524
- // If element has no current sharing organization, it can be accessed (secure by default)
525
- // If element is shared, user must have a matching sharing organization
526
- return elementOrganizations . some ( ( r ) => userOrganizations . includes ( r ) ) ;
527
- }
528
- // If no platform organization is set, user can access
529
- return true ;
591
+ const organizationAllowed = isEntityOrganizationsAllowed ( instance . id , elementOrganizations , user , settings , { useStandardId : true } ) ;
592
+ // either allowed by organization or authorized members
593
+ return organizationAllowed || ( authorized_members . length > 0 && authorizedMemberAllowed ) ;
530
594
} ;
595
+ // end region
531
596
532
597
// region member access
533
598
534
- // returns all user member access ids : his id, his organizations ids (and parent organizations), his groups ids
535
- export const computeUserMemberAccessIds = ( user : AuthUser ) => {
536
- const memberAccessIds = [ user . id ] ;
537
- if ( user . organizations ) {
538
- const userOrganizationsIds = user . organizations . map ( ( org ) => org . internal_id ) ;
539
- memberAccessIds . push ( ...userOrganizationsIds ) ;
540
- }
541
- if ( user . groups ) {
542
- const userGroupsIds = user . groups . map ( ( group ) => group . internal_id ) ;
543
- memberAccessIds . push ( ...userGroupsIds ) ;
544
- }
545
- if ( user . roles ) {
546
- const userRolesIds = user . roles . map ( ( role ) => role . internal_id ) ;
547
- memberAccessIds . push ( ...userRolesIds ) ;
548
- }
549
- return memberAccessIds ;
550
- } ;
551
-
552
599
// user access methods
553
600
export const isDirectAdministrator = ( user : AuthUser , element : any ) => {
554
601
const elementAccessIds = element . authorized_members
@@ -557,32 +604,6 @@ export const isDirectAdministrator = (user: AuthUser, element: any) => {
557
604
const userMemberAccessIds = computeUserMemberAccessIds ( user ) ;
558
605
return elementAccessIds . some ( ( a : string ) => userMemberAccessIds . includes ( a ) ) ;
559
606
} ;
560
- export const getUserAccessRight = ( user : AuthUser , element : any ) => {
561
- if ( ! element . authorized_members || element . authorized_members . length === 0 ) { // no restricted user access on element
562
- return MEMBER_ACCESS_RIGHT_ADMIN ;
563
- }
564
- const accessMembers = [ ...element . authorized_members ] ;
565
- const userMemberAccessIds = computeUserMemberAccessIds ( user ) ;
566
- const foundAccessMembers = accessMembers . filter ( ( u ) => u . id === MEMBER_ACCESS_ALL || userMemberAccessIds . includes ( u . id ) ) ;
567
- // If user have extended capabilities, is an admin
568
- if ( ( element . authorized_authorities ?? [ ] ) . some ( ( c : string ) => userMemberAccessIds . includes ( c ) || isUserHasCapability ( user , c ) ) ) {
569
- return MEMBER_ACCESS_RIGHT_ADMIN ;
570
- }
571
- // if user is bypass, user has admin access (needed for data management usage)
572
- if ( isBypassUser ( user ) ) {
573
- return MEMBER_ACCESS_RIGHT_ADMIN ;
574
- }
575
- if ( ! foundAccessMembers . length ) { // user has no access
576
- return null ;
577
- }
578
- if ( foundAccessMembers . some ( ( m ) => m . access_right === MEMBER_ACCESS_RIGHT_ADMIN ) ) {
579
- return MEMBER_ACCESS_RIGHT_ADMIN ;
580
- }
581
- if ( foundAccessMembers . some ( ( m ) => m . access_right === MEMBER_ACCESS_RIGHT_EDIT ) ) {
582
- return MEMBER_ACCESS_RIGHT_EDIT ;
583
- }
584
- return MEMBER_ACCESS_RIGHT_VIEW ;
585
- } ;
586
607
587
608
// ensure that user can access the element (operation: edit / delete / manage-access)
588
609
export const validateUserAccessOperation = ( user : AuthUser , element : any , operation : 'edit' | 'delete' | 'manage-access' | 'manage-authorities-access' ) => {
0 commit comments