summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gopkg.lock2
-rw-r--r--integrations/api_token_test.go50
-rw-r--r--integrations/integration_test.go5
-rw-r--r--public/swagger.v1.json37
-rw-r--r--routers/api/v1/api.go1
-rw-r--r--routers/api/v1/user/app.go37
-rw-r--r--vendor/code.gitea.io/sdk/gitea/user_app.go7
7 files changed, 138 insertions, 1 deletions
diff --git a/Gopkg.lock b/Gopkg.lock
index d9bf210a17..df8203267f 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -11,7 +11,7 @@
branch = "master"
name = "code.gitea.io/sdk"
packages = ["gitea"]
- revision = "b2308e3f700875a3642a78bd3f6e5db8ef6f974d"
+ revision = "ec80752c9512cf07fc62ddc42565118183743942"
[[projects]]
name = "github.com/PuerkitoBio/goquery"
diff --git a/integrations/api_token_test.go b/integrations/api_token_test.go
new file mode 100644
index 0000000000..2520f356b7
--- /dev/null
+++ b/integrations/api_token_test.go
@@ -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)
+}
diff --git a/integrations/integration_test.go b/integrations/integration_test.go
index 664290cc9d..a1e66ffdfd 100644
--- a/integrations/integration_test.go
+++ b/integrations/integration_test.go
@@ -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 {
diff --git a/public/swagger.v1.json b/public/swagger.v1.json
index 9fd790281a..c2efd66da0 100644
--- a/public/swagger.v1.json
+++ b/public/swagger.v1.json
@@ -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"
},
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 5007a0d56d..689ea22cca 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -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())
})
})
diff --git a/routers/api/v1/user/app.go b/routers/api/v1/user/app.go
index fc4118649c..216190b0f0 100644
--- a/routers/api/v1/user/app.go
+++ b/routers/api/v1/user/app.go
@@ -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)
+}
diff --git a/vendor/code.gitea.io/sdk/gitea/user_app.go b/vendor/code.gitea.io/sdk/gitea/user_app.go
index 08e98513ee..d3bfce971b 100644
--- a/vendor/code.gitea.io/sdk/gitea/user_app.go
+++ b/vendor/code.gitea.io/sdk/gitea/user_app.go
@@ -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
+}