Fix token endpoints ignore specified account (#27080)
Fix #26234 close #26323 close #27040 --------- Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
parent
8531ca0837
commit
f93ee5937b
|
@ -367,6 +367,16 @@ func reqOwner() func(ctx *context.APIContext) {
|
|||
}
|
||||
}
|
||||
|
||||
// reqSelfOrAdmin doer should be the same as the contextUser or site admin
|
||||
func reqSelfOrAdmin() func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
if !ctx.IsUserSiteAdmin() && ctx.ContextUser != ctx.Doer {
|
||||
ctx.Error(http.StatusForbidden, "reqSelfOrAdmin", "doer should be the site admin or be same as the contextUser")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// reqAdmin user should be an owner or a collaborator with admin write of a repository, or site admin
|
||||
func reqAdmin() func(ctx *context.APIContext) {
|
||||
return func(ctx *context.APIContext) {
|
||||
|
@ -910,7 +920,7 @@ func Routes() *web.Route {
|
|||
m.Combo("").Get(user.ListAccessTokens).
|
||||
Post(bind(api.CreateAccessTokenOption{}), reqToken(), user.CreateAccessToken)
|
||||
m.Combo("/{id}").Delete(reqToken(), user.DeleteAccessToken)
|
||||
}, reqBasicOrRevProxyAuth())
|
||||
}, reqSelfOrAdmin(), reqBasicOrRevProxyAuth())
|
||||
|
||||
m.Get("/activities/feeds", user.ListUserActivityFeeds)
|
||||
}, context_service.UserAssignmentAPI())
|
||||
|
|
|
@ -43,8 +43,10 @@ func ListAccessTokens(ctx *context.APIContext) {
|
|||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/AccessTokenList"
|
||||
// "403":
|
||||
// "$ref": "#/responses/forbidden"
|
||||
|
||||
opts := auth_model.ListAccessTokensOptions{UserID: ctx.Doer.ID, ListOptions: utils.GetListOptions(ctx)}
|
||||
opts := auth_model.ListAccessTokensOptions{UserID: ctx.ContextUser.ID, ListOptions: utils.GetListOptions(ctx)}
|
||||
|
||||
count, err := auth_model.CountAccessTokens(ctx, opts)
|
||||
if err != nil {
|
||||
|
@ -95,11 +97,13 @@ func CreateAccessToken(ctx *context.APIContext) {
|
|||
// "$ref": "#/responses/AccessToken"
|
||||
// "400":
|
||||
// "$ref": "#/responses/error"
|
||||
// "403":
|
||||
// "$ref": "#/responses/forbidden"
|
||||
|
||||
form := web.GetForm(ctx).(*api.CreateAccessTokenOption)
|
||||
|
||||
t := &auth_model.AccessToken{
|
||||
UID: ctx.Doer.ID,
|
||||
UID: ctx.ContextUser.ID,
|
||||
Name: form.Name,
|
||||
}
|
||||
|
||||
|
@ -153,6 +157,8 @@ func DeleteAccessToken(ctx *context.APIContext) {
|
|||
// responses:
|
||||
// "204":
|
||||
// "$ref": "#/responses/empty"
|
||||
// "403":
|
||||
// "$ref": "#/responses/forbidden"
|
||||
// "404":
|
||||
// "$ref": "#/responses/notFound"
|
||||
// "422":
|
||||
|
@ -164,7 +170,7 @@ func DeleteAccessToken(ctx *context.APIContext) {
|
|||
if tokenID == 0 {
|
||||
tokens, err := auth_model.ListAccessTokens(ctx, auth_model.ListAccessTokensOptions{
|
||||
Name: token,
|
||||
UserID: ctx.Doer.ID,
|
||||
UserID: ctx.ContextUser.ID,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "ListAccessTokens", err)
|
||||
|
|
9
templates/swagger/v1_json.tmpl
generated
9
templates/swagger/v1_json.tmpl
generated
|
@ -16359,6 +16359,9 @@
|
|||
"responses": {
|
||||
"200": {
|
||||
"$ref": "#/responses/AccessTokenList"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/responses/forbidden"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -16396,6 +16399,9 @@
|
|||
},
|
||||
"400": {
|
||||
"$ref": "#/responses/error"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/responses/forbidden"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16430,6 +16436,9 @@
|
|||
"204": {
|
||||
"$ref": "#/responses/empty"
|
||||
},
|
||||
"403": {
|
||||
"$ref": "#/responses/forbidden"
|
||||
},
|
||||
"404": {
|
||||
"$ref": "#/responses/notFound"
|
||||
},
|
||||
|
|
|
@ -40,6 +40,29 @@ func TestAPIDeleteMissingToken(t *testing.T) {
|
|||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
||||
// TestAPIGetTokensPermission ensures that only the admin can get tokens from other users
|
||||
func TestAPIGetTokensPermission(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
// admin can get tokens for other users
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
req := NewRequestf(t, "GET", "/api/v1/users/user2/tokens")
|
||||
req = AddBasicAuthHeader(req, user.Name)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// non-admin can get tokens for himself
|
||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
req = NewRequestf(t, "GET", "/api/v1/users/user2/tokens")
|
||||
req = AddBasicAuthHeader(req, user.Name)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
// non-admin can't get tokens for other users
|
||||
user = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||
req = NewRequestf(t, "GET", "/api/v1/users/user2/tokens")
|
||||
req = AddBasicAuthHeader(req, user.Name)
|
||||
MakeRequest(t, req, http.StatusForbidden)
|
||||
}
|
||||
|
||||
type permission struct {
|
||||
category auth_model.AccessTokenScopeCategory
|
||||
level auth_model.AccessTokenScopeLevel
|
||||
|
|
Loading…
Reference in a new issue