@@ -592,6 +592,160 @@ _.assignIn(util, {
592
592
593
593
return Promise . resolve ( null ) ;
594
594
} ,
595
+
596
+ /**
597
+ * Check if user match the permission rule.
598
+ *
599
+ * This method uses permission rule defined in `permissionRule`
600
+ * and checks that the `user` matches it.
601
+ *
602
+ * If we define a rule with `projectRoles` list, we also should provide `projectMembers`
603
+ * - the list of project members.
604
+ *
605
+ * @param {Object } permissionRule permission rule
606
+ * @param {Array<String> } permissionRule.projectRoles the list of project roles of the user
607
+ * @param {Array<String> } permissionRule.topcoderRoles the list of Topcoder roles of the user
608
+ * @param {Object } user user for whom we check permissions
609
+ * @param {Object } user.roles list of user roles
610
+ * @param {Object } user.isMachine `true` - if it's machine, `false` - real user
611
+ * @param {Object } user.scopes scopes of user token
612
+ * @param {Array } projectMembers (optional) list of project members - required to check `topcoderRoles`
613
+ *
614
+ * @returns {Boolean } true, if has permission
615
+ */
616
+ matchPermissionRule : ( permissionRule , user , projectMembers ) => {
617
+ const member = _ . find ( projectMembers , { userId : user . userId } ) ;
618
+ let hasProjectRole = false ;
619
+ let hasTopcoderRole = false ;
620
+
621
+ if ( permissionRule ) {
622
+ if ( permissionRule . projectRoles
623
+ && permissionRule . projectRoles . length > 0
624
+ && ! ! member
625
+ ) {
626
+ hasProjectRole = _ . includes ( permissionRule . projectRoles , member . role ) ;
627
+ }
628
+
629
+ if ( permissionRule . topcoderRoles && permissionRule . topcoderRoles . length > 0 ) {
630
+ hasTopcoderRole = util . hasRoles ( { authUser : user } , permissionRule . topcoderRoles ) ;
631
+ }
632
+ }
633
+
634
+ return hasProjectRole || hasTopcoderRole ;
635
+ } ,
636
+
637
+ /**
638
+ * Check if user has permission.
639
+ *
640
+ * This method uses permission defined in `permission` and checks that the `user` matches it.
641
+ *
642
+ * `permission` may be defined in two ways:
643
+ * - **Full** way with defined `allowRule` and optional `denyRule`, example:
644
+ * ```js
645
+ * {
646
+ * allowRule: {
647
+ * projectRoles: [],
648
+ * topcoderRoles: []
649
+ * },
650
+ * denyRule: {
651
+ * projectRoles: [],
652
+ * topcoderRoles: []
653
+ * }
654
+ * }
655
+ * ```
656
+ * If user matches `denyRule` then the access would be dined even if matches `allowRule`.
657
+ * - **Simplified** way may be used if we only want to define `allowRule`.
658
+ * We can skip the `allowRule` property and define `allowRule` directly inside `permission` object, example:
659
+ * ```js
660
+ * {
661
+ * projectRoles: [],
662
+ * topcoderRoles: []
663
+ * }
664
+ * ```
665
+ * This **simplified** permission is equal to a **full** permission:
666
+ * ```js
667
+ * {
668
+ * allowRule: {
669
+ * projectRoles: [],
670
+ * topcoderRoles: []
671
+ * }
672
+ * }
673
+ * ```
674
+ *
675
+ * If we define any rule with `projectRoles` list, we also should provide `projectMembers`
676
+ * - the list of project members.
677
+ *
678
+ * @param {Object } permission permission or permissionRule
679
+ * @param {Object } user user for whom we check permissions
680
+ * @param {Object } user.roles list of user roles
681
+ * @param {Object } user.isMachine `true` - if it's machine, `false` - real user
682
+ * @param {Object } user.scopes scopes of user token
683
+ * @param {Array } projectMembers (optional) list of project members - required to check `topcoderRoles`
684
+ *
685
+ * @returns {Boolean } true, if has permission
686
+ */
687
+ hasPermission : ( permission , user , projectMembers ) => {
688
+ const allowRule = permission . allowRule ? permission . allowRule : permission ;
689
+ const denyRule = permission . denyRule ? permission . denyRule : null ;
690
+
691
+ const allow = util . matchPermissionRule ( allowRule , user , projectMembers ) ;
692
+ const deny = util . matchPermissionRule ( denyRule , user , projectMembers ) ;
693
+
694
+ return allow && ! deny ;
695
+ } ,
696
+
697
+ /**
698
+ * Check if user has permission for the project by `projectId`.
699
+ *
700
+ * This method uses permission defined in `permission` and checks that the `user` matches it.
701
+ *
702
+ * `permission` may be defined in two ways:
703
+ * - **Full** way with defined `allowRule` and optional `denyRule`, example:
704
+ * ```js
705
+ * {
706
+ * allowRule: {
707
+ * projectRoles: [],
708
+ * topcoderRoles: []
709
+ * },
710
+ * denyRule: {
711
+ * projectRoles: [],
712
+ * topcoderRoles: []
713
+ * }
714
+ * }
715
+ * ```
716
+ * If user matches `denyRule` then the access would be dined even if matches `allowRule`.
717
+ * - **Simplified** way may be used if we only want to define `allowRule`.
718
+ * We can skip the `allowRule` property and define `allowRule` directly inside `permission` object, example:
719
+ * ```js
720
+ * {
721
+ * projectRoles: [],
722
+ * topcoderRoles: []
723
+ * }
724
+ * ```
725
+ * This **simplified** permission is equal to a **full** permission:
726
+ * ```js
727
+ * {
728
+ * allowRule: {
729
+ * projectRoles: [],
730
+ * topcoderRoles: []
731
+ * }
732
+ * }
733
+ * ```
734
+ *
735
+ * @param {Object } permission permission or permissionRule
736
+ * @param {Object } user user for whom we check permissions
737
+ * @param {Object } user.roles list of user roles
738
+ * @param {Object } user.isMachine `true` - if it's machine, `false` - real user
739
+ * @param {Object } user.scopes scopes of user token
740
+ * @param {Number } projectId project id to check permissions for
741
+ *
742
+ * @returns {Promise<Boolean> } true, if has permission
743
+ */
744
+ hasPermissionForProject : ( permission , user , projectId ) => (
745
+ models . ProjectMember . getActiveProjectMembers ( projectId ) . then ( projectMembers =>
746
+ util . hasPermission ( permission , user , projectMembers ) ,
747
+ )
748
+ ) ,
595
749
} ) ;
596
750
597
751
export default util ;
0 commit comments