forked from gitea/gitea
		
	Reject duplicate AccessToken names (#10994)
* make sure duplicate token names cannot be used * add check to api routes too * add @lunny s suggestion * fix & don't forget User.ID * AccessTokenByNameExists() return error too * unique token for each test * fix lint Signed-off-by: 6543 <6543@obermui.de> Co-authored-by: Lanre Adelowo <yo@lanre.wtf>
This commit is contained in:
		
							parent
							
								
									980ef24251
								
							
						
					
					
						commit
						ad5c43ae5d
					
				| @ -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") | ||||
|  | ||||
| @ -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. | ||||
|  | ||||
| @ -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") | ||||
|  | ||||
| @ -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? | ||||
|  | ||||
| @ -6,6 +6,7 @@ | ||||
| package user | ||||
| 
 | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"code.gitea.io/gitea/models" | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 6543
						6543