/src/main/java/com/atlassian/jira/collector/plugin/rest/TemplateResource.java
Java | 427 lines | 382 code | 37 blank | 8 comment | 35 complexity | 312bd757e69323b4f5acb4a56767a400 MD5 | raw file
- package com.atlassian.jira.collector.plugin.rest;
- import com.atlassian.crowd.embedded.api.User;
- import com.atlassian.jira.bc.ServiceOutcome;
- import com.atlassian.jira.bc.issue.IssueService;
- import com.atlassian.jira.bc.issue.label.LabelService;
- import com.atlassian.jira.collector.plugin.components.Collector;
- import com.atlassian.jira.config.properties.APKeys;
- import com.atlassian.jira.config.properties.ApplicationProperties;
- import com.atlassian.jira.issue.AttachmentManager;
- import com.atlassian.jira.issue.Issue;
- import com.atlassian.jira.issue.IssueInputParameters;
- import com.atlassian.jira.issue.IssueInputParametersImpl;
- import com.atlassian.jira.issue.attachment.TemporaryAttachment;
- import com.atlassian.jira.project.Project;
- import com.atlassian.jira.project.ProjectManager;
- import com.atlassian.jira.rest.v1.util.CacheControl;
- import com.atlassian.jira.security.JiraAuthenticationContext;
- import com.atlassian.jira.security.PermissionManager;
- import com.atlassian.jira.security.Permissions;
- import com.atlassian.jira.user.util.UserUtil;
- import com.atlassian.jira.util.JiraVelocityUtils;
- import com.atlassian.jira.util.velocity.VelocityRequestContextFactory;
- import com.atlassian.jira.web.action.issue.TemporaryAttachmentsMonitor;
- import com.atlassian.jira.web.util.AttachmentException;
- import com.atlassian.jira.collector.plugin.components.Template;
- import com.atlassian.jira.collector.plugin.components.TemplateStore;
- import com.atlassian.jira.collector.plugin.components.CollectorActivityHelper;
- import com.atlassian.jira.collector.plugin.components.CollectorService;
- import com.atlassian.plugin.webresource.UrlMode;
- import com.atlassian.plugin.webresource.WebResourceManager;
- import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
- import com.atlassian.templaterenderer.TemplateRenderer;
- import org.apache.commons.lang.StringUtils;
- import org.apache.log4j.Logger;
- import org.ofbiz.core.entity.GenericEntityException;
- import java.io.IOException;
- import java.io.StringWriter;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import javax.servlet.http.HttpServletRequest;
- import javax.ws.rs.Consumes;
- import javax.ws.rs.FormParam;
- import javax.ws.rs.GET;
- import javax.ws.rs.POST;
- import javax.ws.rs.Path;
- import javax.ws.rs.PathParam;
- import javax.ws.rs.Produces;
- import javax.ws.rs.QueryParam;
- import javax.ws.rs.core.Context;
- import javax.ws.rs.core.MediaType;
- import javax.ws.rs.core.Response;
- @Path ("template")
- @Produces ( { MediaType.APPLICATION_JSON })
- @Consumes ( { MediaType.APPLICATION_JSON })
- @AnonymousAllowed
- public class TemplateResource
- {
- private static final Logger log = Logger.getLogger(TemplateResource.class);
- private final CollectorService collectorService;
- private final JiraAuthenticationContext authenticationContext;
- private final TemplateRenderer templateRenderer;
- private final WebResourceManager webResourceManager;
- private final IssueService issueService;
- private final UserUtil userUtil;
- private final VelocityRequestContextFactory velocityRequestContextFactory;
- private final TemplateStore templateStore;
- private final PermissionManager permissionManager;
- private final ProjectManager projectManager;
- private final ApplicationProperties applicationProperties;
- private final LabelService labelService;
- private final AttachmentManager attachmentManager;
- @Context
- private HttpServletRequest request;
- public TemplateResource(final CollectorService collectorService, final JiraAuthenticationContext authenticationContext,
- final TemplateRenderer templateRenderer, final WebResourceManager webResourceManager, final IssueService issueService,
- final UserUtil userUtil, final VelocityRequestContextFactory velocityRequestContextFactory,
- final TemplateStore templateStore, final PermissionManager permissionManager, final ProjectManager projectManager,
- final ApplicationProperties applicationProperties, final LabelService labelService, final AttachmentManager attachmentManager)
- {
- this.collectorService = collectorService;
- this.authenticationContext = authenticationContext;
- this.templateRenderer = templateRenderer;
- this.webResourceManager = webResourceManager;
- this.issueService = issueService;
- this.userUtil = userUtil;
- this.velocityRequestContextFactory = velocityRequestContextFactory;
- this.templateStore = templateStore;
- this.permissionManager = permissionManager;
- this.projectManager = projectManager;
- this.applicationProperties = applicationProperties;
- this.labelService = labelService;
- this.attachmentManager = attachmentManager;
- }
- @GET
- @Path ("{templateId}")
- @Produces ( { MediaType.TEXT_HTML })
- public Response renderTemplate(@PathParam ("templateId") String templateId)
- {
- final Template template = templateStore.getTemplate(templateId);
- final HashMap<String, Object> context = new HashMap<String, Object>();
- context.put("showContactForm", true);
- final String out = renderTemplate(template, context);
- if (out == null)
- {
- return createErrorResponse("collector.plugin.collector.unknown.error");
- }
- return Response.ok(out).cacheControl(CacheControl.NO_CACHE).build();
- }
- @GET
- @Path ("form/{collectorId}")
- @Produces ( { MediaType.TEXT_HTML })
- public Response getForm(@PathParam ("collectorId") String collectorId, @QueryParam ("webInfo") String webInfo)
- {
- final ServiceOutcome<Collector> collector = collectorService.getCollector(collectorId);
- if (collector.getReturnedValue() == null)
- {
- return createErrorResponse("collector.plugin.collector.not.found");
- }
- if (!collector.getReturnedValue().isEnabled())
- {
- return createErrorResponse("collector.plugin.collector.disabled.msg");
- }
- //clear previous entries first!
- TemporaryAttachmentsMonitorLocator.getAttachmentsMonitor(request, collector.getReturnedValue().getId()).clearEntriesForIssue(TemporaryAttachmentsResource.UNKNOWN_ISSUE_ID);
- final Map<String, Object> context = new HashMap<String, Object>();
- context.put("collector", collector.getReturnedValue());
- boolean showContactForm = !useLoggedInUser(collector.getReturnedValue());
- context.put("showContactForm", showContactForm);
- if (!showContactForm)
- {
- context.put("user", authenticationContext.getLoggedInUser());
- }
- if (StringUtils.isNotBlank(webInfo))
- {
- context.put("webInfo", webInfo);
- }
- final String out = renderTemplate(collector.getReturnedValue().getTemplate(), context);
- if (out == null)
- {
- return createErrorResponse("collector.plugin.collector.unknown.error");
- }
- return Response.ok(out).cacheControl(CacheControl.NO_CACHE).build();
- }
- public enum Rating
- {
- AWESOME("collector.plugin.template.awesome", ":D"),
- GOOD("collector.plugin.template.good", ":)"),
- MEH("collector.plugin.template.meh", ";)"),
- BAD("collector.plugin.template.bad", ":("),
- HORRIBLE("collector.plugin.template.horrible", "(n)");
- private final String i18nKey;
- private final String smiley;
- Rating(String i18nKey, String smiley)
- {
- this.i18nKey = i18nKey;
- this.smiley = smiley;
- }
- public String getI18nKey()
- {
- return i18nKey;
- }
- public String getSmiley()
- {
- return smiley;
- }
- }
- @POST
- @Path ("feedback/{collectorId}")
- @Consumes ( { MediaType.APPLICATION_FORM_URLENCODED })
- @Produces ( { MediaType.TEXT_HTML })
- public Response createFeedback(@PathParam ("collectorId") String collectorId,
- @FormParam ("description-good") String descriptionGood,
- @FormParam ("description-bad") String descriptionBad,
- @FormParam ("rating") String rating,
- @FormParam ("fullname") String fullname,
- @FormParam ("email") String email,
- @FormParam ("webInfo") String webInfo,
- @FormParam ("filetoconvert") List<Long> screenshotIds)
- {
- final ServiceOutcome<Collector> outcome = collectorService.getCollector(collectorId);
- if (outcome.getReturnedValue() == null)
- {
- return createErrorResponse("collector.plugin.collector.not.found");
- }
- if (!outcome.getReturnedValue().isEnabled())
- {
- return createErrorResponse("collector.plugin.collector.disabled.msg");
- }
- //validate the rating!
- try
- {
- if(StringUtils.isNotBlank(rating))
- {
- Rating.valueOf(rating);
- }
- else
- {
- return createErrorResponse("collector.plugin.collector.unknown.error");
- }
- }
- catch (IllegalArgumentException e)
- {
- return createErrorResponse("collector.plugin.collector.unknown.error");
- }
- final Rating ratingValue = Rating.valueOf(rating);
- final Map<String, Object> context = new HashMap<String, Object>();
- context.put("ratingValue", ratingValue);
- context.put("descriptionGoodHtml", descriptionGood);
- context.put("descriptionBadHtml", descriptionBad);
- final String description = render("templates/feedback-wiki-markup.vm", context);
- return createIssue(outcome.getReturnedValue(), getSummary(descriptionGood + " " + descriptionBad), description, fullname, email, webInfo, screenshotIds);
- }
- @POST
- @Path ("form/{collectorId}")
- @Consumes ( { MediaType.APPLICATION_FORM_URLENCODED })
- @Produces ( { MediaType.TEXT_HTML })
- public Response createIssue(@PathParam ("collectorId") String collectorId,
- @FormParam ("description") String description,
- @FormParam ("fullname") String fullname,
- @FormParam ("email") String email,
- @FormParam ("webInfo") String webInfo,
- @FormParam ("filetoconvert") List<Long> screenshotIds)
- {
- final ServiceOutcome<Collector> outcome = collectorService.getCollector(collectorId);
- if (outcome.getReturnedValue() == null)
- {
- return createErrorResponse("collector.plugin.collector.not.found");
- }
- if (!outcome.getReturnedValue().isEnabled())
- {
- return createErrorResponse("collector.plugin.collector.disabled.msg");
- }
- return createIssue(outcome.getReturnedValue(), getSummary(description), description, fullname, email, webInfo, screenshotIds);
- }
- private Response createIssue(final Collector collector, final String summary, final String description, final String fullname, final String email, final String webInfo, final List<Long> screenshotIds)
- {
- final User remoteUser = authenticationContext.getLoggedInUser();
- final User reporter = getReporter(collector, remoteUser, fullname, email);
- final IssueInputParameters params = new IssueInputParametersImpl();
- params.setReporterId(reporter.getName());
- if (!applicationProperties.getOption(APKeys.JIRA_OPTION_ALLOWUNASSIGNED))
- {
- params.setAssigneeId(reporter.getName());
- }
- params.setEnvironment(webInfo);
- String descriptionIncludingReporter = description;
- if (StringUtils.isNotBlank(fullname))
- {
- descriptionIncludingReporter += "\n\n" + authenticationContext.getI18nHelper().getText("collector.plugin.template.contact.name", fullname);
- }
- if (StringUtils.isNotBlank(email))
- {
- descriptionIncludingReporter += "\n" + authenticationContext.getI18nHelper().getText("collector.plugin.template.contact.email", email);
- }
- params.setDescription(descriptionIncludingReporter);
- params.setSummary(summary);
- params.setIssueTypeId(collector.getIssueTypeId().toString());
- params.setProjectId(collector.getProjectId());
- //this is kinda dodgy but the issue service does actually use the authentication context as well as the user
- //that's passed in :(.
- authenticationContext.setLoggedInUser(reporter);
- try
- {
- final IssueService.CreateValidationResult validationResult = issueService.validateCreate(reporter, params);
- if (validationResult.isValid())
- {
- final IssueService.IssueResult result = issueService.create(reporter, validationResult);
- //label the issue
- final Issue issue = result.getIssue();
- final LabelService.AddLabelValidationResult labelValidationResult = labelService.validateAddLabel(reporter, issue.getId(),
- CollectorActivityHelper.COLLECTOR_LABEL_PREFIX + collector.getId());
- if (labelValidationResult.isValid())
- {
- labelService.addLabel(reporter, labelValidationResult, false);
- }
- //add attachments (if there were any!)
- final TemporaryAttachmentsMonitor attachmentsMonitor = TemporaryAttachmentsMonitorLocator.getAttachmentsMonitor(request, collector.getId());
- final Collection<TemporaryAttachment> attachments = attachmentsMonitor.getByIssueId(TemporaryAttachmentsResource.UNKNOWN_ISSUE_ID);
- if (!attachments.isEmpty())
- {
- try
- {
- attachmentManager.convertTemporaryAttachments(reporter, issue, screenshotIds, attachmentsMonitor);
- }
- catch (AttachmentException e)
- {
- log.error("Error attaching files", e);
- }
- catch (GenericEntityException e)
- {
- log.error("Generic Error attaching files", e);
- }
- }
- final Map<String, Object> context = new HashMap<String, Object>();
- context.put("webResourcesHtml", webResourceManager.getResourceTags("com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:form-collector", UrlMode.ABSOLUTE));
- String feedbackLocation = velocityRequestContextFactory.getJiraVelocityRequestContext().getCanonicalBaseUrl() + "/browse/" + issue.getKey();
- //if the user did not submit a contact form and has permission to browse an issue show the link!
- boolean canBrowseIssue = permissionManager.hasPermission(Permissions.BROWSE, issue, reporter) && StringUtils.isBlank(fullname) && StringUtils.isBlank(email);
- if (canBrowseIssue)
- {
- context.put("thanksHtml", authenticationContext.getI18nHelper().getText("collector.plugin.template.thanks.recorded",
- "<a target=\"_blank\" href=\"" + feedbackLocation + "\">" + feedbackLocation + "</a>"));
- }
- else
- {
- context.put("thanksHtml", authenticationContext.getI18nHelper().getText("collector.plugin.template.thanks.no.permission"));
- }
- final String out = render("templates/collector/thanks.vm", context);
- if (out == null)
- {
- return createErrorResponse("collector.plugin.collector.unknown.error");
- }
- return Response.ok(out).cacheControl(CacheControl.NO_CACHE).build();
- }
- else
- {
- return createErrorResponse("collector.plugin.collector.error.creating.issue");
- }
- }
- finally
- {
- authenticationContext.setLoggedInUser(remoteUser);
- }
- }
- private User getReporter(final Collector collector, final User remoteUser, final String fullname, final String email)
- {
- User reporter = userUtil.getUserObject(collector.getReporter());
- //only use the loggedin user if they have permission to create and if no contact form was filled in!
- if (useLoggedInUser(collector) && StringUtils.isBlank(fullname) && StringUtils.isBlank(email))
- {
- reporter = remoteUser;
- }
- return reporter;
- }
- private Response createErrorResponse(final String messageKey)
- {
- final Map<String, Object> context = new HashMap<String, Object>();
- context.put("message", authenticationContext.getI18nHelper().getText(messageKey));
- context.put("webResourcesHtml", webResourceManager.getResourceTags("com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:form-collector", UrlMode.ABSOLUTE));
- render("templates/collector/disabled.vm", context);
- return Response.ok(render("templates/collector/disabled.vm", context)).cacheControl(CacheControl.NO_CACHE).build();
- }
- private String renderTemplate(Template template, final Map<String, Object> context)
- {
- context.put("webResourcesHtml", webResourceManager.getResourceTags("com.atlassian.jira.collector.plugin.jira-issue-collector-plugin:form-collector", UrlMode.ABSOLUTE));
- context.put("canocialBaseurl", velocityRequestContextFactory.getJiraVelocityRequestContext().getCanonicalBaseUrl());
- return render(template.getTemplatePath(), context);
- }
- private String render(String templatePath, final Map<String, Object> context)
- {
- final StringWriter out = new StringWriter();
- try
- {
- context.putAll(JiraVelocityUtils.createVelocityParams(authenticationContext));
- templateRenderer.render(templatePath, context, out);
- }
- catch (IOException e)
- {
- log.error("Error rendering template", e);
- return null;
- }
- return out.toString();
- }
- private String getSummary(final String description)
- {
- final String[] split = StringUtils.split(description);
- final int minWords = Math.min(split.length, 12);
- String summary = StringUtils.join(split, " ", 0, minWords);
- if (minWords == 12)
- {
- summary += "...";
- }
- return summary;
- }
- private boolean useLoggedInUser(final Collector collector)
- {
- if (authenticationContext.getLoggedInUser() == null)
- {
- return false;
- }
- if (!collector.isUseCredentials())
- {
- return false;
- }
- final Project projectObj = projectManager.getProjectObj(collector.getProjectId());
- return permissionManager.hasPermission(Permissions.CREATE_ISSUE, projectObj, authenticationContext.getLoggedInUser());
- }
- }