Skip to content

Commit e757093

Browse files
committed
Mods to support access requests (#364).
1 parent c19002f commit e757093

File tree

9 files changed

+412
-14
lines changed

9 files changed

+412
-14
lines changed

src/main/java/org/gitlab4j/api/GroupApi.java

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import org.gitlab4j.api.GitLabApi.ApiVersion;
1313
import org.gitlab4j.api.models.AccessLevel;
14+
import org.gitlab4j.api.models.AccessRequest;
1415
import org.gitlab4j.api.models.Group;
1516
import org.gitlab4j.api.models.GroupFilter;
1617
import org.gitlab4j.api.models.GroupProjectsFilter;
@@ -23,6 +24,7 @@
2324
* This class implements the client side API for the GitLab groups calls.
2425
* @see <a href="https://docs.gitlab.com/ce/api/groups.html">Groups API at GitLab</a>
2526
* @see <a href="https://docs.gitlab.com/ee/api/members.html">Group and project members API at GitLab</a>
27+
* @see <a href="https://docs.gitlab.com/ee/api/access_requests.html#group-and-project-access-requests-api">Group and project access requests API</a>
2628
*/
2729
public class GroupApi extends AbstractApi {
2830

@@ -1221,4 +1223,91 @@ public Project transferProject(Object groupIdOrPath, Object projectIdOrPath) thr
12211223
"projects", getProjectIdOrPath(projectIdOrPath));
12221224
return (response.readEntity(Project.class));
12231225
}
1226+
1227+
/**
1228+
* Get a List of the group access requests viewable by the authenticated user.
1229+
*
1230+
* <pre><code>GET /group/:id/access_requests</code></pre>
1231+
*
1232+
* @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path
1233+
* @return a List of project AccessRequest instances accessible by the authenticated user
1234+
* @throws GitLabApiException if any exception occurs
1235+
*/
1236+
public List<AccessRequest> getAccessRequests(Object groupIdOrPath) throws GitLabApiException {
1237+
return (getAccessRequests(groupIdOrPath, getDefaultPerPage()).all());
1238+
}
1239+
1240+
/**
1241+
* Get a Pager of the group access requests viewable by the authenticated user.
1242+
*
1243+
* <pre><code>GET /groups/:id/access_requests</code></pre>
1244+
*
1245+
* @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path
1246+
* @param itemsPerPage the number of AccessRequest instances that will be fetched per page
1247+
* @return a Pager of group AccessRequest instances accessible by the authenticated user
1248+
* @throws GitLabApiException if any exception occurs
1249+
*/
1250+
public Pager<AccessRequest> getAccessRequests(Object groupIdOrPath, int itemsPerPage) throws GitLabApiException {
1251+
return (new Pager<AccessRequest>(this, AccessRequest.class, itemsPerPage, null,
1252+
"groups", getGroupIdOrPath(groupIdOrPath), "access_requests"));
1253+
}
1254+
1255+
/**
1256+
* Get a Stream of the group access requests viewable by the authenticated user.
1257+
*
1258+
* <pre><code>GET /groups/:id/access_requests</code></pre>
1259+
*
1260+
* @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path
1261+
* @return a Stream of group AccessRequest instances accessible by the authenticated user
1262+
* @throws GitLabApiException if any exception occurs
1263+
*/
1264+
public Stream<AccessRequest> getAccessRequestsStream(Object groupIdOrPath) throws GitLabApiException {
1265+
return (getAccessRequests(groupIdOrPath, getDefaultPerPage()).stream());
1266+
}
1267+
1268+
/**
1269+
* Requests access for the authenticated user to the specified group.
1270+
*
1271+
* <pre><code>POST /groups/:id/access_requests</code></pre>
1272+
*
1273+
* @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path
1274+
* @return the created AccessRequest instance
1275+
* @throws GitLabApiException if any exception occurs
1276+
*/
1277+
public AccessRequest requestAccess(Object groupIdOrPath) throws GitLabApiException {
1278+
Response response = post(Response.Status.CREATED, (Form)null, "groups", getGroupIdOrPath(groupIdOrPath), "access_requests");
1279+
return (response.readEntity(AccessRequest.class));
1280+
}
1281+
1282+
/**
1283+
* Approve access for the specified user to the specified group.
1284+
*
1285+
* <pre><code>PUT /groups/:id/access_requests/:user_id/approve</code></pre>
1286+
*
1287+
* @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path
1288+
* @param userId the user ID to approve access for
1289+
* @param accessLevel the access level the user is approved for, if null will be developer (30)
1290+
* @return the approved AccessRequest instance
1291+
* @throws GitLabApiException if any exception occurs
1292+
*/
1293+
public AccessRequest approveAccessRequest(Object groupIdOrPath, Integer userId, AccessLevel accessLevel) throws GitLabApiException {
1294+
GitLabApiForm formData = new GitLabApiForm().withParam("access_level", accessLevel);
1295+
Response response = this.putWithFormData(Response.Status.CREATED, formData,
1296+
"groups", getGroupIdOrPath(groupIdOrPath), "access_requests", userId, "approve");
1297+
return (response.readEntity(AccessRequest.class));
1298+
}
1299+
1300+
/**
1301+
* Deny access for the specified user to the specified group.
1302+
*
1303+
* <pre><code>DELETE /groups/:id/access_requests/:user_id</code></pre>
1304+
*
1305+
* @param groupIdOrPath the group ID, path of the group, or a Group instance holding the group ID or path
1306+
* @param userId the user ID to deny access for
1307+
* @throws GitLabApiException if any exception occurs
1308+
*/
1309+
public void denyAccessRequest(Object groupIdOrPath, Integer userId) throws GitLabApiException {
1310+
delete(Response.Status.NO_CONTENT, null,
1311+
"groups", getGroupIdOrPath(groupIdOrPath), "access_requests", userId);
1312+
}
12241313
}

src/main/java/org/gitlab4j/api/ProjectApi.java

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939

4040
import org.gitlab4j.api.GitLabApi.ApiVersion;
4141
import org.gitlab4j.api.models.AccessLevel;
42+
import org.gitlab4j.api.models.AccessRequest;
4243
import org.gitlab4j.api.models.Event;
4344
import org.gitlab4j.api.models.FileUpload;
4445
import org.gitlab4j.api.models.Issue;
@@ -56,6 +57,7 @@
5657
* This class provides an entry point to all the GitLab API project calls.
5758
* @see <a href="https://docs.gitlab.com/ce/api/projects.html">Projects API at GitLab</a>
5859
* @see <a href="https://docs.gitlab.com/ee/api/members.html">Group and project members API at GitLab</a>
60+
* @see <a href="https://docs.gitlab.com/ee/api/access_requests.html#group-and-project-access-requests-api">Group and project access requests API</a>
5961
*/
6062
public class ProjectApi extends AbstractApi implements Constants {
6163

@@ -2681,4 +2683,90 @@ public Variable updateVariable(Object projectIdOrPath, String key, String value,
26812683
public void deleteVariable(Object projectIdOrPath, String key) throws GitLabApiException {
26822684
delete(Response.Status.NO_CONTENT, null, "projects", getProjectIdOrPath(projectIdOrPath), "variables", key);
26832685
}
2686+
2687+
/**
2688+
* Get a List of the project access requests viewable by the authenticated user.
2689+
*
2690+
* <pre><code>GET /projects/:id/access_requests</code></pre>
2691+
*
2692+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
2693+
* @return a List of project AccessRequest instances accessible by the authenticated user
2694+
* @throws GitLabApiException if any exception occurs
2695+
*/
2696+
public List<AccessRequest> getAccessRequests(Object projectIdOrPath) throws GitLabApiException {
2697+
return (getAccessRequests(projectIdOrPath, getDefaultPerPage()).all());
2698+
}
2699+
2700+
/**
2701+
* Get a Pager of the project access requests viewable by the authenticated user.
2702+
*
2703+
* <pre><code>GET /projects/:id/access_requests</code></pre>
2704+
*
2705+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
2706+
* @param itemsPerPage the number of AccessRequest instances that will be fetched per page
2707+
* @return a Pager of project AccessRequest instances accessible by the authenticated user
2708+
* @throws GitLabApiException if any exception occurs
2709+
*/
2710+
public Pager<AccessRequest> getAccessRequests(Object projectIdOrPath, int itemsPerPage) throws GitLabApiException {
2711+
return (new Pager<AccessRequest>(this, AccessRequest.class, itemsPerPage, null, "projects", getProjectIdOrPath(projectIdOrPath), "access_requests"));
2712+
}
2713+
2714+
/**
2715+
* Get a Stream of the project access requests viewable by the authenticated user.
2716+
*
2717+
* <pre><code>GET /projects/:id/access_requests</code></pre>
2718+
*
2719+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
2720+
* @return a Stream of project AccessRequest instances accessible by the authenticated user
2721+
* @throws GitLabApiException if any exception occurs
2722+
*/
2723+
public Stream<AccessRequest> getAccessRequestsStream(Object projectIdOrPath) throws GitLabApiException {
2724+
return (getAccessRequests(projectIdOrPath, getDefaultPerPage()).stream());
2725+
}
2726+
2727+
/**
2728+
* Requests access for the authenticated user to the specified project.
2729+
*
2730+
* <pre><code>POST /projects/:id/access_requests</code></pre>
2731+
*
2732+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
2733+
* @return the created AccessRequest instance
2734+
* @throws GitLabApiException if any exception occurs
2735+
*/
2736+
public AccessRequest requestAccess(Object projectIdOrPath) throws GitLabApiException {
2737+
Response response = post(Response.Status.CREATED, (Form)null, "projects", getProjectIdOrPath(projectIdOrPath), "access_requests");
2738+
return (response.readEntity(AccessRequest.class));
2739+
}
2740+
2741+
/**
2742+
* Approve access for the specified user to the specified project.
2743+
*
2744+
* <pre><code>PUT /projects/:id/access_requests/:user_id/approve</code></pre>
2745+
*
2746+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
2747+
* @param userId the user ID to approve access for
2748+
* @param accessLevel the access level the user is approved for, if null will be developer (30)
2749+
* @return the approved AccessRequest instance
2750+
* @throws GitLabApiException if any exception occurs
2751+
*/
2752+
public AccessRequest approveAccessRequest(Object projectIdOrPath, Integer userId, AccessLevel accessLevel) throws GitLabApiException {
2753+
GitLabApiForm formData = new GitLabApiForm().withParam("access_level", accessLevel);
2754+
Response response = this.putWithFormData(Response.Status.CREATED, formData,
2755+
"projects", getProjectIdOrPath(projectIdOrPath), "access_requests", userId, "approve");
2756+
return (response.readEntity(AccessRequest.class));
2757+
}
2758+
2759+
/**
2760+
* Deny access for the specified user to the specified project.
2761+
*
2762+
* <pre><code>DELETE /projects/:id/access_requests/:user_id</code></pre>
2763+
*
2764+
* @param projectIdOrPath the project in the form of an Integer(ID), String(path), or Project instance
2765+
* @param userId the user ID to deny access for
2766+
* @throws GitLabApiException if any exception occurs
2767+
*/
2768+
public void denyAccessRequest(Object projectIdOrPath, Integer userId) throws GitLabApiException {
2769+
delete(Response.Status.NO_CONTENT, null,
2770+
"projects", getProjectIdOrPath(projectIdOrPath), "access_requests", userId);
2771+
}
26842772
}

src/test/java/org/gitlab4j/api/IntegrationTestSuite.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.gitlab4j.api.models.User;
1414
import org.gitlab4j.api.models.Visibility;
1515
import org.gitlab4j.api.utils.AccessTokenUtils;
16+
import org.gitlab4j.api.utils.AccessTokenUtils.Scope;
1617
import org.junit.AfterClass;
1718
import org.junit.BeforeClass;
1819
import org.junit.experimental.categories.Categories.IncludeCategory;
@@ -96,7 +97,7 @@ private static void createAccessTokens() throws GitLabApiException {
9697

9798
TEST_PRIVATE_TOKEN = AccessTokenUtils.createPersonalAccessToken(
9899
TEST_HOST_URL, TEST_LOGIN_USERNAME, TEST_LOGIN_PASSWORD,
99-
TEST_PRIVATE_TOKEN_NAME, Arrays.asList("api", "sudo"));
100+
TEST_PRIVATE_TOKEN_NAME, Arrays.asList(Scope.API, Scope.SUDO));
100101
System.out.println("Created private token: " + TEST_PRIVATE_TOKEN);
101102
assertNotNull(TEST_PRIVATE_TOKEN);
102103
assertFalse(TEST_PRIVATE_TOKEN.trim().isEmpty());
@@ -109,7 +110,7 @@ private static void createAccessTokens() throws GitLabApiException {
109110

110111
TEST_ACCESS_TOKEN = AccessTokenUtils.createPersonalAccessToken(
111112
TEST_HOST_URL, TEST_LOGIN_USERNAME, TEST_LOGIN_PASSWORD,
112-
TEST_ACCESS_TOKEN_NAME, Arrays.asList("api", "sudo"));
113+
TEST_ACCESS_TOKEN_NAME, Arrays.asList(Scope.API, Scope.SUDO));
113114
System.out.println("Created access token: " + TEST_ACCESS_TOKEN);
114115
assertNotNull(TEST_ACCESS_TOKEN);
115116
assertFalse(TEST_ACCESS_TOKEN.trim().isEmpty());
@@ -124,7 +125,7 @@ private static void revokeAccessTokens() throws GitLabApiException {
124125
try {
125126
AccessTokenUtils.revokePersonalAccessToken(
126127
TEST_HOST_URL, TEST_LOGIN_USERNAME, TEST_LOGIN_PASSWORD,
127-
TEST_PRIVATE_TOKEN_NAME, Arrays.asList("api", "sudo"));
128+
TEST_PRIVATE_TOKEN_NAME, Arrays.asList(Scope.API, Scope.SUDO));
128129
System.out.format("Revoved '%s'%n", TEST_PRIVATE_TOKEN_NAME);
129130
} catch (Exception ignore) {}
130131
}
@@ -133,7 +134,7 @@ private static void revokeAccessTokens() throws GitLabApiException {
133134
try {
134135
AccessTokenUtils.revokePersonalAccessToken(
135136
TEST_HOST_URL, TEST_LOGIN_USERNAME, TEST_LOGIN_PASSWORD,
136-
TEST_ACCESS_TOKEN_NAME, Arrays.asList("api", "sudo"));
137+
TEST_ACCESS_TOKEN_NAME, Arrays.asList(Scope.API, Scope.SUDO));
137138
System.out.format("Revoved '%s'%n", TEST_ACCESS_TOKEN_NAME);
138139
} catch (Exception ignore) {}
139140
}
@@ -202,7 +203,8 @@ private static void seedData() throws GitLabApiException {
202203
.withName(TEST_PROJECT_NAME)
203204
.withDefaultBranch("master")
204205
.withPublic(true)
205-
.withInitializeWithReadme(true);
206+
.withInitializeWithReadme(true)
207+
.withRequestAccessEnabled(true);
206208
testProject = gitLabApi.getProjectApi().createProject(projectSettings);
207209
System.out.format("Created %s project%n", projectSettings.getName());
208210

@@ -241,7 +243,8 @@ private static void seedData() throws GitLabApiException {
241243
.withName("Test Group")
242244
.withPath(TEST_GROUP)
243245
.withDescription("Test Group")
244-
.withVisibility(Visibility.PUBLIC);
246+
.withVisibility(Visibility.PUBLIC)
247+
.withRequestAccessEnabled(true);
245248
testGroup = gitLabApi.getGroupApi().addGroup(groupSettings);
246249
System.out.format("Created %s group (%s)%n", groupSettings.getName(), groupSettings.getPath());
247250
}

src/test/java/org/gitlab4j/api/PropertyConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public interface PropertyConstants {
2323
public static final String PROXY_PASSWORD_KEY = "TEST_PROXY_PASSWORD";
2424
public static final String PROXY_URI_KEY = "TEST_PROXY_URI";
2525
public static final String PROXY_USERNAME_KEY = "TEST_PROXY_USERNAME";
26+
public static final String TEST_REQUEST_ACCESS_USERNAME_KEY = "TEST_REQUEST_ACCESS_USERNAME";
2627
public static final String SUDO_AS_USERNAME_KEY = "TEST_SUDO_AS_USERNAME";
2728
public static final String USERNAME_KEY = "TEST_USERNAME";
2829
public static final String XFER_NAMESPACE_KEY = "TEST_XFER_NAMESPACE";

src/test/java/org/gitlab4j/api/TestAccessTokenUtils.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.Arrays;
1010

1111
import org.gitlab4j.api.utils.AccessTokenUtils;
12+
import org.gitlab4j.api.utils.AccessTokenUtils.Scope;
1213
import org.junit.Before;
1314
import org.junit.BeforeClass;
1415
import org.junit.Test;
@@ -71,7 +72,7 @@ public void testCreatePersonalAccessToken() throws GitLabApiException {
7172

7273
String accessToken = AccessTokenUtils.createPersonalAccessToken(
7374
TEST_HOST_URL, TEST_LOGIN_USERNAME, TEST_LOGIN_PASSWORD,
74-
tokenName, Arrays.asList("api", "sudo"));
75+
tokenName, Arrays.asList(Scope.API, Scope.SUDO));
7576
System.out.format("Created '%s' personal access token: %s%n", tokenName, accessToken);
7677

7778
assertNotNull(accessToken);
@@ -81,7 +82,7 @@ public void testCreatePersonalAccessToken() throws GitLabApiException {
8182
try {
8283
AccessTokenUtils.revokePersonalAccessToken(
8384
TEST_HOST_URL, TEST_LOGIN_USERNAME, TEST_LOGIN_PASSWORD,
84-
tokenName, Arrays.asList("api", "sudo"));
85+
tokenName, Arrays.asList(Scope.API, Scope.SUDO));
8586
System.out.format("Revoked '%s' personal access token: %s%n", tokenName, accessToken);
8687
} catch (Exception ignore) {}
8788
}
@@ -92,7 +93,7 @@ public void testCreatePersonalAccessTokenFailedLogin() {
9293
try {
9394
AccessTokenUtils.createPersonalAccessToken(
9495
TEST_HOST_URL, TEST_LOGIN_USERNAME, "INVALID PASSWORD",
95-
"Testing Token Creation", Arrays.asList("api", "sudo"));
96+
"Testing Token Creation", Arrays.asList(Scope.API, Scope.SUDO));
9697
fail("Expected a failure, but personal access token was created.");
9798
} catch (GitLabApiException glae) {
9899
assertEquals(401, glae.getHttpStatus());
@@ -106,14 +107,14 @@ public void testRevokePersonalAccessToken() throws GitLabApiException {
106107

107108
String accessToken = AccessTokenUtils.createPersonalAccessToken(
108109
TEST_HOST_URL, TEST_LOGIN_USERNAME, TEST_LOGIN_PASSWORD,
109-
tokenName, Arrays.asList("api", "sudo"));
110+
tokenName, Arrays.asList(Scope.API, Scope.SUDO));
110111
System.out.format("Created '%s' personal access token: %s%n", tokenName, accessToken);
111112
assertNotNull(accessToken);
112113
assertFalse(accessToken.trim().isEmpty());
113114

114115
AccessTokenUtils.revokePersonalAccessToken(
115116
TEST_HOST_URL, TEST_LOGIN_USERNAME, TEST_LOGIN_PASSWORD,
116-
tokenName, Arrays.asList("api", "sudo"));
117+
tokenName, Arrays.asList(Scope.API, Scope.SUDO));
117118
System.out.format("Revoked '%s' personal access token: %s%n", tokenName, accessToken);
118119
}
119120

src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.util.List;
3333
import java.util.Map;
3434

35+
import org.gitlab4j.api.models.AccessRequest;
3536
import org.gitlab4j.api.models.Application;
3637
import org.gitlab4j.api.models.ArtifactsFile;
3738
import org.gitlab4j.api.models.AwardEmoji;
@@ -90,6 +91,12 @@
9091

9192
public class TestGitLabApiBeans {
9293

94+
@Test
95+
public void testAccessRequest() throws Exception {
96+
AccessRequest accessRequest = unmarshalResource(AccessRequest.class, "access-request.json");
97+
assertTrue(compareJson(accessRequest, "access-request.json"));
98+
}
99+
93100
@Test
94101
public void testApplications() throws Exception {
95102
List<Application> applications = unmarshalResourceList(Application.class, "applications.json");

0 commit comments

Comments
 (0)