Fix permissions for Token DELETE endpoint to match GET and POST (#27610) (#28099)

Backport #27610 by @evantobin

Fixes #27598

In #27080, the logic for the tokens endpoints were updated to allow
admins to create and view tokens in other accounts. However, the same
functionality was not added to the DELETE endpoint. This PR makes the
DELETE endpoint function the same as the other token endpoints and adds
unit tests

Co-authored-by: Evan Tobin <me@evantob.in>
This commit is contained in:
Giteabot 2023-11-17 12:24:16 +08:00 committed by GitHub
parent 9f63d27ec4
commit 93ede4bc83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 3 deletions

View file

@ -193,7 +193,7 @@ func DeleteAccessToken(ctx *context.APIContext) {
return return
} }
if err := auth_model.DeleteAccessTokenByID(ctx, tokenID, ctx.Doer.ID); err != nil { if err := auth_model.DeleteAccessTokenByID(ctx, tokenID, ctx.ContextUser.ID); err != nil {
if auth_model.IsErrAccessTokenNotExist(err) { if auth_model.IsErrAccessTokenNotExist(err) {
ctx.NotFound() ctx.NotFound()
} else { } else {

View file

@ -63,6 +63,33 @@ func TestAPIGetTokensPermission(t *testing.T) {
MakeRequest(t, req, http.StatusForbidden) MakeRequest(t, req, http.StatusForbidden)
} }
// TestAPIDeleteTokensPermission ensures that only the admin can delete tokens from other users
func TestAPIDeleteTokensPermission(t *testing.T) {
defer tests.PrepareTestEnv(t)()
admin := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
// admin can delete tokens for other users
createAPIAccessTokenWithoutCleanUp(t, "test-key-1", user2, nil)
req := NewRequestf(t, "DELETE", "/api/v1/users/"+user2.LoginName+"/tokens/test-key-1")
req = AddBasicAuthHeader(req, admin.Name)
MakeRequest(t, req, http.StatusNoContent)
// non-admin can delete tokens for himself
createAPIAccessTokenWithoutCleanUp(t, "test-key-2", user2, nil)
req = NewRequestf(t, "DELETE", "/api/v1/users/"+user2.LoginName+"/tokens/test-key-2")
req = AddBasicAuthHeader(req, user2.Name)
MakeRequest(t, req, http.StatusNoContent)
// non-admin can't delete tokens for other users
createAPIAccessTokenWithoutCleanUp(t, "test-key-3", user2, nil)
req = NewRequestf(t, "DELETE", "/api/v1/users/"+user2.LoginName+"/tokens/test-key-3")
req = AddBasicAuthHeader(req, user4.Name)
MakeRequest(t, req, http.StatusForbidden)
}
type permission struct { type permission struct {
category auth_model.AccessTokenScopeCategory category auth_model.AccessTokenScopeCategory
level auth_model.AccessTokenScopeLevel level auth_model.AccessTokenScopeLevel
@ -526,7 +553,7 @@ func createAPIAccessTokenWithoutCleanUp(t *testing.T, tokenName string, user *us
} }
} }
log.Debug("Requesting creation of token with scopes: %v", scopes) log.Debug("Requesting creation of token with scopes: %v", scopes)
req := NewRequestWithJSON(t, "POST", "/api/v1/users/user1/tokens", payload) req := NewRequestWithJSON(t, "POST", "/api/v1/users/"+user.LoginName+"/tokens", payload)
req = AddBasicAuthHeader(req, user.Name) req = AddBasicAuthHeader(req, user.Name)
resp := MakeRequest(t, req, http.StatusCreated) resp := MakeRequest(t, req, http.StatusCreated)
@ -546,7 +573,7 @@ func createAPIAccessTokenWithoutCleanUp(t *testing.T, tokenName string, user *us
// createAPIAccessTokenWithoutCleanUp Delete an API access token and assert that // createAPIAccessTokenWithoutCleanUp Delete an API access token and assert that
// deletion succeeded. // deletion succeeded.
func deleteAPIAccessToken(t *testing.T, accessToken api.AccessToken, user *user_model.User) { func deleteAPIAccessToken(t *testing.T, accessToken api.AccessToken, user *user_model.User) {
req := NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", accessToken.ID) req := NewRequestf(t, "DELETE", "/api/v1/users/"+user.LoginName+"/tokens/%d", accessToken.ID)
req = AddBasicAuthHeader(req, user.Name) req = AddBasicAuthHeader(req, user.Name)
MakeRequest(t, req, http.StatusNoContent) MakeRequest(t, req, http.StatusNoContent)