parent
							
								
									1675fc4301
								
							
						
					
					
						commit
						ab55ca7ebd
					
				
					 7 changed files with 138 additions and 1 deletions
				
			
		
							
								
								
									
										2
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							|  | @ -11,7 +11,7 @@ | ||||||
|   branch = "master" |   branch = "master" | ||||||
|   name = "code.gitea.io/sdk" |   name = "code.gitea.io/sdk" | ||||||
|   packages = ["gitea"] |   packages = ["gitea"] | ||||||
|   revision = "b2308e3f700875a3642a78bd3f6e5db8ef6f974d" |   revision = "ec80752c9512cf07fc62ddc42565118183743942" | ||||||
| 
 | 
 | ||||||
| [[projects]] | [[projects]] | ||||||
|   name = "github.com/PuerkitoBio/goquery" |   name = "github.com/PuerkitoBio/goquery" | ||||||
|  |  | ||||||
							
								
								
									
										50
									
								
								integrations/api_token_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								integrations/api_token_test.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -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 | 	return request | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func AddBasicAuthHeader(request *http.Request, username string) *http.Request { | ||||||
|  | 	request.SetBasicAuth(username, userPassword) | ||||||
|  | 	return request | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const NoExpectedStatus = -1 | const NoExpectedStatus = -1 | ||||||
| 
 | 
 | ||||||
| func MakeRequest(t testing.TB, req *http.Request, expectedStatus int) *httptest.ResponseRecorder { | func MakeRequest(t testing.TB, req *http.Request, expectedStatus int) *httptest.ResponseRecorder { | ||||||
|  |  | ||||||
							
								
								
									
										37
									
								
								public/swagger.v1.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										37
									
								
								public/swagger.v1.json
									
									
									
									
										vendored
									
									
								
							|  | @ -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": { |     "/version": { | ||||||
|       "get": { |       "get": { | ||||||
|         "produces": [ |         "produces": [ | ||||||
|  | @ -7479,6 +7512,10 @@ | ||||||
|     "AccessToken": { |     "AccessToken": { | ||||||
|       "description": "AccessToken represents a API access token.", |       "description": "AccessToken represents a API access token.", | ||||||
|       "headers": { |       "headers": { | ||||||
|  |         "id": { | ||||||
|  |           "type": "integer", | ||||||
|  |           "format": "int64" | ||||||
|  |         }, | ||||||
|         "name": { |         "name": { | ||||||
|           "type": "string" |           "type": "string" | ||||||
|         }, |         }, | ||||||
|  |  | ||||||
|  | @ -302,6 +302,7 @@ func RegisterRoutes(m *macaron.Macaron) { | ||||||
| 				m.Group("/tokens", func() { | 				m.Group("/tokens", func() { | ||||||
| 					m.Combo("").Get(user.ListAccessTokens). | 					m.Combo("").Get(user.ListAccessTokens). | ||||||
| 						Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken) | 						Post(bind(api.CreateAccessTokenOption{}), user.CreateAccessToken) | ||||||
|  | 					m.Combo("/:id").Delete(user.DeleteAccessToken) | ||||||
| 				}, reqBasicAuth()) | 				}, reqBasicAuth()) | ||||||
| 			}) | 			}) | ||||||
| 		}) | 		}) | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // 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
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -36,6 +37,7 @@ func ListAccessTokens(ctx *context.APIContext) { | ||||||
| 	apiTokens := make([]*api.AccessToken, len(tokens)) | 	apiTokens := make([]*api.AccessToken, len(tokens)) | ||||||
| 	for i := range tokens { | 	for i := range tokens { | ||||||
| 		apiTokens[i] = &api.AccessToken{ | 		apiTokens[i] = &api.AccessToken{ | ||||||
|  | 			ID:   tokens[i].ID, | ||||||
| 			Name: tokens[i].Name, | 			Name: tokens[i].Name, | ||||||
| 			Sha1: tokens[i].Sha1, | 			Sha1: tokens[i].Sha1, | ||||||
| 		} | 		} | ||||||
|  | @ -72,5 +74,40 @@ func CreateAccessToken(ctx *context.APIContext, form api.CreateAccessTokenOption | ||||||
| 	ctx.JSON(201, &api.AccessToken{ | 	ctx.JSON(201, &api.AccessToken{ | ||||||
| 		Name: t.Name, | 		Name: t.Name, | ||||||
| 		Sha1: t.Sha1, | 		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) | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										7
									
								
								vendor/code.gitea.io/sdk/gitea/user_app.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/code.gitea.io/sdk/gitea/user_app.go
									
									
									
										generated
									
									
										vendored
									
									
								
							|  | @ -20,6 +20,7 @@ func BasicAuthEncode(user, pass string) string { | ||||||
| // AccessToken represents a API access token.
 | // AccessToken represents a API access token.
 | ||||||
| // swagger:response AccessToken
 | // swagger:response AccessToken
 | ||||||
| type AccessToken struct { | type AccessToken struct { | ||||||
|  | 	ID   int64  `json:"id"` | ||||||
| 	Name string `json:"name"` | 	Name string `json:"name"` | ||||||
| 	Sha1 string `json:"sha1"` | 	Sha1 string `json:"sha1"` | ||||||
| } | } | ||||||
|  | @ -54,3 +55,9 @@ func (c *Client) CreateAccessToken(user, pass string, opt CreateAccessTokenOptio | ||||||
| 			"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, | 			"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, | ||||||
| 		bytes.NewReader(body), t) | 		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 | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue