@@ -50,19 +50,20 @@ var utils = {
50
50
return o . hasOwnProperty ( propName ) && o [ propName ] !== undefined ;
51
51
} ,
52
52
/**
53
- * Converts the given (string) value into an array of string.
54
- * Note that this does not throw if the value is not a string or array.
55
- * It will silently return `null`.
53
+ * Converts the given (string) value into an array of string. Note that
54
+ * this does not throw if the value is not a string or array. It will
55
+ * silently return `[]` (empty array). So where ever it's used, the host
56
+ * function should consider throwing.
56
57
* @param {Any } value
57
- * @returns {Boolean|null }
58
+ * @returns {string[] }
58
59
*/
59
60
toStringArray : function ( value ) {
60
61
if ( Array . isArray ( value ) )
61
62
return value ;
62
63
if ( typeof value === 'string' )
63
64
return value . trim ( ) . split ( / \s * [ ; , ] \s * / ) ;
64
- // throw new Error('Cannot convert value to array!' );
65
- return null ;
65
+ // throw new Error('Expected a string or array of strings, got ' + utils.type(value) );
66
+ return [ ] ;
66
67
} ,
67
68
/**
68
69
* Checks whether the given array consists of non-empty string items.
@@ -298,14 +299,11 @@ var utils = {
298
299
* is invalid.
299
300
*/
300
301
validRoleObject : function ( grants , roleName ) {
301
- console . log ( 'enter!' ) ;
302
302
var role = grants [ roleName ] ;
303
303
if ( ! role || utils . type ( role ) !== 'object' ) {
304
- console . log ( 'Invalid role:' , roleName ) ;
305
304
throw new core_1 . AccessControlError ( "Invalid role definition." ) ;
306
305
}
307
306
utils . eachKey ( role , function ( resourceName ) {
308
- console . log ( resourceName , utils . validName ( resourceName , false ) ) ;
309
307
if ( ! utils . validName ( resourceName , false ) ) {
310
308
if ( resourceName === '$extend' ) {
311
309
var extRoles = role [ resourceName ] ; // semantics
@@ -322,8 +320,8 @@ var utils = {
322
320
throw new core_1 . AccessControlError ( "Cannot use reserved name \"" + resourceName + "\" for a resource." ) ;
323
321
}
324
322
}
325
- else if ( ! utils . validResourceObject ( role [ resourceName ] ) ) {
326
- // throw new AccessControlError(`Invalid resource definition ("${ resourceName}") for role "${roleName}".`);
323
+ else {
324
+ utils . validResourceObject ( role [ resourceName ] ) ; // throws on failure
327
325
}
328
326
} ) ;
329
327
return true ;
@@ -347,9 +345,12 @@ var utils = {
347
345
if ( type === 'object' ) {
348
346
utils . eachKey ( o , function ( roleName ) {
349
347
if ( utils . validName ( roleName ) ) {
350
- return utils . validRoleObject ( o , roleName ) ; // will throw on failure
348
+ return utils . validRoleObject ( o , roleName ) ; // throws on failure
351
349
}
350
+ /* istanbul ignore next */
352
351
return false ;
352
+ // above is redundant, previous checks will already throw on
353
+ // failure so we'll never need to break early from this.
353
354
} ) ;
354
355
grants = o ;
355
356
}
@@ -393,7 +394,8 @@ var utils = {
393
394
if ( asString === void 0 ) { asString = false ; }
394
395
// validate and normalize action
395
396
if ( typeof info . action !== 'string' ) {
396
- throw new core_1 . AccessControlError ( "Invalid action: " + info . action ) ;
397
+ // throw new AccessControlError(`Invalid action: ${info.action}`);
398
+ throw new core_1 . AccessControlError ( "Invalid action: " + JSON . stringify ( info ) ) ;
397
399
}
398
400
var s = info . action . split ( ':' ) ;
399
401
if ( enums_1 . actions . indexOf ( s [ 0 ] . trim ( ) . toLowerCase ( ) ) < 0 ) {
@@ -466,12 +468,12 @@ var utils = {
466
468
access = Object . assign ( { } , access ) ;
467
469
// validate and normalize role(s)
468
470
access . role = utils . toStringArray ( access . role ) ;
469
- if ( ! utils . isFilledStringArray ( access . role ) ) {
471
+ if ( access . role . length === 0 || ! utils . isFilledStringArray ( access . role ) ) {
470
472
throw new core_1 . AccessControlError ( "Invalid role(s): " + JSON . stringify ( access . role ) ) ;
471
473
}
472
474
// validate and normalize resource
473
475
access . resource = utils . toStringArray ( access . resource ) ;
474
- if ( ! utils . isFilledStringArray ( access . resource ) ) {
476
+ if ( access . resource . length === 0 || ! utils . isFilledStringArray ( access . resource ) ) {
475
477
throw new core_1 . AccessControlError ( "Invalid resource(s): " + JSON . stringify ( access . resource ) ) ;
476
478
}
477
479
// normalize attributes
@@ -515,7 +517,7 @@ var utils = {
515
517
getRoleHierarchyOf : function ( grants , roleName , rootRole ) {
516
518
// `rootRole` is for memory storage. Do NOT set it when using;
517
519
// and do NOT document this paramter.
518
- rootRole = rootRole || roleName ;
520
+ // rootRole = rootRole || roleName;
519
521
var role = grants [ roleName ] ;
520
522
if ( ! role )
521
523
throw new core_1 . AccessControlError ( "Role not found: \"" + roleName + "\"" ) ;
@@ -531,10 +533,10 @@ var utils = {
531
533
}
532
534
// throw if cross-inheritance and also avoid memory leak with
533
535
// maximum call stack error
534
- if ( rootRole === exRoleName ) {
536
+ if ( rootRole && ( rootRole === exRoleName ) ) {
535
537
throw new core_1 . AccessControlError ( "Cross inheritance is not allowed. Role \"" + exRoleName + "\" already extends \"" + rootRole + "\"." ) ;
536
538
}
537
- var ext = utils . getRoleHierarchyOf ( grants , exRoleName , rootRole ) ;
539
+ var ext = utils . getRoleHierarchyOf ( grants , exRoleName , rootRole || roleName ) ;
538
540
arr = utils . uniqConcat ( arr , ext ) ;
539
541
} ) ;
540
542
return arr ;
@@ -543,11 +545,12 @@ var utils = {
543
545
* Gets roles and extended roles in a flat array.
544
546
*/
545
547
getFlatRoles : function ( grants , roles ) {
546
- roles = utils . toStringArray ( roles ) ;
547
- if ( ! roles )
548
+ var arrRoles = utils . toStringArray ( roles ) ;
549
+ if ( arrRoles . length === 0 ) {
548
550
throw new core_1 . AccessControlError ( "Invalid role(s): " + JSON . stringify ( roles ) ) ;
549
- var arr = utils . uniqConcat ( [ ] , roles ) ; // roles.concat();
550
- roles . forEach ( function ( roleName ) {
551
+ }
552
+ var arr = utils . uniqConcat ( [ ] , arrRoles ) ; // roles.concat();
553
+ arrRoles . forEach ( function ( roleName ) {
551
554
arr = utils . uniqConcat ( arr , utils . getRoleHierarchyOf ( grants , roleName ) ) ;
552
555
} ) ;
553
556
// console.log(`flat roles for ${roles}`, arr);
@@ -581,13 +584,14 @@ var utils = {
581
584
*
582
585
* @param {Any } grants - Grants model to be checked.
583
586
* @param {string } roles - Target role to be checked.
584
- * @param {string|string[] } extenderRoles - Extender role(s) to be
585
- * checked.
586
- * @returns {Boolean }
587
+ * @param {string|string[] } extenderRoles - Extender role(s) to be checked.
588
+ *
589
+ * @returns {string|null } - Returns the first cross extending role. `null`
590
+ * if none.
587
591
*/
588
- getCrossInheritedRole : function ( grants , roleName , extenderRoles ) {
589
- var extenders = utils . toStringArray ( extenderRoles ) ; // [roleName].concat();
590
- var crossInherited = false ;
592
+ getCrossExtendingRole : function ( grants , roleName , extenderRoles ) {
593
+ var extenders = utils . toStringArray ( extenderRoles ) ;
594
+ var crossInherited = null ;
591
595
utils . each ( extenders , function ( e ) {
592
596
if ( crossInherited || roleName === e ) {
593
597
return false ; // break out of loop
@@ -623,43 +627,41 @@ var utils = {
623
627
* a cross-inherited role.
624
628
*/
625
629
extendRole : function ( grants , roles , extenderRoles ) {
630
+ // roles cannot be omitted or an empty array
631
+ roles = utils . toStringArray ( roles ) ;
632
+ if ( roles . length === 0 ) {
633
+ throw new core_1 . AccessControlError ( "Invalid role(s): " + JSON . stringify ( roles ) ) ;
634
+ }
635
+ // extenderRoles cannot be omitted or but can be an empty array
636
+ if ( utils . isEmptyArray ( extenderRoles ) )
637
+ return ;
626
638
var arrExtRoles = utils . toStringArray ( extenderRoles ) . concat ( ) ;
627
- if ( ! arrExtRoles )
639
+ if ( arrExtRoles . length === 0 ) {
628
640
throw new core_1 . AccessControlError ( "Cannot inherit invalid role(s): " + JSON . stringify ( extenderRoles ) ) ;
641
+ }
629
642
var nonExistentExtRoles = utils . getNonExistentRoles ( grants , arrExtRoles ) ;
630
643
if ( nonExistentExtRoles . length > 0 ) {
631
644
throw new core_1 . AccessControlError ( "Cannot inherit non-existent role(s): \"" + nonExistentExtRoles . join ( ', ' ) + "\"" ) ;
632
645
}
633
- roles = utils . toStringArray ( roles ) ;
634
- if ( ! roles )
635
- throw new core_1 . AccessControlError ( "Invalid role(s): " + JSON . stringify ( roles ) ) ;
636
646
roles . forEach ( function ( roleName ) {
637
647
if ( ! grants [ roleName ] )
638
648
throw new core_1 . AccessControlError ( "Role not found: \"" + roleName + "\"" ) ;
639
649
if ( arrExtRoles . indexOf ( roleName ) >= 0 ) {
640
650
throw new core_1 . AccessControlError ( "Cannot extend role \"" + roleName + "\" by itself." ) ;
641
651
}
642
- // getCrossInheritedRole () returns false or the first
652
+ // getCrossExtendingRole () returns false or the first
643
653
// cross-inherited role, if found.
644
- var crossInherited = utils . getCrossInheritedRole ( grants , roleName , arrExtRoles ) ;
654
+ var crossInherited = utils . getCrossExtendingRole ( grants , roleName , arrExtRoles ) ;
645
655
if ( crossInherited ) {
646
656
throw new core_1 . AccessControlError ( "Cross inheritance is not allowed. Role \"" + crossInherited + "\" already extends \"" + roleName + "\"." ) ;
647
657
}
648
- if ( utils . validName ( roleName ) ) {
649
- if ( ! grants . hasOwnProperty ( roleName ) ) {
650
- grants [ roleName ] = {
651
- $extend : arrExtRoles
652
- } ;
653
- }
654
- else {
655
- var r = grants [ roleName ] ;
656
- if ( Array . isArray ( r . $extend ) ) {
657
- r . $extend = utils . uniqConcat ( r . $extend , arrExtRoles ) ;
658
- }
659
- else {
660
- r . $extend = arrExtRoles ;
661
- }
662
- }
658
+ utils . validName ( roleName ) ; // throws if false
659
+ var r = grants [ roleName ] ;
660
+ if ( Array . isArray ( r . $extend ) ) {
661
+ r . $extend = utils . uniqConcat ( r . $extend , arrExtRoles ) ;
662
+ }
663
+ else {
664
+ r . $extend = arrExtRoles ;
663
665
}
664
666
} ) ;
665
667
} ,
@@ -728,31 +730,27 @@ var utils = {
728
730
* @returns {string[] } - Array of union'ed attributes.
729
731
*/
730
732
getUnionAttrsOfRoles : function ( grants , query ) {
731
- if ( ! grants ) {
732
- throw new core_1 . AccessControlError ( 'Grants are not set.' ) ;
733
- }
734
733
// throws if has any invalid property value
735
734
query = utils . normalizeQueryInfo ( query ) ;
736
- var grantItem ;
735
+ var role ;
737
736
var resource ;
738
737
var attrsList = [ ] ;
739
738
// get roles and extended roles in a flat array
740
739
var roles = utils . getFlatRoles ( grants , query . role ) ;
741
740
// iterate through roles and add permission attributes (array) of
742
741
// each role to attrsList (array).
743
- roles . forEach ( function ( role , index ) {
744
- grantItem = grants [ role ] ;
745
- if ( grantItem ) {
746
- resource = grantItem [ query . resource ] ;
747
- if ( resource ) {
748
- // e.g. resource['create:own']
749
- // If action has possession "any", it will also return
750
- // `granted=true` for "own", if "own" is not defined.
751
- attrsList . push ( ( resource [ query . action + ':' + query . possession ]
752
- || resource [ query . action + ':any' ]
753
- || [ ] ) . concat ( ) ) ;
754
- // console.log(resource, 'for:', action + '.' + possession);
755
- }
742
+ roles . forEach ( function ( roleName , index ) {
743
+ role = grants [ roleName ] ;
744
+ // no need to check role existence #getFlatRoles() does that.
745
+ resource = role [ query . resource ] ;
746
+ if ( resource ) {
747
+ // e.g. resource['create:own']
748
+ // If action has possession "any", it will also return
749
+ // `granted=true` for "own", if "own" is not defined.
750
+ attrsList . push ( ( resource [ query . action + ':' + query . possession ]
751
+ || resource [ query . action + ':any' ]
752
+ || [ ] ) . concat ( ) ) ;
753
+ // console.log(resource, 'for:', action + '.' + possession);
756
754
}
757
755
} ) ;
758
756
// union all arrays of (permitted resource) attributes (for each role)
@@ -776,16 +774,17 @@ var utils = {
776
774
*/
777
775
lockAC : function ( ac ) {
778
776
var _ac = ac ; // ts
779
- if ( ! _ac . _grants ) {
780
- throw new core_1 . AccessControlError ( 'Cannot lock due to invalid grants model.' ) ;
777
+ if ( ! _ac . _grants || Object . keys ( _ac . _grants ) . length === 0 ) {
778
+ throw new core_1 . AccessControlError ( 'Cannot lock empty or invalid grants model.' ) ;
781
779
}
782
780
var locked = ac . isLocked && Object . isFrozen ( _ac . _grants ) ;
783
781
if ( ! locked )
784
782
locked = Boolean ( utils . deepFreeze ( _ac . _grants ) ) ;
783
+ /* istanbul ignore next */
785
784
if ( ! locked ) {
786
785
throw new core_1 . AccessControlError ( "Could not lock grants: " + typeof _ac . _grants ) ;
787
786
}
788
- _ac . _locked = locked ;
787
+ _ac . _isLocked = locked ;
789
788
} ,
790
789
// ----------------------
791
790
// NOTATION/GLOB UTILS
0 commit comments