2021-12-18 07:07:12 -08:00
|
|
|
package services
|
2021-12-17 17:58:51 -08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"testing"
|
2021-12-17 18:10:35 -08:00
|
|
|
"time"
|
2021-12-17 17:58:51 -08:00
|
|
|
|
2024-07-09 17:57:05 -07:00
|
|
|
"github.com/stretchr/testify/assert"
|
2021-12-17 17:58:51 -08:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2024-07-11 21:09:15 -07:00
|
|
|
"git.grosinger.net/tgrosinger/saasitone/pkg/models/sqlc"
|
|
|
|
"git.grosinger.net/tgrosinger/saasitone/pkg/db"
|
2021-12-17 17:58:51 -08:00
|
|
|
)
|
|
|
|
|
2022-01-08 12:32:18 -08:00
|
|
|
func TestAuthClient_Auth(t *testing.T) {
|
2021-12-17 17:58:51 -08:00
|
|
|
assertNoAuth := func() {
|
|
|
|
_, err := c.Auth.GetAuthenticatedUserID(ctx)
|
|
|
|
assert.True(t, errors.Is(err, NotAuthenticatedError{}))
|
|
|
|
_, err = c.Auth.GetAuthenticatedUser(ctx)
|
|
|
|
assert.True(t, errors.Is(err, NotAuthenticatedError{}))
|
|
|
|
}
|
|
|
|
|
|
|
|
assertNoAuth()
|
|
|
|
|
|
|
|
err := c.Auth.Login(ctx, usr.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
uid, err := c.Auth.GetAuthenticatedUserID(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, usr.ID, uid)
|
|
|
|
|
|
|
|
u, err := c.Auth.GetAuthenticatedUser(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, u.ID, usr.ID)
|
|
|
|
|
|
|
|
err = c.Auth.Logout(ctx)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
assertNoAuth()
|
|
|
|
}
|
|
|
|
|
2022-01-08 12:32:18 -08:00
|
|
|
func TestAuthClient_PasswordHashing(t *testing.T) {
|
2021-12-17 17:58:51 -08:00
|
|
|
pw := "testcheckpassword"
|
|
|
|
hash, err := c.Auth.HashPassword(pw)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.NotEqual(t, hash, pw)
|
|
|
|
err = c.Auth.CheckPassword(pw, hash)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2022-01-08 12:32:18 -08:00
|
|
|
func TestAuthClient_GeneratePasswordResetToken(t *testing.T) {
|
2021-12-17 17:58:51 -08:00
|
|
|
token, pt, err := c.Auth.GeneratePasswordResetToken(ctx, usr.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Len(t, token, c.Config.App.PasswordToken.Length)
|
|
|
|
assert.NoError(t, c.Auth.CheckPassword(token, pt.Hash))
|
|
|
|
}
|
|
|
|
|
2022-01-08 12:32:18 -08:00
|
|
|
func TestAuthClient_GetValidPasswordToken(t *testing.T) {
|
2021-12-17 18:10:35 -08:00
|
|
|
// Check that a fake token is not valid
|
2022-01-27 05:44:12 -08:00
|
|
|
_, err := c.Auth.GetValidPasswordToken(ctx, usr.ID, 1, "faketoken")
|
2021-12-17 17:58:51 -08:00
|
|
|
assert.Error(t, err)
|
|
|
|
|
2021-12-17 18:10:35 -08:00
|
|
|
// Generate a valid token and check that it is returned
|
2021-12-17 17:58:51 -08:00
|
|
|
token, pt, err := c.Auth.GeneratePasswordResetToken(ctx, usr.ID)
|
|
|
|
require.NoError(t, err)
|
2022-01-27 05:44:12 -08:00
|
|
|
pt2, err := c.Auth.GetValidPasswordToken(ctx, usr.ID, pt.ID, token)
|
2021-12-17 17:58:51 -08:00
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, pt.ID, pt2.ID)
|
2021-12-17 18:10:35 -08:00
|
|
|
|
2022-04-12 18:05:19 -07:00
|
|
|
// Expire the token by pushing the date far enough back
|
2024-07-11 21:09:15 -07:00
|
|
|
err = c.DB.C.UpdatePasswordTokenCreatedAt(context.Background(), sqlc.UpdatePasswordTokenCreatedAtParams{
|
|
|
|
CreatedAt: db.Time{Time: time.Now().Add(-(c.Config.App.PasswordToken.Expiration + time.Hour))},
|
|
|
|
ID: pt.ID,
|
|
|
|
})
|
2021-12-17 18:10:35 -08:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Expired tokens should not be valid
|
2022-01-27 05:44:12 -08:00
|
|
|
_, err = c.Auth.GetValidPasswordToken(ctx, usr.ID, pt.ID, token)
|
2021-12-17 18:10:35 -08:00
|
|
|
assert.Error(t, err)
|
2021-12-17 17:58:51 -08:00
|
|
|
}
|
|
|
|
|
2022-01-08 12:32:18 -08:00
|
|
|
func TestAuthClient_DeletePasswordTokens(t *testing.T) {
|
2021-12-17 18:10:35 -08:00
|
|
|
// Create three tokens for the user
|
2021-12-17 17:58:51 -08:00
|
|
|
for i := 0; i < 3; i++ {
|
|
|
|
_, _, err := c.Auth.GeneratePasswordResetToken(ctx, usr.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
}
|
|
|
|
|
2021-12-17 18:10:35 -08:00
|
|
|
// Delete all tokens for the user
|
2021-12-17 17:58:51 -08:00
|
|
|
err := c.Auth.DeletePasswordTokens(ctx, usr.ID)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2021-12-17 18:10:35 -08:00
|
|
|
// Check that no tokens remain
|
2024-07-11 21:09:15 -07:00
|
|
|
tokens, err := c.DB.C.GetAllPasswordTokensForUser(context.Background(), usr.ID)
|
2021-12-17 17:58:51 -08:00
|
|
|
require.NoError(t, err)
|
2024-07-11 21:09:15 -07:00
|
|
|
assert.Len(t, tokens, 0)
|
2021-12-17 17:58:51 -08:00
|
|
|
}
|
|
|
|
|
2022-01-08 12:32:18 -08:00
|
|
|
func TestAuthClient_RandomToken(t *testing.T) {
|
2021-12-22 16:18:33 -08:00
|
|
|
length := c.Config.App.PasswordToken.Length
|
2021-12-17 17:58:51 -08:00
|
|
|
a, err := c.Auth.RandomToken(length)
|
|
|
|
require.NoError(t, err)
|
|
|
|
b, err := c.Auth.RandomToken(length)
|
|
|
|
require.NoError(t, err)
|
2021-12-22 16:18:33 -08:00
|
|
|
assert.Len(t, a, length)
|
|
|
|
assert.Len(t, b, length)
|
2021-12-17 17:58:51 -08:00
|
|
|
assert.NotEqual(t, a, b)
|
|
|
|
}
|
2022-01-08 12:32:18 -08:00
|
|
|
|
|
|
|
func TestAuthClient_EmailVerificationToken(t *testing.T) {
|
|
|
|
t.Run("valid token", func(t *testing.T) {
|
|
|
|
email := "test@localhost.com"
|
|
|
|
token, err := c.Auth.GenerateEmailVerificationToken(email)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
tokenEmail, err := c.Auth.ValidateEmailVerificationToken(token)
|
|
|
|
require.NoError(t, err)
|
|
|
|
assert.Equal(t, email, tokenEmail)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("invalid token", func(t *testing.T) {
|
|
|
|
badToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InRlc3RAbG9jYWxob3N0LmNvbSIsImV4cCI6MTkxNzg2NDAwMH0.ScJCpfEEzlilKfRs_aVouzwPNKI28M3AIm-hyImQHUQ"
|
|
|
|
_, err := c.Auth.ValidateEmailVerificationToken(badToken)
|
|
|
|
assert.Error(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("expired token", func(t *testing.T) {
|
|
|
|
c.Config.App.EmailVerificationTokenExpiration = -time.Hour
|
|
|
|
email := "test@localhost.com"
|
|
|
|
token, err := c.Auth.GenerateEmailVerificationToken(email)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
_, err = c.Auth.ValidateEmailVerificationToken(token)
|
|
|
|
assert.Error(t, err)
|
|
|
|
|
|
|
|
c.Config.App.EmailVerificationTokenExpiration = time.Hour * 12
|
|
|
|
})
|
|
|
|
}
|