PageRenderTime 50ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/jira-project/jira-components/jira-core/src/main/java/com/atlassian/jira/security/WorkflowBasedPermissionManager.java

https://bitbucket.org/ahmed_bilal_360factors/jira7-core
Java | 261 lines | 188 code | 28 blank | 45 comment | 41 complexity | 095b67ae02bbcecdd6048e81aeb9e2d4 MD5 | raw file
Possible License(s): Apache-2.0
  1. package com.atlassian.jira.security;
  2. import com.atlassian.jira.component.ComponentAccessor;
  3. import com.atlassian.jira.config.SubTaskManager;
  4. import com.atlassian.jira.issue.Issue;
  5. import com.atlassian.jira.issue.status.Status;
  6. import com.atlassian.jira.permission.PermissionContext;
  7. import com.atlassian.jira.permission.PermissionContextFactory;
  8. import com.atlassian.jira.permission.WorkflowPermission;
  9. import com.atlassian.jira.permission.WorkflowPermissionFactory;
  10. import com.atlassian.jira.project.Project;
  11. import com.atlassian.jira.security.plugin.ProjectPermissionKey;
  12. import com.atlassian.jira.security.plugin.ProjectPermissionTypesManager;
  13. import com.atlassian.jira.user.ApplicationUser;
  14. import com.opensymphony.workflow.loader.ActionDescriptor;
  15. import org.ofbiz.core.entity.GenericValue;
  16. import org.slf4j.Logger;
  17. import org.slf4j.LoggerFactory;
  18. import javax.annotation.Nonnull;
  19. import javax.annotation.Nullable;
  20. import java.util.List;
  21. import static com.atlassian.jira.permission.LegacyProjectPermissionKeyMapping.getKey;
  22. /**
  23. * Permission manager which allows workflow permissions to be further restricted for each workflow step, in the workflow XML descriptor.
  24. * For instance, if the workflow contains a step:
  25. * <pre>
  26. * &lt;step id="1" name="Open"&gt;
  27. * &lt;meta name="jira.status.id"&gt;1&lt;/meta&gt;
  28. * &lt;meta name="jira.permission.comment.group"&gt;acme-bizusers&lt;/meta&gt;
  29. * &lt;meta name="jira.permission.comment.user"&gt;qa&lt;/meta&gt;
  30. * &lt;meta name="jira.permission.edit.group.1"&gt;jira-developers&lt;/meta&gt;
  31. * &lt;meta name="jira.permission.edit.group.2"&gt;jira-editors&lt;/meta&gt;
  32. * &lt;meta name="jira.permission.edit.projectrole">10001&lt;/meta>
  33. * </pre>
  34. * then only members of the acme-bizusers group and user 'qa' will be able to comment on open issues, and only members of
  35. * 'jira-developers' and 'jira-editors' groups or members of the project role with id '10001' will be able to edit issues.
  36. * Assuming, of course, these users already have the relevant permission in the permission scheme.<p>
  37. * Meta attributes can also modify subtasks' permissions. For example if the 'Bug' workflow's Open step has:
  38. * <pre>
  39. * &lt;meta name="jira.permission.subtasks.edit.group"&gt;jira-qa&lt;/meta&gt;
  40. * </pre>
  41. * Then subtasks of Bugs will only be editable by 'jira-qa' members, when their parent is in the Open state.<p>
  42. * The format is 'jira.permission.[subtasks.]{permission}.{type}[.suffix]', where:
  43. * <ul>
  44. * <li>{permission} is a short name specified in {@link Permissions}
  45. * <li>{type} is a type (group, user, assignee, reporter, lead, userCF, projectrole)
  46. * of permission granted, or <tt>denied</tt> to deny the permission.
  47. * <li><tt>subtasks.</tt>, if specified, indicates that the permission
  48. * applies to the subtasks of issues in this step.
  49. * <p>
  50. * <b>Important:</b>Workflow permissions can only <i>restrict</i>
  51. * permissions set in the permission scheme, not grant permissions.
  52. *
  53. * @see com.atlassian.jira.permission.WorkflowBasedPermissionSchemeManager
  54. */
  55. public class WorkflowBasedPermissionManager extends DefaultPermissionManager {
  56. private static final Logger log = LoggerFactory.getLogger(WorkflowBasedPermissionManager.class);
  57. private final WorkflowPermissionFactory workflowPermissionFactory;
  58. private final PermissionContextFactory permissionContextFactory;
  59. public WorkflowBasedPermissionManager(final WorkflowPermissionFactory workflowPermissionFactory,
  60. final PermissionContextFactory permissionContextFactory,
  61. final ProjectPermissionTypesManager projectPermissionTypesManager,
  62. final ProjectPermissionOverrideDescriptorCache projectPermissionOverrideDescriptorCache) {
  63. super(projectPermissionTypesManager, projectPermissionOverrideDescriptorCache);
  64. this.workflowPermissionFactory = workflowPermissionFactory;
  65. this.permissionContextFactory = permissionContextFactory;
  66. }
  67. @Override
  68. public boolean hasPermission(final int permissionsId, final Issue issue, final ApplicationUser user) {
  69. final boolean permSchemeAllows = super.hasPermission(permissionsId, issue, user);
  70. return workflowPermissionCheck(permSchemeAllows, permissionsId, issue, user);
  71. }
  72. @Override
  73. public boolean hasPermission(@Nonnull final ProjectPermissionKey permissionsKey, @Nonnull final Issue issue, final ApplicationUser user) {
  74. final boolean permSchemeAllows = super.hasPermission(permissionsKey, issue, user);
  75. return workflowPermissionCheck(permSchemeAllows, permissionsKey, issue, user);
  76. }
  77. @Override
  78. public boolean hasPermission(@Nonnull final ProjectPermissionKey permissionKey, @Nonnull final Issue issue, @Nullable final ApplicationUser user, @Nullable final ActionDescriptor actionDescriptor) {
  79. // Check for permission ignoring workflow/status
  80. final boolean permSchemeAllows = super.hasPermission(permissionKey, issue, user);
  81. // Now see if the new status will change permissions
  82. return workflowPermissionCheck(permSchemeAllows, permissionKey, issue, user, actionDescriptor);
  83. }
  84. @Override
  85. public boolean hasPermission(@Nonnull final ProjectPermissionKey permissionKey, @Nonnull final Issue issue, @Nullable final ApplicationUser user, @Nonnull final Status status) {
  86. // Check for permission ignoring workflow/status
  87. final boolean permSchemeAllows = super.hasPermission(permissionKey, issue, user);
  88. // Now see if the new status will change permissions
  89. return workflowPermissionCheck(permSchemeAllows, permissionKey, issue, user, status);
  90. }
  91. @Override
  92. public boolean hasPermission(final int permissionsId, final Project project, final ApplicationUser user) {
  93. final boolean permSchemeAllows = super.hasPermission(permissionsId, project, user);
  94. return workflowPermissionCheck(permSchemeAllows, permissionsId, project.getGenericValue(), user);
  95. }
  96. @Override
  97. public boolean hasPermission(@Nonnull final ProjectPermissionKey permissionsKey, @Nonnull final Project project, @Nullable final ApplicationUser user) {
  98. final boolean permSchemeAllows = super.hasPermission(permissionsKey, project, user);
  99. return workflowPermissionCheck(permSchemeAllows, permissionsKey, getIssueOrNull(project.getGenericValue()), user);
  100. }
  101. @Override
  102. public boolean hasPermission(final int permissionsId, final Project project, final ApplicationUser user, final boolean issueCreation) {
  103. final boolean permSchemeAllows = super.hasPermission(permissionsId, project, user, issueCreation);
  104. return workflowPermissionCheck(permSchemeAllows, permissionsId, project.getGenericValue(), user);
  105. }
  106. @Override
  107. public boolean hasPermission(@Nonnull final ProjectPermissionKey permissionsKey, @Nonnull final Project project, final ApplicationUser user, final boolean issueCreation) {
  108. final boolean permSchemeAllows = super.hasPermission(permissionsKey, project, user, issueCreation);
  109. return workflowPermissionCheck(permSchemeAllows, permissionsKey, getIssueOrNull(project.getGenericValue()), user);
  110. }
  111. private boolean workflowPermissionCheck(final boolean permissionSchemeAllows, final int permissionId, final GenericValue entity, final ApplicationUser user) {
  112. ProjectPermissionKey permissionKey = getKey(permissionId);
  113. return workflowPermissionCheck(permissionSchemeAllows, permissionKey, getIssueOrNull(entity), user);
  114. }
  115. private boolean workflowPermissionCheck(final boolean permissionSchemeAllows, final int permissionId, final Issue issue, final ApplicationUser user) {
  116. final ProjectPermissionKey permissionKey = getKey(permissionId);
  117. return workflowPermissionCheck(permissionSchemeAllows, permissionKey, issue, user);
  118. }
  119. private boolean workflowPermissionCheck(final boolean permissionSchemeAllows, final ProjectPermissionKey permissionKey, final Issue issue, final ApplicationUser user) {
  120. return workflowPermissionCheck(permissionSchemeAllows, permissionKey, issue, user, (ActionDescriptor) null);
  121. }
  122. private boolean workflowPermissionCheck(final boolean permissionSchemeAllows, final ProjectPermissionKey permissionKey,
  123. final Issue issue, final ApplicationUser user, @Nonnull final Status status) {
  124. if (permissionKey == null) {
  125. return permissionSchemeAllows;
  126. }
  127. if (permissionSchemeAllows) {
  128. if (issue != null) {
  129. return workflowPermissionCheck(permissionSchemeAllows, permissionKey, issue, user,
  130. permissionContextFactory.getPermissionContext(issue, status));
  131. } else {
  132. if (log.isDebugEnabled()) {
  133. log.debug(permissionKey.permissionKey() + " permission granted by permission scheme");
  134. }
  135. return true;
  136. }
  137. } else {
  138. if (log.isDebugEnabled()) {
  139. log.debug(permissionKey.permissionKey() + " permission denied by permission scheme");
  140. }
  141. return false;
  142. }
  143. }
  144. private boolean workflowPermissionCheck(final boolean permissionSchemeAllows, final ProjectPermissionKey permissionKey,
  145. final Issue issue, final ApplicationUser user, @Nullable final ActionDescriptor actionDescriptor) {
  146. if (permissionKey == null) {
  147. return permissionSchemeAllows;
  148. }
  149. if (permissionSchemeAllows) {
  150. if (issue != null) {
  151. return workflowPermissionCheck(permissionSchemeAllows, permissionKey, issue, user,
  152. permissionContextFactory.getPermissionContext(issue, actionDescriptor));
  153. } else {
  154. if (log.isDebugEnabled()) {
  155. log.debug(permissionKey.permissionKey() + " permission granted by permission scheme");
  156. }
  157. return true;
  158. }
  159. } else {
  160. if (log.isDebugEnabled()) {
  161. log.debug(permissionKey.permissionKey() + " permission denied by permission scheme");
  162. }
  163. return false;
  164. }
  165. }
  166. private boolean workflowPermissionCheck(final boolean permissionSchemeAllows, final ProjectPermissionKey permissionKey,
  167. final Issue issue, final ApplicationUser user, @Nonnull final PermissionContext permissionContext) {
  168. if (permissionKey == null) {
  169. return permissionSchemeAllows;
  170. }
  171. if (permissionSchemeAllows) {
  172. if (issue != null) {
  173. final List<WorkflowPermission> workflowPerms = workflowPermissionFactory.getWorkflowPermissions(
  174. permissionContext, permissionKey, false);
  175. // add parent workflow permissions if issue is a sub-task
  176. addParentPermissionsIfSubTask(workflowPerms, issue, permissionKey);
  177. if (!workflowPerms.isEmpty()) {
  178. for (final WorkflowPermission permission : workflowPerms) {
  179. if (permission.allows(permissionKey, issue, user)) {
  180. if (log.isInfoEnabled()) {
  181. log.info(permissionKey.permissionKey() + " granted by permission scheme and " + permission);
  182. }
  183. return true;
  184. }
  185. if (log.isInfoEnabled()) {
  186. log.info("\t" + permissionKey.permissionKey() + " not granted by " + permission);
  187. }
  188. }
  189. if (log.isInfoEnabled()) {
  190. log.info(permissionKey.permissionKey() + " granted by permission scheme but DENIED by workflow");
  191. }
  192. return false;
  193. } else {
  194. if (log.isDebugEnabled()) {
  195. log.debug(permissionKey.permissionKey() + " granted by permission scheme");
  196. }
  197. return true;
  198. }
  199. } else {
  200. if (log.isDebugEnabled()) {
  201. log.debug(permissionKey.permissionKey() + " permission granted by permission scheme");
  202. }
  203. return true;
  204. }
  205. } else {
  206. if (log.isDebugEnabled()) {
  207. log.debug(permissionKey.permissionKey() + " permission denied by permission scheme");
  208. }
  209. return false;
  210. }
  211. }
  212. private Issue getIssueOrNull(final GenericValue entity) {
  213. if (entity != null && "Issue".equals(entity.getEntityName())) {
  214. return ComponentAccessor.getIssueFactory().getIssue(entity);
  215. }
  216. return null;
  217. }
  218. /**
  219. * Adds parent's workflow permissions if sub-tasks are enabled and the given issue is a sub-task
  220. *
  221. * @param workflowPerms list of workflow permissions to add parent's into
  222. * @param issue issue to check for being a sub-task
  223. * @param permissionId permission id
  224. */
  225. private void addParentPermissionsIfSubTask(final List<WorkflowPermission> workflowPerms, final Issue issue, final ProjectPermissionKey permissionId) {
  226. final SubTaskManager subTaskManager = ComponentAccessor.getSubTaskManager();
  227. final Issue parent = issue.getParentObject();
  228. if (subTaskManager.isSubTasksEnabled() && (parent != null)) {
  229. final PermissionContext parentPermissionContext = permissionContextFactory.getPermissionContext(parent);
  230. workflowPerms.addAll(workflowPermissionFactory.getWorkflowPermissions(parentPermissionContext, permissionId, true));
  231. }
  232. }
  233. }