Skip to content

Commit b590fb0

Browse files
committed
Merge branch 'feature/util-has-permission' into feature/workstreams-refactored-permissions
2 parents 941086a + a965c22 commit b590fb0

File tree

1 file changed

+154
-0
lines changed

1 file changed

+154
-0
lines changed

src/util.js

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,160 @@ _.assignIn(util, {
592592

593593
return Promise.resolve(null);
594594
},
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+
),
595749
});
596750

597751
export default util;

0 commit comments

Comments
 (0)