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

Commit 3026116

Browse files
committed
Enable project level admins to configure on project level #193
1 parent e6717f4 commit 3026116

22 files changed

+384
-243
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
Changelog of Pull Request Notifier for Bitbucket.
44

55
## Unreleased
6+
### GitHub [#193](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/issues/193) Enable project level admins to configure on project level
7+
Enable project level admins to configure on project level
8+
9+
[64f670125111045](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/commit/64f670125111045) Tomas Bjerre *2017-02-05 09:00:55*
10+
11+
### No issue
12+
doc
13+
14+
[e6717f40011194e](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/commit/e6717f40011194e) Tomas Bjerre *2017-02-03 13:15:33*
15+
16+
## 2.52
617
### GitHub [#192](https://github.com/tomasbjerre/pull-request-notifier-for-bitbucket/issues/192) Include status for participants
718
Variables to display names of approved, unapproved and needs work
819

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ The Pull Request Notifier for Bitbucket Server can:
3434
* Only if PR has no conflicts
3535
* Nice configuration GUI.
3636
* Global at */bitbucket/plugins/servlet/prnfb/admin*
37+
* Project level at */bitbucket/plugins/servlet/prnfb/admin/PROJECT_1*
3738
* Repo level at */bitbucket/plugins/servlet/prnfb/admin/PROJECT_1/rep_1*
3839

3940
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.

src/main/java/se/bjurr/prnfb/presentation/ButtonServlet.java

Lines changed: 47 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
55
import static javax.ws.rs.core.Response.ok;
66
import static javax.ws.rs.core.Response.status;
7+
import static javax.ws.rs.core.Response.Status.NOT_FOUND;
78
import static javax.ws.rs.core.Response.Status.OK;
89
import static javax.ws.rs.core.Response.Status.UNAUTHORIZED;
910
import static se.bjurr.prnfb.transformer.ButtonTransformer.toButtonDto;
@@ -27,6 +28,8 @@
2728
import javax.ws.rs.core.Response;
2829

2930
import com.atlassian.annotations.security.XsrfProtectionExcluded;
31+
import com.google.common.base.Optional;
32+
import com.google.common.collect.Iterables;
3033

3134
import se.bjurr.prnfb.http.NotificationResponse;
3235
import se.bjurr.prnfb.presentation.dto.ButtonDTO;
@@ -60,9 +63,7 @@ public ButtonServlet(
6063
@Consumes(APPLICATION_JSON)
6164
@Produces(APPLICATION_JSON)
6265
public Response create(ButtonDTO buttonDto) {
63-
if (!userCheckService.isAdminAllowed( //
64-
buttonDto.getProjectKey().orNull(), //
65-
buttonDto.getRepositorySlug().orNull())) {
66+
if (!userCheckService.isAdminAllowed(buttonDto)) {
6667
return status(UNAUTHORIZED) //
6768
.build();
6869
}
@@ -82,10 +83,7 @@ public Response create(ButtonDTO buttonDto) {
8283
@Produces(APPLICATION_JSON)
8384
public Response delete(@PathParam("uuid") UUID prnfbButtonUuid) {
8485
PrnfbButton prnfbButton = settingsService.getButton(prnfbButtonUuid);
85-
if (!userCheckService.isAdminAllowed( //
86-
prnfbButton.getProjectKey().orNull() //
87-
,
88-
prnfbButton.getRepositorySlug().orNull())) {
86+
if (!userCheckService.isAdminAllowed(prnfbButton)) {
8987
return status(UNAUTHORIZED) //
9088
.build();
9189
}
@@ -97,40 +95,18 @@ public Response delete(@PathParam("uuid") UUID prnfbButtonUuid) {
9795
@Produces(APPLICATION_JSON)
9896
public Response get() {
9997
List<PrnfbButton> buttons = settingsService.getButtons();
100-
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAllowed(buttons);
98+
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAdminAllowed(buttons);
10199
List<ButtonDTO> dtos = toButtonDtoList(allowedButtons);
102100
Collections.sort(dtos);
103101
return ok(dtos, APPLICATION_JSON).build();
104102
}
105103

106-
@GET
107-
@Path("/repository/{repositoryId}/pullrequest/{pullRequestId}")
108-
@Produces(APPLICATION_JSON)
109-
public Response get(
110-
@PathParam("repositoryId") Integer repositoryId,
111-
@PathParam("pullRequestId") Long pullRequestId) {
112-
if (!userCheckService.isViewAllowed()) {
113-
return status(UNAUTHORIZED).build();
114-
}
115-
List<PrnfbButton> buttons = buttonsService.getButtons(repositoryId, pullRequestId);
116-
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAllowed(buttons);
117-
List<ButtonDTO> dtos = toButtonDtoList(allowedButtons);
118-
Collections.sort(dtos);
119-
120-
populateButtonFormDtoList(repositoryId, pullRequestId, dtos);
121-
122-
return ok(dtos, APPLICATION_JSON).build();
123-
}
124-
125104
@GET
126105
@Path("/projectKey/{projectKey}")
127106
@Produces(APPLICATION_JSON)
128107
public Response get(@PathParam("projectKey") String projectKey) {
129-
if (!userCheckService.isViewAllowed()) {
130-
return status(UNAUTHORIZED).build();
131-
}
132108
List<PrnfbButton> buttons = settingsService.getButtons(projectKey);
133-
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAllowed(buttons);
109+
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAdminAllowed(buttons);
134110
List<ButtonDTO> dtos = toButtonDtoList(allowedButtons);
135111
Collections.sort(dtos);
136112
return ok(dtos, APPLICATION_JSON).build();
@@ -142,11 +118,8 @@ public Response get(@PathParam("projectKey") String projectKey) {
142118
public Response get(
143119
@PathParam("projectKey") String projectKey,
144120
@PathParam("repositorySlug") String repositorySlug) {
145-
if (!userCheckService.isViewAllowed()) {
146-
return status(UNAUTHORIZED).build();
147-
}
148121
List<PrnfbButton> buttons = settingsService.getButtons(projectKey, repositorySlug);
149-
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAllowed(buttons);
122+
Iterable<PrnfbButton> allowedButtons = userCheckService.filterAdminAllowed(buttons);
150123
List<ButtonDTO> dtos = toButtonDtoList(allowedButtons);
151124
Collections.sort(dtos);
152125
return ok(dtos, APPLICATION_JSON).build();
@@ -157,30 +130,26 @@ public Response get(
157130
@Produces(APPLICATION_JSON)
158131
public Response get(@PathParam("uuid") UUID uuid) {
159132
PrnfbButton button = settingsService.getButton(uuid);
160-
if (!userCheckService.isAllowedUseButton(button)) {
133+
if (!userCheckService.isAdminAllowed(button)) {
161134
return status(UNAUTHORIZED).build();
162135
}
163136
ButtonDTO dto = toButtonDto(button);
164137
return ok(dto, APPLICATION_JSON).build();
165138
}
166139

167-
private void populateButtonFormDtoList(
168-
Integer repositoryId, Long pullRequestId, List<ButtonDTO> dtos) {
169-
for (ButtonDTO dto : dtos) {
170-
PrnfbRendererWrapper renderer =
171-
buttonsService.getRenderer(repositoryId, pullRequestId, dto.getUuid());
172-
List<ButtonFormElementDTO> buttonFormDtoList = dto.getButtonFormList();
173-
if (buttonFormDtoList != null) {
174-
for (ButtonFormElementDTO buttonFormElementDto : buttonFormDtoList) {
175-
String defaultValue = buttonFormElementDto.getDefaultValue();
176-
if (!isNullOrEmpty(defaultValue)) {
177-
String defaultValueRendered = renderer.render(defaultValue, ENCODE_FOR.NONE);
178-
buttonFormElementDto.setDefaultValue(defaultValueRendered);
179-
}
180-
}
181-
dto.setButtonFormList(buttonFormDtoList);
182-
}
183-
}
140+
@GET
141+
@Path("/repository/{repositoryId}/pullrequest/{pullRequestId}")
142+
@Produces(APPLICATION_JSON)
143+
public Response get(
144+
@PathParam("repositoryId") Integer repositoryId,
145+
@PathParam("pullRequestId") Long pullRequestId) {
146+
List<PrnfbButton> buttons = buttonsService.getButtons(repositoryId, pullRequestId);
147+
List<ButtonDTO> dtos = toButtonDtoList(buttons);
148+
Collections.sort(dtos);
149+
150+
populateButtonFormDtoList(repositoryId, pullRequestId, dtos);
151+
152+
return ok(dtos, APPLICATION_JSON).build();
184153
}
185154

186155
@POST
@@ -192,15 +161,36 @@ public Response press(
192161
@PathParam("repositoryId") Integer repositoryId,
193162
@PathParam("pullRequestId") Long pullRequestId,
194163
@PathParam("uuid") final UUID buttionUuid) {
195-
PrnfbButton button = settingsService.getButton(buttionUuid);
196-
if (!userCheckService.isAllowedUseButton(button)) {
197-
return status(UNAUTHORIZED).build();
164+
List<PrnfbButton> buttons = buttonsService.getButtons(repositoryId, pullRequestId);
165+
Optional<PrnfbButton> button =
166+
Iterables.tryFind(buttons, (b) -> b.getUuid().equals(buttionUuid));
167+
if (!button.isPresent()) {
168+
return status(NOT_FOUND).build();
198169
}
199170
String formData = request.getParameter("form");
200171
List<NotificationResponse> results =
201172
buttonsService.handlePressed(repositoryId, pullRequestId, buttionUuid, formData);
202173

203-
ButtonPressDTO dto = toTriggerResultDto(button, results);
174+
ButtonPressDTO dto = toTriggerResultDto(button.get(), results);
204175
return ok(dto, APPLICATION_JSON).build();
205176
}
177+
178+
private void populateButtonFormDtoList(
179+
Integer repositoryId, Long pullRequestId, List<ButtonDTO> dtos) {
180+
for (ButtonDTO dto : dtos) {
181+
PrnfbRendererWrapper renderer =
182+
buttonsService.getRenderer(repositoryId, pullRequestId, dto.getUuid());
183+
List<ButtonFormElementDTO> buttonFormDtoList = dto.getButtonFormList();
184+
if (buttonFormDtoList != null) {
185+
for (ButtonFormElementDTO buttonFormElementDto : buttonFormDtoList) {
186+
String defaultValue = buttonFormElementDto.getDefaultValue();
187+
if (!isNullOrEmpty(defaultValue)) {
188+
String defaultValueRendered = renderer.render(defaultValue, ENCODE_FOR.NONE);
189+
buttonFormElementDto.setDefaultValue(defaultValueRendered);
190+
}
191+
}
192+
dto.setButtonFormList(buttonFormDtoList);
193+
}
194+
}
195+
}
206196
}

src/main/java/se/bjurr/prnfb/presentation/GlobalAdminServlet.java

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
import javax.servlet.http.HttpServletRequest;
1414
import javax.servlet.http.HttpServletResponse;
1515

16-
import se.bjurr.prnfb.service.UserCheckService;
17-
16+
import com.atlassian.bitbucket.project.Project;
17+
import com.atlassian.bitbucket.project.ProjectService;
1818
import com.atlassian.bitbucket.repository.Repository;
1919
import com.atlassian.bitbucket.repository.RepositoryService;
2020
import com.atlassian.sal.api.auth.LoginUriProvider;
@@ -24,11 +24,14 @@
2424
import com.google.common.annotations.VisibleForTesting;
2525
import com.google.common.base.Optional;
2626

27+
import se.bjurr.prnfb.service.UserCheckService;
28+
2729
public class GlobalAdminServlet extends HttpServlet {
2830
private static final long serialVersionUID = 3846987953228399693L;
2931
private final LoginUriProvider loginUriProvider;
3032
private final TemplateRenderer renderer;
3133
private final RepositoryService repositoryService;
34+
private final ProjectService projectService;
3235
private final UserCheckService userCheckService;
3336
private final UserManager userManager;
3437

@@ -37,12 +40,14 @@ public GlobalAdminServlet(
3740
LoginUriProvider loginUriProvider,
3841
TemplateRenderer renderer,
3942
RepositoryService repositoryService,
40-
UserCheckService userCheckService) {
43+
UserCheckService userCheckService,
44+
ProjectService projectService) {
4145
this.userManager = userManager;
4246
this.loginUriProvider = loginUriProvider;
4347
this.renderer = renderer;
4448
this.repositoryService = repositoryService;
4549
this.userCheckService = userCheckService;
50+
this.projectService = projectService;
4651
}
4752

4853
@Override
@@ -54,24 +59,44 @@ public void doGet(HttpServletRequest request, HttpServletResponse response) {
5459
return;
5560
}
5661

57-
final Optional<Repository> repository = getRepository(request.getPathInfo());
58-
boolean isSystemAdmin = this.userCheckService.isSystemAdmin(user.getUserKey());
5962
String projectKey = null;
6063
String repositorySlug = null;
64+
65+
final Optional<Repository> repository = getRepository(request.getPathInfo());
6166
if (repository.isPresent()) {
6267
projectKey = repository.get().getProject().getKey();
6368
repositorySlug = repository.get().getSlug();
6469
}
70+
71+
final Optional<Project> project = getProject(request.getPathInfo());
72+
if (project.isPresent()) {
73+
projectKey = project.get().getKey();
74+
repositorySlug = null;
75+
}
76+
6577
boolean isAdmin =
6678
this.userCheckService.isAdmin(user.getUserKey(), projectKey, repositorySlug);
79+
boolean isSystemAdmin = this.userCheckService.isSystemAdmin(user.getUserKey());
6780

6881
Map<String, Object> context = newHashMap();
6982
if (repository.isPresent()) {
7083
context =
7184
of( //
72-
"repository", repository.orNull(), //
73-
"isAdmin", isAdmin, //
74-
"isSystemAdmin", isSystemAdmin);
85+
"repository",
86+
repository.get(), //
87+
"isAdmin",
88+
isAdmin, //
89+
"isSystemAdmin",
90+
isSystemAdmin);
91+
} else if (project.isPresent()) {
92+
context =
93+
of( //
94+
"project",
95+
project.get(), //
96+
"isAdmin",
97+
isAdmin, //
98+
"isSystemAdmin",
99+
isSystemAdmin);
75100
} else {
76101
context =
77102
of( //
@@ -99,23 +124,46 @@ private URI getUri(HttpServletRequest request) {
99124
}
100125

101126
@VisibleForTesting
102-
Optional<Repository> getRepository(String pathInfo) {
103-
if (pathInfo == null
104-
|| !pathInfo.contains("/")
105-
|| pathInfo.endsWith("prnfb/admin")
106-
|| pathInfo.endsWith("prnfb/admin/")) {
127+
Optional<Project> getProject(String pathInfo) {
128+
Optional<String[]> componentsOpt = getComponents(pathInfo);
129+
if (!componentsOpt.isPresent() || componentsOpt.get().length != 1) {
107130
return absent();
108131
}
109-
String[] components = pathInfo.split("/");
110-
if (components.length == 0) {
132+
String[] components = componentsOpt.get();
133+
String projectKey = components[0];
134+
Project project = projectService.getByKey(projectKey);
135+
return Optional.of(project);
136+
}
137+
138+
@VisibleForTesting
139+
Optional<Repository> getRepository(String pathInfo) {
140+
Optional<String[]> componentsOpt = getComponents(pathInfo);
141+
if (!componentsOpt.isPresent() || componentsOpt.get().length != 2) {
111142
return absent();
112143
}
113-
String project = components[components.length - 2];
114-
String repoSlug = components[components.length - 1];
144+
String[] components = componentsOpt.get();
145+
String project = components[0];
146+
String repoSlug = components[1];
115147
final Repository repository =
116148
checkNotNull(
117149
this.repositoryService.getBySlug(project, repoSlug), //
118150
"Did not find " + project + " " + repoSlug);
119151
return Optional.of(repository);
120152
}
153+
154+
private Optional<String[]> getComponents(String pathInfo) {
155+
if (pathInfo == null || pathInfo.isEmpty()) {
156+
return absent();
157+
}
158+
int indexOf = pathInfo.indexOf("prnfb/admin/");
159+
if (indexOf == -1) {
160+
return absent();
161+
}
162+
String root = pathInfo.substring(indexOf + "prnfb/admin/".length());
163+
if (root.isEmpty()) {
164+
return absent();
165+
}
166+
String[] split = root.split("/");
167+
return Optional.of(split);
168+
}
121169
}

0 commit comments

Comments
 (0)