121 lines
3.1 KiB
Go
121 lines
3.1 KiB
Go
package store
|
|
|
|
import (
|
|
"context"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/oklog/ulid/v2"
|
|
)
|
|
|
|
func newSetupTokenTestStore(t *testing.T) (*Store, string, string) {
|
|
t.Helper()
|
|
st, err := Open(context.Background(), filepath.Join(t.TempDir(), "rm.db"))
|
|
if err != nil {
|
|
t.Fatalf("open: %v", err)
|
|
}
|
|
t.Cleanup(func() { _ = st.Close() })
|
|
uid := ulid.Make().String()
|
|
creator := ulid.Make().String()
|
|
now := time.Now().UTC()
|
|
if err := st.CreateUser(context.Background(), User{
|
|
ID: creator, Username: "creator", PasswordHash: "x",
|
|
Role: RoleAdmin, CreatedAt: now,
|
|
}); err != nil {
|
|
t.Fatalf("create creator: %v", err)
|
|
}
|
|
if err := st.CreateUser(context.Background(), User{
|
|
ID: uid, Username: "target", PasswordHash: "",
|
|
Role: RoleOperator, CreatedAt: now, MustChangePassword: true,
|
|
}); err != nil {
|
|
t.Fatalf("create target: %v", err)
|
|
}
|
|
return st, uid, creator
|
|
}
|
|
|
|
func TestSetupTokenSetAndLookup(t *testing.T) {
|
|
t.Parallel()
|
|
st, uid, creator := newSetupTokenTestStore(t)
|
|
ctx := context.Background()
|
|
now := time.Now().UTC()
|
|
|
|
if err := st.SetSetupToken(ctx, SetupToken{
|
|
UserID: uid, TokenHash: "abc123",
|
|
ExpiresAt: now.Add(time.Hour),
|
|
CreatedAt: now, CreatedBy: &creator,
|
|
}); err != nil {
|
|
t.Fatalf("set: %v", err)
|
|
}
|
|
got, err := st.LookupSetupToken(ctx, "abc123")
|
|
if err != nil {
|
|
t.Fatalf("lookup: %v", err)
|
|
}
|
|
if got.UserID != uid {
|
|
t.Errorf("user_id: got %q want %q", got.UserID, uid)
|
|
}
|
|
}
|
|
|
|
func TestSetupTokenReplaces(t *testing.T) {
|
|
t.Parallel()
|
|
st, uid, creator := newSetupTokenTestStore(t)
|
|
ctx := context.Background()
|
|
now := time.Now().UTC()
|
|
|
|
_ = st.SetSetupToken(ctx, SetupToken{
|
|
UserID: uid, TokenHash: "old",
|
|
ExpiresAt: now.Add(time.Hour), CreatedAt: now, CreatedBy: &creator,
|
|
})
|
|
_ = st.SetSetupToken(ctx, SetupToken{
|
|
UserID: uid, TokenHash: "new",
|
|
ExpiresAt: now.Add(time.Hour), CreatedAt: now, CreatedBy: &creator,
|
|
})
|
|
if _, err := st.LookupSetupToken(ctx, "old"); err == nil {
|
|
t.Error("old token should be gone")
|
|
}
|
|
if _, err := st.LookupSetupToken(ctx, "new"); err != nil {
|
|
t.Errorf("new token should resolve: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSetupTokenDelete(t *testing.T) {
|
|
t.Parallel()
|
|
st, uid, creator := newSetupTokenTestStore(t)
|
|
ctx := context.Background()
|
|
now := time.Now().UTC()
|
|
|
|
_ = st.SetSetupToken(ctx, SetupToken{
|
|
UserID: uid, TokenHash: "tk",
|
|
ExpiresAt: now.Add(time.Hour), CreatedAt: now, CreatedBy: &creator,
|
|
})
|
|
if err := st.DeleteSetupToken(ctx, uid); err != nil {
|
|
t.Fatalf("delete: %v", err)
|
|
}
|
|
if _, err := st.LookupSetupToken(ctx, "tk"); err == nil {
|
|
t.Error("deleted token should not resolve")
|
|
}
|
|
}
|
|
|
|
func TestSetupTokenCleanupExpired(t *testing.T) {
|
|
t.Parallel()
|
|
st, uid, creator := newSetupTokenTestStore(t)
|
|
ctx := context.Background()
|
|
now := time.Now().UTC()
|
|
|
|
_ = st.SetSetupToken(ctx, SetupToken{
|
|
UserID: uid, TokenHash: "stale",
|
|
ExpiresAt: now.Add(-time.Hour), CreatedAt: now.Add(-2 * time.Hour),
|
|
CreatedBy: &creator,
|
|
})
|
|
n, err := st.CleanupExpiredSetupTokens(ctx, now)
|
|
if err != nil {
|
|
t.Fatalf("cleanup: %v", err)
|
|
}
|
|
if n != 1 {
|
|
t.Errorf("cleanup count: got %d want 1", n)
|
|
}
|
|
if _, err := st.LookupSetupToken(ctx, "stale"); err == nil {
|
|
t.Error("stale token should be gone")
|
|
}
|
|
}
|