mirror of https://github.com/gogs/gogs.git
token: disallow multiple tokens with same name (#5820)
* api/v1: don't allow multiple tokens with same name Fail with 422 Unprocessable Entity if the token name already exist ref: https://github.com/gogs/gogs/issues/5587 * Move new token error type to models/errors/token * Remove "useless" ListAccessTokensByName function * Add an i18n entry for token_name_existspull/5827/head
parent
1c82c42cb3
commit
ffbb0f6a60
|
@ -374,6 +374,7 @@ delete_token = Delete
|
||||||
access_token_deletion = Personal Access Token Deletion
|
access_token_deletion = Personal Access Token Deletion
|
||||||
access_token_deletion_desc = Delete this personal access token will remove all related accesses of application. Do you want to continue?
|
access_token_deletion_desc = Delete this personal access token will remove all related accesses of application. Do you want to continue?
|
||||||
delete_token_success = Personal access token has been removed successfully! Don't forget to update your application as well.
|
delete_token_success = Personal access token has been removed successfully! Don't forget to update your application as well.
|
||||||
|
token_name_exists = Token with same name already exists.
|
||||||
|
|
||||||
orgs.none = You are not a member of any organizations.
|
orgs.none = You are not a member of any organizations.
|
||||||
orgs.leave_title = Leave organization
|
orgs.leave_title = Leave organization
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package errors
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type AccessTokenNameAlreadyExist struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsAccessTokenNameAlreadyExist(err error) bool {
|
||||||
|
_, ok := err.(AccessTokenNameAlreadyExist)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err AccessTokenNameAlreadyExist) Error() string {
|
||||||
|
return fmt.Sprintf("access token already exist [name: %s]", err.Name)
|
||||||
|
}
|
|
@ -5,12 +5,13 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-xorm/xorm"
|
"github.com/go-xorm/xorm"
|
||||||
gouuid "github.com/satori/go.uuid"
|
"github.com/gogs/gogs/models/errors"
|
||||||
|
|
||||||
"github.com/gogs/gogs/pkg/tool"
|
"github.com/gogs/gogs/pkg/tool"
|
||||||
|
gouuid "github.com/satori/go.uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AccessToken represents a personal access token.
|
// AccessToken represents a personal access token.
|
||||||
|
@ -47,10 +48,21 @@ func (t *AccessToken) AfterSet(colName string, _ xorm.Cell) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isAccessTokenNameExist(uid int64, name string) (bool, error) {
|
||||||
|
return x.Where("uid=?", uid).And("name=?", name).Get(&AccessToken{})
|
||||||
|
}
|
||||||
|
|
||||||
// NewAccessToken creates new access token.
|
// NewAccessToken creates new access token.
|
||||||
func NewAccessToken(t *AccessToken) error {
|
func NewAccessToken(t *AccessToken) error {
|
||||||
t.Sha1 = tool.SHA1(gouuid.NewV4().String())
|
t.Sha1 = tool.SHA1(gouuid.NewV4().String())
|
||||||
_, err := x.Insert(t)
|
has, err := isAccessTokenNameExist(t.UID, t.Name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("IsAccessTokenNameExists: %v", err)
|
||||||
|
} else if has {
|
||||||
|
return errors.AccessTokenNameAlreadyExist{t.Name}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = x.Insert(t)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
api "github.com/gogs/go-gogs-client"
|
api "github.com/gogs/go-gogs-client"
|
||||||
|
|
||||||
"github.com/gogs/gogs/models"
|
"github.com/gogs/gogs/models"
|
||||||
|
"github.com/gogs/gogs/models/errors"
|
||||||
"github.com/gogs/gogs/pkg/context"
|
"github.com/gogs/gogs/pkg/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,7 +34,11 @@ func CreateAccessToken(c *context.APIContext, form api.CreateAccessTokenOption)
|
||||||
Name: form.Name,
|
Name: form.Name,
|
||||||
}
|
}
|
||||||
if err := models.NewAccessToken(t); err != nil {
|
if err := models.NewAccessToken(t); err != nil {
|
||||||
c.ServerError("NewAccessToken", err)
|
if errors.IsAccessTokenNameAlreadyExist(err) {
|
||||||
|
c.Error(http.StatusUnprocessableEntity, "", err)
|
||||||
|
} else {
|
||||||
|
c.ServerError("NewAccessToken", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusCreated, &api.AccessToken{t.Name, t.Sha1})
|
c.JSON(http.StatusCreated, &api.AccessToken{t.Name, t.Sha1})
|
||||||
|
|
|
@ -607,7 +607,12 @@ func SettingsApplicationsPost(c *context.Context, f form.NewAccessToken) {
|
||||||
Name: f.Name,
|
Name: f.Name,
|
||||||
}
|
}
|
||||||
if err := models.NewAccessToken(t); err != nil {
|
if err := models.NewAccessToken(t); err != nil {
|
||||||
c.ServerError("NewAccessToken", err)
|
if errors.IsAccessTokenNameAlreadyExist(err) {
|
||||||
|
c.Flash.Error(c.Tr("settings.token_name_exists"))
|
||||||
|
c.SubURLRedirect("/user/settings/applications")
|
||||||
|
} else {
|
||||||
|
c.ServerError("NewAccessToken", err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue