Skip to content

Commit 06011dd

Browse files
maltem-zajmini
authored andcommitted
UserApi implement createPersonalAccessToken
* adds missing scopes * factors out common logic
1 parent 2d2fe24 commit 06011dd

File tree

3 files changed

+76
-21
lines changed

3 files changed

+76
-21
lines changed

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

+38-15
Original file line numberDiff line numberDiff line change
@@ -904,21 +904,7 @@ public Optional<ImpersonationToken> getOptionalImpersonationToken(Object userIdO
904904
* @throws GitLabApiException if any exception occurs
905905
*/
906906
public ImpersonationToken createImpersonationToken(Object userIdOrUsername, String name, Date expiresAt, Scope[] scopes) throws GitLabApiException {
907-
908-
if (scopes == null || scopes.length == 0) {
909-
throw new RuntimeException("scopes cannot be null or empty");
910-
}
911-
912-
GitLabApiForm formData = new GitLabApiForm()
913-
.withParam("name", name, true)
914-
.withParam("expires_at", expiresAt);
915-
916-
for (Scope scope : scopes) {
917-
formData.withParam("scopes[]", scope.toString());
918-
}
919-
920-
Response response = post(Response.Status.CREATED, formData, "users", getUserIdOrUsername(userIdOrUsername), "impersonation_tokens");
921-
return (response.readEntity(ImpersonationToken.class));
907+
return createPersonalAccessTokenOrImpersonationToken(userIdOrUsername, name, expiresAt, scopes, true);
922908
}
923909

924910
/**
@@ -940,6 +926,43 @@ public void revokeImpersonationToken(Object userIdOrUsername, Long tokenId) thro
940926
delete(expectedStatus, null, "users", getUserIdOrUsername(userIdOrUsername), "impersonation_tokens", tokenId);
941927
}
942928

929+
/**
930+
* Create a personal access token. Available only for admin users.
931+
*
932+
* <pre><code>GitLab Endpoint: POST /users/:user_id/personal_access_tokens</code></pre>
933+
*
934+
* @param userIdOrUsername the user in the form of an Integer(ID), String(username), or User instance
935+
* @param name the name of the personal access token, required
936+
* @param expiresAt the expiration date of the personal access token, optional
937+
* @param scopes an array of scopes of the personal access token
938+
* @return the created PersonalAccessToken instance
939+
* @throws GitLabApiException if any exception occurs
940+
*/
941+
public ImpersonationToken createPersonalAccessToken(Object userIdOrUsername, String name, Date expiresAt, Scope[] scopes) throws GitLabApiException {
942+
return createPersonalAccessTokenOrImpersonationToken(userIdOrUsername, name, expiresAt, scopes, false);
943+
}
944+
945+
// as per https://docs.gitlab.com/ee/api/README.html#impersonation-tokens, impersonation tokens are a type of
946+
// personal access token
947+
private ImpersonationToken createPersonalAccessTokenOrImpersonationToken(Object userIdOrUsername, String name, Date expiresAt, Scope[] scopes, boolean impersonation) throws GitLabApiException {
948+
949+
if (scopes == null || scopes.length == 0) {
950+
throw new RuntimeException("scopes cannot be null or empty");
951+
}
952+
953+
GitLabApiForm formData = new GitLabApiForm()
954+
.withParam("name", name, true)
955+
.withParam("expires_at", expiresAt);
956+
957+
for (Scope scope : scopes) {
958+
formData.withParam("scopes[]", scope.toString());
959+
}
960+
961+
String tokenTypePathArg = impersonation ? "impersonation_tokens" : "personal_access_tokens";
962+
Response response = post(Response.Status.CREATED, formData, "users", getUserIdOrUsername(userIdOrUsername), tokenTypePathArg);
963+
return (response.readEntity(ImpersonationToken.class));
964+
}
965+
943966
/**
944967
* Populate the REST form with data from the User instance.
945968
*

src/main/java/org/gitlab4j/api/models/ImpersonationToken.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public class ImpersonationToken {
1414
/** Enum to specify the scope of an ImpersonationToken. */
1515
public enum Scope {
1616

17-
API, READ_USER, READ_REPOSITORY, WRITE_REPOSITORY, READ_REGISTRY, SUDO;
17+
API, READ_API, READ_USER, READ_REPOSITORY, WRITE_REPOSITORY, READ_REGISTRY, WRITE_REGISTRY, SUDO;
1818

1919
private static JacksonJsonEnumHelper<Scope> enumHelper = new JacksonJsonEnumHelper<>(Scope.class);
2020

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

+37-5
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ public class TestUserApi extends AbstractIntegrationTest {
6161
private static final String TEST_BLOCK_USERNAME = HelperUtils.getProperty(BLOCK_USERNAME_KEY);
6262
private static final String TEST_SUDO_AS_USERNAME = HelperUtils.getProperty(SUDO_AS_USERNAME_KEY);
6363

64-
private static final String TEST_IMPERSONATION_TOKEN_NAME = "token1";
64+
private static final String TEST_IMPERSONATION_TOKEN_NAME = "ipt_1";
65+
private static final String TEST_PERSONAL_ACCESS_TOKEN_NAME = "pat_1";
6566
private static final String TEST_SSH_KEY =
6667
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3rWzl/oPAD+Em2iGTmR81HcYZsopvnKp7jelI4XS91fT1NjCRrGsxf5Mw/" +
6768
"KnmtBjhk+kQjkhIrnsBDcs6DZWtNcHJtyWJZrYsfxMTqWCaQv+OTRwVboqS2pmPcbK3gizUd5GCLFTKbg4OMpdywTwi6NAPwQ" +
@@ -325,9 +326,9 @@ public void testCreateImpersonationToken() throws GitLabApiException, ParseExcep
325326

326327
User user = gitLabApi.getUserApi().getCurrentUser();
327328

328-
// NOTE: READ_REGISTRY scope is left out because the GitLab server docker instance does not have the
329-
// registry configured and the test would thus fail.
330-
Scope[] scopes = {Scope.API, Scope.READ_USER, Scope.READ_REPOSITORY, Scope.WRITE_REPOSITORY, Scope.SUDO};
329+
// NOTE: READ_REGISTRY & WRITE_REGISTRY scopes are left out because the GitLab server docker instance does not
330+
// have the registry configured and the test would thus fail.
331+
Scope[] scopes = {Scope.API, Scope.READ_API, Scope.READ_USER, Scope.READ_REPOSITORY, Scope.WRITE_REPOSITORY, Scope.SUDO};
331332
Date expiresAt = ISO8601.toDate("2018-01-01T00:00:00Z");
332333

333334
ImpersonationToken token = null;
@@ -401,7 +402,7 @@ public void testGetImpersonationTokens() throws GitLabApiException, ParseExcepti
401402
}
402403

403404
@Test
404-
public void testDeleteImpersonationTokens() throws GitLabApiException, ParseException {
405+
public void testRevokeImpersonationToken() throws GitLabApiException, ParseException {
405406

406407
User user = gitLabApi.getUserApi().getCurrentUser();
407408
Scope[] scopes = {Scope.API, Scope.READ_USER};
@@ -418,6 +419,37 @@ public void testDeleteImpersonationTokens() throws GitLabApiException, ParseExce
418419
assertFalse(token.getActive());
419420
}
420421

422+
@Test
423+
public void testCreatePersonalAccessToken() throws GitLabApiException, ParseException {
424+
425+
User user = gitLabApi.getUserApi().getCurrentUser();
426+
427+
// NOTE: READ_REGISTRY & WRITE_REGISTRY scopes are left out because the GitLab server docker instance does not
428+
// have the registry configured and the test would thus fail.
429+
Scope[] scopes = {Scope.API, Scope.READ_API, Scope.READ_USER, Scope.READ_REPOSITORY, Scope.WRITE_REPOSITORY, Scope.SUDO};
430+
Date expiresAt = ISO8601.toDate("2018-01-01T00:00:00Z");
431+
432+
ImpersonationToken token = null;
433+
try {
434+
435+
token = gitLabApi.getUserApi().createPersonalAccessToken(user, TEST_PERSONAL_ACCESS_TOKEN_NAME, expiresAt, scopes);
436+
437+
assertNotNull(token);
438+
assertNotNull(token.getId());
439+
assertEquals(TEST_PERSONAL_ACCESS_TOKEN_NAME, token.getName());
440+
assertEquals(expiresAt.getTime(), token.getExpiresAt().getTime());
441+
assertEquals(scopes.length, token.getScopes().size());
442+
assertThat(token.getScopes(), contains(scopes));
443+
444+
} finally {
445+
if (user != null && token != null) {
446+
// GitLab doesn't have this API method yet - not a big issue since multiple tokens with the same name
447+
// can be created. Note that you won't see a token in the UI unless the expiry date is in the future.
448+
// gitLabApi.getUserApi().revokePersonalAccessToken(user.getId(), token.getId());
449+
}
450+
}
451+
}
452+
421453
@Test
422454
public void testGetSshKeys() throws GitLabApiException {
423455

0 commit comments

Comments
 (0)