404 lines
12 KiB
Go
404 lines
12 KiB
Go
package controllers_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.badhouseplants.net/softplayer/softplayer-backend/internal/controllers"
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func newTestTokensController(ctx context.Context) *controllers.TokenController {
|
|
return &controllers.TokenController{
|
|
DB: newTestDBConnection(ctx),
|
|
Redis: newTestRedisConnection(),
|
|
}
|
|
}
|
|
|
|
func TestIntegrationCreateToken_Success(t *testing.T) {
|
|
// Create a user for the token
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
id, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: id,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
tokenVal, tokenID, err := ctrl.Create(t.Context(), tokenData)
|
|
assert.NoError(t, err)
|
|
assert.NotEmpty(t, tokenID)
|
|
assert.NotEmpty(t, tokenVal)
|
|
}
|
|
|
|
func TestIntegrationCreateToken_UserNotExist(t *testing.T) {
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: uuid.NewString(),
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
tokenVal, tokenID, err := ctrl.Create(t.Context(), tokenData)
|
|
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, controllers.ErrUserNotFound)
|
|
assert.Empty(t, tokenID)
|
|
assert.Empty(t, tokenVal)
|
|
}
|
|
|
|
func TestIntegrationGetToken_Success(t *testing.T) {
|
|
// Create a user for the token
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
|
|
now := time.Now()
|
|
userID, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: userID,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
_, tokenID, err := ctrl.Create(t.Context(), tokenData)
|
|
assert.NoError(t, err)
|
|
|
|
token, err := ctrl.Get(t.Context(), tokenID, userID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, now.Truncate(time.Second), token.GeneratedAt.Truncate(time.Second))
|
|
assert.Equal(t, now.Truncate(time.Second), token.CreatedAt.Truncate(time.Second))
|
|
assert.Equal(t, tokenData.Scopes, token.Scopes)
|
|
assert.Equal(t, tokenData.Name, token.Name)
|
|
assert.Equal(t, tokenData.ExpiresAt.Truncate(time.Second), token.ExpiresAt.Truncate(time.Second))
|
|
}
|
|
|
|
func TestIntegrationGetToken_NotExists(t *testing.T) {
|
|
ctrl := newTestTokensController(t.Context())
|
|
token, err := ctrl.Get(t.Context(), uuid.NewString(), uuid.NewString())
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, controllers.ErrTokenNotFound)
|
|
assert.Empty(t, token)
|
|
}
|
|
|
|
func TestIntegrationGetToken_WrongRequest(t *testing.T) {
|
|
ctrl := newTestTokensController(t.Context())
|
|
token, err := ctrl.Get(t.Context(), "test", "test")
|
|
assert.Error(t, err)
|
|
assert.ErrorIs(t, err, controllers.ErrServerError)
|
|
assert.Empty(t, token)
|
|
}
|
|
|
|
func TestIntegrationVerifyTokenOwner_Success(t *testing.T) {
|
|
// Create a user for the token
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
|
|
userID, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: userID,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
_, tokenID, err := ctrl.Create(t.Context(), tokenData)
|
|
assert.NoError(t, err)
|
|
assert.NoError(t, ctrl.VerifyTokenOwner(t.Context(), userID, tokenID))
|
|
}
|
|
|
|
func TestIntegrationVerifyTokenOwner_WrongOwner(t *testing.T) {
|
|
// Create a user for the token
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
|
|
secondAccountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
userID, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
secondUserID, err := ctrlAccount.Create(t.Context(), secondAccountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: userID,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
_, tokenID, err := ctrl.Create(t.Context(), tokenData)
|
|
assert.NoError(t, err)
|
|
assert.ErrorIs(t, ctrl.VerifyTokenOwner(t.Context(), secondUserID, tokenID), controllers.ErrUserTokenMismatch)
|
|
}
|
|
|
|
func TestIntegrationForceExpiration_Success(t *testing.T) {
|
|
// Create a user for the token
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
|
|
userID, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: userID,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
_, tokenID, err := ctrl.Create(t.Context(), tokenData)
|
|
assert.NoError(t, err)
|
|
now := time.Now()
|
|
assert.NoError(t, ctrl.ForceExpiration(t.Context(), tokenID))
|
|
token, err := ctrl.Get(t.Context(), tokenID, userID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, now.Truncate(time.Second), token.RevokedAt.Truncate(time.Second))
|
|
}
|
|
|
|
func TestIntegrationRegenerateToken_Success(t *testing.T) {
|
|
// Create a user for the token
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
|
|
now := time.Now()
|
|
userID, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: userID,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
_, tokenID, err := ctrl.Create(t.Context(), tokenData)
|
|
assert.NoError(t, err)
|
|
|
|
token, err := ctrl.Get(t.Context(), tokenID, userID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, now.Truncate(time.Second), token.GeneratedAt.Truncate(time.Second))
|
|
assert.Equal(t, now.Truncate(time.Second), token.CreatedAt.Truncate(time.Second))
|
|
assert.Equal(t, tokenData.Scopes, token.Scopes)
|
|
assert.Equal(t, tokenData.Name, token.Name)
|
|
assert.Equal(t, tokenData.ExpiresAt.Truncate(time.Second), token.ExpiresAt.Truncate(time.Second))
|
|
time.Sleep(5 * time.Second)
|
|
|
|
newNow := time.Now()
|
|
newToken, err := ctrl.Regenerate(t.Context(), tokenID)
|
|
assert.NotEmpty(t, newToken)
|
|
assert.NoError(t, err)
|
|
|
|
newExpiresAt := tokenData.ExpiresAt.Add(5 * time.Second)
|
|
|
|
updatedToken, err := ctrl.Get(t.Context(), tokenID, userID)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, newNow.Truncate(time.Second), updatedToken.GeneratedAt.Truncate(time.Second))
|
|
assert.Equal(t, now.Truncate(time.Second), updatedToken.CreatedAt.Truncate(time.Second))
|
|
assert.Equal(t, tokenData.Scopes, updatedToken.Scopes)
|
|
assert.Equal(t, tokenData.Name, updatedToken.Name)
|
|
assert.Equal(t, newExpiresAt.Truncate(time.Second), updatedToken.ExpiresAt.Truncate(time.Second))
|
|
}
|
|
|
|
func TestIntegrationListTokens_Success(t *testing.T) {
|
|
// Create a user for the token
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
|
|
userID, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenDataOne := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: userID,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
tokenDataTwo := &controllers.TokenData{
|
|
Name: "Test Token again",
|
|
UserID: userID,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
_, _, err = ctrl.Create(t.Context(), tokenDataOne)
|
|
assert.NoError(t, err)
|
|
_, _, err = ctrl.Create(t.Context(), tokenDataTwo)
|
|
assert.NoError(t, err)
|
|
|
|
tokens, err := ctrl.List(t.Context(), userID)
|
|
assert.NoError(t, err)
|
|
assert.Len(t, tokens, 2)
|
|
}
|
|
|
|
func TestIntegrationAuthenticateWithToken_Success(t *testing.T) {
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
id, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: id,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
tokenVal, _, err := ctrl.Create(t.Context(), tokenData)
|
|
assert.NoError(t, err)
|
|
|
|
auth, err := ctrl.AuthenticateWithToken(t.Context(), tokenVal)
|
|
assert.NoError(t, err)
|
|
assert.NotEmpty(t, auth.Scope)
|
|
assert.NotEmpty(t, auth.UserID)
|
|
assert.Equal(t, id, auth.UserID)
|
|
|
|
scope := map[string][]string{}
|
|
assert.NoError(t, json.Unmarshal([]byte(auth.Scope), &scope))
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, tokenData.Scopes, scope)
|
|
}
|
|
|
|
func TestIntegrationAuthenticateWithToken_UnknownToken(t *testing.T) {
|
|
ctrl := newTestTokensController(t.Context())
|
|
auth, err := ctrl.AuthenticateWithToken(t.Context(), "dummy")
|
|
assert.Error(t, err)
|
|
assert.Nil(t, auth)
|
|
assert.ErrorIs(t, err, controllers.ErrTokenNotFound)
|
|
}
|
|
|
|
func TestIntegrationAuthenticateWithToken_Expired(t *testing.T) {
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
id, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: id,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
tokenVal, _, err := ctrl.Create(t.Context(), tokenData)
|
|
assert.NoError(t, err)
|
|
|
|
auth, err := ctrl.AuthenticateWithToken(t.Context(), tokenVal)
|
|
assert.NoError(t, err)
|
|
assert.NotEmpty(t, auth.Scope)
|
|
assert.NotEmpty(t, auth.UserID)
|
|
assert.Equal(t, id, auth.UserID)
|
|
|
|
time.Sleep(time.Second * 6)
|
|
auth, err = ctrl.AuthenticateWithToken(t.Context(), tokenVal)
|
|
assert.Error(t, err)
|
|
assert.Nil(t, auth)
|
|
assert.ErrorIs(t, err, controllers.ErrBadToken)
|
|
}
|
|
|
|
func TestIntegrationAuthenticateWithToken_Revoked(t *testing.T) {
|
|
ctrlAccount := newTestAccountController(t.Context())
|
|
accountData := &controllers.AccountData{
|
|
Password: "qwertyu9",
|
|
Email: newTestUniqueEmail("accounts"),
|
|
}
|
|
id, err := ctrlAccount.Create(t.Context(), accountData)
|
|
assert.NoError(t, err)
|
|
|
|
tokenData := &controllers.TokenData{
|
|
Name: "Test Token",
|
|
UserID: id,
|
|
ExpiresAt: time.Now().Add(time.Second * 5),
|
|
Scopes: map[string][]string{
|
|
"Test": {"test", "test2"},
|
|
},
|
|
}
|
|
|
|
ctrl := newTestTokensController(t.Context())
|
|
tokenVal, tokenID, err := ctrl.Create(t.Context(), tokenData)
|
|
assert.NoError(t, err)
|
|
auth, err := ctrl.AuthenticateWithToken(t.Context(), tokenVal)
|
|
assert.NoError(t, err)
|
|
assert.NotEmpty(t, auth.Scope)
|
|
assert.NotEmpty(t, auth.UserID)
|
|
assert.Equal(t, id, auth.UserID)
|
|
|
|
assert.NoError(t, ctrl.ForceExpiration(t.Context(), tokenID))
|
|
auth, err = ctrl.AuthenticateWithToken(t.Context(), tokenVal)
|
|
assert.Error(t, err)
|
|
assert.Nil(t, auth)
|
|
assert.ErrorIs(t, err, controllers.ErrBadToken)
|
|
}
|