diff --git a/CHANGELOG.md b/CHANGELOG.md index 44a90a93..f5f62eab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,20 @@ Changelog of Pull Request Notifier for Bitbucket. ## Unreleased +### GitHub [#119](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/issues/119) You are not permitted to access this resource + Getting clone URL:s with admin permission + + [f09e3bfac1e030f](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/commit/f09e3bfac1e030f) Tomas Bjerre *2016-05-28 16:29:17* + ### No issue + Show buttons only on PR where the button belongs to + + [2cfaea05e0312d4](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/commit/2cfaea05e0312d4) Stefan Anzinger *2016-05-27 09:00:34* + + Updating screenshots + + [eb2b5922f7473ce](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/commit/eb2b5922f7473ce) Tomas Bjerre *2016-05-15 18:25:55* + Docker [76aa6838a73a556](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/commit/76aa6838a73a556) Tomas Bjerre *2016-05-15 10:24:55* diff --git a/src/main/java/se/bjurr/prnfb/service/PrnfbRenderer.java b/src/main/java/se/bjurr/prnfb/service/PrnfbRenderer.java index e055aa24..559c8a34 100644 --- a/src/main/java/se/bjurr/prnfb/service/PrnfbRenderer.java +++ b/src/main/java/se/bjurr/prnfb/service/PrnfbRenderer.java @@ -16,6 +16,7 @@ import com.atlassian.bitbucket.repository.RepositoryService; import com.atlassian.bitbucket.server.ApplicationPropertiesService; import com.atlassian.bitbucket.user.ApplicationUser; +import com.atlassian.bitbucket.user.SecurityService; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Supplier; @@ -27,6 +28,7 @@ public class PrnfbRenderer { private final PullRequest pullRequest; private final PrnfbPullRequestAction pullRequestAction; private final RepositoryService repositoryService; + private final SecurityService securityService; /** * Contains special variables that are only available for specific events like * {@link PrnfbVariable#BUTTON_TRIGGER_TITLE} and @@ -36,7 +38,7 @@ public class PrnfbRenderer { PrnfbRenderer(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, - PrnfbNotification prnfbNotification, Map> variables) { + PrnfbNotification prnfbNotification, Map> variables, SecurityService securityService) { this.pullRequest = pullRequest; this.pullRequestAction = pullRequestAction; this.applicationUser = applicationUser; @@ -44,6 +46,7 @@ public class PrnfbRenderer { this.prnfbNotification = prnfbNotification; this.propertiesService = propertiesService; this.variables = variables; + this.securityService = securityService; } public String render(String string, Boolean forUrl, ClientKeyStore clientKeyStore, Boolean shouldAcceptAnyCertificate) { @@ -64,7 +67,7 @@ private String getRenderedString(String string, Boolean forUrl, ClientKeyStore c throws UnsupportedEncodingException { String resolved = variable.resolve(this.pullRequest, this.pullRequestAction, this.applicationUser, this.repositoryService, this.propertiesService, this.prnfbNotification, this.variables, clientKeyStore, - shouldAcceptAnyCertificate); + shouldAcceptAnyCertificate, this.securityService); return getRenderedStringResolved(string, forUrl, regExpStr, resolved); } diff --git a/src/main/java/se/bjurr/prnfb/service/PrnfbRendererFactory.java b/src/main/java/se/bjurr/prnfb/service/PrnfbRendererFactory.java index 50161528..afa8463f 100644 --- a/src/main/java/se/bjurr/prnfb/service/PrnfbRendererFactory.java +++ b/src/main/java/se/bjurr/prnfb/service/PrnfbRendererFactory.java @@ -9,6 +9,7 @@ import com.atlassian.bitbucket.pull.PullRequest; import com.atlassian.bitbucket.repository.RepositoryService; import com.atlassian.bitbucket.server.ApplicationPropertiesService; +import com.atlassian.bitbucket.user.SecurityService; import com.google.common.base.Supplier; public class PrnfbRendererFactory { @@ -16,17 +17,19 @@ public class PrnfbRendererFactory { private final AuthenticationContext authenticationContext; private final ApplicationPropertiesService propertiesService; private final RepositoryService repositoryService; + private final SecurityService securityService; public PrnfbRendererFactory(RepositoryService repositoryService, ApplicationPropertiesService propertiesService, - AuthenticationContext authenticationContext) { + AuthenticationContext authenticationContext, SecurityService securityService) { this.repositoryService = repositoryService; this.propertiesService = propertiesService; this.authenticationContext = authenticationContext; + this.securityService = securityService; } public PrnfbRenderer create(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, PrnfbNotification prnfbNotification, Map> variables) { return new PrnfbRenderer(pullRequest, pullRequestAction, this.authenticationContext.getCurrentUser(), - this.repositoryService, this.propertiesService, prnfbNotification, variables); + this.repositoryService, this.propertiesService, prnfbNotification, variables, this.securityService); } } diff --git a/src/main/java/se/bjurr/prnfb/service/PrnfbVariable.java b/src/main/java/se/bjurr/prnfb/service/PrnfbVariable.java index d08f2ca7..b125ec61 100644 --- a/src/main/java/se/bjurr/prnfb/service/PrnfbVariable.java +++ b/src/main/java/se/bjurr/prnfb/service/PrnfbVariable.java @@ -5,12 +5,14 @@ import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Ordering.usingToString; +import static com.google.common.collect.Sets.newTreeSet; import static java.util.regex.Pattern.compile; import static se.bjurr.prnfb.http.UrlInvoker.urlInvoker; import static se.bjurr.prnfb.http.UrlInvoker.HTTP_METHOD.GET; import static se.bjurr.prnfb.service.RepoProtocol.http; import static se.bjurr.prnfb.service.RepoProtocol.ssh; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -22,6 +24,7 @@ import se.bjurr.prnfb.listener.PrnfbPullRequestAction; import se.bjurr.prnfb.settings.PrnfbNotification; +import com.atlassian.bitbucket.permission.Permission; import com.atlassian.bitbucket.pull.PullRequest; import com.atlassian.bitbucket.pull.PullRequestParticipant; import com.atlassian.bitbucket.repository.Repository; @@ -29,7 +32,9 @@ import com.atlassian.bitbucket.repository.RepositoryService; import com.atlassian.bitbucket.server.ApplicationPropertiesService; import com.atlassian.bitbucket.user.ApplicationUser; +import com.atlassian.bitbucket.user.SecurityService; import com.atlassian.bitbucket.util.NamedLink; +import com.atlassian.bitbucket.util.Operation; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Predicate; import com.google.common.base.Supplier; @@ -41,7 +46,8 @@ public enum PrnfbVariable { public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return getOrEmpty(variables, BUTTON_TRIGGER_TITLE); } }), EVERYTHING_URL(new PrnfbVariableResolver() { @@ -49,7 +55,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { List parts = newArrayList(); for (PrnfbVariable v : PrnfbVariable.values()) { if (v != EVERYTHING_URL) { @@ -63,7 +70,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { if (!prnfbNotification.getInjectionUrl().isPresent()) { return ""; } @@ -98,7 +106,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return prnfbPullRequestAction.name(); } }), PULL_REQUEST_AUTHOR_DISPLAY_NAME(new PrnfbVariableResolver() { @@ -106,7 +115,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getAuthor().getUser().getDisplayName(); } }), PULL_REQUEST_AUTHOR_EMAIL(new PrnfbVariableResolver() { @@ -114,7 +124,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getAuthor().getUser().getEmailAddress(); } }), PULL_REQUEST_AUTHOR_ID(new PrnfbVariableResolver() { @@ -122,7 +133,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getAuthor().getUser().getId() + ""; } }), PULL_REQUEST_AUTHOR_NAME(new PrnfbVariableResolver() { @@ -130,7 +142,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getAuthor().getUser().getName(); } }), PULL_REQUEST_AUTHOR_SLUG(new PrnfbVariableResolver() { @@ -138,7 +151,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getAuthor().getUser().getSlug(); } }), PULL_REQUEST_COMMENT_TEXT(new PrnfbVariableResolver() { @@ -146,7 +160,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return getOrEmpty(variables, PULL_REQUEST_COMMENT_TEXT); } }), PULL_REQUEST_FROM_BRANCH(new PrnfbVariableResolver() { @@ -154,7 +169,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getFromRef().getDisplayId(); } }), PULL_REQUEST_FROM_HASH(new PrnfbVariableResolver() { @@ -162,7 +178,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getFromRef().getLatestCommit(); } }), PULL_REQUEST_FROM_HTTP_CLONE_URL(new PrnfbVariableResolver() { @@ -170,15 +187,17 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { - return cloneUrlFromRepository(http, pullRequest.getFromRef().getRepository(), repositoryService); + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { + return cloneUrlFromRepository(http, pullRequest.getFromRef().getRepository(), repositoryService, securityService); } }), PULL_REQUEST_FROM_ID(new PrnfbVariableResolver() { @Override public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getFromRef().getId(); } }), PULL_REQUEST_FROM_REPO_ID(new PrnfbVariableResolver() { @@ -186,7 +205,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getFromRef().getRepository().getId() + ""; } }), PULL_REQUEST_FROM_REPO_NAME(new PrnfbVariableResolver() { @@ -194,7 +214,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getFromRef().getRepository().getName() + ""; } }), PULL_REQUEST_FROM_REPO_PROJECT_ID(new PrnfbVariableResolver() { @@ -202,7 +223,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getFromRef().getRepository().getProject().getId() + ""; } }), PULL_REQUEST_FROM_REPO_PROJECT_KEY(new PrnfbVariableResolver() { @@ -210,7 +232,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getFromRef().getRepository().getProject().getKey(); } }), PULL_REQUEST_FROM_REPO_SLUG(new PrnfbVariableResolver() { @@ -218,7 +241,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getFromRef().getRepository().getSlug() + ""; } }), PULL_REQUEST_FROM_SSH_CLONE_URL(new PrnfbVariableResolver() { @@ -226,15 +250,17 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { - return cloneUrlFromRepository(ssh, pullRequest.getFromRef().getRepository(), repositoryService); + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { + return cloneUrlFromRepository(ssh, pullRequest.getFromRef().getRepository(), repositoryService, securityService); } }), PULL_REQUEST_ID(new PrnfbVariableResolver() { @Override public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getId() + ""; } }), PULL_REQUEST_MERGE_COMMIT(new PrnfbVariableResolver() { @@ -242,7 +268,7 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfsPullRequestAction, ApplicationUser stashUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfsNotification, Map> variables, ClientKeyStore clientKeyStore, - boolean shouldAcceptAnyCertificate) { + boolean shouldAcceptAnyCertificate, SecurityService securityService) { return getOrEmpty(variables, PULL_REQUEST_MERGE_COMMIT); } }), PULL_REQUEST_PARTICIPANTS_APPROVED_COUNT(new PrnfbVariableResolver() { @@ -250,7 +276,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfsPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return Integer.toString(newArrayList(filter(pullRequest.getParticipants(), isApproved)).size()); } }), PULL_REQUEST_REVIEWERS(new PrnfbVariableResolver() { @@ -258,7 +285,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return iterableToString(transform(pullRequest.getReviewers(), (p) -> p.getUser().getDisplayName())); } }), PULL_REQUEST_REVIEWERS_APPROVED_COUNT(new PrnfbVariableResolver() { @@ -266,7 +294,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return Integer.toString(newArrayList(filter(pullRequest.getReviewers(), isApproved)).size()); } }), PULL_REQUEST_REVIEWERS_ID(new PrnfbVariableResolver() { @@ -274,7 +303,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return iterableToString(transform(pullRequest.getReviewers(), (p) -> Integer.toString(p.getUser().getId()))); } }), PULL_REQUEST_REVIEWERS_SLUG(new PrnfbVariableResolver() { @@ -282,7 +312,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return iterableToString(transform(pullRequest.getReviewers(), (p) -> p.getUser().getSlug())); } @@ -291,7 +322,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getTitle(); } }), PULL_REQUEST_TO_BRANCH(new PrnfbVariableResolver() { @@ -299,7 +331,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getToRef().getDisplayId(); } }), PULL_REQUEST_TO_HASH(new PrnfbVariableResolver() { @@ -307,7 +340,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getToRef().getLatestCommit(); } }), PULL_REQUEST_TO_HTTP_CLONE_URL(new PrnfbVariableResolver() { @@ -315,15 +349,17 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { - return cloneUrlFromRepository(http, pullRequest.getToRef().getRepository(), repositoryService); + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { + return cloneUrlFromRepository(http, pullRequest.getToRef().getRepository(), repositoryService, securityService); } }), PULL_REQUEST_TO_ID(new PrnfbVariableResolver() { @Override public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getToRef().getId(); } }), PULL_REQUEST_TO_REPO_ID(new PrnfbVariableResolver() { @@ -331,7 +367,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getToRef().getRepository().getId() + ""; } }), PULL_REQUEST_TO_REPO_NAME(new PrnfbVariableResolver() { @@ -339,7 +376,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getToRef().getRepository().getName() + ""; } }), PULL_REQUEST_TO_REPO_PROJECT_ID(new PrnfbVariableResolver() { @@ -347,7 +385,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getToRef().getRepository().getProject().getId() + ""; } }), PULL_REQUEST_TO_REPO_PROJECT_KEY(new PrnfbVariableResolver() { @@ -355,7 +394,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getToRef().getRepository().getProject().getKey(); } }), PULL_REQUEST_TO_REPO_SLUG(new PrnfbVariableResolver() { @@ -363,7 +403,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getToRef().getRepository().getSlug() + ""; } }), PULL_REQUEST_TO_SSH_CLONE_URL(new PrnfbVariableResolver() { @@ -371,15 +412,17 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { - return cloneUrlFromRepository(ssh, pullRequest.getToRef().getRepository(), repositoryService); + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { + return cloneUrlFromRepository(ssh, pullRequest.getToRef().getRepository(), repositoryService, securityService); } }), PULL_REQUEST_URL(new PrnfbVariableResolver() { @Override public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return getPullRequestUrl(propertiesService, pullRequest); } }), PULL_REQUEST_USER_DISPLAY_NAME(new PrnfbVariableResolver() { @@ -387,7 +430,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return applicationUser.getDisplayName(); } }), PULL_REQUEST_USER_EMAIL_ADDRESS(new PrnfbVariableResolver() { @@ -395,7 +439,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return applicationUser.getEmailAddress(); } }), PULL_REQUEST_USER_ID(new PrnfbVariableResolver() { @@ -403,7 +448,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullR public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return applicationUser.getId() + ""; } }), PULL_REQUEST_USER_NAME(new PrnfbVariableResolver() { @@ -411,7 +457,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return applicationUser.getName(); } }), PULL_REQUEST_USER_SLUG(new PrnfbVariableResolver() { @@ -419,7 +466,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return applicationUser.getSlug(); } }), PULL_REQUEST_VERSION(new PrnfbVariableResolver() { @@ -427,7 +475,8 @@ public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullReques public String resolve(PullRequest pullRequest, PrnfbPullRequestAction prnfbPullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return pullRequest.getVersion() + ""; } }); @@ -452,11 +501,28 @@ public static void setInvoker(Invoker invoker) { } private static String cloneUrlFromRepository(RepoProtocol protocol, Repository repository, - RepositoryService repositoryService) { - RepositoryCloneLinksRequest request = new RepositoryCloneLinksRequest.Builder().protocol(protocol.name()) - .repository(repository).build(); - final Set cloneLinks = repositoryService.getCloneLinks(request); - return cloneLinks.iterator().hasNext() ? cloneLinks.iterator().next().getHref() : ""; + RepositoryService repositoryService, SecurityService securityService) { + return securityService// + .withPermission(Permission.ADMIN, "cloneUrls")// + .call(new Operation() { + @Override + public String perform() throws RuntimeException { + RepositoryCloneLinksRequest request = new RepositoryCloneLinksRequest.Builder()// + .protocol(protocol.name())// + .repository(repository)// + .build(); + final Set cloneLinks = repositoryService.getCloneLinks(request); + Set allUrls = newTreeSet(); + Iterator itr = cloneLinks.iterator(); + while (itr.hasNext()) { + allUrls.add(itr.next().getHref()); + } + if (allUrls.isEmpty()) { + return ""; + } + return allUrls.iterator().next(); + } + }); } private static Invoker createInvoker() { @@ -497,8 +563,9 @@ private static String iterableToString(Iterable slist) { public String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, - Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate) { + Map> variables, ClientKeyStore clientKeyStore, boolean shouldAcceptAnyCertificate, + SecurityService securityService) { return this.resolver.resolve(pullRequest, pullRequestAction, applicationUser, repositoryService, propertiesService, - prnfbNotification, variables, clientKeyStore, shouldAcceptAnyCertificate); + prnfbNotification, variables, clientKeyStore, shouldAcceptAnyCertificate, securityService); } } diff --git a/src/main/java/se/bjurr/prnfb/service/PrnfbVariableResolver.java b/src/main/java/se/bjurr/prnfb/service/PrnfbVariableResolver.java index f1418aee..b28770fc 100644 --- a/src/main/java/se/bjurr/prnfb/service/PrnfbVariableResolver.java +++ b/src/main/java/se/bjurr/prnfb/service/PrnfbVariableResolver.java @@ -10,6 +10,7 @@ import com.atlassian.bitbucket.repository.RepositoryService; import com.atlassian.bitbucket.server.ApplicationPropertiesService; import com.atlassian.bitbucket.user.ApplicationUser; +import com.atlassian.bitbucket.user.SecurityService; import com.google.common.base.Supplier; public interface PrnfbVariableResolver { @@ -17,5 +18,5 @@ public interface PrnfbVariableResolver { String resolve(PullRequest pullRequest, PrnfbPullRequestAction pullRequestAction, ApplicationUser applicationUser, RepositoryService repositoryService, ApplicationPropertiesService propertiesService, PrnfbNotification prnfbNotification, Map> variables, ClientKeyStore clientKeyStore, - boolean shouldAcceptAnyCertificate); + boolean shouldAcceptAnyCertificate, SecurityService securityService); } diff --git a/src/test/java/se/bjurr/prnfb/service/PrnfbRendererTest.java b/src/test/java/se/bjurr/prnfb/service/PrnfbRendererTest.java index 49fb8b2b..dbe77fe4 100644 --- a/src/test/java/se/bjurr/prnfb/service/PrnfbRendererTest.java +++ b/src/test/java/se/bjurr/prnfb/service/PrnfbRendererTest.java @@ -31,6 +31,7 @@ import com.atlassian.bitbucket.repository.RepositoryService; import com.atlassian.bitbucket.server.ApplicationPropertiesService; import com.atlassian.bitbucket.user.ApplicationUser; +import com.atlassian.bitbucket.user.SecurityService; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; @@ -50,6 +51,7 @@ public class PrnfbRendererTest { private PrnfbPullRequestAction pullRequestAction; @Mock private RepositoryService repositoryService; + private SecurityService securityService; private final Boolean shouldAcceptAnyCertificate = true; private PrnfbRenderer sut; private final Map> variables = newHashMap(); @@ -62,7 +64,7 @@ public void before() throws ValidationException { .withTrigger(APPROVED)// .build(); this.sut = new PrnfbRenderer(this.pullRequest, this.pullRequestAction, this.applicationUser, this.repositoryService, - this.propertiesService, this.prnfbNotification, this.variables); + this.propertiesService, this.prnfbNotification, this.variables, this.securityService); when(this.pullRequest.getFromRef())// .thenReturn(this.fromRef); @@ -82,7 +84,7 @@ public void testThatEverythingCanBeRendered() throws UnsupportedEncodingExceptio String actual = this.sut.getRenderedStringResolved("asd ${" + EVERYTHING_URL.name() + "} asd", this.forUrl, this.sut .regexp(EVERYTHING_URL), EVERYTHING_URL.resolve(this.pullRequest, this.pullRequestAction, this.applicationUser, this.repositoryService, this.propertiesService, this.prnfbNotification, this.variables, this.clientKeyStore, - this.shouldAcceptAnyCertificate)); + this.shouldAcceptAnyCertificate, this.securityService)); assertThat(actual)// .isEqualTo( @@ -96,7 +98,7 @@ public void testThatInjectionUrlCanBeRendered() throws ValidationException { .withTrigger(APPROVED)// .build(); this.sut = new PrnfbRenderer(this.pullRequest, this.pullRequestAction, this.applicationUser, this.repositoryService, - this.propertiesService, this.prnfbNotification, this.variables); + this.propertiesService, this.prnfbNotification, this.variables, this.securityService); String actual = this.sut.render("my ${" + INJECTION_URL_VALUE + "} string", this.forUrl, this.clientKeyStore, this.shouldAcceptAnyCertificate); diff --git a/src/test/java/se/bjurr/prnfb/service/PrnfbVariableTest.java b/src/test/java/se/bjurr/prnfb/service/PrnfbVariableTest.java index 786111e7..068d8675 100644 --- a/src/test/java/se/bjurr/prnfb/service/PrnfbVariableTest.java +++ b/src/test/java/se/bjurr/prnfb/service/PrnfbVariableTest.java @@ -20,6 +20,7 @@ import com.atlassian.bitbucket.repository.RepositoryService; import com.atlassian.bitbucket.server.ApplicationPropertiesService; import com.atlassian.bitbucket.user.ApplicationUser; +import com.atlassian.bitbucket.user.SecurityService; import com.google.common.base.Supplier; import com.google.common.io.Files; import com.google.common.io.Resources; @@ -33,6 +34,7 @@ public class PrnfbVariableTest { private PullRequest pullRequest; private PrnfbPullRequestAction pullRequestAction; private RepositoryService repositoryService; + private SecurityService securityService; private boolean shouldAcceptAnyCertificate; private Map> variables; @@ -56,7 +58,7 @@ public void testThatAdminAndReadmeContainsVariables() throws IOException, URISyn public void testThatEverythingVariableIsResolvedToEveryOtherVariable() { String actual = EVERYTHING_URL.resolve(this.pullRequest, this.pullRequestAction, this.applicationUser, this.repositoryService, this.propertiesService, this.prnfbNotification, this.variables, this.clientKeyStore, - this.shouldAcceptAnyCertificate); + this.shouldAcceptAnyCertificate, this.securityService); assertThat(actual)// .isEqualTo( "BUTTON_TRIGGER_TITLE=\\${BUTTON_TRIGGER_TITLE}&INJECTION_URL_VALUE=\\${INJECTION_URL_VALUE}&PULL_REQUEST_ACTION=\\${PULL_REQUEST_ACTION}&PULL_REQUEST_AUTHOR_DISPLAY_NAME=\\${PULL_REQUEST_AUTHOR_DISPLAY_NAME}&PULL_REQUEST_AUTHOR_EMAIL=\\${PULL_REQUEST_AUTHOR_EMAIL}&PULL_REQUEST_AUTHOR_ID=\\${PULL_REQUEST_AUTHOR_ID}&PULL_REQUEST_AUTHOR_NAME=\\${PULL_REQUEST_AUTHOR_NAME}&PULL_REQUEST_AUTHOR_SLUG=\\${PULL_REQUEST_AUTHOR_SLUG}&PULL_REQUEST_COMMENT_TEXT=\\${PULL_REQUEST_COMMENT_TEXT}&PULL_REQUEST_FROM_BRANCH=\\${PULL_REQUEST_FROM_BRANCH}&PULL_REQUEST_FROM_HASH=\\${PULL_REQUEST_FROM_HASH}&PULL_REQUEST_FROM_HTTP_CLONE_URL=\\${PULL_REQUEST_FROM_HTTP_CLONE_URL}&PULL_REQUEST_FROM_ID=\\${PULL_REQUEST_FROM_ID}&PULL_REQUEST_FROM_REPO_ID=\\${PULL_REQUEST_FROM_REPO_ID}&PULL_REQUEST_FROM_REPO_NAME=\\${PULL_REQUEST_FROM_REPO_NAME}&PULL_REQUEST_FROM_REPO_PROJECT_ID=\\${PULL_REQUEST_FROM_REPO_PROJECT_ID}&PULL_REQUEST_FROM_REPO_PROJECT_KEY=\\${PULL_REQUEST_FROM_REPO_PROJECT_KEY}&PULL_REQUEST_FROM_REPO_SLUG=\\${PULL_REQUEST_FROM_REPO_SLUG}&PULL_REQUEST_FROM_SSH_CLONE_URL=\\${PULL_REQUEST_FROM_SSH_CLONE_URL}&PULL_REQUEST_ID=\\${PULL_REQUEST_ID}&PULL_REQUEST_MERGE_COMMIT=\\${PULL_REQUEST_MERGE_COMMIT}&PULL_REQUEST_PARTICIPANTS_APPROVED_COUNT=\\${PULL_REQUEST_PARTICIPANTS_APPROVED_COUNT}&PULL_REQUEST_REVIEWERS=\\${PULL_REQUEST_REVIEWERS}&PULL_REQUEST_REVIEWERS_APPROVED_COUNT=\\${PULL_REQUEST_REVIEWERS_APPROVED_COUNT}&PULL_REQUEST_REVIEWERS_ID=\\${PULL_REQUEST_REVIEWERS_ID}&PULL_REQUEST_REVIEWERS_SLUG=\\${PULL_REQUEST_REVIEWERS_SLUG}&PULL_REQUEST_TITLE=\\${PULL_REQUEST_TITLE}&PULL_REQUEST_TO_BRANCH=\\${PULL_REQUEST_TO_BRANCH}&PULL_REQUEST_TO_HASH=\\${PULL_REQUEST_TO_HASH}&PULL_REQUEST_TO_HTTP_CLONE_URL=\\${PULL_REQUEST_TO_HTTP_CLONE_URL}&PULL_REQUEST_TO_ID=\\${PULL_REQUEST_TO_ID}&PULL_REQUEST_TO_REPO_ID=\\${PULL_REQUEST_TO_REPO_ID}&PULL_REQUEST_TO_REPO_NAME=\\${PULL_REQUEST_TO_REPO_NAME}&PULL_REQUEST_TO_REPO_PROJECT_ID=\\${PULL_REQUEST_TO_REPO_PROJECT_ID}&PULL_REQUEST_TO_REPO_PROJECT_KEY=\\${PULL_REQUEST_TO_REPO_PROJECT_KEY}&PULL_REQUEST_TO_REPO_SLUG=\\${PULL_REQUEST_TO_REPO_SLUG}&PULL_REQUEST_TO_SSH_CLONE_URL=\\${PULL_REQUEST_TO_SSH_CLONE_URL}&PULL_REQUEST_URL=\\${PULL_REQUEST_URL}&PULL_REQUEST_USER_DISPLAY_NAME=\\${PULL_REQUEST_USER_DISPLAY_NAME}&PULL_REQUEST_USER_EMAIL_ADDRESS=\\${PULL_REQUEST_USER_EMAIL_ADDRESS}&PULL_REQUEST_USER_ID=\\${PULL_REQUEST_USER_ID}&PULL_REQUEST_USER_NAME=\\${PULL_REQUEST_USER_NAME}&PULL_REQUEST_USER_SLUG=\\${PULL_REQUEST_USER_SLUG}&PULL_REQUEST_VERSION=\\${PULL_REQUEST_VERSION}")//