Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
佳 邓
Gitlab4j Api
Commits
2d9a588f
Unverified
Commit
2d9a588f
authored
Aug 23, 2023
by
Benjamin Schmitz
Committed by
GitHub
Aug 23, 2023
Browse files
Add Project Access Tokens (#1018)
parent
f9baa81b
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/main/java/org/gitlab4j/api/Constants.java
View file @
2d9a588f
...
...
@@ -919,6 +919,28 @@ public interface Constants {
}
}
/** Enum to use for specifying the project token scope. */
public
enum
ProjectAccessTokenScope
{
API
,
READ_API
,
READ_REGISTRY
,
WRITE_REGISTRY
,
READ_REPOSITORY
,
WRITE_REPOSITORY
,
CREATE_RUNNER
;
private
static
JacksonJsonEnumHelper
<
ProjectAccessTokenScope
>
enumHelper
=
new
JacksonJsonEnumHelper
<>(
ProjectAccessTokenScope
.
class
);
@JsonCreator
public
static
ProjectAccessTokenScope
forValue
(
String
value
)
{
return
enumHelper
.
forValue
(
value
);
}
@JsonValue
public
String
toValue
()
{
return
(
enumHelper
.
toString
(
this
));
}
@Override
public
String
toString
()
{
return
(
enumHelper
.
toString
(
this
));
}
}
/** Enum for the build_git_strategy of the project instance. */
enum
SquashOption
{
...
...
src/main/java/org/gitlab4j/api/ProjectApi.java
View file @
2d9a588f
...
...
@@ -51,6 +51,7 @@ import org.gitlab4j.api.models.Issue;
import
org.gitlab4j.api.models.Member
;
import
org.gitlab4j.api.models.Namespace
;
import
org.gitlab4j.api.models.Project
;
import
org.gitlab4j.api.models.ProjectAccessToken
;
import
org.gitlab4j.api.models.ProjectApprovalsConfig
;
import
org.gitlab4j.api.models.ProjectFetches
;
import
org.gitlab4j.api.models.ProjectFilter
;
...
...
@@ -3901,4 +3902,101 @@ public class ProjectApi extends AbstractApi implements Constants {
"projects"
,
getProjectIdOrPath
(
projectIdOrPath
),
"remote_mirrors"
,
mirrorId
);
return
(
response
.
readEntity
(
RemoteMirror
.
class
));
}
/**
* Lists the projects access tokens for the project.
*
* @param projectIdOrPath the project in the form of a Long(ID), String(path), or Project instance
* @return the list of ProjectAccessTokens. The token and lastUsedAt attribute of each object is unset.
* @throws GitLabApiException if any exception occurs
*/
public
List
<
ProjectAccessToken
>
listProjectAccessTokens
(
Object
projectIdOrPath
)
throws
GitLabApiException
{
Response
response
=
get
(
Response
.
Status
.
OK
,
null
,
"projects"
,
getProjectIdOrPath
(
projectIdOrPath
),
"access_tokens"
);
return
(
response
.
readEntity
(
new
GenericType
<
List
<
ProjectAccessToken
>>()
{
}));
}
/**
* Gets the specific project access token.
* Only working with GitLab 14.10 and above.
*
* @param projectIdOrPath the project in the form of a Long(ID), String(path), or Project instance
* @param tokenId the id of the token
* @return the ProjectAccessToken. The token attribute of the object is unset.
* @throws GitLabApiException if any exception occurs
*/
public
ProjectAccessToken
getProjectAccessToken
(
Object
projectIdOrPath
,
Long
tokenId
)
throws
GitLabApiException
{
Response
response
=
get
(
Response
.
Status
.
OK
,
null
,
"projects"
,
getProjectIdOrPath
(
projectIdOrPath
),
"access_tokens"
,
tokenId
);
return
(
response
.
readEntity
(
ProjectAccessToken
.
class
));
}
/**
* Creates a new project access token.
*
* @param projectIdOrPath the project in the form of a Long(ID), String(path), or Project instance
* @param name the name of the token
* @param scopes the scope of the token
* @param expiresAt the date when the token should expire
* @param accessLevel The access level of the token is optional. It can either be 10, 20, 30, 40, or 50.
* @return the newly created ProjectAccessToken. The lastUsedAt attribute of each object is unset.
* @throws GitLabApiException if any exception occurs
*/
public
ProjectAccessToken
createProjectAccessToken
(
Object
projectIdOrPath
,
String
name
,
List
<
Constants
.
ProjectAccessTokenScope
>
scopes
,
Date
expiresAt
,
Long
accessLevel
)
throws
GitLabApiException
{
GitLabApiForm
formData
=
new
GitLabApiForm
()
.
withParam
(
"name"
,
name
,
true
)
.
withParam
(
"expires_at"
,
expiresAt
,
true
)
.
withParam
(
"scopes"
,
scopes
,
true
)
.
withParam
(
"access_level"
,
accessLevel
,
false
);
Response
response
=
post
(
Response
.
Status
.
CREATED
,
formData
,
"projects"
,
getProjectIdOrPath
(
projectIdOrPath
),
"access_tokens"
);
return
(
response
.
readEntity
(
ProjectAccessToken
.
class
));
}
/**
* Creates a new project access token.
* The default value for the accessLevel is used.
*
* @param projectIdOrPath the project in the form of a Long(ID), String(path), or Project instance
* @param name the name of the token
* @param scopes the scope of the token
* @param expiresAt the date when the token should expire
* @return the newly created ProjectAccessToken. The lastUsedAt attribute of each object is unset.
* @throws GitLabApiException if any exception occurs
*/
public
ProjectAccessToken
createProjectAccessToken
(
Object
projectIdOrPath
,
String
name
,
List
<
Constants
.
ProjectAccessTokenScope
>
scopes
,
Date
expiresAt
)
throws
GitLabApiException
{
GitLabApiForm
formData
=
new
GitLabApiForm
()
.
withParam
(
"name"
,
name
,
true
)
.
withParam
(
"expires_at"
,
ISO8601
.
dateOnly
(
expiresAt
),
true
)
.
withParam
(
"scopes"
,
scopes
,
true
)
.
withParam
(
"access_level"
,
(
Object
)
null
,
false
);
Response
response
=
post
(
Response
.
Status
.
CREATED
,
formData
,
"projects"
,
getProjectIdOrPath
(
projectIdOrPath
),
"access_tokens"
);
return
(
response
.
readEntity
(
ProjectAccessToken
.
class
));
}
/**
* Rotates the given project access token.
* The token is revoked and a new one which will expire in one week is created to replace it.
* Only working with GitLab 16.0 and above.
*
* @param projectIdOrPath the project in the form of a Long(ID), String(path), or Project instance
* @param tokenId the id
* @return the newly created ProjectAccessToken.
* @throws GitLabApiException if any exception occurs
*/
public
ProjectAccessToken
rotateProjectAccessToken
(
Object
projectIdOrPath
,
Long
tokenId
)
throws
GitLabApiException
{
Response
response
=
post
(
Response
.
Status
.
OK
,
(
Object
)
null
,
"projects"
,
getProjectIdOrPath
(
projectIdOrPath
),
"access_tokens"
,
tokenId
,
"rotate"
);
return
(
response
.
readEntity
(
ProjectAccessToken
.
class
));
}
/**
* Revokes the project access token.
*
* @param projectIdOrPath the project in the form of a Long(ID), String(path), or Project instance
* @param tokenId the id of the token, which should be revoked
* @throws GitLabApiException if any exception occurs
*/
public
void
revokeProjectAccessToken
(
Object
projectIdOrPath
,
Long
tokenId
)
throws
GitLabApiException
{
delete
(
Response
.
Status
.
NO_CONTENT
,
null
,
"projects"
,
getProjectIdOrPath
(
projectIdOrPath
),
"access_tokens"
,
tokenId
);
}
}
src/main/java/org/gitlab4j/api/models/ProjectAccessToken.java
0 → 100644
View file @
2d9a588f
package
org.gitlab4j.api.models
;
import
com.fasterxml.jackson.annotation.JsonFormat
;
import
com.fasterxml.jackson.annotation.JsonProperty
;
import
org.gitlab4j.api.Constants
;
import
org.gitlab4j.api.utils.JacksonJson
;
import
java.util.Date
;
import
java.util.List
;
public
class
ProjectAccessToken
{
private
Long
userId
;
private
List
<
Constants
.
ProjectAccessTokenScope
>
scopes
;
private
String
name
;
private
Date
expiresAt
;
private
Long
id
;
private
Boolean
active
;
private
Date
createdAt
;
private
Boolean
revoked
;
private
Long
accessLevel
;
private
Date
lastUsedAt
;
private
String
token
;
public
Long
getUserId
()
{
return
userId
;
}
public
void
setUserId
(
Long
userId
)
{
this
.
userId
=
userId
;
}
public
List
<
Constants
.
ProjectAccessTokenScope
>
getScopes
()
{
return
scopes
;
}
public
void
setScopes
(
List
<
Constants
.
ProjectAccessTokenScope
>
scopes
)
{
this
.
scopes
=
scopes
;
}
public
String
getName
()
{
return
name
;
}
public
void
setName
(
String
name
)
{
this
.
name
=
name
;
}
public
Date
getExpiresAt
()
{
return
expiresAt
;
}
public
void
setExpiresAt
(
Date
expiredAt
)
{
this
.
expiresAt
=
expiredAt
;
}
public
Long
getId
()
{
return
id
;
}
public
void
setId
(
Long
id
)
{
this
.
id
=
id
;
}
public
Boolean
isActive
()
{
return
active
;
}
public
void
setActive
(
Boolean
active
)
{
this
.
active
=
active
;
}
public
Date
getCreatedAt
()
{
return
createdAt
;
}
public
void
setCreatedAt
(
Date
createdAt
)
{
this
.
createdAt
=
createdAt
;
}
public
Boolean
isRevoked
()
{
return
revoked
;
}
public
void
setRevoked
(
Boolean
revoked
)
{
this
.
revoked
=
revoked
;
}
public
Long
getAccessLevel
()
{
return
accessLevel
;
}
public
void
setAccessLevel
(
Long
accessLevel
)
{
this
.
accessLevel
=
accessLevel
;
}
public
Date
getLastUsedAt
()
{
return
lastUsedAt
;
}
public
void
setLastUsedAt
(
Date
lastUsedAt
)
{
this
.
lastUsedAt
=
lastUsedAt
;
}
public
String
getToken
()
{
return
token
;
}
public
void
setToken
(
String
token
)
{
this
.
token
=
token
;
}
@Override
public
String
toString
()
{
return
JacksonJson
.
toJsonString
(
this
);
}
}
src/test/java/org/gitlab4j/api/SetupIntegrationTestExtension.java
View file @
2d9a588f
...
...
@@ -168,7 +168,7 @@ public class SetupIntegrationTestExtension implements BeforeAllCallback, Extensi
GitLabApi
gitLabApi
=
GitLabApi
.
oauth2Login
(
TEST_HOST_URL
,
username
,
password
,
null
,
null
,
true
);
// If the tester user doen't exist
s
, create it
// If the tester user doe
s
n't exist, create it
Optional
<
User
>
optionalUser
=
gitLabApi
.
getUserApi
().
getOptionalUser
(
TEST_LOGIN_USERNAME
);
if
(!
optionalUser
.
isPresent
())
{
User
userSettings
=
new
User
()
...
...
@@ -185,7 +185,7 @@ public class SetupIntegrationTestExtension implements BeforeAllCallback, Extensi
// so use OAUTH2 to get the GitLabApi instance
gitLabApi
=
GitLabApi
.
oauth2Login
(
TEST_HOST_URL
,
TEST_LOGIN_USERNAME
,
TEST_LOGIN_PASSWORD
,
null
,
null
,
true
);
// Create the sudo as user if it does not exist
s
// Create the sudo as user if it does not exist
username
=
HelperUtils
.
getProperty
(
SUDO_AS_USERNAME_KEY
,
"user1"
);
optionalUser
=
gitLabApi
.
getUserApi
().
getOptionalUser
(
username
);
if
(!
optionalUser
.
isPresent
())
{
...
...
src/test/java/org/gitlab4j/api/TestGitLabApiBeans.java
View file @
2d9a588f
...
...
@@ -96,6 +96,7 @@ import org.gitlab4j.api.models.PackageFile;
import
org.gitlab4j.api.models.Pipeline
;
import
org.gitlab4j.api.models.PipelineSchedule
;
import
org.gitlab4j.api.models.Project
;
import
org.gitlab4j.api.models.ProjectAccessToken
;
import
org.gitlab4j.api.models.ProjectApprovalsConfig
;
import
org.gitlab4j.api.models.ProjectFetches
;
import
org.gitlab4j.api.models.ProjectGroup
;
...
...
@@ -783,4 +784,10 @@ public class TestGitLabApiBeans {
List
<
SearchBlob
>
searchResults
=
unmarshalResourceList
(
SearchBlob
.
class
,
"wiki-blobs.json"
);
assertTrue
(
compareJson
(
searchResults
,
"wiki-blobs.json"
));
}
@Test
public
void
testProjectAccessToken
()
throws
Exception
{
ProjectAccessToken
token
=
unmarshalResource
(
ProjectAccessToken
.
class
,
"project-access-token.json"
);
assertTrue
(
compareJson
(
token
,
"project-access-token.json"
));
}
}
src/test/java/org/gitlab4j/api/TestProjectApi.java
View file @
2d9a588f
...
...
@@ -25,12 +25,15 @@ package org.gitlab4j.api;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertEquals
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertFalse
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertNotEquals
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertNotNull
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertNull
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertTrue
;
import
static
org
.
junit
.
jupiter
.
api
.
Assumptions
.
assumeTrue
;
import
java.time.Instant
;
import
java.util.Arrays
;
import
java.util.Date
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Optional
;
...
...
@@ -43,11 +46,13 @@ import org.gitlab4j.api.models.AccessRequest;
import
org.gitlab4j.api.models.Group
;
import
org.gitlab4j.api.models.Member
;
import
org.gitlab4j.api.models.Project
;
import
org.gitlab4j.api.models.ProjectAccessToken
;
import
org.gitlab4j.api.models.ProjectFetches
;
import
org.gitlab4j.api.models.ProjectFilter
;
import
org.gitlab4j.api.models.User
;
import
org.gitlab4j.api.models.Variable
;
import
org.gitlab4j.api.models.Visibility
;
import
org.gitlab4j.api.utils.ISO8601
;
import
org.junit.jupiter.api.AfterAll
;
import
org.junit.jupiter.api.BeforeAll
;
import
org.junit.jupiter.api.BeforeEach
;
...
...
@@ -884,4 +889,62 @@ public class TestProjectApi extends AbstractIntegrationTest {
}
}
}
@Test
public
void
testCreateProjectAccessToken
()
throws
GitLabApiException
{
final
String
tokenName
=
"token-"
+
HelperUtils
.
getRandomInt
(
1000
);;
final
List
<
Constants
.
ProjectAccessTokenScope
>
scopes
=
Arrays
.
asList
(
Constants
.
ProjectAccessTokenScope
.
READ_API
,
Constants
.
ProjectAccessTokenScope
.
READ_REPOSITORY
);
final
Date
expiresAt
=
Date
.
from
(
Instant
.
now
().
plusSeconds
(
48
*
60
*
60
));
assertNotNull
(
testProject
);
// This does not work with the GitLab version used for the integration tests
// final int size = gitLabApi.getProjectApi().listProjectAccessTokens(testProject.getId()).size() + 1;
//
// ProjectAccessToken token = gitLabApi.getProjectApi().createProjectAccessToken(testProject.getId(), tokenName, scopes, expiresAt);
//
// assertEquals(size, gitLabApi.getProjectApi().listProjectAccessTokens(testProject.getId()).size());
// assertNotNull(token.getCreatedAt());
// assertEquals(ISO8601.dateOnly(expiresAt), ISO8601.dateOnly(token.getExpiresAt()));
// assertNotNull(token.getId());
// assertEquals(tokenName, token.getName());
// assertFalse(token.isRevoked());
// assertEquals(scopes, token.getScopes());
// assertNotNull(token.getToken());
// assertNotEquals(token.getToken(), "");
// assertNotNull(token.getUserId());
// // unset
// assertNull(token.getLastUsedAt());
//
// gitLabApi.getProjectApi().revokeProjectAccessToken(testProject.getId(), token.getId());
// assertTrue(gitLabApi.getProjectApi().getProjectAccessToken(testProject.getId(), token.getId()).isRevoked());
}
@Test
public
void
testRotateProjectAccessToken
()
throws
GitLabApiException
{
final
String
tokenName
=
"token-"
+
HelperUtils
.
getRandomInt
(
1000
);;
final
List
<
Constants
.
ProjectAccessTokenScope
>
scopes
=
Arrays
.
asList
(
Constants
.
ProjectAccessTokenScope
.
READ_API
,
Constants
.
ProjectAccessTokenScope
.
READ_REPOSITORY
);
final
Date
expiresAt
=
Date
.
from
(
Instant
.
now
().
plusSeconds
(
7
*
24
*
60
*
60
));
assertNotNull
(
testProject
);
// This does not work with the GitLab version used for the integration tests
// ProjectAccessToken rotatedToken = gitLabApi.getProjectApi().createProjectAccessToken(testProject.getId(), tokenName, scopes, expiresAt);
// ProjectAccessToken token = gitLabApi.getProjectApi().rotateProjectAccessToken(testProject.getId(), rotatedToken.getId());
// rotatedToken = gitLabApi.getProjectApi().getProjectAccessToken(testProject.getId(), rotatedToken.getId());
//
// assertNotNull(token.getCreatedAt());
// assertEquals(ISO8601.dateOnly(expiresAt), ISO8601.dateOnly(token.getExpiresAt()));
// assertNotNull(token.getId());
// assertNotEquals(rotatedToken.getId(), token.getId());
// assertEquals(tokenName, token.getName());
// assertFalse(token.isRevoked());
// assertTrue(rotatedToken.isRevoked());
// assertEquals(scopes, token.getScopes());
// assertNotNull(token.getToken());
// assertNotEquals(token.getToken(), "");
// assertNotEquals(rotatedToken.getToken(), token.getToken());
// assertNotNull(token.getUserId());
//
// gitLabApi.getProjectApi().revokeProjectAccessToken(testProject.getId(), token.getId());
// assertTrue(gitLabApi.getProjectApi().getProjectAccessToken(testProject.getId(), token.getId()).isRevoked());
}
}
src/test/resources/org/gitlab4j/api/project-access-token.json
0 → 100644
View file @
2d9a588f
{
"user_id"
:
3
,
"scopes"
:
[
"api"
,
"read_repository"
],
"name"
:
"Project Access Token Name"
,
"expires_at"
:
"2021-01-31T00:00:00Z"
,
"id"
:
10
,
"active"
:
true
,
"created_at"
:
"2021-01-20T22:11:48.151Z"
,
"revoked"
:
false
,
"access_level"
:
40
,
"last_used_at"
:
"2022-03-15T11:05:42.437Z"
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment