Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[API] Delete Token accept names too #12366

Merged
merged 21 commits into from
Aug 28, 2020
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
4fae2f8
Delete Token accept names too
6543 Aug 5, 2020
4445464
Merge branch 'master' into docu_api-delete-token
6543 Aug 6, 2020
7cfbd68
Merge branch 'master' into docu_api-delete-token
6543 Aug 8, 2020
255a02d
Merge branch 'master' into docu_api-delete-token
zeripath Aug 10, 2020
f163554
Merge branch 'master' into docu_api-delete-token
6543 Aug 11, 2020
5f898c2
Merge branch 'master' into docu_api-delete-token
6543 Aug 12, 2020
584c8f1
better description
6543 Aug 13, 2020
eb6c311
Merge branch 'master' into docu_api-delete-token
6543 Aug 13, 2020
0770d26
Merge branch 'master' into docu_api-delete-token
6543 Aug 14, 2020
faef516
Merge branch 'master' into docu_api-delete-token
6543 Aug 14, 2020
d743880
Merge branch 'master' into docu_api-delete-token
6543 Aug 16, 2020
a2e51a3
Merge branch 'master' into docu_api-delete-token
6543 Aug 17, 2020
0acdea9
Merge branch 'master' into docu_api-delete-token
6543 Aug 18, 2020
03eacd4
Merge branch 'master' into docu_api-delete-token
6543 Aug 19, 2020
efdde05
Merge branch 'master' into docu_api-delete-token
6543 Aug 20, 2020
c6f0ace
Merge branch 'master' into docu_api-delete-token
6543 Aug 21, 2020
5ecc566
Merge branch 'master' into docu_api-delete-token
6543 Aug 24, 2020
1c64185
Merge branch 'master' into docu_api-delete-token
6543 Aug 24, 2020
f8a2bc3
Merge branch 'master' into docu_api-delete-token
6543 Aug 25, 2020
5d38b3a
Merge branch 'master' into docu_api-delete-token
6543 Aug 28, 2020
35489e8
Merge branch 'master' into docu_api-delete-token
lafriks Aug 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions integrations/api_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ func TestAPICreateAndDeleteToken(t *testing.T) {
MakeRequest(t, req, http.StatusNoContent)

models.AssertNotExistsBean(t, &models.AccessToken{ID: newAccessToken.ID})

req = NewRequestWithJSON(t, "POST", "/api/v1/users/user1/tokens", map[string]string{
"name": "test-key-2",
})
req = AddBasicAuthHeader(req, user.Name)
resp = MakeRequest(t, req, http.StatusCreated)
DecodeJSON(t, resp, &newAccessToken)

req = NewRequestf(t, "DELETE", "/api/v1/users/user1/tokens/%s", newAccessToken.Name)
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
Expand Down
25 changes: 18 additions & 7 deletions models/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,27 @@ func AccessTokenByNameExists(token *AccessToken) (bool, error) {
return x.Table("access_token").Where("name = ?", token.Name).And("uid = ?", token.UID).Exist()
}

// ListAccessTokensOptions contain filter options
type ListAccessTokensOptions struct {
ListOptions
Name string
UserID int64
}

// ListAccessTokens returns a list of access tokens belongs to given user.
func ListAccessTokens(uid int64, listOptions ListOptions) ([]*AccessToken, error) {
sess := x.
Where("uid=?", uid).
Desc("id")
func ListAccessTokens(opts ListAccessTokensOptions) ([]*AccessToken, error) {
sess := x.Where("uid=?", opts.UserID)

if len(opts.Name) != 0 {
sess = sess.Where("name=?", opts.Name)
}

sess = sess.Desc("id")

if listOptions.Page != 0 {
sess = listOptions.setSessionPagination(sess)
if opts.Page != 0 {
sess = opts.setSessionPagination(sess)

tokens := make([]*AccessToken, 0, listOptions.PageSize)
tokens := make([]*AccessToken, 0, opts.PageSize)
return tokens, sess.Find(&tokens)
}

Expand Down
6 changes: 3 additions & 3 deletions models/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func TestGetAccessTokenBySHA(t *testing.T) {

func TestListAccessTokens(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
tokens, err := ListAccessTokens(1, ListOptions{})
tokens, err := ListAccessTokens(ListAccessTokensOptions{UserID: 1})
assert.NoError(t, err)
if assert.Len(t, tokens, 2) {
assert.Equal(t, int64(1), tokens[0].UID)
Expand All @@ -92,14 +92,14 @@ func TestListAccessTokens(t *testing.T) {
assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token B")
}

tokens, err = ListAccessTokens(2, ListOptions{})
tokens, err = ListAccessTokens(ListAccessTokensOptions{UserID: 2})
assert.NoError(t, err)
if assert.Len(t, tokens, 1) {
assert.Equal(t, int64(2), tokens[0].UID)
assert.Equal(t, "Token A", tokens[0].Name)
}

tokens, err = ListAccessTokens(100, ListOptions{})
tokens, err = ListAccessTokens(ListAccessTokensOptions{UserID: 100})
assert.NoError(t, err)
assert.Empty(t, tokens)
}
Expand Down
41 changes: 36 additions & 5 deletions routers/api/v1/user/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ package user

import (
"errors"
"fmt"
"net/http"
"strconv"

"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
Expand Down Expand Up @@ -41,7 +43,7 @@ func ListAccessTokens(ctx *context.APIContext) {
// "200":
// "$ref": "#/responses/AccessTokenList"

tokens, err := models.ListAccessTokens(ctx.User.ID, utils.GetListOptions(ctx))
tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{UserID: ctx.User.ID, ListOptions: utils.GetListOptions(ctx)})
if err != nil {
ctx.Error(http.StatusInternalServerError, "ListAccessTokens", err)
return
Expand Down Expand Up @@ -128,15 +130,44 @@ func DeleteAccessToken(ctx *context.APIContext) {
// required: true
// - name: token
// in: path
// description: token to be deleted
// type: integer
// format: int64
// description: token to be deleted, identified by ID and if not available by name
// type: string
// required: true
// responses:
// "204":
// "$ref": "#/responses/empty"
// "422":
// "$ref": "#/responses/error"

token := ctx.Params(":id")
tokenID, _ := strconv.ParseInt(token, 0, 64)

if tokenID == 0 {
tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{
Name: token,
UserID: ctx.User.ID,
})
if err != nil {
ctx.Error(http.StatusInternalServerError, "ListAccessTokens", err)
return
}

switch len(tokens) {
case 0:
ctx.NotFound()
return
case 1:
tokenID = tokens[0].ID
default:
ctx.Error(http.StatusUnprocessableEntity, "DeleteAccessTokenByID", fmt.Errorf("multible matches for token name '%s'", token))
return
}
}
if tokenID == 0 {
ctx.Error(http.StatusInternalServerError, "Invalid TokenID", nil)
return
}

tokenID := ctx.ParamsInt64(":id")
if err := models.DeleteAccessTokenByID(tokenID, ctx.User.ID); err != nil {
if models.IsErrAccessTokenNotExist(err) {
ctx.NotFound()
Expand Down
2 changes: 1 addition & 1 deletion routers/user/setting/applications.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func DeleteApplication(ctx *context.Context) {
}

func loadApplicationsData(ctx *context.Context) {
tokens, err := models.ListAccessTokens(ctx.User.ID, models.ListOptions{})
tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{UserID: ctx.User.ID})
if err != nil {
ctx.ServerError("ListAccessTokens", err)
return
Expand Down
2 changes: 1 addition & 1 deletion routers/user/setting/security.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func loadSecurityData(ctx *context.Context) {
ctx.Data["RequireU2F"] = true
}

tokens, err := models.ListAccessTokens(ctx.User.ID, models.ListOptions{})
tokens, err := models.ListAccessTokens(models.ListAccessTokensOptions{UserID: ctx.User.ID})
if err != nil {
ctx.ServerError("ListAccessTokens", err)
return
Expand Down
8 changes: 5 additions & 3 deletions templates/swagger/v1_json.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10635,9 +10635,8 @@
"required": true
},
{
"type": "integer",
"format": "int64",
"description": "token to be deleted",
"type": "string",
"description": "token to be deleted, identified by ID and if not available by name",
"name": "token",
"in": "path",
"required": true
Expand All @@ -10646,6 +10645,9 @@
"responses": {
"204": {
"$ref": "#/responses/empty"
},
"422": {
"$ref": "#/responses/error"
}
}
}
Expand Down