a73x

internal/server/store/apitokens_test.go

Ref:   Size: 2.3 KiB   History

package store

import (
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestAPITokenMintAndUse(t *testing.T) {
	s := newStore(t)

	secret, id, err := s.CreateAPIToken(testTenant, "laptop", 0)
	require.NoError(t, err)
	assert.True(t, strings.HasPrefix(secret, "eitri_pat_"), "greppable prefix")
	assert.NotEmpty(t, id)

	tenant, ok, err := s.TenantForAPIToken(secret)
	require.NoError(t, err)
	require.True(t, ok)
	assert.Equal(t, testTenant, tenant)

	// Using it stamps last_used_at.
	toks, err := s.ListAPITokens(testTenant)
	require.NoError(t, err)
	require.Len(t, toks, 1)
	assert.Equal(t, id, toks[0].ID)
	assert.Equal(t, "laptop", toks[0].Name)
	require.NotNil(t, toks[0].LastUsedAt)
	assert.Nil(t, toks[0].ExpiresAt, "ttl 0 ⇒ non-expiring")
}

func TestAPITokenUnknown(t *testing.T) {
	s := newStore(t)
	_, ok, err := s.TenantForAPIToken("eitri_pat_nope")
	require.NoError(t, err)
	assert.False(t, ok)
}

func TestAPITokenExpiry(t *testing.T) {
	s := newStore(t)
	secret, _, err := s.CreateAPIToken(testTenant, "short", -time.Minute)
	require.NoError(t, err)

	_, ok, err := s.TenantForAPIToken(secret)
	require.NoError(t, err)
	assert.False(t, ok, "expired token must not resolve")
}

func TestAPITokenRevoke(t *testing.T) {
	s := newStore(t)
	secret, id, err := s.CreateAPIToken(testTenant, "revme", time.Hour)
	require.NoError(t, err)

	require.NoError(t, s.RevokeAPIToken(testTenant, id))

	_, ok, err := s.TenantForAPIToken(secret)
	require.NoError(t, err)
	assert.False(t, ok, "revoked token must not resolve")

	// Revoked token still lists (metadata), with revoked_at set.
	toks, err := s.ListAPITokens(testTenant)
	require.NoError(t, err)
	require.Len(t, toks, 1)
	require.NotNil(t, toks[0].RevokedAt)
}

func TestAPITokenTenantIsolation(t *testing.T) {
	s := newStore(t)
	other, err := s.CreateTenantForIdentity("https://idp", "sub-1", "alex@a.com")
	require.NoError(t, err)

	_, id, err := s.CreateAPIToken(testTenant, "mine", time.Hour)
	require.NoError(t, err)

	// Another tenant cannot see it…
	toks, err := s.ListAPITokens(other.ID)
	require.NoError(t, err)
	assert.Empty(t, toks)

	// …nor revoke it (not-found semantics).
	err = s.RevokeAPIToken(other.ID, id)
	require.Error(t, err)

	// The owner still can.
	require.NoError(t, s.RevokeAPIToken(testTenant, id))
}