diff --git a/CHANGELOG.md b/CHANGELOG.md index a7616745..fe476525 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Changelog of Pull Request Notifier for Stash. ## 1.18 * Triggers can be named. To make it easier to keep track of them in large installations. +* Trigger Notification Button on Pull Request View * Building against latest Stash version (3.11.1) using latest Atlassian Maven Plugin Suite version (6.0.3) ## 1.17 diff --git a/README.md b/README.md index d9d52c02..41d60854 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,10 @@ The Pull Request Notifier for Stash can: * Invoke any URL, or set of URL:s, when a pull request event happens. * With variables available to add necessary parameters. * HTTP POST, PUT, GET and DELETE. POST and PUT also supports rendered post content. -* Be configured to trigger on any [pull request event](https://developer.atlassian.com/static/javadoc/stash/3.10.0/api/reference/com/atlassian/stash/event/pull/package-summary.html). Including source branch change (RESCOPED_FROM) and target branch change (RESCOPED_TO). +* Be configured to trigger on any [pull request event](https://developer.atlassian.com/static/javadoc/stash/3.10.0/api/reference/com/atlassian/stash/event/pull/package-summary.html). Including extended events: + * RESCOPED_FROM, when source branch change + * RESCOPED_TO, when target branch change + * MANUAL_TRIGGER, when trigger button in pull request view is pressed * Be configured to only trigger if the pull request mathches a filter. A filter text is constructed with any combination of the variables and then a regexp is constructed to match that text. * Authenticate with HTTP basic authentication. * Send custom HTTP headers diff --git a/pom.xml b/pom.xml index 75e5745e..a2a49c21 100644 --- a/pom.xml +++ b/pom.xml @@ -100,6 +100,11 @@ stash-scm-git-api provided + + com.atlassian.plugins + atlassian-plugins-webfragment + provided + javax.servlet servlet-api diff --git a/src/main/java/se/bjurr/prnfs/ManualResource.java b/src/main/java/se/bjurr/prnfs/ManualResource.java new file mode 100644 index 00000000..c47496e4 --- /dev/null +++ b/src/main/java/se/bjurr/prnfs/ManualResource.java @@ -0,0 +1,89 @@ +package se.bjurr.prnfs; + +import static com.atlassian.stash.user.Permission.ADMIN; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static javax.ws.rs.core.Response.status; +import static javax.ws.rs.core.Response.Status.OK; +import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; +import static se.bjurr.prnfs.listener.PrnfsPullRequestAction.MANUAL_TRIGGER; +import static se.bjurr.prnfs.settings.SettingsStorage.getPrnfsSettings; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; + +import se.bjurr.prnfs.listener.PrnfsPullRequestAction; +import se.bjurr.prnfs.listener.PrnfsPullRequestEventListener; +import se.bjurr.prnfs.listener.PrnfsRenderer; +import se.bjurr.prnfs.settings.PrnfsNotification; +import se.bjurr.prnfs.settings.PrnfsSettings; + +import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory; +import com.atlassian.sal.api.user.UserManager; +import com.atlassian.stash.event.pull.PullRequestEvent; +import com.atlassian.stash.pull.PullRequest; +import com.atlassian.stash.pull.PullRequestService; +import com.atlassian.stash.repository.RepositoryService; +import com.atlassian.stash.user.Permission; +import com.atlassian.stash.user.SecurityService; +import com.atlassian.stash.user.StashUser; +import com.atlassian.stash.user.UserService; +import com.atlassian.stash.util.Operation; + +@Path("/manual") +public class ManualResource { + private final UserManager userManager; + private final UserService userService; + private final PullRequestService pullRequestService; + private final PrnfsPullRequestEventListener prnfsPullRequestEventListener; + private final RepositoryService repositoryService; + private final SecurityService securityService; + private final PluginSettingsFactory pluginSettingsFactory; + + public ManualResource(UserManager userManager, UserService userService, PluginSettingsFactory pluginSettingsFactory, + PullRequestService pullRequestService, PrnfsPullRequestEventListener prnfsPullRequestEventListener, + RepositoryService repositoryService, SecurityService securityService) { + this.userManager = userManager; + this.userService = userService; + this.pullRequestService = pullRequestService; + this.prnfsPullRequestEventListener = prnfsPullRequestEventListener; + this.repositoryService = repositoryService; + this.securityService = securityService; + this.pluginSettingsFactory = pluginSettingsFactory; + } + + @GET + @Path("{repositoryId}/{pullRequestId}") + @Produces(APPLICATION_JSON) + public Response get(@Context HttpServletRequest request, @PathParam("repositoryId") Integer repositoryId, + @PathParam("pullRequestId") Long pullRequestId) throws Exception { + if (userManager.getRemoteUser(request) == null) { + return status(UNAUTHORIZED).build(); + } + + final PullRequest pullRequest = pullRequestService.getById(repositoryId, pullRequestId); + PullRequestEvent pullRequestEvent = null; + final PrnfsSettings settings = securityService.withPermission(ADMIN, "Getting config").call( + new Operation() { + @Override + public PrnfsSettings perform() throws Exception { + return getPrnfsSettings(pluginSettingsFactory.createGlobalSettings()); + } + }); + for (PrnfsNotification prnfsNotification : settings.getNotifications()) { + PrnfsPullRequestAction pullRequestAction = PrnfsPullRequestAction.valueOf(MANUAL_TRIGGER); + if (!prnfsNotification.getTriggers().contains(pullRequestAction)) { + continue; + } + StashUser stashUser = userService.getUserBySlug(userManager.getRemoteUser(request).getUsername()); + PrnfsRenderer renderer = new PrnfsRenderer(pullRequest, pullRequestAction, stashUser, repositoryService, + prnfsNotification, pullRequestEvent); + prnfsPullRequestEventListener.notify(prnfsNotification, renderer, pullRequest); + } + return status(OK).build(); + } +} \ No newline at end of file diff --git a/src/main/java/se/bjurr/prnfs/ShouldShowTriggerButtonCondition.java b/src/main/java/se/bjurr/prnfs/ShouldShowTriggerButtonCondition.java new file mode 100644 index 00000000..0dacb7ba --- /dev/null +++ b/src/main/java/se/bjurr/prnfs/ShouldShowTriggerButtonCondition.java @@ -0,0 +1,69 @@ +package se.bjurr.prnfs; + +import static com.atlassian.stash.user.Permission.ADMIN; +import static java.lang.Boolean.TRUE; +import static se.bjurr.prnfs.settings.SettingsStorage.getPrnfsSettings; + +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import se.bjurr.prnfs.settings.PrnfsSettings; + +import com.atlassian.plugin.PluginParseException; +import com.atlassian.plugin.web.Condition; +import com.atlassian.sal.api.pluginsettings.PluginSettingsFactory; +import com.atlassian.sal.api.user.UserManager; +import com.atlassian.stash.user.SecurityService; +import com.atlassian.stash.user.StashAuthenticationContext; +import com.atlassian.stash.util.Operation; + +public class ShouldShowTriggerButtonCondition implements Condition { + private static final Logger logger = LoggerFactory.getLogger(ShouldShowTriggerButtonCondition.class); + + public static final String REPOSITORY = "repository"; + private final PluginSettingsFactory pluginSettingsFactory; + private final SecurityService securityService; + private final UserManager userManager; + private final StashAuthenticationContext stashAuthenticationContext; + + public ShouldShowTriggerButtonCondition(PluginSettingsFactory pluginSettingsFactory, SecurityService securityService, + StashAuthenticationContext stashAuthenticationContext, UserManager userManager) { + this.pluginSettingsFactory = pluginSettingsFactory; + this.securityService = securityService; + this.userManager = userManager; + this.stashAuthenticationContext = stashAuthenticationContext; + } + + @Override + public void init(Map map) throws PluginParseException { + + } + + @Override + public boolean shouldDisplay(Map context) { + try { + PrnfsSettings settings = securityService.withPermission(ADMIN, "Getting config").call( + new Operation() { + @Override + public PrnfsSettings perform() throws Exception { + return getPrnfsSettings(pluginSettingsFactory.createGlobalSettings()); + } + }); + + return shouldShowTriggerButton(settings); + } catch (Exception e) { + logger.error("Error when checking if PRNFS trigger button should be shown in PR view", e); + return false; + } + } + + private boolean shouldShowTriggerButton(PrnfsSettings settings) { + // TODO + stashAuthenticationContext.getCurrentUser(); + userManager.isAdmin(userManager.getRemoteUserKey()); + return TRUE; + } + +} diff --git a/src/main/java/se/bjurr/prnfs/admin/AdminFormValues.java b/src/main/java/se/bjurr/prnfs/admin/AdminFormValues.java index dd08ca22..90bd70f0 100644 --- a/src/main/java/se/bjurr/prnfs/admin/AdminFormValues.java +++ b/src/main/java/se/bjurr/prnfs/admin/AdminFormValues.java @@ -16,7 +16,9 @@ public final class AdminFormValues extends ArrayList> { public static final String DEFAULT_NAME = "Unnamed trigger"; + public static final String GLOBAL_CONFIG_FORM_IDENTIFIER = "GLOBAL_CONFIG_FORM_IDENTIFIER"; + public enum FIELDS { - user, password, events, FORM_IDENTIFIER, url, filter_string, filter_regexp, method, post_content, proxy_user, proxy_password, proxy_server, proxy_port, header_name, header_value, name + user, password, events, FORM_IDENTIFIER, url, filter_string, filter_regexp, method, post_content, proxy_user, proxy_password, proxy_server, proxy_port, header_name, header_value, name, button_title, button_visibility } } diff --git a/src/main/java/se/bjurr/prnfs/admin/ConfigResource.java b/src/main/java/se/bjurr/prnfs/admin/ConfigResource.java index f9f6efbb..50238552 100644 --- a/src/main/java/se/bjurr/prnfs/admin/ConfigResource.java +++ b/src/main/java/se/bjurr/prnfs/admin/ConfigResource.java @@ -50,7 +50,7 @@ public ConfigResource(UserManager userManager, PluginSettingsFactory pluginSetti @DELETE @Path("{id}") public Response delete(@PathParam("id") final String id, @Context HttpServletRequest request) { - if (!isAdminLoggedIn(request)) { + if (!isSystemAdminLoggedIn(request)) { return status(UNAUTHORIZED).build(); } @@ -70,7 +70,7 @@ public Object doInTransaction() { @GET @Produces(APPLICATION_JSON) public Response get(@Context HttpServletRequest request) { - if (!isAdminLoggedIn(request)) { + if (!isSystemAdminLoggedIn(request)) { return status(UNAUTHORIZED).build(); } @@ -94,7 +94,7 @@ public UserManager getUserManager() { return userManager; } - private boolean isAdminLoggedIn(HttpServletRequest request) { + private boolean isSystemAdminLoggedIn(HttpServletRequest request) { final UserProfile user = userManager.getRemoteUser(request); if (user == null) { return false; @@ -109,7 +109,7 @@ private boolean isAdminLoggedIn(HttpServletRequest request) { @Consumes(APPLICATION_JSON) @Produces(APPLICATION_JSON) public Response post(final AdminFormValues config, @Context HttpServletRequest request) { - if (!isAdminLoggedIn(request)) { + if (!isSystemAdminLoggedIn(request)) { return status(UNAUTHORIZED).build(); } diff --git a/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestAction.java b/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestAction.java index 6690ad57..cbecae9e 100644 --- a/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestAction.java +++ b/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestAction.java @@ -26,6 +26,8 @@ public class PrnfsPullRequestAction { public static final String RESCOPED_FROM = "RESCOPED_FROM"; + public static final String MANUAL_TRIGGER = "MANUAL_TRIGGER"; + private static final Map values = new ImmutableMap.Builder() .put(APPROVED.name(), new PrnfsPullRequestAction(APPROVED.name())) // .put(COMMENTED.name(), new PrnfsPullRequestAction(COMMENTED.name())) // @@ -38,6 +40,7 @@ public class PrnfsPullRequestAction { .put(RESCOPED_TO, new PrnfsPullRequestAction(RESCOPED_TO)) // .put(UNAPPROVED.name(), new PrnfsPullRequestAction(UNAPPROVED.name())) // .put(UPDATED.name(), new PrnfsPullRequestAction(UPDATED.name())) // + .put(MANUAL_TRIGGER, new PrnfsPullRequestAction(MANUAL_TRIGGER)) // .build(); private final String name; diff --git a/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestEventListener.java b/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestEventListener.java index 6c42e7d0..b601c951 100644 --- a/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestEventListener.java +++ b/src/main/java/se/bjurr/prnfs/listener/PrnfsPullRequestEventListener.java @@ -120,8 +120,9 @@ public void handleEvent(PullRequestEvent pullRequestEvent) { } final PrnfsSettings settings = getPrnfsSettings(pluginSettingsFactory.createGlobalSettings()); for (final PrnfsNotification notification : settings.getNotifications()) { - final PrnfsRenderer renderer = new PrnfsRenderer(pullRequestEvent, repositoryService, notification); PrnfsPullRequestAction action = fromPullRequestEvent(pullRequestEvent, notification); + final PrnfsRenderer renderer = new PrnfsRenderer(pullRequestEvent.getPullRequest(), action, + pullRequestEvent.getUser(), repositoryService, notification, pullRequestEvent); PullRequest pr = pullRequestEvent.getPullRequest(); if (notification.getFilterRegexp().isPresent() && notification.getFilterString().isPresent() @@ -130,34 +131,38 @@ public void handleEvent(PullRequestEvent pullRequestEvent) { continue; } if (notification.getTriggers().contains(action)) { - Optional postContent = absent(); - if (notification.getPostContent().isPresent()) { - postContent = Optional.of(renderer.render(notification.getPostContent().get())); - } - String renderedUrl = renderer.render(notification.getUrl()); - logger.info(notification.getName() + " > " + action.getName() + " "// - + pr.getFromRef().getId() + "(" + pr.getFromRef().getLatestChangeset() + ") -> " // - + pr.getToRef().getId() + "(" + pr.getToRef().getLatestChangeset() + ")" + " " // - + renderedUrl); - UrlInvoker urlInvoker = urlInvoker().withUrlParam(renderedUrl).withMethod(notification.getMethod()) - .withPostContent(postContent); - if (notification.getUser().isPresent() && notification.getPassword().isPresent()) { - final String userpass = notification.getUser().get() + ":" + notification.getPassword().get(); - final String basicAuth = "Basic " + new String(printBase64Binary(userpass.getBytes(UTF_8))); - urlInvoker.withHeader(AUTHORIZATION, basicAuth); - } - for (Header header : notification.getHeaders()) { - urlInvoker.withHeader(header.getName(), renderer.render(header.getValue())); - } - urlInvoker.withProxyServer(notification.getProxyServer()); - urlInvoker.withProxyPort(notification.getProxyPort()); - urlInvoker.withProxyUser(notification.getProxyUser()); - urlInvoker.withProxyPassword(notification.getProxyPassword()); - invoker.invoke(urlInvoker); + notify(notification, renderer, pr); } } } catch (final ValidationException e) { logger.error("", e); } } + + public void notify(final PrnfsNotification notification, final PrnfsRenderer renderer, PullRequest pr) { + Optional postContent = absent(); + if (notification.getPostContent().isPresent()) { + postContent = Optional.of(renderer.render(notification.getPostContent().get())); + } + String renderedUrl = renderer.render(notification.getUrl()); + logger.info(notification.getName() + " > " // + + pr.getFromRef().getId() + "(" + pr.getFromRef().getLatestChangeset() + ") -> " // + + pr.getToRef().getId() + "(" + pr.getToRef().getLatestChangeset() + ")" + " " // + + renderedUrl); + UrlInvoker urlInvoker = urlInvoker().withUrlParam(renderedUrl).withMethod(notification.getMethod()) + .withPostContent(postContent); + if (notification.getUser().isPresent() && notification.getPassword().isPresent()) { + final String userpass = notification.getUser().get() + ":" + notification.getPassword().get(); + final String basicAuth = "Basic " + new String(printBase64Binary(userpass.getBytes(UTF_8))); + urlInvoker.withHeader(AUTHORIZATION, basicAuth); + } + for (Header header : notification.getHeaders()) { + urlInvoker.withHeader(header.getName(), renderer.render(header.getValue())); + } + urlInvoker.withProxyServer(notification.getProxyServer()); + urlInvoker.withProxyPort(notification.getProxyPort()); + urlInvoker.withProxyUser(notification.getProxyUser()); + urlInvoker.withProxyPassword(notification.getProxyPassword()); + invoker.invoke(urlInvoker); + } } \ No newline at end of file diff --git a/src/main/java/se/bjurr/prnfs/listener/PrnfsRenderer.java b/src/main/java/se/bjurr/prnfs/listener/PrnfsRenderer.java index 9179c601..767d7299 100644 --- a/src/main/java/se/bjurr/prnfs/listener/PrnfsRenderer.java +++ b/src/main/java/se/bjurr/prnfs/listener/PrnfsRenderer.java @@ -1,18 +1,21 @@ package se.bjurr.prnfs.listener; -import static se.bjurr.prnfs.listener.PrnfsPullRequestAction.fromPullRequestEvent; import static se.bjurr.prnfs.listener.PrnfsRenderer.REPO_PROTOCOL.http; import static se.bjurr.prnfs.listener.PrnfsRenderer.REPO_PROTOCOL.ssh; import java.util.Set; +import javax.annotation.Nullable; + import se.bjurr.prnfs.settings.PrnfsNotification; import com.atlassian.stash.event.pull.PullRequestCommentAddedEvent; import com.atlassian.stash.event.pull.PullRequestEvent; +import com.atlassian.stash.pull.PullRequest; import com.atlassian.stash.repository.Repository; import com.atlassian.stash.repository.RepositoryCloneLinksRequest; import com.atlassian.stash.repository.RepositoryService; +import com.atlassian.stash.user.StashUser; import com.atlassian.stash.util.NamedLink; public class PrnfsRenderer { @@ -25,178 +28,176 @@ public enum PrnfsVariable { PULL_REQUEST_FROM_HASH(new Resolver() { @SuppressWarnings("deprecation") @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getLatestChangeset(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getFromRef().getLatestChangeset(); } }), PULL_REQUEST_FROM_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getId(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getFromRef().getId(); } }), PULL_REQUEST_FROM_BRANCH(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getDisplayId(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getFromRef().getDisplayId(); } }), PULL_REQUEST_FROM_REPO_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getFromRef().getRepository().getId() + ""; } }), PULL_REQUEST_FROM_REPO_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getName() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getFromRef().getRepository().getName() + ""; } }), PULL_REQUEST_FROM_REPO_PROJECT_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getProject().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getFromRef().getRepository().getProject().getId() + ""; } }), PULL_REQUEST_FROM_REPO_PROJECT_KEY(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getProject().getKey(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getFromRef().getRepository().getProject().getKey(); } }), PULL_REQUEST_FROM_REPO_SLUG(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getFromRef().getRepository().getSlug() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getFromRef().getRepository().getSlug() + ""; } }), PULL_REQUEST_FROM_SSH_CLONE_URL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return cloneUrlFromRepository(ssh, pullRequestEvent.getPullRequest().getFromRef().getRepository(), - repositoryService); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return cloneUrlFromRepository(ssh, pullRequest.getFromRef().getRepository(), repositoryService); } }), PULL_REQUEST_FROM_HTTP_CLONE_URL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return cloneUrlFromRepository(http, pullRequestEvent.getPullRequest().getFromRef().getRepository(), - repositoryService); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return cloneUrlFromRepository(http, pullRequest.getFromRef().getRepository(), repositoryService); } }), PULL_REQUEST_ACTION(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return fromPullRequestEvent(pullRequestEvent, prnfsNotification).getName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return prnfsPullRequestAction.getName(); } }), PULL_REQUEST_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getId() + ""; } }), PULL_REQUEST_VERSION(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getVersion() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getVersion() + ""; } }), PULL_REQUEST_AUTHOR_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getAuthor().getUser().getId() + ""; } }), PULL_REQUEST_AUTHOR_DISPLAY_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getDisplayName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getAuthor().getUser().getDisplayName(); } }), PULL_REQUEST_AUTHOR_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getAuthor().getUser().getName(); } }), PULL_REQUEST_AUTHOR_EMAIL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getEmailAddress(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getAuthor().getUser().getEmailAddress(); } }), PULL_REQUEST_AUTHOR_SLUG(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getAuthor().getUser().getSlug(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getAuthor().getUser().getSlug(); } }), PULL_REQUEST_TO_HASH(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getLatestChangeset(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getToRef().getLatestChangeset(); } }), PULL_REQUEST_TO_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getId(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getToRef().getId(); } }), PULL_REQUEST_TO_BRANCH(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getDisplayId(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getToRef().getDisplayId(); } }), PULL_REQUEST_TO_REPO_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getToRef().getRepository().getId() + ""; } }), PULL_REQUEST_TO_REPO_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getName() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getToRef().getRepository().getName() + ""; } }), PULL_REQUEST_TO_REPO_PROJECT_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getProject().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getToRef().getRepository().getProject().getId() + ""; } }), PULL_REQUEST_TO_REPO_PROJECT_KEY(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getProject().getKey(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getToRef().getRepository().getProject().getKey(); } }), PULL_REQUEST_TO_REPO_SLUG(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getPullRequest().getToRef().getRepository().getSlug() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return pullRequest.getToRef().getRepository().getSlug() + ""; } }), PULL_REQUEST_TO_SSH_CLONE_URL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return cloneUrlFromRepository(ssh, pullRequestEvent.getPullRequest().getToRef().getRepository(), repositoryService); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return cloneUrlFromRepository(ssh, pullRequest.getToRef().getRepository(), repositoryService); } }), PULL_REQUEST_TO_HTTP_CLONE_URL(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return cloneUrlFromRepository(http, pullRequestEvent.getPullRequest().getToRef().getRepository(), repositoryService); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return cloneUrlFromRepository(http, pullRequest.getToRef().getRepository(), repositoryService); } }), PULL_REQUEST_COMMENT_TEXT(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { if (pullRequestEvent instanceof PullRequestCommentAddedEvent) { return ((PullRequestCommentAddedEvent) pullRequestEvent).getComment().getText(); } else { @@ -205,33 +206,33 @@ public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repos } }), PULL_REQUEST_USER_DISPLAY_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getDisplayName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return stashUser.getDisplayName(); } }), PULL_REQUEST_USER_EMAIL_ADDRESS(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getEmailAddress(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction prnfsPullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return stashUser.getEmailAddress(); } }), PULL_REQUEST_USER_ID(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getId() + ""; + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return stashUser.getId() + ""; } }), PULL_REQUEST_USER_NAME(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getName(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return stashUser.getName(); } }), PULL_REQUEST_USER_SLUG(new Resolver() { @Override - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return pullRequestEvent.getUser().getSlug(); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return stashUser.getSlug(); } }); @@ -249,24 +250,38 @@ private static String cloneUrlFromRepository(REPO_PROTOCOL protocol, Repository this.resolver = resolver; } - public String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { - return resolver.resolve(pullRequestEvent, repositoryService, prnfsNotification); + public String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent) { + return resolver.resolve(pullRequest, pullRequestAction, stashUser, repositoryService, prnfsNotification, + pullRequestEvent); } } public interface Resolver { - String resolve(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification); + String resolve(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, PrnfsNotification prnfsNotification, PullRequestEvent pullRequestEvent); } - private final PullRequestEvent pullRequestEvent; private final RepositoryService repositoryService; private final PrnfsNotification prnfsNotification; + private final PullRequest pullRequest; + private final PrnfsPullRequestAction pullRequestAction; + private final StashUser stashUser; + private final PullRequestEvent pullRequestEvent; - public PrnfsRenderer(PullRequestEvent pullRequestEvent, RepositoryService repositoryService, - PrnfsNotification prnfsNotification) { + /** + * @param prnfsNotification + * May be null, if triggered via trigger button in Pull Request view + * @param pullRequestEvent + * May be null, if triggered via trigger button in Pull Request view + */ + public PrnfsRenderer(PullRequest pullRequest, PrnfsPullRequestAction pullRequestAction, StashUser stashUser, + RepositoryService repositoryService, @Nullable PrnfsNotification prnfsNotification, + @Nullable PullRequestEvent pullRequestEvent) { + this.pullRequest = pullRequest; + this.pullRequestAction = pullRequestAction; this.pullRequestEvent = pullRequestEvent; + this.stashUser = stashUser; this.repositoryService = repositoryService; this.prnfsNotification = prnfsNotification; } @@ -275,7 +290,8 @@ public String render(String string) { for (final PrnfsVariable variable : PrnfsVariable.values()) { final String regExpStr = "\\$\\{" + variable.name() + "\\}"; if (string.contains(regExpStr.replaceAll("\\\\", ""))) { - string = string.replaceAll(regExpStr, variable.resolve(pullRequestEvent, repositoryService, prnfsNotification)); + string = string.replaceAll(regExpStr, variable.resolve(pullRequest, pullRequestAction, stashUser, + repositoryService, prnfsNotification, pullRequestEvent)); } } return string; diff --git a/src/main/java/se/bjurr/prnfs/settings/SettingsStorage.java b/src/main/java/se/bjurr/prnfs/settings/SettingsStorage.java index 9f2183db..1b597d00 100644 --- a/src/main/java/se/bjurr/prnfs/settings/SettingsStorage.java +++ b/src/main/java/se/bjurr/prnfs/settings/SettingsStorage.java @@ -10,6 +10,7 @@ import static com.google.common.collect.Maps.newTreeMap; import static java.lang.System.currentTimeMillis; import static se.bjurr.prnfs.admin.AdminFormValues.DEFAULT_NAME; +import static se.bjurr.prnfs.admin.AdminFormValues.GLOBAL_CONFIG_FORM_IDENTIFIER; import static se.bjurr.prnfs.admin.AdminFormValues.NAME; import static se.bjurr.prnfs.admin.AdminFormValues.VALUE; import static se.bjurr.prnfs.settings.PrnfsNotificationBuilder.prnfsNotificationBuilder; @@ -41,7 +42,7 @@ public class SettingsStorage { private static Random random = new Random(currentTimeMillis()); - private static final String STORAGE_KEY = AdminFormValues.class.getName() + "_2"; + public static final String STORAGE_KEY = AdminFormValues.class.getName() + "_2"; public static void deleteSettings(PluginSettings pluginSettings, String id) { final Map map = getNotificationsMap(pluginSettings); @@ -220,15 +221,19 @@ public static void storeSettings(PluginSettings pluginSettings, final AdminFormV final Optional> formIdOpt = tryFind(config, predicate(AdminFormValues.FIELDS.FORM_IDENTIFIER.name())); - if (!formIdOpt.isPresent() || formIdOpt.get().get(VALUE).trim().isEmpty()) { - final String generatedIdentifier = formIdentifierGnerator(); - removeIf(config, predicate(AdminFormValues.FIELDS.FORM_IDENTIFIER.name())); - config.add(new ImmutableMap.Builder().put(NAME, AdminFormValues.FIELDS.FORM_IDENTIFIER.name()) - .put(VALUE, generatedIdentifier).build()); + if (!isGlobalConfigForm(formIdOpt)) { + if (!formIdOpt.isPresent() || formIdOpt.get().get(VALUE).trim().isEmpty()) { + final String generatedIdentifier = formIdentifierGnerator(); + removeIf(config, predicate(AdminFormValues.FIELDS.FORM_IDENTIFIER.name())); + config.add(new ImmutableMap.Builder().put(NAME, AdminFormValues.FIELDS.FORM_IDENTIFIER.name()) + .put(VALUE, generatedIdentifier).build()); + } } - allNotificationsMap.put(find(config, predicate(AdminFormValues.FIELDS.FORM_IDENTIFIER.name())).get(VALUE), config); - storeNotificationsMap(pluginSettings, allNotificationsMap); } + + private static boolean isGlobalConfigForm(Optional> formIdOpt) { + return formIdOpt.isPresent() && formIdOpt.get().get(VALUE).equals(GLOBAL_CONFIG_FORM_IDENTIFIER); + } } diff --git a/src/main/resources/admin.css b/src/main/resources/admin.css index b8e0dd54..a4b0403f 100644 --- a/src/main/resources/admin.css +++ b/src/main/resources/admin.css @@ -1,10 +1,7 @@ -.trigger { +.config-area { border: 1px; border-color: black; border-style: dotted; -} - -.trigger { width: 400px; padding: 5px 15px; } diff --git a/src/main/resources/admin.js b/src/main/resources/admin.js index 6917cb87..1a2ccf55 100644 --- a/src/main/resources/admin.js +++ b/src/main/resources/admin.js @@ -101,7 +101,20 @@ }).done(function(configs) { $(".prnfs").html(""); $.each(configs, function(index, config) { - var $template = $(".prnfs-template").clone(); + var isGlobalConfig = false; + $.each(config, function(fieldIndex,field_map) { + if (field_map.name === 'FORM_IDENTIFIER' && field_map.value === 'GLOBAL_CONFIG_FORM_IDENTIFIER') { + isGlobalConfig = true; + } + }); + + var $template; + if (isGlobalConfig) { + $template = $(".prnfs-global"); + } else { + $template = $(".prnfs-template").clone(); + } + $.each(config, function(fieldIndex,field_map) { $('.variable[data-variable="'+field_map.name+'"]', $template).html(field_map.value); $('input[type="text"][name="'+field_map.name+'"]', $template).attr('value', field_map.value); @@ -112,26 +125,28 @@ $('input[type="radio"][name="'+field_map.name+'"][value="'+field_map.value+'"]', $template).attr('checked','checked'); $('.visibleif.'+field_map.name+'_'+field_map.value.replace(/[^a-zA-Z]/g,''), $template).show(); }); - - var header_names = []; - var header_values = []; - $.each(config, function(fieldIndex,field_map) { - if (field_map.name == 'header_name') { - header_names.push(field_map.value); - } else if (field_map.name == 'header_value') { - header_values.push(field_map.value); + + if (!isGlobalConfig) { + var header_names = []; + var header_values = []; + $.each(config, function(fieldIndex,field_map) { + if (field_map.name == 'header_name') { + header_names.push(field_map.value); + } else if (field_map.name == 'header_value') { + header_values.push(field_map.value); + } + }); + for (var i = 0; i < header_names.length; i++) { + $('input[type="text"][name="header_name"]', $template).last().attr('value', header_names[i]); + $('input[type="text"][name="header_value"]', $template).last().attr('value', header_values[i]); + adjustHeaders($(".headers", $template)); } - }); - for (var i = 0; i < header_names.length; i++) { - $('input[type="text"][name="header_name"]', $template).last().attr('value', header_names[i]); - $('input[type="text"][name="header_value"]', $template).last().attr('value', header_values[i]); - adjustHeaders($(".headers", $template)); - } - if (!$('input[name=method]:checked', $template).val()) { - $('input[name=method][value=GET]', $template).attr('checked','checked'); + if (!$('input[name=method]:checked', $template).val()) { + $('input[name=method][value=GET]', $template).attr('checked','checked'); + } + $(".prnfs").append($template.html()); } - $(".prnfs").append($template.html()); }); addNewForm(); setEvents(); diff --git a/src/main/resources/admin.vm b/src/main/resources/admin.vm index 18229b7c..2236bad4 100644 --- a/src/main/resources/admin.vm +++ b/src/main/resources/admin.vm @@ -5,6 +5,43 @@ $webResourceManager.requireResource("se.bjurr.prnfs.pull-request-notifier-for-stash:resources") + +
+
+
+ +
+
+ Trigger notification -button in pull request view + + +
+
+
+
+ Show button for + +
+ +
+ +
+ +
+
+
+
+
+ + +
+
+
+
+
+ + +
You can use variables when invoking the URL, when forming the filter string, custom header values or in POST content. @@ -51,7 +88,7 @@
-
+