This repository has been archived by the owner on Jun 9, 2021. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Trigger Notification Button on Pull Request View #33
- Loading branch information
1 parent
bc2820e
commit a3854c7
Showing
22 changed files
with
945 additions
and
222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,8 +20,12 @@ 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. | ||
* Add buttons to pull request view in Stash. And map those buttons to URL invocations. This can be done by setting the filter string to ${BUTTON_TRIGGER_TITLE} and the filter regexp to title of button. | ||
* Authenticate with HTTP basic authentication. | ||
* Send custom HTTP headers | ||
* Can optionally use proxy to connect | ||
|
@@ -34,6 +38,7 @@ The filter text as well as the URL support variables. These are: | |
* ${PULL_REQUEST_VERSION} Example: 1 | ||
* ${PULL_REQUEST_COMMENT_TEXT} Example: A comment | ||
* ${PULL_REQUEST_ACTION} Example: OPENED | ||
* ${BUTTON_TRIGGER_TITLE} Example: Trigger Notification | ||
* ${PULL_REQUEST_URL} Example: http://localhost:7990/projects/PROJECT_1/repos/rep_1/pull-requests/1 | ||
* ${PULL_REQUEST_USER_DISPLAY_NAME} Example: Some User | ||
* ${PULL_REQUEST_USER_EMAIL_ADDRESS} Example: [email protected] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package se.bjurr.prnfs; | ||
|
||
import static com.atlassian.stash.user.Permission.ADMIN; | ||
import static com.google.common.collect.Iterables.find; | ||
import static com.google.common.collect.Lists.newArrayList; | ||
import static java.lang.Boolean.FALSE; | ||
import static java.lang.Boolean.TRUE; | ||
import static javax.ws.rs.core.MediaType.APPLICATION_JSON; | ||
import static javax.ws.rs.core.Response.ok; | ||
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.admin.AdminFormValues.BUTTON_VISIBILITY.EVERYONE; | ||
import static se.bjurr.prnfs.admin.AdminFormValues.BUTTON_VISIBILITY.SYSTEM_ADMIN; | ||
import static se.bjurr.prnfs.listener.PrnfsPullRequestAction.BUTTON_TRIGGER; | ||
import static se.bjurr.prnfs.listener.PrnfsRenderer.PrnfsVariable.BUTTON_TRIGGER_TITLE; | ||
import static se.bjurr.prnfs.settings.SettingsStorage.getPrnfsSettings; | ||
|
||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import javax.servlet.http.HttpServletRequest; | ||
import javax.ws.rs.GET; | ||
import javax.ws.rs.POST; | ||
import javax.ws.rs.Path; | ||
import javax.ws.rs.Produces; | ||
import javax.ws.rs.QueryParam; | ||
import javax.ws.rs.core.Context; | ||
import javax.ws.rs.core.Response; | ||
|
||
import se.bjurr.prnfs.admin.AdminFormValues; | ||
import se.bjurr.prnfs.admin.AdminFormValues.BUTTON_VISIBILITY; | ||
import se.bjurr.prnfs.listener.PrnfsPullRequestAction; | ||
import se.bjurr.prnfs.listener.PrnfsPullRequestEventListener; | ||
import se.bjurr.prnfs.listener.PrnfsRenderer; | ||
import se.bjurr.prnfs.listener.PrnfsRenderer.PrnfsVariable; | ||
import se.bjurr.prnfs.settings.PrnfsButton; | ||
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.UserKey; | ||
import com.atlassian.sal.api.user.UserManager; | ||
import com.atlassian.stash.pull.PullRequest; | ||
import com.atlassian.stash.pull.PullRequestService; | ||
import com.atlassian.stash.repository.RepositoryService; | ||
import com.atlassian.stash.server.ApplicationPropertiesService; | ||
import com.atlassian.stash.user.SecurityService; | ||
import com.atlassian.stash.user.StashUser; | ||
import com.atlassian.stash.user.UserService; | ||
import com.atlassian.stash.util.Operation; | ||
import com.google.common.base.Predicate; | ||
import com.google.common.base.Supplier; | ||
import com.google.gson.Gson; | ||
|
||
@Path("/manual") | ||
public class ManualResource { | ||
private static Gson gson = new Gson(); | ||
private final UserManager userManager; | ||
private final UserService userService; | ||
private final PullRequestService pullRequestService; | ||
private final PrnfsPullRequestEventListener prnfsPullRequestEventListener; | ||
private final SecurityService securityService; | ||
private final PluginSettingsFactory pluginSettingsFactory; | ||
private static final List<AdminFormValues.BUTTON_VISIBILITY> adminOk = newArrayList(); | ||
private static final List<AdminFormValues.BUTTON_VISIBILITY> systemAdminOk = newArrayList(); | ||
static { | ||
adminOk.add(BUTTON_VISIBILITY.ADMIN); | ||
adminOk.add(SYSTEM_ADMIN); | ||
systemAdminOk.add(SYSTEM_ADMIN); | ||
} | ||
|
||
public ManualResource(UserManager userManager, UserService userService, PluginSettingsFactory pluginSettingsFactory, | ||
PullRequestService pullRequestService, PrnfsPullRequestEventListener prnfsPullRequestEventListener, | ||
RepositoryService repositoryService, ApplicationPropertiesService propertiesService, SecurityService securityService) { | ||
this.userManager = userManager; | ||
this.userService = userService; | ||
this.pullRequestService = pullRequestService; | ||
this.prnfsPullRequestEventListener = prnfsPullRequestEventListener; | ||
this.securityService = securityService; | ||
this.pluginSettingsFactory = pluginSettingsFactory; | ||
} | ||
|
||
@GET | ||
@Produces(APPLICATION_JSON) | ||
public Response get(@Context HttpServletRequest request) throws Exception { | ||
if (userManager.getRemoteUser(request) == null) { | ||
return status(UNAUTHORIZED).build(); | ||
} | ||
List<PrnfsButton> buttons = newArrayList(); | ||
for (PrnfsButton candidate : getSettings().getButtons()) { | ||
UserKey userKey = userManager.getRemoteUserKey(); | ||
if (canUseButton(candidate, userManager.isAdmin(userKey), userManager.isSystemAdmin(userKey))) { | ||
buttons.add(candidate); | ||
} | ||
} | ||
return ok(gson.toJson(buttons), APPLICATION_JSON).build(); | ||
} | ||
|
||
static boolean canUseButton(PrnfsButton candidate, boolean isAdmin, boolean isSystemAdmin) { | ||
if (candidate.getVisibility().equals(EVERYONE)) { | ||
return TRUE; | ||
} | ||
if (isSystemAdmin && systemAdminOk.contains(candidate.getVisibility())) { | ||
return TRUE; | ||
} else if (isAdmin && adminOk.contains(candidate.getVisibility())) { | ||
return TRUE; | ||
} else if (candidate.getVisibility().equals(EVERYONE)) { | ||
return TRUE; | ||
} | ||
return FALSE; | ||
} | ||
|
||
@POST | ||
@Produces(APPLICATION_JSON) | ||
public Response post(@Context HttpServletRequest request, @QueryParam("repositoryId") Integer repositoryId, | ||
@QueryParam("pullRequestId") Long pullRequestId, @QueryParam("formIdentifier") final String formIdentifier) | ||
throws Exception { | ||
if (userManager.getRemoteUser(request) == null) { | ||
return status(UNAUTHORIZED).build(); | ||
} | ||
|
||
final PullRequest pullRequest = pullRequestService.getById(repositoryId, pullRequestId); | ||
final PrnfsSettings settings = getSettings(); | ||
for (PrnfsNotification prnfsNotification : settings.getNotifications()) { | ||
PrnfsPullRequestAction pullRequestAction = PrnfsPullRequestAction.valueOf(BUTTON_TRIGGER); | ||
StashUser stashUser = userService.getUserBySlug(userManager.getRemoteUser(request).getUsername()); | ||
Map<PrnfsVariable, Supplier<String>> variables = new HashMap<PrnfsRenderer.PrnfsVariable, Supplier<String>>(); | ||
variables.put(BUTTON_TRIGGER_TITLE, new Supplier<String>() { | ||
@Override | ||
public String get() { | ||
return find(settings.getButtons(), new Predicate<PrnfsButton>() { | ||
@Override | ||
public boolean apply(PrnfsButton input) { | ||
return input.getFormIdentifier().equals(formIdentifier); | ||
} | ||
}).getTitle(); | ||
} | ||
}); | ||
prnfsPullRequestEventListener.notify(prnfsNotification, pullRequestAction, pullRequest, stashUser, variables); | ||
} | ||
return status(OK).build(); | ||
} | ||
|
||
private PrnfsSettings getSettings() throws Exception { | ||
final PrnfsSettings settings = securityService.withPermission(ADMIN, "Getting config").call( | ||
new Operation<PrnfsSettings, Exception>() { | ||
@Override | ||
public PrnfsSettings perform() throws Exception { | ||
return getPrnfsSettings(pluginSettingsFactory.createGlobalSettings()); | ||
} | ||
}); | ||
return settings; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.