mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-26 06:16:56 +09:00
test: consolidate Go tests (#39962)
Consolidate all Go tests. Coverage is identical to before. Go tests are around 5% faster while being 7% smaller. No non-test code is touched.
This commit is contained in:
1 parent
ce7364e215
commit
8abda62312
388 files changed
+18410
-29561
No files matched your search
+127
-131
@@ -14,97 +14,148 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewAccessToken(t *testing.T) {
|
||||
func TestAccessTokenLifecycle(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
token := &auth_model.AccessToken{
|
||||
UID: 3,
|
||||
Name: "Token C",
|
||||
}
|
||||
assert.NoError(t, auth_model.NewAccessToken(t.Context(), token))
|
||||
unittest.AssertExistsAndLoadBean(t, token)
|
||||
|
||||
invalidToken := &auth_model.AccessToken{
|
||||
ID: token.ID, // duplicate
|
||||
UID: 2,
|
||||
Name: "Token F",
|
||||
}
|
||||
assert.Error(t, auth_model.NewAccessToken(t.Context(), invalidToken))
|
||||
}
|
||||
t.Run("GetAccessTokenBySHA", func(t *testing.T) {
|
||||
token, err := auth_model.GetAccessTokenBySHA(t.Context(), "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)
|
||||
|
||||
func TestAccessTokenByNameExists(t *testing.T) {
|
||||
name := "Token Gitea"
|
||||
_, err = auth_model.GetAccessTokenBySHA(t.Context(), "notahash")
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
token := &auth_model.AccessToken{
|
||||
UID: 3,
|
||||
Name: name,
|
||||
}
|
||||
_, err = auth_model.GetAccessTokenBySHA(t.Context(), "")
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
})
|
||||
|
||||
// Check to make sure it doesn't exists already
|
||||
exist, err := auth_model.AccessTokenByNameExists(t.Context(), token)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exist)
|
||||
t.Run("ListAccessTokens", func(t *testing.T) {
|
||||
tokens, err := db.Find[auth_model.AccessToken](t.Context(), 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")
|
||||
}
|
||||
|
||||
// Save it to the database
|
||||
assert.NoError(t, auth_model.NewAccessToken(t.Context(), token))
|
||||
unittest.AssertExistsAndLoadBean(t, token)
|
||||
tokens, err = db.Find[auth_model.AccessToken](t.Context(), 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)
|
||||
}
|
||||
|
||||
// This token must be found by name in the DB now
|
||||
exist, err = auth_model.AccessTokenByNameExists(t.Context(), token)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exist)
|
||||
tokens, err = db.Find[auth_model.AccessToken](t.Context(), auth_model.ListAccessTokensOptions{UserID: 100})
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, tokens)
|
||||
})
|
||||
|
||||
user4Token := &auth_model.AccessToken{
|
||||
UID: 4,
|
||||
Name: name,
|
||||
}
|
||||
t.Run("NewAccessToken", func(t *testing.T) {
|
||||
token := &auth_model.AccessToken{
|
||||
UID: 3,
|
||||
Name: "Token C",
|
||||
}
|
||||
assert.NoError(t, auth_model.NewAccessToken(t.Context(), token))
|
||||
unittest.AssertExistsAndLoadBean(t, token)
|
||||
|
||||
// Name matches but different user ID, this shouldn't exists in the
|
||||
// database
|
||||
exist, err = auth_model.AccessTokenByNameExists(t.Context(), user4Token)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exist)
|
||||
}
|
||||
invalidToken := &auth_model.AccessToken{
|
||||
ID: token.ID, // duplicate
|
||||
UID: 2,
|
||||
Name: "Token F",
|
||||
}
|
||||
assert.Error(t, auth_model.NewAccessToken(t.Context(), invalidToken))
|
||||
})
|
||||
|
||||
func TestGetAccessTokenBySHA(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
token, err := auth_model.GetAccessTokenBySHA(t.Context(), "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)
|
||||
t.Run("AccessTokenByNameExists", func(t *testing.T) {
|
||||
name := "Token Gitea"
|
||||
|
||||
_, err = auth_model.GetAccessTokenBySHA(t.Context(), "notahash")
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
token := &auth_model.AccessToken{
|
||||
UID: 3,
|
||||
Name: name,
|
||||
}
|
||||
|
||||
_, err = auth_model.GetAccessTokenBySHA(t.Context(), "")
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
}
|
||||
// Check to make sure it doesn't exists already
|
||||
exist, err := auth_model.AccessTokenByNameExists(t.Context(), token)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exist)
|
||||
|
||||
func TestListAccessTokens(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
tokens, err := db.Find[auth_model.AccessToken](t.Context(), 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")
|
||||
}
|
||||
// Save it to the database
|
||||
assert.NoError(t, auth_model.NewAccessToken(t.Context(), token))
|
||||
unittest.AssertExistsAndLoadBean(t, token)
|
||||
|
||||
tokens, err = db.Find[auth_model.AccessToken](t.Context(), 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)
|
||||
}
|
||||
// This token must be found by name in the DB now
|
||||
exist, err = auth_model.AccessTokenByNameExists(t.Context(), token)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, exist)
|
||||
|
||||
tokens, err = db.Find[auth_model.AccessToken](t.Context(), auth_model.ListAccessTokensOptions{UserID: 100})
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, tokens)
|
||||
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(t.Context(), user4Token)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, exist)
|
||||
})
|
||||
|
||||
t.Run("RegenerateAccessToken", func(t *testing.T) {
|
||||
const oldToken = "d2c6c1ba3890b309189a8e618c72a162e4efbf36"
|
||||
|
||||
// prime the successful-lookup cache with the old token value, as a real request would
|
||||
before, err := auth_model.GetAccessTokenBySHA(t.Context(), oldToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Token A", before.Name)
|
||||
|
||||
regenerated, err := auth_model.RegenerateAccessToken(t.Context(), before.ID, before.UID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, before.ID, regenerated.ID)
|
||||
assert.Equal(t, before.Name, regenerated.Name)
|
||||
assert.Equal(t, before.Scope, regenerated.Scope)
|
||||
assert.NotEqual(t, before.TokenHash, regenerated.TokenHash)
|
||||
assert.NotEmpty(t, regenerated.Token)
|
||||
|
||||
// the old token value must stop authenticating, even though it was cached as successful above
|
||||
_, err = auth_model.GetAccessTokenBySHA(t.Context(), oldToken)
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
|
||||
// the new token value must authenticate
|
||||
found, err := auth_model.GetAccessTokenBySHA(t.Context(), regenerated.Token)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, before.ID, found.ID)
|
||||
assert.Equal(t, before.UpdatedUnix, found.UpdatedUnix)
|
||||
|
||||
// wrong owner
|
||||
_, err = auth_model.RegenerateAccessToken(t.Context(), before.ID, before.UID+1)
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
|
||||
// nonexistent token
|
||||
_, err = auth_model.RegenerateAccessToken(t.Context(), 100, 100)
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
})
|
||||
|
||||
t.Run("DeleteAccessTokenByID", func(t *testing.T) {
|
||||
token, err := auth_model.GetAccessTokenBySHA(t.Context(), "4c6f36e6cf498e2a448662f915d932c09c5a146c")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), token.UID)
|
||||
|
||||
assert.NoError(t, auth_model.DeleteAccessTokenByID(t.Context(), token.ID, 1))
|
||||
unittest.AssertNotExistsBean(t, token)
|
||||
|
||||
err = auth_model.DeleteAccessTokenByID(t.Context(), 100, 100)
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateAccessToken(t *testing.T) {
|
||||
@@ -116,58 +167,3 @@ func TestUpdateAccessToken(t *testing.T) {
|
||||
assert.NoError(t, auth_model.UpdateAccessToken(t.Context(), token))
|
||||
unittest.AssertExistsAndLoadBean(t, token)
|
||||
}
|
||||
|
||||
func TestRegenerateAccessToken(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
const oldToken = "d2c6c1ba3890b309189a8e618c72a162e4efbf36"
|
||||
|
||||
// prime the successful-lookup cache with the old token value, as a real request would
|
||||
before, err := auth_model.GetAccessTokenBySHA(t.Context(), oldToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "Token A", before.Name)
|
||||
|
||||
regenerated, err := auth_model.RegenerateAccessToken(t.Context(), before.ID, before.UID)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, before.ID, regenerated.ID)
|
||||
assert.Equal(t, before.Name, regenerated.Name)
|
||||
assert.Equal(t, before.Scope, regenerated.Scope)
|
||||
assert.NotEqual(t, before.TokenHash, regenerated.TokenHash)
|
||||
assert.NotEmpty(t, regenerated.Token)
|
||||
|
||||
// the old token value must stop authenticating, even though it was cached as successful above
|
||||
_, err = auth_model.GetAccessTokenBySHA(t.Context(), oldToken)
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
|
||||
// the new token value must authenticate
|
||||
found, err := auth_model.GetAccessTokenBySHA(t.Context(), regenerated.Token)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, before.ID, found.ID)
|
||||
assert.Equal(t, before.UpdatedUnix, found.UpdatedUnix)
|
||||
|
||||
// wrong owner
|
||||
_, err = auth_model.RegenerateAccessToken(t.Context(), before.ID, before.UID+1)
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
|
||||
// nonexistent token
|
||||
_, err = auth_model.RegenerateAccessToken(t.Context(), 100, 100)
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
}
|
||||
|
||||
func TestDeleteAccessTokenByID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
token, err := auth_model.GetAccessTokenBySHA(t.Context(), "4c6f36e6cf498e2a448662f915d932c09c5a146c")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), token.UID)
|
||||
|
||||
assert.NoError(t, auth_model.DeleteAccessTokenByID(t.Context(), token.ID, 1))
|
||||
unittest.AssertNotExistsBean(t, token)
|
||||
|
||||
err = auth_model.DeleteAccessTokenByID(t.Context(), 100, 100)
|
||||
assert.Error(t, err)
|
||||
assert.ErrorIs(t, err, util.ErrNotExist)
|
||||
}
|
||||
+104
-127
@@ -57,13 +57,105 @@ func TestOAuth2AuthorizationCode(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestOAuth2Application_GenerateClientSecret(t *testing.T) {
|
||||
func TestOAuth2ApplicationAndGrant(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
secret, err := app.GenerateClientSecret(t.Context())
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, secret)
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1, ClientSecret: app.ClientSecret})
|
||||
|
||||
t.Run("GetOAuth2ApplicationByClientID", func(t *testing.T) {
|
||||
app, err := auth_model.GetOAuth2ApplicationByClientID(t.Context(), "da7da3ba-9a13-4167-856f-3899de0b0138")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "da7da3ba-9a13-4167-856f-3899de0b0138", app.ClientID)
|
||||
|
||||
app, err = auth_model.GetOAuth2ApplicationByClientID(t.Context(), "invalid client id")
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, app)
|
||||
})
|
||||
|
||||
t.Run("OAuth2Application_GetGrantByUserID", func(t *testing.T) {
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
grant, err := app.GetGrantByUserID(t.Context(), 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), grant.UserID)
|
||||
|
||||
grant, err = app.GetGrantByUserID(t.Context(), 34923458)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, grant)
|
||||
})
|
||||
|
||||
t.Run("GetOAuth2GrantByID", func(t *testing.T) {
|
||||
grant, err := auth_model.GetOAuth2GrantByID(t.Context(), 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), grant.ID)
|
||||
|
||||
grant, err = auth_model.GetOAuth2GrantByID(t.Context(), 34923458)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, grant)
|
||||
})
|
||||
|
||||
t.Run("OAuth2Grant_ScopeContains", func(t *testing.T) {
|
||||
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"))
|
||||
assert.False(t, grant.ScopeContains("profile2"))
|
||||
})
|
||||
|
||||
t.Run("GetOAuth2GrantsByUserID", func(t *testing.T) {
|
||||
result, err := auth_model.GetOAuth2GrantsByUserID(t.Context(), 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 = auth_model.GetOAuth2GrantsByUserID(t.Context(), 34134)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, result)
|
||||
})
|
||||
|
||||
t.Run("OAuth2Grant_GenerateNewAuthorizationCode", func(t *testing.T) {
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1})
|
||||
code, err := grant.GenerateNewAuthorizationCode(t.Context(), "https://example2.com/callback", "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", "S256")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, code)
|
||||
assert.Greater(t, len(code.Code), 32) // secret length > 32
|
||||
})
|
||||
|
||||
t.Run("OAuth2Application_CreateGrant", func(t *testing.T) {
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
grant, err := app.CreateGrant(t.Context(), 2, "")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, grant)
|
||||
assert.Equal(t, int64(2), grant.UserID)
|
||||
assert.Equal(t, int64(1), grant.ApplicationID)
|
||||
assert.Empty(t, grant.Scope)
|
||||
})
|
||||
|
||||
t.Run("OAuth2Grant_IncreaseCounter", func(t *testing.T) {
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 1})
|
||||
stale := *grant
|
||||
assert.NoError(t, grant.IncreaseCounter(t.Context()))
|
||||
assert.Equal(t, int64(2), grant.Counter)
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 2})
|
||||
err := stale.IncreaseCounter(t.Context())
|
||||
assert.ErrorIs(t, err, auth_model.ErrOAuth2GrantStaleCounter)
|
||||
})
|
||||
|
||||
t.Run("OAuth2Application_GenerateClientSecret", func(t *testing.T) {
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
secret, err := app.GenerateClientSecret(t.Context())
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, secret)
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1, ClientSecret: app.ClientSecret})
|
||||
assert.True(t, app.ValidateClientSecret([]byte(secret)))
|
||||
assert.False(t, app.ValidateClientSecret([]byte("fewijfowejgfiowjeoifew")))
|
||||
})
|
||||
|
||||
t.Run("CreateOAuth2Application", func(t *testing.T) {
|
||||
app, err := auth_model.CreateOAuth2Application(t.Context(), 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, &auth_model.OAuth2Application{Name: "newapp"})
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkOAuth2Application_GenerateClientSecret(b *testing.B) {
|
||||
@@ -106,15 +198,12 @@ func TestOAuth2Application_ContainsRedirectURI_WithPort(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestOAuth2Application_ContainsRedirect_Slash(t *testing.T) {
|
||||
app := &auth_model.OAuth2Application{RedirectURIs: []string{"http://127.0.0.1"}}
|
||||
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1"))
|
||||
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/"))
|
||||
assert.False(t, app.ContainsRedirectURI("http://127.0.0.1/other"))
|
||||
|
||||
app = &auth_model.OAuth2Application{RedirectURIs: []string{"http://127.0.0.1/"}}
|
||||
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1"))
|
||||
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/"))
|
||||
assert.False(t, app.ContainsRedirectURI("http://127.0.0.1/other"))
|
||||
for _, redirectURI := range []string{"http://127.0.0.1", "http://127.0.0.1/"} {
|
||||
app := &auth_model.OAuth2Application{RedirectURIs: []string{redirectURI}}
|
||||
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1"))
|
||||
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/"))
|
||||
assert.False(t, app.ContainsRedirectURI("http://127.0.0.1/other"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestOAuth2Application_ContainsRedirectURI_ASCIIOnlyNormalization(t *testing.T) {
|
||||
@@ -158,128 +247,16 @@ func TestOAuth2Application_ContainsRedirectURI_ASCIIOnlyNormalization(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
func TestOAuth2Application_ValidateClientSecret(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
secret, err := app.GenerateClientSecret(t.Context())
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, app.ValidateClientSecret([]byte(secret)))
|
||||
assert.False(t, app.ValidateClientSecret([]byte("fewijfowejgfiowjeoifew")))
|
||||
}
|
||||
|
||||
func TestGetOAuth2ApplicationByClientID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app, err := auth_model.GetOAuth2ApplicationByClientID(t.Context(), "da7da3ba-9a13-4167-856f-3899de0b0138")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "da7da3ba-9a13-4167-856f-3899de0b0138", app.ClientID)
|
||||
|
||||
app, err = auth_model.GetOAuth2ApplicationByClientID(t.Context(), "invalid client id")
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, app)
|
||||
}
|
||||
|
||||
func TestCreateOAuth2Application(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app, err := auth_model.CreateOAuth2Application(t.Context(), 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, &auth_model.OAuth2Application{Name: "newapp"})
|
||||
}
|
||||
|
||||
func TestOAuth2Application_TableName(t *testing.T) {
|
||||
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, &auth_model.OAuth2Application{ID: 1})
|
||||
grant, err := app.GetGrantByUserID(t.Context(), 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), grant.UserID)
|
||||
|
||||
grant, err = app.GetGrantByUserID(t.Context(), 34923458)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, grant)
|
||||
}
|
||||
|
||||
func TestOAuth2Application_CreateGrant(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
app := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Application{ID: 1})
|
||||
grant, err := app.CreateGrant(t.Context(), 2, "")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, grant)
|
||||
assert.Equal(t, int64(2), grant.UserID)
|
||||
assert.Equal(t, int64(1), grant.ApplicationID)
|
||||
assert.Empty(t, grant.Scope)
|
||||
}
|
||||
|
||||
//////////////////// Grant
|
||||
|
||||
func TestGetOAuth2GrantByID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
grant, err := auth_model.GetOAuth2GrantByID(t.Context(), 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(1), grant.ID)
|
||||
|
||||
grant, err = auth_model.GetOAuth2GrantByID(t.Context(), 34923458)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, grant)
|
||||
}
|
||||
|
||||
func TestOAuth2Grant_IncreaseCounter(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 1})
|
||||
assert.NoError(t, grant.IncreaseCounter(t.Context()))
|
||||
assert.Equal(t, int64(2), grant.Counter)
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 2})
|
||||
}
|
||||
|
||||
func TestOAuth2Grant_IncreaseCounterRejectsStaleCounter(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1, Counter: 1})
|
||||
stale := *grant
|
||||
|
||||
assert.NoError(t, grant.IncreaseCounter(t.Context()))
|
||||
err := stale.IncreaseCounter(t.Context())
|
||||
assert.ErrorIs(t, err, auth_model.ErrOAuth2GrantStaleCounter)
|
||||
}
|
||||
|
||||
func TestOAuth2Grant_ScopeContains(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
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"))
|
||||
assert.False(t, grant.ScopeContains("profile2"))
|
||||
}
|
||||
|
||||
func TestOAuth2Grant_GenerateNewAuthorizationCode(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
grant := unittest.AssertExistsAndLoadBean(t, &auth_model.OAuth2Grant{ID: 1})
|
||||
code, err := grant.GenerateNewAuthorizationCode(t.Context(), "https://example2.com/callback", "CjvyTLSdR47G5zYenDA-eDWW4lRrO8yvjcWwbD_deOg", "S256")
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, code)
|
||||
assert.Greater(t, len(code.Code), 32) // secret length > 32
|
||||
}
|
||||
|
||||
func TestOAuth2Grant_TableName(t *testing.T) {
|
||||
assert.Equal(t, "oauth2_grant", new(auth_model.OAuth2Grant).TableName())
|
||||
}
|
||||
|
||||
func TestGetOAuth2GrantsByUserID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
result, err := auth_model.GetOAuth2GrantsByUserID(t.Context(), 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 = auth_model.GetOAuth2GrantsByUserID(t.Context(), 34134)
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, result)
|
||||
}
|
||||
|
||||
func TestRevokeOAuth2Grant(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
assert.NoError(t, auth_model.RevokeOAuth2Grant(t.Context(), 1, 1))
|
||||
|
||||
@@ -16,67 +16,68 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTwoFactorValidateAndConsumeTOTP(t *testing.T) {
|
||||
func TestTwoFactorLifecycle(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
key, err := totp.Generate(totp.GenerateOpts{SecretSize: 40, Issuer: "gitea-test", AccountName: "consume"})
|
||||
require.NoError(t, err)
|
||||
t.Run("TwoFactorValidateAndConsumeTOTP", func(t *testing.T) {
|
||||
key, err := totp.Generate(totp.GenerateOpts{SecretSize: 40, Issuer: "gitea-test", AccountName: "consume"})
|
||||
require.NoError(t, err)
|
||||
|
||||
tfa := &auth_model.TwoFactor{UID: 1}
|
||||
require.NoError(t, tfa.SetSecret(key.Secret()))
|
||||
require.NoError(t, auth_model.NewTwoFactor(t.Context(), tfa))
|
||||
tfa := &auth_model.TwoFactor{UID: 1}
|
||||
require.NoError(t, tfa.SetSecret(key.Secret()))
|
||||
require.NoError(t, auth_model.NewTwoFactor(t.Context(), tfa))
|
||||
|
||||
passcode, err := totp.GenerateCode(key.Secret(), time.Now())
|
||||
require.NoError(t, err)
|
||||
passcode, err := totp.GenerateCode(key.Secret(), time.Now())
|
||||
require.NoError(t, err)
|
||||
|
||||
// first use of a valid passcode succeeds
|
||||
ok, err := tfa.ValidateAndConsumeTOTP(t.Context(), passcode)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, ok)
|
||||
// first use of a valid passcode succeeds
|
||||
ok, err := tfa.ValidateAndConsumeTOTP(t.Context(), passcode)
|
||||
require.NoError(t, err)
|
||||
assert.True(t, ok)
|
||||
|
||||
// replaying the same passcode is refused, even when still inside the TOTP validity window
|
||||
reloaded, err := auth_model.GetTwoFactorByUID(t.Context(), tfa.UID)
|
||||
require.NoError(t, err)
|
||||
ok, err = reloaded.ValidateAndConsumeTOTP(t.Context(), passcode)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, ok)
|
||||
// replaying the same passcode is refused, even when still inside the TOTP validity window
|
||||
reloaded, err := auth_model.GetTwoFactorByUID(t.Context(), tfa.UID)
|
||||
require.NoError(t, err)
|
||||
ok, err = reloaded.ValidateAndConsumeTOTP(t.Context(), passcode)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, ok)
|
||||
|
||||
// an invalid passcode is rejected without consuming anything
|
||||
ok, err = reloaded.ValidateAndConsumeTOTP(t.Context(), "000000")
|
||||
require.NoError(t, err)
|
||||
assert.False(t, ok)
|
||||
}
|
||||
|
||||
func TestDisableTwoFactor(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
ctx := t.Context()
|
||||
|
||||
const uid = 1000 // a uid with no user/2FA fixtures
|
||||
|
||||
// Enroll TOTP and register a WebAuthn credential.
|
||||
tfa := &auth_model.TwoFactor{UID: uid}
|
||||
require.NoError(t, tfa.SetSecret("test-secret"))
|
||||
require.NoError(t, auth_model.NewTwoFactor(ctx, tfa))
|
||||
_, err := auth_model.CreateCredential(ctx, uid, "test-key", &webauthn.Credential{ID: []byte("test-cred-id")})
|
||||
require.NoError(t, err)
|
||||
|
||||
has, err := auth_model.HasTwoFactorOrWebAuthn(ctx, uid)
|
||||
require.NoError(t, err)
|
||||
require.True(t, has)
|
||||
|
||||
// Both records are removed and counted separately.
|
||||
totp, webAuthn, err := auth_model.DisableTwoFactor(ctx, uid)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, totp)
|
||||
assert.EqualValues(t, 1, webAuthn)
|
||||
|
||||
has, err = auth_model.HasTwoFactorOrWebAuthn(ctx, uid)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, has)
|
||||
|
||||
// A second call on a user without 2FA is a no-op.
|
||||
totp, webAuthn, err = auth_model.DisableTwoFactor(ctx, uid)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, totp)
|
||||
assert.EqualValues(t, 0, webAuthn)
|
||||
// an invalid passcode is rejected without consuming anything
|
||||
ok, err = reloaded.ValidateAndConsumeTOTP(t.Context(), "000000")
|
||||
require.NoError(t, err)
|
||||
assert.False(t, ok)
|
||||
})
|
||||
|
||||
t.Run("DisableTwoFactor", func(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
|
||||
const uid = 1000 // a uid with no user/2FA fixtures
|
||||
|
||||
// Enroll TOTP and register a WebAuthn credential.
|
||||
tfa := &auth_model.TwoFactor{UID: uid}
|
||||
require.NoError(t, tfa.SetSecret("test-secret"))
|
||||
require.NoError(t, auth_model.NewTwoFactor(ctx, tfa))
|
||||
_, err := auth_model.CreateCredential(ctx, uid, "test-key", &webauthn.Credential{ID: []byte("test-cred-id")})
|
||||
require.NoError(t, err)
|
||||
|
||||
has, err := auth_model.HasTwoFactorOrWebAuthn(ctx, uid)
|
||||
require.NoError(t, err)
|
||||
require.True(t, has)
|
||||
|
||||
// Both records are removed and counted separately.
|
||||
totp, webAuthn, err := auth_model.DisableTwoFactor(ctx, uid)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, totp)
|
||||
assert.EqualValues(t, 1, webAuthn)
|
||||
|
||||
has, err = auth_model.HasTwoFactorOrWebAuthn(ctx, uid)
|
||||
require.NoError(t, err)
|
||||
assert.False(t, has)
|
||||
|
||||
// A second call on a user without 2FA is a no-op.
|
||||
totp, webAuthn, err = auth_model.DisableTwoFactor(ctx, uid)
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, totp)
|
||||
assert.EqualValues(t, 0, webAuthn)
|
||||
})
|
||||
}
|
||||
@@ -13,29 +13,38 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGetWebAuthnCredentialByID(t *testing.T) {
|
||||
func TestWebAuthnCredentials(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
res, err := auth_model.GetWebAuthnCredentialByID(t.Context(), 32, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "WebAuthn credential", res.Name)
|
||||
t.Run("GetWebAuthnCredentialByID", func(t *testing.T) {
|
||||
res, err := auth_model.GetWebAuthnCredentialByID(t.Context(), 32, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "WebAuthn credential", res.Name)
|
||||
|
||||
_, err = auth_model.GetWebAuthnCredentialByID(t.Context(), 99999, 1)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, auth_model.IsErrWebAuthnCredentialNotExist(err))
|
||||
_, err = auth_model.GetWebAuthnCredentialByID(t.Context(), 99999, 1)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, auth_model.IsErrWebAuthnCredentialNotExist(err))
|
||||
|
||||
_, err = auth_model.GetWebAuthnCredentialByID(t.Context(), 32, 99999)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, auth_model.IsErrWebAuthnCredentialNotExist(err))
|
||||
}
|
||||
_, err = auth_model.GetWebAuthnCredentialByID(t.Context(), 32, 99999)
|
||||
assert.Error(t, err)
|
||||
assert.True(t, auth_model.IsErrWebAuthnCredentialNotExist(err))
|
||||
})
|
||||
|
||||
func TestGetWebAuthnCredentialsByUID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
t.Run("GetWebAuthnCredentialsByUID", func(t *testing.T) {
|
||||
res, err := auth_model.GetWebAuthnCredentialsByUID(t.Context(), 32)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, res, 1)
|
||||
assert.Equal(t, "WebAuthn credential", res[0].Name)
|
||||
})
|
||||
|
||||
res, err := auth_model.GetWebAuthnCredentialsByUID(t.Context(), 32)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, res, 1)
|
||||
assert.Equal(t, "WebAuthn credential", res[0].Name)
|
||||
t.Run("CreateCredential", func(t *testing.T) {
|
||||
res, err := auth_model.CreateCredential(t.Context(), 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.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{Name: "WebAuthn Created Credential", UserID: 1})
|
||||
})
|
||||
}
|
||||
|
||||
func TestWebAuthnCredential_TableName(t *testing.T) {
|
||||
@@ -43,28 +52,11 @@ func TestWebAuthnCredential_TableName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWebAuthnCredential_UpdateSignCount(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1})
|
||||
cred.SignCount = 1
|
||||
assert.NoError(t, cred.UpdateSignCount(t.Context()))
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1, SignCount: 1})
|
||||
}
|
||||
|
||||
func TestWebAuthnCredential_UpdateLargeCounter(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1})
|
||||
cred.SignCount = 0xffffffff
|
||||
assert.NoError(t, cred.UpdateSignCount(t.Context()))
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1, SignCount: 0xffffffff})
|
||||
}
|
||||
|
||||
func TestCreateCredential(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
res, err := auth_model.CreateCredential(t.Context(), 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.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{Name: "WebAuthn Created Credential", UserID: 1})
|
||||
for _, signCount := range []uint32{1, 0xffffffff} {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
cred := unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1})
|
||||
cred.SignCount = signCount
|
||||
assert.NoError(t, cred.UpdateSignCount(t.Context()))
|
||||
unittest.AssertExistsAndLoadBean(t, &auth_model.WebAuthnCredential{ID: 1, SignCount: signCount})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user