| @@ -11,7 +11,7 @@ | |||
| branch = "master" | |||
| name = "code.gitea.io/sdk" | |||
| packages = ["gitea"] | |||
| revision = "b2308e3f700875a3642a78bd3f6e5db8ef6f974d" | |||
| revision = "ec80752c9512cf07fc62ddc42565118183743942" | |||
| [[projects]] | |||
| name = "github.com/PuerkitoBio/goquery" | |||
| @@ -0,0 +1,50 @@ | |||
| // Copyright 2018 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package integrations | |||
| import ( | |||
| "net/http" | |||
| "testing" | |||
| "code.gitea.io/gitea/models" | |||
| api "code.gitea.io/sdk/gitea" | |||
| ) | |||
| // TestAPICreateAndDeleteToken tests that token that was just created can be deleted | |||
| func TestAPICreateAndDeleteToken(t *testing.T) { | |||
| prepareTestEnv(t) | |||
| user := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User) | |||
| req := NewRequestWithJSON(t, "POST", "/api/v1/users/user1/tokens", map[string]string{ | |||
| "name": "test-key-1", | |||
| }) | |||
| req = AddBasicAuthHeader(req, user.Name) | |||
| resp := MakeRequest(t, req, http.StatusCreated) | |||
| var newAccessToken api.AccessToken | |||
| DecodeJSON(t, resp, &newAccessToken) | |||
| models.AssertExistsAndLoadBean(t, &models.AccessToken{ | |||
| ID: newAccessToken.ID, | |||
| Name: newAccessToken.Name, | |||
| Sha1: newAccessToken.Sha1, | |||
| UID: user.ID, | |||
| }) | |||
| req = NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", newAccessToken.ID) | |||
| req = AddBasicAuthHeader(req, user.Name) | |||
| MakeRequest(t, req, http.StatusNoContent) | |||
| models.AssertNotExistsBean(t, &models.AccessToken{ID: newAccessToken.ID}) | |||
| } | |||
| // TestAPIDeleteMissingToken ensures that error is thrown when token not found | |||
| func TestAPIDeleteMissingToken(t *testing.T) { | |||
| prepareTestEnv(t) | |||
| user := models.AssertExistsAndLoadBean(t, &models.User{ID: 1}).(*models.User) | |||
| req := NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%d", models.NonexistentID) | |||
| req = AddBasicAuthHeader(req, user.Name) | |||
| MakeRequest(t, req, http.StatusNotFound) | |||
| } | |||
| @@ -256,6 +256,11 @@ func NewRequestWithBody(t testing.TB, method, urlStr string, body io.Reader) *ht | |||
| return request | |||
| } | |||
| func AddBasicAuthHeader(request *http.Request, username string) *http.Request { | |||
| request.SetBasicAuth(username, userPassword) | |||
| return request | |||
| } | |||
| const NoExpectedStatus = -1 | |||
| func MakeRequest(t testing.TB, req *http.Request, expectedStatus int) *httptest.ResponseRecorder { | |||
| @@ -5441,6 +5441,39 @@ | |||
| } | |||
| } | |||
| }, | |||
| "/users/{username}/tokens/{token}": { | |||
| "delete": { | |||
| "produces": [ | |||
| "application/json" | |||
| ], | |||
| "tags": [ | |||
| "user" | |||
| ], | |||
| "summary": "delete an access token", | |||
| "operationId": "userDeleteAccessToken", | |||
| "parameters": [ | |||
| { | |||
| "type": "string", | |||
| "description": "username of user", | |||
| "name": "username", | |||
| "in": "path", | |||
| "required": true | |||
| }, | |||
| { | |||
| "type": "integer", | |||
| "description": "token to be deleted", | |||
| "name": "token", | |||
| "in": "path", | |||
| "required": true | |||
| } | |||
| ], | |||
| "responses": { | |||
| "204": { | |||
| "$ref": "#/responses/empty" | |||
| } | |||
| } | |||
| } | |||
| }, | |||
| "/version": { | |||
| "get": { | |||
| "produces": [ | |||
| @@ -7479,6 +7512,10 @@ | |||
| "AccessToken": { | |||
| "description": "AccessToken represents a API access token.", | |||
| "headers": { | |||
| "id": { | |||
| "type": "integer", | |||
| "format": "int64" | |||
| }, | |||
| "name": { | |||
| "type": "string" | |||
| }, | |||
| @@ -302,6 +302,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
| m.Group("/tokens", func() { | |||
| m.Combo("").Get(user.ListAccessTokens). | |||
| Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken) | |||
| m.Combo("/:id").Delete(user.DeleteAccessToken) | |||
| }, reqBasicAuth()) | |||
| }) | |||
| }) | |||
| @@ -1,4 +1,5 @@ | |||
| // Copyright 2014 The Gogs Authors. All rights reserved. | |||
| // Copyright 2018 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| @@ -36,6 +37,7 @@ func ListAccessTokens(ctx *context.APIContext) { | |||
| apiTokens := make([]*api.AccessToken, len(tokens)) | |||
| for i := range tokens { | |||
| apiTokens[i] = &api.AccessToken{ | |||
| ID: tokens[i].ID, | |||
| Name: tokens[i].Name, | |||
| Sha1: tokens[i].Sha1, | |||
| } | |||
| @@ -72,5 +74,40 @@ func CreateAccessToken(ctx *context.APIContext, form api.CreateAccessTokenOption | |||
| ctx.JSON(201, &api.AccessToken{ | |||
| Name: t.Name, | |||
| Sha1: t.Sha1, | |||
| ID: t.ID, | |||
| }) | |||
| } | |||
| // DeleteAccessToken delete access tokens | |||
| func DeleteAccessToken(ctx *context.APIContext) { | |||
| // swagger:operation DELETE /users/{username}/tokens/{token} user userDeleteAccessToken | |||
| // --- | |||
| // summary: delete an access token | |||
| // produces: | |||
| // - application/json | |||
| // parameters: | |||
| // - name: username | |||
| // in: path | |||
| // description: username of user | |||
| // type: string | |||
| // required: true | |||
| // - name: token | |||
| // in: path | |||
| // description: token to be deleted | |||
| // type: integer | |||
| // required: true | |||
| // responses: | |||
| // "204": | |||
| // "$ref": "#/responses/empty" | |||
| tokenID := ctx.ParamsInt64(":id") | |||
| if err := models.DeleteAccessTokenByID(tokenID, ctx.User.ID); err != nil { | |||
| if models.IsErrAccessTokenNotExist(err) { | |||
| ctx.Status(404) | |||
| } else { | |||
| ctx.Error(500, "DeleteAccessTokenByID", err) | |||
| } | |||
| return | |||
| } | |||
| ctx.Status(204) | |||
| } | |||
| @@ -20,6 +20,7 @@ func BasicAuthEncode(user, pass string) string { | |||
| // AccessToken represents a API access token. | |||
| // swagger:response AccessToken | |||
| type AccessToken struct { | |||
| ID int64 `json:"id"` | |||
| Name string `json:"name"` | |||
| Sha1 string `json:"sha1"` | |||
| } | |||
| @@ -54,3 +55,9 @@ func (c *Client) CreateAccessToken(user, pass string, opt CreateAccessTokenOptio | |||
| "Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, | |||
| bytes.NewReader(body), t) | |||
| } | |||
| // DeleteAccessToken delete token with key id | |||
| func (c *Client) DeleteAccessToken(user string, keyID int64) error { | |||
| _, err := c.getResponse("DELETE", fmt.Sprintf("/user/%s/tokens/%d", user, keyID), nil, nil) | |||
| return err | |||
| } | |||