mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-28 23:50:05 +00:00
feat: add deploy tokens (#37306)
Deploy keys only work over SSH. A deploy token is their counterpart for HTTPS: a repository scoped credential, used as the password of a Git request, with read or read and write access. It covers Git operations and LFS, and can be regenerated in place. Signed-off-by: silverwind <me@silverwind.io> Co-authored-by: Claude Mythos <noreply@anthropic.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: bircni <bircni@icloud.com> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
asymkey_model "gitea.dev/models/asymkey"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
deploykey_model "gitea.dev/models/deploykey"
|
||||
"gitea.dev/models/perm"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
@@ -66,7 +67,7 @@ func TestCreateReadOnlyDeployKey(t *testing.T) {
|
||||
resp := MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
newDeployKey := DecodeJSON(t, resp, &api.DeployKey{})
|
||||
unittest.AssertExistsAndLoadBean(t, &asymkey_model.DeployKey{
|
||||
unittest.AssertExistsAndLoadBean(t, &deploykey_model.DeployKey{
|
||||
ID: newDeployKey.ID,
|
||||
Name: rawKeyBody.Title,
|
||||
Mode: perm.AccessModeRead,
|
||||
@@ -103,7 +104,7 @@ func TestCreateReadWriteDeployKey(t *testing.T) {
|
||||
resp := MakeRequest(t, req, http.StatusCreated)
|
||||
|
||||
newDeployKey := DecodeJSON(t, resp, &api.DeployKey{})
|
||||
unittest.AssertExistsAndLoadBean(t, &asymkey_model.DeployKey{
|
||||
unittest.AssertExistsAndLoadBean(t, &deploykey_model.DeployKey{
|
||||
ID: newDeployKey.ID,
|
||||
Name: rawKeyBody.Title,
|
||||
Mode: perm.AccessModeWrite,
|
||||
@@ -204,3 +205,31 @@ func TestCreateUserKey(t *testing.T) {
|
||||
fingerprintPublicKeys = DecodeJSON(t, resp, []api.PublicKey{})
|
||||
assert.Empty(t, fingerprintPublicKeys)
|
||||
}
|
||||
|
||||
func TestCreateDeployToken(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: "repo1"})
|
||||
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
|
||||
|
||||
session := loginUser(t, repoOwner.Name)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||
keysURL := fmt.Sprintf("/api/v1/repos/%s/%s/keys", repoOwner.Name, repo.Name)
|
||||
|
||||
req := NewRequestWithJSON(t, "POST", keysURL+"/tokens", api.CreateDeployKeyTokenOption{Title: "ci", ReadOnly: true}).
|
||||
AddTokenAuth(token)
|
||||
created := DecodeJSON(t, MakeRequest(t, req, http.StatusCreated), &api.DeployKey{})
|
||||
assert.NotEmpty(t, created.Token)
|
||||
assert.True(t, created.ReadOnly)
|
||||
|
||||
// a token is listed and deleted like a deploy key, but it is never readable again
|
||||
resp := MakeRequest(t, NewRequest(t, "GET", keysURL).AddTokenAuth(token), http.StatusOK)
|
||||
listed := DecodeJSON(t, resp, []api.DeployKey{})
|
||||
assert.Len(t, listed, 1)
|
||||
assert.NotContains(t, resp.Body.String(), created.Token)
|
||||
assert.Equal(t, created.Fingerprint, listed[0].Fingerprint)
|
||||
assert.Contains(t, created.Fingerprint, "********")
|
||||
|
||||
MakeRequest(t, NewRequest(t, "DELETE", fmt.Sprintf("%s/%d", keysURL, created.ID)).AddTokenAuth(token), http.StatusNoContent)
|
||||
resp = MakeRequest(t, NewRequest(t, "GET", keysURL).AddTokenAuth(token), http.StatusOK)
|
||||
assert.Empty(t, DecodeJSON(t, resp, []api.DeployKey{}))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user