mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-22 21:49:22 +00:00
Fix incorrect /tokens
api (#32085)
Fixes #32078 - Add missing scopes output. - Disallow empty scope. --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> (cherry picked from commit 08adbc468f8875fd4763c3656b334203c11adc0a)
This commit is contained in:
parent
6275d1bc50
commit
526054332a
|
@ -118,6 +118,10 @@ func CreateAccessToken(ctx *context.APIContext) {
|
||||||
ctx.Error(http.StatusBadRequest, "AccessTokenScope.Normalize", fmt.Errorf("invalid access token scope provided: %w", err))
|
ctx.Error(http.StatusBadRequest, "AccessTokenScope.Normalize", fmt.Errorf("invalid access token scope provided: %w", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if scope == "" {
|
||||||
|
ctx.Error(http.StatusBadRequest, "AccessTokenScope", "access token must have a scope")
|
||||||
|
return
|
||||||
|
}
|
||||||
t.Scope = scope
|
t.Scope = scope
|
||||||
|
|
||||||
if err := auth_model.NewAccessToken(ctx, t); err != nil {
|
if err := auth_model.NewAccessToken(ctx, t); err != nil {
|
||||||
|
@ -129,6 +133,7 @@ func CreateAccessToken(ctx *context.APIContext) {
|
||||||
Token: t.Token,
|
Token: t.Token,
|
||||||
ID: t.ID,
|
ID: t.ID,
|
||||||
TokenLastEight: t.TokenLastEight,
|
TokenLastEight: t.TokenLastEight,
|
||||||
|
Scopes: t.Scope.StringSlice(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,10 @@ func TestAPICreateAndDeleteToken(t *testing.T) {
|
||||||
defer tests.PrepareTestEnv(t)()
|
defer tests.PrepareTestEnv(t)()
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
|
|
||||||
newAccessToken := createAPIAccessTokenWithoutCleanUp(t, "test-key-1", user, nil)
|
newAccessToken := createAPIAccessTokenWithoutCleanUp(t, "test-key-1", user, []auth_model.AccessTokenScope{auth_model.AccessTokenScopeAll})
|
||||||
deleteAPIAccessToken(t, newAccessToken, user)
|
deleteAPIAccessToken(t, newAccessToken, user)
|
||||||
|
|
||||||
newAccessToken = createAPIAccessTokenWithoutCleanUp(t, "test-key-2", user, nil)
|
newAccessToken = createAPIAccessTokenWithoutCleanUp(t, "test-key-2", user, []auth_model.AccessTokenScope{auth_model.AccessTokenScopeAll})
|
||||||
deleteAPIAccessToken(t, newAccessToken, user)
|
deleteAPIAccessToken(t, newAccessToken, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,19 +72,19 @@ func TestAPIDeleteTokensPermission(t *testing.T) {
|
||||||
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||||
|
|
||||||
// admin can delete tokens for other users
|
// admin can delete tokens for other users
|
||||||
createAPIAccessTokenWithoutCleanUp(t, "test-key-1", user2, nil)
|
createAPIAccessTokenWithoutCleanUp(t, "test-key-1", user2, []auth_model.AccessTokenScope{auth_model.AccessTokenScopeAll})
|
||||||
req := NewRequest(t, "DELETE", "/api/v1/users/"+user2.LoginName+"/tokens/test-key-1").
|
req := NewRequest(t, "DELETE", "/api/v1/users/"+user2.LoginName+"/tokens/test-key-1").
|
||||||
AddBasicAuth(admin.Name)
|
AddBasicAuth(admin.Name)
|
||||||
MakeRequest(t, req, http.StatusNoContent)
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
||||||
// non-admin can delete tokens for himself
|
// non-admin can delete tokens for himself
|
||||||
createAPIAccessTokenWithoutCleanUp(t, "test-key-2", user2, nil)
|
createAPIAccessTokenWithoutCleanUp(t, "test-key-2", user2, []auth_model.AccessTokenScope{auth_model.AccessTokenScopeAll})
|
||||||
req = NewRequest(t, "DELETE", "/api/v1/users/"+user2.LoginName+"/tokens/test-key-2").
|
req = NewRequest(t, "DELETE", "/api/v1/users/"+user2.LoginName+"/tokens/test-key-2").
|
||||||
AddBasicAuth(user2.Name)
|
AddBasicAuth(user2.Name)
|
||||||
MakeRequest(t, req, http.StatusNoContent)
|
MakeRequest(t, req, http.StatusNoContent)
|
||||||
|
|
||||||
// non-admin can't delete tokens for other users
|
// non-admin can't delete tokens for other users
|
||||||
createAPIAccessTokenWithoutCleanUp(t, "test-key-3", user2, nil)
|
createAPIAccessTokenWithoutCleanUp(t, "test-key-3", user2, []auth_model.AccessTokenScope{auth_model.AccessTokenScopeAll})
|
||||||
req = NewRequest(t, "DELETE", "/api/v1/users/"+user2.LoginName+"/tokens/test-key-3").
|
req = NewRequest(t, "DELETE", "/api/v1/users/"+user2.LoginName+"/tokens/test-key-3").
|
||||||
AddBasicAuth(user4.Name)
|
AddBasicAuth(user4.Name)
|
||||||
MakeRequest(t, req, http.StatusForbidden)
|
MakeRequest(t, req, http.StatusForbidden)
|
||||||
|
@ -520,7 +520,7 @@ func runTestCase(t *testing.T, testCase *requiredScopeTestCase, user *user_model
|
||||||
unauthorizedScopes = append(unauthorizedScopes, cateogoryUnauthorizedScopes...)
|
unauthorizedScopes = append(unauthorizedScopes, cateogoryUnauthorizedScopes...)
|
||||||
}
|
}
|
||||||
|
|
||||||
accessToken := createAPIAccessTokenWithoutCleanUp(t, "test-token", user, &unauthorizedScopes)
|
accessToken := createAPIAccessTokenWithoutCleanUp(t, "test-token", user, unauthorizedScopes)
|
||||||
defer deleteAPIAccessToken(t, accessToken, user)
|
defer deleteAPIAccessToken(t, accessToken, user)
|
||||||
|
|
||||||
// Request the endpoint. Verify that permission is denied.
|
// Request the endpoint. Verify that permission is denied.
|
||||||
|
@ -532,20 +532,12 @@ func runTestCase(t *testing.T, testCase *requiredScopeTestCase, user *user_model
|
||||||
|
|
||||||
// createAPIAccessTokenWithoutCleanUp Create an API access token and assert that
|
// createAPIAccessTokenWithoutCleanUp Create an API access token and assert that
|
||||||
// creation succeeded. The caller is responsible for deleting the token.
|
// creation succeeded. The caller is responsible for deleting the token.
|
||||||
func createAPIAccessTokenWithoutCleanUp(t *testing.T, tokenName string, user *user_model.User, scopes *[]auth_model.AccessTokenScope) api.AccessToken {
|
func createAPIAccessTokenWithoutCleanUp(t *testing.T, tokenName string, user *user_model.User, scopes []auth_model.AccessTokenScope) api.AccessToken {
|
||||||
payload := map[string]any{
|
payload := map[string]any{
|
||||||
"name": tokenName,
|
"name": tokenName,
|
||||||
|
"scopes": scopes,
|
||||||
}
|
}
|
||||||
if scopes != nil {
|
|
||||||
for _, scope := range *scopes {
|
|
||||||
scopes, scopesExists := payload["scopes"].([]string)
|
|
||||||
if !scopesExists {
|
|
||||||
scopes = make([]string, 0)
|
|
||||||
}
|
|
||||||
scopes = append(scopes, string(scope))
|
|
||||||
payload["scopes"] = scopes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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/"+user.LoginName+"/tokens", payload).
|
req := NewRequestWithJSON(t, "POST", "/api/v1/users/"+user.LoginName+"/tokens", payload).
|
||||||
AddBasicAuth(user.Name)
|
AddBasicAuth(user.Name)
|
||||||
|
@ -563,8 +555,7 @@ func createAPIAccessTokenWithoutCleanUp(t *testing.T, tokenName string, user *us
|
||||||
return newAccessToken
|
return newAccessToken
|
||||||
}
|
}
|
||||||
|
|
||||||
// createAPIAccessTokenWithoutCleanUp Delete an API access token and assert that
|
// deleteAPIAccessToken deletes 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/"+user.LoginName+"/tokens/%d", accessToken.ID).
|
req := NewRequestf(t, "DELETE", "/api/v1/users/"+user.LoginName+"/tokens/%d", accessToken.ID).
|
||||||
AddBasicAuth(user.Name)
|
AddBasicAuth(user.Name)
|
||||||
|
|
Loading…
Reference in a new issue