mirror of
https://github.com/go-gitea/gitea
synced 2025-07-23 02:38:35 +00:00
Move some files into models' sub packages (#20262)
* Move some files into models' sub packages * Move functions * merge main branch * Fix check * fix check * Fix some tests * Fix lint * Fix lint * Revert lint changes * Fix error comments * Fix lint Co-authored-by: 6543 <6543@obermui.de>
This commit is contained in:
@@ -2,24 +2,22 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package auth
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
_ "code.gitea.io/gitea/models"
|
||||
_ "code.gitea.io/gitea/models/activities"
|
||||
_ "code.gitea.io/gitea/models/auth"
|
||||
_ "code.gitea.io/gitea/models/perm/access"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
unittest.MainTest(m, &unittest.TestOptions{
|
||||
GiteaRootPath: filepath.Join("..", ".."),
|
||||
FixtureFiles: []string{
|
||||
"login_source.yml",
|
||||
"oauth2_application.yml",
|
||||
"oauth2_authorization_code.yml",
|
||||
"oauth2_grant.yml",
|
||||
"webauthn_credential.yml",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@@ -2,11 +2,12 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package auth
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
@@ -17,23 +18,23 @@ import (
|
||||
|
||||
func TestOAuth2Application_GenerateClientSecret(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app := unittest.AssertExistsAndLoadBean(t, &OAuth2Application{ID: 1})
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
secret, err := app.GenerateClientSecret()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, len(secret) > 0)
|
||||
unittest.AssertExistsAndLoadBean(t, &OAuth2Application{ID: 1, ClientSecret: app.ClientSecret})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1, ClientSecret: app.ClientSecret})
|
||||
}
|
||||
|
||||
func BenchmarkOAuth2Application_GenerateClientSecret(b *testing.B) {
|
||||
assert.NoError(b, unittest.PrepareTestDatabase())
|
||||
app := unittest.AssertExistsAndLoadBean(b, &OAuth2Application{ID: 1})
|
||||
app := unittest.AssertExistsAndLoadBean(b, &auth_model.OAuth2Application{ID: 1})
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, _ = app.GenerateClientSecret()
|
||||
}
|
||||
}
|
||||
|
||||
func TestOAuth2Application_ContainsRedirectURI(t *testing.T) {
|
||||
app := &OAuth2Application{
|
||||
app := &auth_model.OAuth2Application{
|
||||
RedirectURIs: []string{"a", "b", "c"},
|
||||
}
|
||||
assert.True(t, app.ContainsRedirectURI("a"))
|
||||
@@ -44,7 +45,7 @@ func TestOAuth2Application_ContainsRedirectURI(t *testing.T) {
|
||||
|
||||
func TestOAuth2Application_ValidateClientSecret(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app := unittest.AssertExistsAndLoadBean(t, &OAuth2Application{ID: 1})
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
secret, err := app.GenerateClientSecret()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, app.ValidateClientSecret([]byte(secret)))
|
||||
@@ -53,31 +54,31 @@ func TestOAuth2Application_ValidateClientSecret(t *testing.T) {
|
||||
|
||||
func TestGetOAuth2ApplicationByClientID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app, err := GetOAuth2ApplicationByClientID(db.DefaultContext, "da7da3ba-9a13-4167-856f-3899de0b0138")
|
||||
app, err := auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "da7da3ba-9a13-4167-856f-3899de0b0138")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "da7da3ba-9a13-4167-856f-3899de0b0138", app.ClientID)
|
||||
|
||||
app, err = GetOAuth2ApplicationByClientID(db.DefaultContext, "invalid client id")
|
||||
app, err = auth_model.GetOAuth2ApplicationByClientID(db.DefaultContext, "invalid client id")
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, app)
|
||||
}
|
||||
|
||||
func TestCreateOAuth2Application(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app, err := CreateOAuth2Application(db.DefaultContext, CreateOAuth2ApplicationOptions{Name: "newapp", UserID: 1})
|
||||
app, err := auth_model.CreateOAuth2Application(db.DefaultContext, auth_model.CreateOAuth2ApplicationOptions{Name: "newapp", UserID: 1})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "newapp", app.Name)
|
||||
assert.Len(t, app.ClientID, 36)
|
||||
unittest.AssertExistsAndLoadBean(t, &OAuth2Application{Name: "newapp"})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{Name: "newapp"})
|
||||
}
|
||||
|
||||
func TestOAuth2Application_TableName(t *testing.T) {
|
||||
assert.Equal(t, "oauth2_application", new(OAuth2Application).TableName())
|
||||
assert.Equal(t, "oauth2_application", new(auth_model.OAuth2Application).TableName())
|
||||
}
|
||||
|
||||
func TestOAuth2Application_GetGrantByUserID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app := unittest.AssertExistsAndLoadBean(t, &OAuth2Application{ID: 1})
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
grant, err := app.GetGrantByUserID(db.DefaultContext, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), grant.UserID)
|
||||
@@ -89,7 +90,7 @@ func TestOAuth2Application_GetGrantByUserID(t *testing.T) {
|
||||
|
||||
func TestOAuth2Application_CreateGrant(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app := unittest.AssertExistsAndLoadBean(t, &OAuth2Application{ID: 1})
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
grant, err := app.CreateGrant(db.DefaultContext, 2, "")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, grant)
|
||||
@@ -102,26 +103,26 @@ func TestOAuth2Application_CreateGrant(t *testing.T) {
|
||||
|
||||
func TestGetOAuth2GrantByID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
grant, err := GetOAuth2GrantByID(db.DefaultContext, 1)
|
||||
grant, err := auth_model.GetOAuth2GrantByID(db.DefaultContext, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), grant.ID)
|
||||
|
||||
grant, err = GetOAuth2GrantByID(db.DefaultContext, 34923458)
|
||||
grant, err = auth_model.GetOAuth2GrantByID(db.DefaultContext, 34923458)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, grant)
|
||||
}
|
||||
|
||||
func TestOAuth2Grant_IncreaseCounter(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &OAuth2Grant{ID: 1, Counter: 1})
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 1})
|
||||
assert.NoError(t, grant.IncreaseCounter(db.DefaultContext))
|
||||
assert.Equal(t, int64(2), grant.Counter)
|
||||
unittest.AssertExistsAndLoadBean(t, &OAuth2Grant{ID: 1, Counter: 2})
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 2})
|
||||
}
|
||||
|
||||
func TestOAuth2Grant_ScopeContains(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &OAuth2Grant{ID: 1, Scope: "openid profile"})
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Scope: "openid profile"})
|
||||
assert.True(t, grant.ScopeContains("openid"))
|
||||
assert.True(t, grant.ScopeContains("profile"))
|
||||
assert.False(t, grant.ScopeContains("profil"))
|
||||
@@ -130,7 +131,7 @@ func TestOAuth2Grant_ScopeContains(t *testing.T) {
|
||||
|
||||
func TestOAuth2Grant_GenerateNewAuthorizationCode(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &OAuth2Grant{ID: 1})
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1})
|
||||
code, err := grant.GenerateNewAuthorizationCode(db.DefaultContext, "https://example2.com/callback", "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", "S256")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, code)
|
||||
@@ -138,46 +139,46 @@ func TestOAuth2Grant_GenerateNewAuthorizationCode(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOAuth2Grant_TableName(t *testing.T) {
|
||||
assert.Equal(t, "oauth2_grant", new(OAuth2Grant).TableName())
|
||||
assert.Equal(t, "oauth2_grant", new(auth_model.OAuth2Grant).TableName())
|
||||
}
|
||||
|
||||
func TestGetOAuth2GrantsByUserID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
result, err := GetOAuth2GrantsByUserID(db.DefaultContext, 1)
|
||||
result, err := auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, result, 1)
|
||||
assert.Equal(t, int64(1), result[0].ID)
|
||||
assert.Equal(t, result[0].ApplicationID, result[0].Application.ID)
|
||||
|
||||
result, err = GetOAuth2GrantsByUserID(db.DefaultContext, 34134)
|
||||
result, err = auth_model.GetOAuth2GrantsByUserID(db.DefaultContext, 34134)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, result)
|
||||
}
|
||||
|
||||
func TestRevokeOAuth2Grant(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
assert.NoError(t, RevokeOAuth2Grant(db.DefaultContext, 1, 1))
|
||||
unittest.AssertNotExistsBean(t, &OAuth2Grant{ID: 1, UserID: 1})
|
||||
assert.NoError(t, auth_model.RevokeOAuth2Grant(db.DefaultContext, 1, 1))
|
||||
unittest.AssertNotExistsBean(t, &auth_model.OAuth2Grant{ID: 1, UserID: 1})
|
||||
}
|
||||
|
||||
//////////////////// Authorization Code
|
||||
|
||||
func TestGetOAuth2AuthorizationByCode(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
code, err := GetOAuth2AuthorizationByCode(db.DefaultContext, "authcode")
|
||||
code, err := auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "authcode")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, code)
|
||||
assert.Equal(t, "authcode", code.Code)
|
||||
assert.Equal(t, int64(1), code.ID)
|
||||
|
||||
code, err = GetOAuth2AuthorizationByCode(db.DefaultContext, "does not exist")
|
||||
code, err = auth_model.GetOAuth2AuthorizationByCode(db.DefaultContext, "does not exist")
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, code)
|
||||
}
|
||||
|
||||
func TestOAuth2AuthorizationCode_ValidateCodeChallenge(t *testing.T) {
|
||||
// test plain
|
||||
code := &OAuth2AuthorizationCode{
|
||||
code := &auth_model.OAuth2AuthorizationCode{
|
||||
CodeChallengeMethod: "plain",
|
||||
CodeChallenge: "test123",
|
||||
}
|
||||
@@ -185,7 +186,7 @@ func TestOAuth2AuthorizationCode_ValidateCodeChallenge(t *testing.T) {
|
||||
assert.False(t, code.ValidateCodeChallenge("ierwgjoergjio"))
|
||||
|
||||
// test S256
|
||||
code = &OAuth2AuthorizationCode{
|
||||
code = &auth_model.OAuth2AuthorizationCode{
|
||||
CodeChallengeMethod: "S256",
|
||||
CodeChallenge: "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg",
|
||||
}
|
||||
@@ -193,14 +194,14 @@ func TestOAuth2AuthorizationCode_ValidateCodeChallenge(t *testing.T) {
|
||||
assert.False(t, code.ValidateCodeChallenge("wiogjerogorewngoenrgoiuenorg"))
|
||||
|
||||
// test unknown
|
||||
code = &OAuth2AuthorizationCode{
|
||||
code = &auth_model.OAuth2AuthorizationCode{
|
||||
CodeChallengeMethod: "monkey",
|
||||
CodeChallenge: "foiwgjioriogeiogjerger",
|
||||
}
|
||||
assert.False(t, code.ValidateCodeChallenge("foiwgjioriogeiogjerger"))
|
||||
|
||||
// test no code challenge
|
||||
code = &OAuth2AuthorizationCode{
|
||||
code = &auth_model.OAuth2AuthorizationCode{
|
||||
CodeChallengeMethod: "",
|
||||
CodeChallenge: "foierjiogerogerg",
|
||||
}
|
||||
@@ -208,7 +209,7 @@ func TestOAuth2AuthorizationCode_ValidateCodeChallenge(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOAuth2AuthorizationCode_GenerateRedirectURI(t *testing.T) {
|
||||
code := &OAuth2AuthorizationCode{
|
||||
code := &auth_model.OAuth2AuthorizationCode{
|
||||
RedirectURI: "https://example.com/callback",
|
||||
Code: "thecode",
|
||||
}
|
||||
@@ -224,11 +225,11 @@ func TestOAuth2AuthorizationCode_GenerateRedirectURI(t *testing.T) {
|
||||
|
||||
func TestOAuth2AuthorizationCode_Invalidate(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
code := unittest.AssertExistsAndLoadBean(t, &OAuth2AuthorizationCode{Code: "authcode"})
|
||||
code := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"})
|
||||
assert.NoError(t, code.Invalidate(db.DefaultContext))
|
||||
unittest.AssertNotExistsBean(t, &OAuth2AuthorizationCode{Code: "authcode"})
|
||||
unittest.AssertNotExistsBean(t, &auth_model.OAuth2AuthorizationCode{Code: "authcode"})
|
||||
}
|
||||
|
||||
func TestOAuth2AuthorizationCode_TableName(t *testing.T) {
|
||||
assert.Equal(t, "oauth2_authorization_code", new(OAuth2AuthorizationCode).TableName())
|
||||
assert.Equal(t, "oauth2_authorization_code", new(auth_model.OAuth2AuthorizationCode).TableName())
|
||||
}
|
||||
|
@@ -2,12 +2,13 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package auth
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
@@ -37,13 +38,13 @@ func (source *TestSource) ToDB() ([]byte, error) {
|
||||
func TestDumpAuthSource(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
authSourceSchema, err := db.TableInfo(new(Source))
|
||||
authSourceSchema, err := db.TableInfo(new(auth_model.Source))
|
||||
assert.NoError(t, err)
|
||||
|
||||
RegisterTypeConfig(OAuth2, new(TestSource))
|
||||
auth_model.RegisterTypeConfig(auth_model.OAuth2, new(TestSource))
|
||||
|
||||
CreateSource(&Source{
|
||||
Type: OAuth2,
|
||||
auth_model.CreateSource(&auth_model.Source{
|
||||
Type: auth_model.OAuth2,
|
||||
Name: "TestSource",
|
||||
IsActive: false,
|
||||
Cfg: &TestSource{
|
||||
|
230
models/auth/token.go
Normal file
230
models/auth/token.go
Normal file
@@ -0,0 +1,230 @@
|
||||
// Copyright 2014 The Gogs Authors. All rights reserved.
|
||||
// Copyright 2019 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 auth
|
||||
|
||||
import (
|
||||
"crypto/subtle"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
gouuid "github.com/google/uuid"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
// ErrAccessTokenNotExist represents a "AccessTokenNotExist" kind of error.
|
||||
type ErrAccessTokenNotExist struct {
|
||||
Token string
|
||||
}
|
||||
|
||||
// IsErrAccessTokenNotExist checks if an error is a ErrAccessTokenNotExist.
|
||||
func IsErrAccessTokenNotExist(err error) bool {
|
||||
_, ok := err.(ErrAccessTokenNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrAccessTokenNotExist) Error() string {
|
||||
return fmt.Sprintf("access token does not exist [sha: %s]", err.Token)
|
||||
}
|
||||
|
||||
// ErrAccessTokenEmpty represents a "AccessTokenEmpty" kind of error.
|
||||
type ErrAccessTokenEmpty struct{}
|
||||
|
||||
// IsErrAccessTokenEmpty checks if an error is a ErrAccessTokenEmpty.
|
||||
func IsErrAccessTokenEmpty(err error) bool {
|
||||
_, ok := err.(ErrAccessTokenEmpty)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (err ErrAccessTokenEmpty) Error() string {
|
||||
return "access token is empty"
|
||||
}
|
||||
|
||||
var successfulAccessTokenCache *lru.Cache
|
||||
|
||||
// AccessToken represents a personal access token.
|
||||
type AccessToken struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UID int64 `xorm:"INDEX"`
|
||||
Name string
|
||||
Token string `xorm:"-"`
|
||||
TokenHash string `xorm:"UNIQUE"` // sha256 of token
|
||||
TokenSalt string
|
||||
TokenLastEight string `xorm:"token_last_eight"`
|
||||
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (t *AccessToken) AfterLoad() {
|
||||
t.HasUsed = t.UpdatedUnix > t.CreatedUnix
|
||||
t.HasRecentActivity = t.UpdatedUnix.AddDuration(7*24*time.Hour) > timeutil.TimeStampNow()
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(AccessToken), func() error {
|
||||
if setting.SuccessfulTokensCacheSize > 0 {
|
||||
var err error
|
||||
successfulAccessTokenCache, err = lru.New(setting.SuccessfulTokensCacheSize)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to allocate AccessToken cache: %v", err)
|
||||
}
|
||||
} else {
|
||||
successfulAccessTokenCache = nil
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// NewAccessToken creates new access token.
|
||||
func NewAccessToken(t *AccessToken) error {
|
||||
salt, err := util.CryptoRandomString(10)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.TokenSalt = salt
|
||||
t.Token = base.EncodeSha1(gouuid.New().String())
|
||||
t.TokenHash = HashToken(t.Token, t.TokenSalt)
|
||||
t.TokenLastEight = t.Token[len(t.Token)-8:]
|
||||
_, err = db.GetEngine(db.DefaultContext).Insert(t)
|
||||
return err
|
||||
}
|
||||
|
||||
func getAccessTokenIDFromCache(token string) int64 {
|
||||
if successfulAccessTokenCache == nil {
|
||||
return 0
|
||||
}
|
||||
tInterface, ok := successfulAccessTokenCache.Get(token)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
t, ok := tInterface.(int64)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// GetAccessTokenBySHA returns access token by given token value
|
||||
func GetAccessTokenBySHA(token string) (*AccessToken, error) {
|
||||
if token == "" {
|
||||
return nil, ErrAccessTokenEmpty{}
|
||||
}
|
||||
// A token is defined as being SHA1 sum these are 40 hexadecimal bytes long
|
||||
if len(token) != 40 {
|
||||
return nil, ErrAccessTokenNotExist{token}
|
||||
}
|
||||
for _, x := range []byte(token) {
|
||||
if x < '0' || (x > '9' && x < 'a') || x > 'f' {
|
||||
return nil, ErrAccessTokenNotExist{token}
|
||||
}
|
||||
}
|
||||
|
||||
lastEight := token[len(token)-8:]
|
||||
|
||||
if id := getAccessTokenIDFromCache(token); id > 0 {
|
||||
token := &AccessToken{
|
||||
TokenLastEight: lastEight,
|
||||
}
|
||||
// Re-get the token from the db in case it has been deleted in the intervening period
|
||||
has, err := db.GetEngine(db.DefaultContext).ID(id).Get(token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if has {
|
||||
return token, nil
|
||||
}
|
||||
successfulAccessTokenCache.Remove(token)
|
||||
}
|
||||
|
||||
var tokens []AccessToken
|
||||
err := db.GetEngine(db.DefaultContext).Table(&AccessToken{}).Where("token_last_eight = ?", lastEight).Find(&tokens)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if len(tokens) == 0 {
|
||||
return nil, ErrAccessTokenNotExist{token}
|
||||
}
|
||||
|
||||
for _, t := range tokens {
|
||||
tempHash := HashToken(token, t.TokenSalt)
|
||||
if subtle.ConstantTimeCompare([]byte(t.TokenHash), []byte(tempHash)) == 1 {
|
||||
if successfulAccessTokenCache != nil {
|
||||
successfulAccessTokenCache.Add(token, t.ID)
|
||||
}
|
||||
return &t, nil
|
||||
}
|
||||
}
|
||||
return nil, ErrAccessTokenNotExist{token}
|
||||
}
|
||||
|
||||
// AccessTokenByNameExists checks if a token name has been used already by a user.
|
||||
func AccessTokenByNameExists(token *AccessToken) (bool, error) {
|
||||
return db.GetEngine(db.DefaultContext).Table("access_token").Where("name = ?", token.Name).And("uid = ?", token.UID).Exist()
|
||||
}
|
||||
|
||||
// ListAccessTokensOptions contain filter options
|
||||
type ListAccessTokensOptions struct {
|
||||
db.ListOptions
|
||||
Name string
|
||||
UserID int64
|
||||
}
|
||||
|
||||
// ListAccessTokens returns a list of access tokens belongs to given user.
|
||||
func ListAccessTokens(opts ListAccessTokensOptions) ([]*AccessToken, error) {
|
||||
sess := db.GetEngine(db.DefaultContext).Where("uid=?", opts.UserID)
|
||||
|
||||
if len(opts.Name) != 0 {
|
||||
sess = sess.Where("name=?", opts.Name)
|
||||
}
|
||||
|
||||
sess = sess.Desc("created_unix")
|
||||
|
||||
if opts.Page != 0 {
|
||||
sess = db.SetSessionPagination(sess, &opts)
|
||||
|
||||
tokens := make([]*AccessToken, 0, opts.PageSize)
|
||||
return tokens, sess.Find(&tokens)
|
||||
}
|
||||
|
||||
tokens := make([]*AccessToken, 0, 5)
|
||||
return tokens, sess.Find(&tokens)
|
||||
}
|
||||
|
||||
// UpdateAccessToken updates information of access token.
|
||||
func UpdateAccessToken(t *AccessToken) error {
|
||||
_, err := db.GetEngine(db.DefaultContext).ID(t.ID).AllCols().Update(t)
|
||||
return err
|
||||
}
|
||||
|
||||
// CountAccessTokens count access tokens belongs to given user by options
|
||||
func CountAccessTokens(opts ListAccessTokensOptions) (int64, error) {
|
||||
sess := db.GetEngine(db.DefaultContext).Where("uid=?", opts.UserID)
|
||||
if len(opts.Name) != 0 {
|
||||
sess = sess.Where("name=?", opts.Name)
|
||||
}
|
||||
return sess.Count(&AccessToken{})
|
||||
}
|
||||
|
||||
// DeleteAccessTokenByID deletes access token by given ID.
|
||||
func DeleteAccessTokenByID(id, userID int64) error {
|
||||
cnt, err := db.GetEngine(db.DefaultContext).ID(id).Delete(&AccessToken{
|
||||
UID: userID,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
} else if cnt != 1 {
|
||||
return ErrAccessTokenNotExist{}
|
||||
}
|
||||
return nil
|
||||
}
|
132
models/auth/token_test.go
Normal file
132
models/auth/token_test.go
Normal file
@@ -0,0 +1,132 @@
|
||||
// Copyright 2016 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 auth_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewAccessToken(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
token := &auth_model.AccessToken{
|
||||
UID: 3,
|
||||
Name: "Token C",
|
||||
}
|
||||
assert.NoError(t, auth_model.NewAccessToken(token))
|
||||
unittest.AssertExistsAndLoadBean(t, token)
|
||||
|
||||
invalidToken := &auth_model.AccessToken{
|
||||
ID: token.ID, // duplicate
|
||||
UID: 2,
|
||||
Name: "Token F",
|
||||
}
|
||||
assert.Error(t, auth_model.NewAccessToken(invalidToken))
|
||||
}
|
||||
|
||||
func TestAccessTokenByNameExists(t *testing.T) {
|
||||
name := "Token Gitea"
|
||||
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
token := &auth_model.AccessToken{
|
||||
UID: 3,
|
||||
Name: name,
|
||||
}
|
||||
|
||||
// Check to make sure it doesn't exists already
|
||||
exist, err := auth_model.AccessTokenByNameExists(token)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exist)
|
||||
|
||||
// Save it to the database
|
||||
assert.NoError(t, auth_model.NewAccessToken(token))
|
||||
unittest.AssertExistsAndLoadBean(t, token)
|
||||
|
||||
// This token must be found by name in the DB now
|
||||
exist, err = auth_model.AccessTokenByNameExists(token)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exist)
|
||||
|
||||
user4Token := &auth_model.AccessToken{
|
||||
UID: 4,
|
||||
Name: name,
|
||||
}
|
||||
|
||||
// Name matches but different user ID, this shouldn't exists in the
|
||||
// database
|
||||
exist, err = auth_model.AccessTokenByNameExists(user4Token)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exist)
|
||||
}
|
||||
|
||||
func TestGetAccessTokenBySHA(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
token, err := auth_model.GetAccessTokenBySHA("d2c6c1ba3890b309189a8e618c72a162e4efbf36")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), token.UID)
|
||||
assert.Equal(t, "Token A", token.Name)
|
||||
assert.Equal(t, "2b3668e11cb82d3af8c6e4524fc7841297668f5008d1626f0ad3417e9fa39af84c268248b78c481daa7e5dc437784003494f", token.TokenHash)
|
||||
assert.Equal(t, "e4efbf36", token.TokenLastEight)
|
||||
|
||||
_, err = auth_model.GetAccessTokenBySHA("notahash")
|
||||
assert.Error(t, err)
|
||||
assert.True(t, auth_model.IsErrAccessTokenNotExist(err))
|
||||
|
||||
_, err = auth_model.GetAccessTokenBySHA("")
|
||||
assert.Error(t, err)
|
||||
assert.True(t, auth_model.IsErrAccessTokenEmpty(err))
|
||||
}
|
||||
|
||||
func TestListAccessTokens(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
tokens, err := auth_model.ListAccessTokens(auth_model.ListAccessTokensOptions{UserID: 1})
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, tokens, 2) {
|
||||
assert.Equal(t, int64(1), tokens[0].UID)
|
||||
assert.Equal(t, int64(1), tokens[1].UID)
|
||||
assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token A")
|
||||
assert.Contains(t, []string{tokens[0].Name, tokens[1].Name}, "Token B")
|
||||
}
|
||||
|
||||
tokens, err = auth_model.ListAccessTokens(auth_model.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 = auth_model.ListAccessTokens(auth_model.ListAccessTokensOptions{UserID: 100})
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, tokens)
|
||||
}
|
||||
|
||||
func TestUpdateAccessToken(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
token, err := auth_model.GetAccessTokenBySHA("4c6f36e6cf498e2a448662f915d932c09c5a146c")
|
||||
assert.NoError(t, err)
|
||||
token.Name = "Token Z"
|
||||
|
||||
assert.NoError(t, auth_model.UpdateAccessToken(token))
|
||||
unittest.AssertExistsAndLoadBean(t, token)
|
||||
}
|
||||
|
||||
func TestDeleteAccessTokenByID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
token, err := auth_model.GetAccessTokenBySHA("4c6f36e6cf498e2a448662f915d932c09c5a146c")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), token.UID)
|
||||
|
||||
assert.NoError(t, auth_model.DeleteAccessTokenByID(token.ID, 1))
|
||||
unittest.AssertNotExistsBean(t, token)
|
||||
|
||||
err = auth_model.DeleteAccessTokenByID(100, 100)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, auth_model.IsErrAccessTokenNotExist(err))
|
||||
}
|
@@ -2,11 +2,12 @@
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package auth
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
"github.com/duo-labs/webauthn/webauthn"
|
||||
@@ -16,51 +17,51 @@ import (
|
||||
func TestGetWebAuthnCredentialByID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
res, err := GetWebAuthnCredentialByID(1)
|
||||
res, err := auth_model.GetWebAuthnCredentialByID(1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "WebAuthn credential", res.Name)
|
||||
|
||||
_, err = GetWebAuthnCredentialByID(342432)
|
||||
_, err = auth_model.GetWebAuthnCredentialByID(342432)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrWebAuthnCredentialNotExist(err))
|
||||
assert.True(t, auth_model.IsErrWebAuthnCredentialNotExist(err))
|
||||
}
|
||||
|
||||
func TestGetWebAuthnCredentialsByUID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
res, err := GetWebAuthnCredentialsByUID(32)
|
||||
res, err := auth_model.GetWebAuthnCredentialsByUID(32)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, res, 1)
|
||||
assert.Equal(t, "WebAuthn credential", res[0].Name)
|
||||
}
|
||||
|
||||
func TestWebAuthnCredential_TableName(t *testing.T) {
|
||||
assert.Equal(t, "webauthn_credential", WebAuthnCredential{}.TableName())
|
||||
assert.Equal(t, "webauthn_credential", auth_model.WebAuthnCredential{}.TableName())
|
||||
}
|
||||
|
||||
func TestWebAuthnCredential_UpdateSignCount(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
cred := unittest.AssertExistsAndLoadBean(t, &WebAuthnCredential{ID: 1})
|
||||
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1})
|
||||
cred.SignCount = 1
|
||||
assert.NoError(t, cred.UpdateSignCount())
|
||||
unittest.AssertExistsIf(t, true, &WebAuthnCredential{ID: 1, SignCount: 1})
|
||||
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{ID: 1, SignCount: 1})
|
||||
}
|
||||
|
||||
func TestWebAuthnCredential_UpdateLargeCounter(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
cred := unittest.AssertExistsAndLoadBean(t, &WebAuthnCredential{ID: 1})
|
||||
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1})
|
||||
cred.SignCount = 0xffffffff
|
||||
assert.NoError(t, cred.UpdateSignCount())
|
||||
unittest.AssertExistsIf(t, true, &WebAuthnCredential{ID: 1, SignCount: 0xffffffff})
|
||||
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{ID: 1, SignCount: 0xffffffff})
|
||||
}
|
||||
|
||||
func TestCreateCredential(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
res, err := CreateCredential(1, "WebAuthn Created Credential", &webauthn.Credential{ID: []byte("Test")})
|
||||
res, err := auth_model.CreateCredential(1, "WebAuthn Created Credential", &webauthn.Credential{ID: []byte("Test")})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "WebAuthn Created Credential", res.Name)
|
||||
assert.Equal(t, []byte("Test"), res.CredentialID)
|
||||
|
||||
unittest.AssertExistsIf(t, true, &WebAuthnCredential{Name: "WebAuthn Created Credential", UserID: 1})
|
||||
unittest.AssertExistsIf(t, true, &auth_model.WebAuthnCredential{Name: "WebAuthn Created Credential", UserID: 1})
|
||||
}
|
||||
|
Reference in New Issue
Block a user