Skip to content
This repository has been archived by the owner on Jun 9, 2021. It is now read-only.

Commit

Permalink
Enable project level admins to configure on project level #193
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasbjerre committed Feb 5, 2017
1 parent e6717f4 commit 3026116
Show file tree
Hide file tree
Showing 22 changed files with 384 additions and 243 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
Changelog of Pull Request Notifier for Bitbucket.

## Unreleased
### GitHub [#193](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/issues/193) Enable project level admins to configure on project level
Enable project level admins to configure on project level

[64f670125111045](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/commit/64f670125111045) Tomas Bjerre *2017-02-05 09:00:55*

### No issue
doc

[e6717f40011194e](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/commit/e6717f40011194e) Tomas Bjerre *2017-02-03 13:15:33*

## 2.52
### GitHub [#192](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/issues/192) Include status for participants
Variables to display names of approved, unapproved and needs work

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ The Pull Request Notifier for Bitbucket Server can:
* Only if PR has no conflicts
* Nice configuration GUI.
* Global at */bitbucket/plugins/servlet/prnfb/admin*
* Project level at */bitbucket/plugins/servlet/prnfb/admin/PROJECT_1*
* Repo level at */bitbucket/plugins/servlet/prnfb/admin/PROJECT_1/rep_1*

The plugin has its own implementation to create the RESCOPED_FROM and RESCOPED_TO events. RESCOPED is transformed to RESCOPED_TO if target branch changed, RESCOPED_FROM if source branch, or both, changed.
Expand Down
104 changes: 47 additions & 57 deletions src/main/java/se/bjurr/prnfb/presentation/ButtonServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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.NOT_FOUND;
import static javax.ws.rs.core.Response.Status.OK;
import static javax.ws.rs.core.Response.Status.UNAUTHORIZED;
import static se.bjurr.prnfb.transformer.ButtonTransformer.toButtonDto;
Expand All @@ -27,6 +28,8 @@
import javax.ws.rs.core.Response;

import com.atlassian.annotations.security.XsrfProtectionExcluded;
import com.google.common.base.Optional;
import com.google.common.collect.Iterables;

import se.bjurr.prnfb.http.NotificationResponse;
import se.bjurr.prnfb.presentation.dto.ButtonDTO;
Expand Down Expand Up @@ -60,9 +63,7 @@ public ButtonServlet(
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
public Response create(ButtonDTO buttonDto) {
if (!userCheckService.isAdminAllowed( //
buttonDto.getProjectKey().orNull(), //
buttonDto.getRepositorySlug().orNull())) {
if (!userCheckService.isAdminAllowed(buttonDto)) {
return status(UNAUTHORIZED) //
.build();
}
Expand All @@ -82,10 +83,7 @@ public Response create(ButtonDTO buttonDto) {
@Produces(APPLICATION_JSON)
public Response delete(@PathParam("uuid") UUID prnfbButtonUuid) {
PrnfbButton prnfbButton = settingsService.getButton(prnfbButtonUuid);
if (!userCheckService.isAdminAllowed( //
prnfbButton.getProjectKey().orNull() //
,
prnfbButton.getRepositorySlug().orNull())) {
if (!userCheckService.isAdminAllowed(prnfbButton)) {
return status(UNAUTHORIZED) //
.build();
}
Expand All @@ -97,40 +95,18 @@ public Response delete(@PathParam("uuid") UUID prnfbButtonUuid) {
@Produces(APPLICATION_JSON)
public Response get() {
List<PrnfbButton> buttons = settingsService.getButtons();
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAllowed(buttons);
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAdminAllowed(buttons);
List<ButtonDTO> dtos = toButtonDtoList(allowedButtons);
Collections.sort(dtos);
return ok(dtos, APPLICATION_JSON).build();
}

@GET
@Path("/repository/{repositoryId}/pullrequest/{pullRequestId}")
@Produces(APPLICATION_JSON)
public Response get(
@PathParam("repositoryId") Integer repositoryId,
@PathParam("pullRequestId") Long pullRequestId) {
if (!userCheckService.isViewAllowed()) {
return status(UNAUTHORIZED).build();
}
List<PrnfbButton> buttons = buttonsService.getButtons(repositoryId, pullRequestId);
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAllowed(buttons);
List<ButtonDTO> dtos = toButtonDtoList(allowedButtons);
Collections.sort(dtos);

populateButtonFormDtoList(repositoryId, pullRequestId, dtos);

return ok(dtos, APPLICATION_JSON).build();
}

@GET
@Path("/projectKey/{projectKey}")
@Produces(APPLICATION_JSON)
public Response get(@PathParam("projectKey") String projectKey) {
if (!userCheckService.isViewAllowed()) {
return status(UNAUTHORIZED).build();
}
List<PrnfbButton> buttons = settingsService.getButtons(projectKey);
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAllowed(buttons);
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAdminAllowed(buttons);
List<ButtonDTO> dtos = toButtonDtoList(allowedButtons);
Collections.sort(dtos);
return ok(dtos, APPLICATION_JSON).build();
Expand All @@ -142,11 +118,8 @@ public Response get(@PathParam("projectKey") String projectKey) {
public Response get(
@PathParam("projectKey") String projectKey,
@PathParam("repositorySlug") String repositorySlug) {
if (!userCheckService.isViewAllowed()) {
return status(UNAUTHORIZED).build();
}
List<PrnfbButton> buttons = settingsService.getButtons(projectKey, repositorySlug);
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAllowed(buttons);
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAdminAllowed(buttons);
List<ButtonDTO> dtos = toButtonDtoList(allowedButtons);
Collections.sort(dtos);
return ok(dtos, APPLICATION_JSON).build();
Expand All @@ -157,30 +130,26 @@ public Response get(
@Produces(APPLICATION_JSON)
public Response get(@PathParam("uuid") UUID uuid) {
PrnfbButton button = settingsService.getButton(uuid);
if (!userCheckService.isAllowedUseButton(button)) {
if (!userCheckService.isAdminAllowed(button)) {
return status(UNAUTHORIZED).build();
}
ButtonDTO dto = toButtonDto(button);
return ok(dto, APPLICATION_JSON).build();
}

private void populateButtonFormDtoList(
Integer repositoryId, Long pullRequestId, List<ButtonDTO> dtos) {
for (ButtonDTO dto : dtos) {
PrnfbRendererWrapper renderer =
buttonsService.getRenderer(repositoryId, pullRequestId, dto.getUuid());
List<ButtonFormElementDTO> buttonFormDtoList = dto.getButtonFormList();
if (buttonFormDtoList != null) {
for (ButtonFormElementDTO buttonFormElementDto : buttonFormDtoList) {
String defaultValue = buttonFormElementDto.getDefaultValue();
if (!isNullOrEmpty(defaultValue)) {
String defaultValueRendered = renderer.render(defaultValue, ENCODE_FOR.NONE);
buttonFormElementDto.setDefaultValue(defaultValueRendered);
}
}
dto.setButtonFormList(buttonFormDtoList);
}
}
@GET
@Path("/repository/{repositoryId}/pullrequest/{pullRequestId}")
@Produces(APPLICATION_JSON)
public Response get(
@PathParam("repositoryId") Integer repositoryId,
@PathParam("pullRequestId") Long pullRequestId) {
List<PrnfbButton> buttons = buttonsService.getButtons(repositoryId, pullRequestId);
List<ButtonDTO> dtos = toButtonDtoList(buttons);
Collections.sort(dtos);

populateButtonFormDtoList(repositoryId, pullRequestId, dtos);

return ok(dtos, APPLICATION_JSON).build();
}

@POST
Expand All @@ -192,15 +161,36 @@ public Response press(
@PathParam("repositoryId") Integer repositoryId,
@PathParam("pullRequestId") Long pullRequestId,
@PathParam("uuid") final UUID buttionUuid) {
PrnfbButton button = settingsService.getButton(buttionUuid);
if (!userCheckService.isAllowedUseButton(button)) {
return status(UNAUTHORIZED).build();
List<PrnfbButton> buttons = buttonsService.getButtons(repositoryId, pullRequestId);
Optional<PrnfbButton> button =
Iterables.tryFind(buttons, (b) -> b.getUuid().equals(buttionUuid));
if (!button.isPresent()) {
return status(NOT_FOUND).build();
}
String formData = request.getParameter("form");
List<NotificationResponse> results =
buttonsService.handlePressed(repositoryId, pullRequestId, buttionUuid, formData);

ButtonPressDTO dto = toTriggerResultDto(button, results);
ButtonPressDTO dto = toTriggerResultDto(button.get(), results);
return ok(dto, APPLICATION_JSON).build();
}

private void populateButtonFormDtoList(
Integer repositoryId, Long pullRequestId, List<ButtonDTO> dtos) {
for (ButtonDTO dto : dtos) {
PrnfbRendererWrapper renderer =
buttonsService.getRenderer(repositoryId, pullRequestId, dto.getUuid());
List<ButtonFormElementDTO> buttonFormDtoList = dto.getButtonFormList();
if (buttonFormDtoList != null) {
for (ButtonFormElementDTO buttonFormElementDto : buttonFormDtoList) {
String defaultValue = buttonFormElementDto.getDefaultValue();
if (!isNullOrEmpty(defaultValue)) {
String defaultValueRendered = renderer.render(defaultValue, ENCODE_FOR.NONE);
buttonFormElementDto.setDefaultValue(defaultValueRendered);
}
}
dto.setButtonFormList(buttonFormDtoList);
}
}
}
}
82 changes: 65 additions & 17 deletions src/main/java/se/bjurr/prnfb/presentation/GlobalAdminServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import se.bjurr.prnfb.service.UserCheckService;

import com.atlassian.bitbucket.project.Project;
import com.atlassian.bitbucket.project.ProjectService;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.repository.RepositoryService;
import com.atlassian.sal.api.auth.LoginUriProvider;
Expand All @@ -24,11 +24,14 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;

import se.bjurr.prnfb.service.UserCheckService;

public class GlobalAdminServlet extends HttpServlet {
private static final long serialVersionUID = 3846987953228399693L;
private final LoginUriProvider loginUriProvider;
private final TemplateRenderer renderer;
private final RepositoryService repositoryService;
private final ProjectService projectService;
private final UserCheckService userCheckService;
private final UserManager userManager;

Expand All @@ -37,12 +40,14 @@ public GlobalAdminServlet(
LoginUriProvider loginUriProvider,
TemplateRenderer renderer,
RepositoryService repositoryService,
UserCheckService userCheckService) {
UserCheckService userCheckService,
ProjectService projectService) {
this.userManager = userManager;
this.loginUriProvider = loginUriProvider;
this.renderer = renderer;
this.repositoryService = repositoryService;
this.userCheckService = userCheckService;
this.projectService = projectService;
}

@Override
Expand All @@ -54,24 +59,44 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) {
return;
}

final Optional<Repository> repository = getRepository(request.getPathInfo());
boolean isSystemAdmin = this.userCheckService.isSystemAdmin(user.getUserKey());
String projectKey = null;
String repositorySlug = null;

final Optional<Repository> repository = getRepository(request.getPathInfo());
if (repository.isPresent()) {
projectKey = repository.get().getProject().getKey();
repositorySlug = repository.get().getSlug();
}

final Optional<Project> project = getProject(request.getPathInfo());
if (project.isPresent()) {
projectKey = project.get().getKey();
repositorySlug = null;
}

boolean isAdmin =
this.userCheckService.isAdmin(user.getUserKey(), projectKey, repositorySlug);
boolean isSystemAdmin = this.userCheckService.isSystemAdmin(user.getUserKey());

Map<String, Object> context = newHashMap();
if (repository.isPresent()) {
context =
of( //
"repository", repository.orNull(), //
"isAdmin", isAdmin, //
"isSystemAdmin", isSystemAdmin);
"repository",
repository.get(), //
"isAdmin",
isAdmin, //
"isSystemAdmin",
isSystemAdmin);
} else if (project.isPresent()) {
context =
of( //
"project",
project.get(), //
"isAdmin",
isAdmin, //
"isSystemAdmin",
isSystemAdmin);
} else {
context =
of( //
Expand Down Expand Up @@ -99,23 +124,46 @@ private URI getUri(HttpServletRequest request) {
}

@VisibleForTesting
Optional<Repository> getRepository(String pathInfo) {
if (pathInfo == null
|| !pathInfo.contains("/")
|| pathInfo.endsWith("prnfb/admin")
|| pathInfo.endsWith("prnfb/admin/")) {
Optional<Project> getProject(String pathInfo) {
Optional<String[]> componentsOpt = getComponents(pathInfo);
if (!componentsOpt.isPresent() || componentsOpt.get().length != 1) {
return absent();
}
String[] components = pathInfo.split("/");
if (components.length == 0) {
String[] components = componentsOpt.get();
String projectKey = components[0];
Project project = projectService.getByKey(projectKey);
return Optional.of(project);
}

@VisibleForTesting
Optional<Repository> getRepository(String pathInfo) {
Optional<String[]> componentsOpt = getComponents(pathInfo);
if (!componentsOpt.isPresent() || componentsOpt.get().length != 2) {
return absent();
}
String project = components[components.length - 2];
String repoSlug = components[components.length - 1];
String[] components = componentsOpt.get();
String project = components[0];
String repoSlug = components[1];
final Repository repository =
checkNotNull(
this.repositoryService.getBySlug(project, repoSlug), //
"Did not find " + project + " " + repoSlug);
return Optional.of(repository);
}

private Optional<String[]> getComponents(String pathInfo) {
if (pathInfo == null || pathInfo.isEmpty()) {
return absent();
}
int indexOf = pathInfo.indexOf("prnfb/admin/");
if (indexOf == -1) {
return absent();
}
String root = pathInfo.substring(indexOf + "prnfb/admin/".length());
if (root.isEmpty()) {
return absent();
}
String[] split = root.split("/");
return Optional.of(split);
}
}
Loading

0 comments on commit 3026116

Please sign in to comment.