Skip to content

Reject duplicate AccessToken names #10994

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

Merged
merged 17 commits into from
Apr 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion integrations/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,14 +330,18 @@ func loginUserWithPassword(t testing.TB, userName, password string) *TestSession
return session
}

//token has to be unique this counter take care of
var tokenCounter int64

func getTokenForLoggedInUser(t testing.TB, session *TestSession) string {
t.Helper()
tokenCounter++
req := NewRequest(t, "GET", "/user/settings/applications")
resp := session.MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
req = NewRequestWithValues(t, "POST", "/user/settings/applications", map[string]string{
"_csrf": doc.GetCSRF(),
"name": "api-testing-token",
"name": fmt.Sprintf("api-testing-token-%d", tokenCounter),
})
resp = session.MakeRequest(t, req, http.StatusFound)
req = NewRequest(t, "GET", "/user/settings/applications")
Expand Down
5 changes: 5 additions & 0 deletions models/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ func GetAccessTokenBySHA(token string) (*AccessToken, error) {
return nil, ErrAccessTokenNotExist{token}
}

// AccessTokenByNameExists checks if a token name has been used already by a user.
func AccessTokenByNameExists(token *AccessToken) (bool, error) {
return x.Table("access_token").Where("name = ?", token.Name).And("uid = ?", token.UID).Exist()
}

// ListAccessTokens returns a list of access tokens belongs to given user.
func ListAccessTokens(uid int64, listOptions ListOptions) ([]*AccessToken, error) {
sess := x.
Expand Down
36 changes: 36 additions & 0 deletions models/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,42 @@ func TestNewAccessToken(t *testing.T) {
assert.Error(t, NewAccessToken(invalidToken))
}

func TestAccessTokenByNameExists(t *testing.T) {

name := "Token Gitea"

assert.NoError(t, PrepareTestDatabase())
token := &AccessToken{
UID: 3,
Name: name,
}

// Check to make sure it doesn't exists already
exist, err := AccessTokenByNameExists(token)
assert.NoError(t, err)
assert.False(t, exist)

// Save it to the database
assert.NoError(t, NewAccessToken(token))
AssertExistsAndLoadBean(t, token)

// This token must be found by name in the DB now
exist, err = AccessTokenByNameExists(token)
assert.NoError(t, err)
assert.True(t, exist)

user4Token := &AccessToken{
UID: 4,
Name: name,
}

// Name matches but different user ID, this shouldn't exists in the
// database
exist, err = AccessTokenByNameExists(user4Token)
assert.NoError(t, err)
assert.False(t, exist)
}

func TestGetAccessTokenBySHA(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())
token, err := GetAccessTokenBySHA("d2c6c1ba3890b309189a8e618c72a162e4efbf36")
Expand Down
1 change: 1 addition & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ new_token_desc = Applications using a token have full access to your account.
token_name = Token Name
generate_token = Generate Token
generate_token_success = Your new token has been generated. Copy it now as it will not be shown again.
generate_token_name_duplicate = <strong>%s</strong> has been used as an application name already. Please use a new one.
delete_token = Delete
access_token_deletion = Delete Access Token
access_token_deletion_desc = Deleting a token will revoke access to your account for applications using it. Continue?
Expand Down
12 changes: 12 additions & 0 deletions routers/api/v1/user/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package user

import (
"errors"
"net/http"

"code.gitea.io/gitea/models"
Expand Down Expand Up @@ -89,6 +90,17 @@ func CreateAccessToken(ctx *context.APIContext, form api.CreateAccessTokenOption
UID: ctx.User.ID,
Name: form.Name,
}

exist, err := models.AccessTokenByNameExists(t)
if err != nil {
ctx.InternalServerError(err)
return
}
if exist {
ctx.Error(http.StatusBadRequest, "AccessTokenByNameExists", errors.New("access token name has been used already"))
return
}

if err := models.NewAccessToken(t); err != nil {
ctx.Error(http.StatusInternalServerError, "NewAccessToken", err)
return
Expand Down
12 changes: 12 additions & 0 deletions routers/user/setting/applications.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ func ApplicationsPost(ctx *context.Context, form auth.NewAccessTokenForm) {
UID: ctx.User.ID,
Name: form.Name,
}

exist, err := models.AccessTokenByNameExists(t)
if err != nil {
ctx.ServerError("AccessTokenByNameExists", err)
return
}
if exist {
ctx.Flash.Error(ctx.Tr("settings.generate_token_name_duplicate", t.Name))
ctx.Redirect(setting.AppSubURL + "/user/settings/applications")
return
}

if err := models.NewAccessToken(t); err != nil {
ctx.ServerError("NewAccessToken", err)
return
Expand Down