PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/src/main/java/com/atlassian/jconnect/rest/resources/JMCAdminResource.java

https://bitbucket.org/atlassian/jiraconnect-jiraplugin/
Java | 211 lines | 169 code | 32 blank | 10 comment | 19 complexity | fbd3dd45ba48396bc003315233b5b4c8 MD5 | raw file
  1. package com.atlassian.jconnect.rest.resources;
  2. import com.atlassian.crowd.embedded.api.User;
  3. import com.atlassian.jconnect.jira.JMCProjectService;
  4. import com.atlassian.jconnect.jira.UserHelper;
  5. import com.atlassian.jconnect.rest.entities.AdminForm;
  6. import com.atlassian.jconnect.rest.entities.ProjectStatusEntity;
  7. import com.atlassian.jconnect.util.Either;
  8. import com.atlassian.jira.bc.ServiceOutcome;
  9. import com.atlassian.jira.bc.project.ProjectService;
  10. import com.atlassian.jira.project.Project;
  11. import com.atlassian.jira.security.PermissionManager;
  12. import com.atlassian.jira.security.Permissions;
  13. import com.atlassian.jira.util.json.JSONException;
  14. import com.atlassian.jira.util.json.JSONObject;
  15. import com.atlassian.jira.util.lang.Pair;
  16. import com.atlassian.sal.api.user.UserManager;
  17. import org.slf4j.Logger;
  18. import org.slf4j.LoggerFactory;
  19. import javax.ws.rs.GET;
  20. import javax.ws.rs.POST;
  21. import javax.ws.rs.Path;
  22. import javax.ws.rs.Produces;
  23. import javax.ws.rs.QueryParam;
  24. import javax.ws.rs.core.MediaType;
  25. import javax.ws.rs.core.Response;
  26. import java.util.List;
  27. /**
  28. * This resource should only be accesible by jira admins.
  29. * It provides methods for enabling/disabling JMC for a specific JIRA Project.
  30. * There are also methods to query the active number of JMCified projects.
  31. */
  32. @Path("/admin")
  33. public class JMCAdminResource {
  34. private ProjectService jiraProjectService;
  35. private JMCProjectService jmcProjectService;
  36. private UserManager userManager;
  37. private UserHelper userHelper;
  38. private PermissionManager permissionManager;
  39. private static final Logger log = LoggerFactory.getLogger(JMCAdminResource.class);
  40. public JMCAdminResource(PermissionManager permissionManager,
  41. UserManager userManager,
  42. UserHelper userHelper,
  43. ProjectService jiraProjectService,
  44. JMCProjectService projectService) {
  45. this.jiraProjectService = jiraProjectService;
  46. this.jmcProjectService = projectService;
  47. this.userManager = userManager;
  48. this.userHelper = userHelper;
  49. this.permissionManager = permissionManager;
  50. }
  51. /**
  52. * Returns a ProjectStatus object, indicating whether or not JMC is enabled.disabled,
  53. * keys are active/inactive etc
  54. * **/
  55. @GET
  56. @Path("projectStatus")
  57. @Produces(MediaType.APPLICATION_JSON)
  58. public Response projectStatus(@QueryParam("projectId") Long projectId) throws Exception {
  59. final Either<Pair<Project, User>, Response.ResponseBuilder> result = validateProject(projectId);
  60. if (result.getRight() != null) {
  61. return result.getRight().build();
  62. }
  63. final Project project = result.getLeft().first();
  64. final boolean enabled = jmcProjectService.isJiraConnectProject(project);
  65. final String apiKey = enabled ? jmcProjectService.lookupApiKeyFor(project) : "";
  66. final boolean reindexRequired = false; // re-index only required on state change
  67. final boolean apiKeyActive = jmcProjectService.isApiKeyEnabledFor(project);
  68. final boolean crashesEnabled = jmcProjectService.isCrashesEnabledFor(project);
  69. return Response.ok(new ProjectStatusEntity(project.getId(), project.getKey(), enabled, apiKey, reindexRequired, apiKeyActive, crashesEnabled)).build();
  70. }
  71. @POST
  72. @Path("toggleOnOff")
  73. @Produces(MediaType.APPLICATION_JSON)
  74. public Response enableProject(AdminForm form) throws Exception {
  75. final Either<Pair<Project, User>, Response.ResponseBuilder> result = validateProject(form.getProjectId());
  76. if (result.getRight() != null) {
  77. return result.getRight().build();
  78. }
  79. final User user = result.getLeft().second();
  80. final Project project = result.getLeft().first();
  81. final boolean enabled = jmcProjectService.toggleForJiraConnect(project);
  82. final String apiKey = enabled ? jmcProjectService.generateOrRetrieveAPIKeyFor(project) : "";
  83. final boolean reindexRequired = jmcProjectService.reindexRequiredFor(project, user);
  84. final boolean apiKeyActive = jmcProjectService.isApiKeyEnabledFor(project);
  85. final boolean crashesEnabled = jmcProjectService.isCrashesEnabledFor(project);
  86. //TODO: prompt user to add Location to all screens ? all view Screens ?
  87. return Response.ok(new ProjectStatusEntity(project.getId(), project.getKey(), enabled, apiKey, reindexRequired, apiKeyActive,crashesEnabled)).build();
  88. }
  89. @POST
  90. @Path("resetApiKey")
  91. @Produces(MediaType.APPLICATION_JSON)
  92. public Response resetApiKey(AdminForm form) throws Exception {
  93. final Either<Pair<Project, User>, Response.ResponseBuilder> result = validateProject(form.getProjectId());
  94. if (result.getRight() != null) {
  95. return result.getRight().build();
  96. }
  97. final Project project = result.getLeft().first();
  98. final String newApiKey = jmcProjectService.generateApiKeyFor(project);
  99. final boolean enabled = jmcProjectService.isJiraConnectProject(project);
  100. final boolean crashesEnabled = jmcProjectService.isCrashesEnabledFor(project);
  101. final boolean apiKeyActive = jmcProjectService.isApiKeyEnabledFor(project);
  102. return Response.ok(new ProjectStatusEntity(form.getProjectId(), project.getKey(), enabled, newApiKey, false, apiKeyActive, crashesEnabled)).build();
  103. }
  104. @POST
  105. @Path("setApiKeyActiveStatus")
  106. @Produces(MediaType.APPLICATION_JSON)
  107. public Response toggleApiKey(AdminForm form) throws Exception {
  108. final Either<Pair<Project, User>, Response.ResponseBuilder> result = validateProject(form.getProjectId());
  109. if (result.getRight() != null) {
  110. return result.getRight().build();
  111. }
  112. final Project project = result.getLeft().first();
  113. final boolean jiraConnectProject = jmcProjectService.isJiraConnectProject(project);
  114. final boolean crashesEnabled = jmcProjectService.isCrashesEnabledFor(project);
  115. final boolean apiKeyActive = jmcProjectService.toggleApiKeyFor(project, form.isActive());
  116. return Response.ok(new ProjectStatusEntity(form.getProjectId(), project.getKey(), jiraConnectProject, null, false, apiKeyActive, crashesEnabled)).build();
  117. }
  118. @POST
  119. @Path("setCrashesEnabledStatus")
  120. @Produces(MediaType.APPLICATION_JSON)
  121. public Response toggleCrashesEnabledStatus(AdminForm form) throws Exception {
  122. final Either<Pair<Project, User>, Response.ResponseBuilder> result = validateProject(form.getProjectId());
  123. if (result.getRight() != null) {
  124. return result.getRight().build();
  125. }
  126. final Project project = result.getLeft().first();
  127. final boolean jiraConnectProject = jmcProjectService.isJiraConnectProject(project);
  128. final boolean apiKeyActive = jmcProjectService.isApiKeyEnabledFor(project);
  129. final boolean crashesEnabled = jmcProjectService.toggleCrashesFor(project, form.isCrashesEnabled());
  130. return Response.ok(new ProjectStatusEntity(form.getProjectId(), project.getKey(), jiraConnectProject, null, false, apiKeyActive, crashesEnabled)).build();
  131. }
  132. @GET
  133. @Path("stats")
  134. @Produces(MediaType.APPLICATION_JSON)
  135. public Response getStatistics() {
  136. final String remoteUsername = userManager.getRemoteUsername();
  137. final User user = userHelper.getUser(remoteUsername);
  138. if (!userManager.isSystemAdmin(remoteUsername)) {
  139. return Response.status(Response.Status.UNAUTHORIZED).entity("Only System Administrators may access this resource").build();
  140. }
  141. final ServiceOutcome<List<Project>> allProjects = this.jiraProjectService.getAllProjects(user);
  142. final List<Project> projects = allProjects.getReturnedValue();
  143. int jmcProjectCount = 0;
  144. for (Project project : projects) {
  145. jmcProjectCount += jmcProjectService.isJiraConnectProject(project) ? 1 : 0;
  146. }
  147. final long jmcIssueCount = jmcProjectService.countJMCIssues(user);
  148. final JSONObject json = new JSONObject();
  149. try {
  150. json.put("projectCount", jmcProjectCount);
  151. json.put("issueCount", jmcIssueCount);
  152. return Response.ok(json.toString(), MediaType.APPLICATION_JSON_TYPE).build();
  153. } catch (JSONException e) {
  154. log.error(e.getMessage(), e);
  155. return Response.serverError().entity(e.getMessage()).build();
  156. }
  157. }
  158. private Either<Pair<Project, User>, Response.ResponseBuilder> validateProject(Long projectId) {
  159. final String remoteUsername = userManager.getRemoteUsername();
  160. if (projectId == null) {
  161. return Either.right(Response.status(Response.Status.BAD_REQUEST).entity("Missing projectId parameter in request"));
  162. }
  163. final Project project = jiraProjectService.getProjectById(userHelper.getUser(remoteUsername), projectId).getProject();
  164. if (project == null) {
  165. return Either.right(Response.status(Response.Status.BAD_REQUEST).entity("Project with ID: " + projectId + " not found"));
  166. }
  167. final User user = userHelper.getUser(remoteUsername);
  168. if (user == null || !userHasAdminPermission(remoteUsername, project, user))
  169. {
  170. return Either.right(Response.status(Response.Status.UNAUTHORIZED).entity("Permission denied: Admins only."));
  171. }
  172. return Either.left(Pair.of(project, user));
  173. }
  174. private boolean userHasAdminPermission(String remoteUsername, Project project, User user) {
  175. return permissionManager.hasPermission(Permissions.PROJECT_ADMIN, project, user) ||
  176. permissionManager.hasPermission(Permissions.ADMINISTER, user) ||
  177. userManager.isSystemAdmin(remoteUsername);
  178. }
  179. }