mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-05-20 19:20:14 +00:00
refactor(db): use new store interface (#831)
This commit is contained in:
@@ -0,0 +1,472 @@
|
||||
package memory_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tinyauthapp/tinyauth/internal/repository"
|
||||
"github.com/tinyauthapp/tinyauth/internal/repository/memory"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
||||
func TestMemoryStore(t *testing.T) {
|
||||
type testCase struct {
|
||||
description string
|
||||
run func(t *testing.T, s repository.Store)
|
||||
}
|
||||
|
||||
tests := []testCase{
|
||||
{
|
||||
description: "Create and get session",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
sess, err := s.CreateSession(ctx, repository.CreateSessionParams{
|
||||
UUID: "uuid-1",
|
||||
Username: "alice",
|
||||
Expiry: 9999,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "uuid-1", sess.UUID)
|
||||
assert.Equal(t, "alice", sess.Username)
|
||||
|
||||
got, err := s.GetSession(ctx, "uuid-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, sess, got)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get session not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetSession(ctx, "missing")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Update session",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateSession(ctx, repository.CreateSessionParams{UUID: "uuid-1", Username: "alice"})
|
||||
require.NoError(t, err)
|
||||
|
||||
updated, err := s.UpdateSession(ctx, repository.UpdateSessionParams{
|
||||
UUID: "uuid-1",
|
||||
Username: "bob",
|
||||
Email: "bob@example.com",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "bob", updated.Username)
|
||||
assert.Equal(t, "bob@example.com", updated.Email)
|
||||
|
||||
got, err := s.GetSession(ctx, "uuid-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, updated, got)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Update session not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.UpdateSession(ctx, repository.UpdateSessionParams{UUID: "missing"})
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete session",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateSession(ctx, repository.CreateSessionParams{UUID: "uuid-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.DeleteSession(ctx, "uuid-1"))
|
||||
|
||||
_, err = s.GetSession(ctx, "uuid-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete expired sessions",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateSession(ctx, repository.CreateSessionParams{UUID: "expired", Expiry: 10})
|
||||
require.NoError(t, err)
|
||||
_, err = s.CreateSession(ctx, repository.CreateSessionParams{UUID: "valid", Expiry: 100})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.DeleteExpiredSessions(ctx, 50))
|
||||
|
||||
_, err = s.GetSession(ctx, "expired")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
|
||||
_, err = s.GetSession(ctx, "valid")
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Create and get OIDC code",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
code, err := s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{
|
||||
Sub: "sub-1",
|
||||
CodeHash: "hash-1",
|
||||
Scope: "openid",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "sub-1", code.Sub)
|
||||
|
||||
// destructive read removes the record
|
||||
got, err := s.GetOidcCode(ctx, "hash-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, code, got)
|
||||
|
||||
_, err = s.GetOidcCode(ctx, "hash-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC code not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetOidcCode(ctx, "missing")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC code by sub",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{Sub: "sub-1", CodeHash: "hash-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := s.GetOidcCodeBySub(ctx, "sub-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "sub-1", got.Sub)
|
||||
|
||||
// destructive — gone after read
|
||||
_, err = s.GetOidcCodeBySub(ctx, "sub-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC code by sub not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetOidcCodeBySub(ctx, "missing")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC code unsafe",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{Sub: "sub-1", CodeHash: "hash-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := s.GetOidcCodeUnsafe(ctx, "hash-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "sub-1", got.Sub)
|
||||
|
||||
// non-destructive — still present
|
||||
_, err = s.GetOidcCodeUnsafe(ctx, "hash-1")
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC code unsafe not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetOidcCodeUnsafe(ctx, "missing")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC code by sub unsafe",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{Sub: "sub-1", CodeHash: "hash-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := s.GetOidcCodeBySubUnsafe(ctx, "sub-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "hash-1", got.CodeHash)
|
||||
|
||||
// non-destructive — still present
|
||||
_, err = s.GetOidcCodeBySubUnsafe(ctx, "sub-1")
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC code by sub unsafe not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetOidcCodeBySubUnsafe(ctx, "missing")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Create OIDC code unique sub constraint",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{Sub: "sub-1", CodeHash: "hash-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{Sub: "sub-1", CodeHash: "hash-2"})
|
||||
assert.ErrorContains(t, err, "UNIQUE constraint failed: oidc_codes.sub")
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete OIDC code",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{Sub: "sub-1", CodeHash: "hash-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.DeleteOidcCode(ctx, "hash-1"))
|
||||
|
||||
_, err = s.GetOidcCodeUnsafe(ctx, "hash-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete OIDC code by sub",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{Sub: "sub-1", CodeHash: "hash-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.DeleteOidcCodeBySub(ctx, "sub-1"))
|
||||
|
||||
_, err = s.GetOidcCodeUnsafe(ctx, "hash-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete expired OIDC codes",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{Sub: "sub-1", CodeHash: "hash-1", ExpiresAt: 10})
|
||||
require.NoError(t, err)
|
||||
_, err = s.CreateOidcCode(ctx, repository.CreateOidcCodeParams{Sub: "sub-2", CodeHash: "hash-2", ExpiresAt: 100})
|
||||
require.NoError(t, err)
|
||||
|
||||
deleted, err := s.DeleteExpiredOidcCodes(ctx, 50)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, deleted, 1)
|
||||
assert.Equal(t, "hash-1", deleted[0].CodeHash)
|
||||
|
||||
_, err = s.GetOidcCodeUnsafe(ctx, "hash-2")
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Create and get OIDC token",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
tok, err := s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{
|
||||
Sub: "sub-1",
|
||||
AccessTokenHash: "at-hash-1",
|
||||
CodeHash: "code-hash-1",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "sub-1", tok.Sub)
|
||||
|
||||
got, err := s.GetOidcToken(ctx, "at-hash-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tok, got)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC token not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetOidcToken(ctx, "missing")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Create OIDC token unique sub constraint",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{Sub: "sub-1", AccessTokenHash: "at-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{Sub: "sub-1", AccessTokenHash: "at-2"})
|
||||
assert.ErrorContains(t, err, "UNIQUE constraint failed: oidc_tokens.sub")
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC token by refresh token",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{
|
||||
Sub: "sub-1",
|
||||
AccessTokenHash: "at-1",
|
||||
RefreshTokenHash: "rt-1",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := s.GetOidcTokenByRefreshToken(ctx, "rt-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "sub-1", got.Sub)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC token by refresh token not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetOidcTokenByRefreshToken(ctx, "missing")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC token by sub",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{
|
||||
Sub: "sub-1",
|
||||
AccessTokenHash: "at-1",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
got, err := s.GetOidcTokenBySub(ctx, "sub-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "at-1", got.AccessTokenHash)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC token by sub not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetOidcTokenBySub(ctx, "missing")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Update OIDC token by refresh token",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{
|
||||
Sub: "sub-1",
|
||||
AccessTokenHash: "at-1",
|
||||
RefreshTokenHash: "rt-1",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
updated, err := s.UpdateOidcTokenByRefreshToken(ctx, repository.UpdateOidcTokenByRefreshTokenParams{
|
||||
RefreshTokenHash_2: "rt-1",
|
||||
AccessTokenHash: "at-2",
|
||||
RefreshTokenHash: "rt-2",
|
||||
TokenExpiresAt: 200,
|
||||
RefreshTokenExpiresAt: 400,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "at-2", updated.AccessTokenHash)
|
||||
assert.Equal(t, "rt-2", updated.RefreshTokenHash)
|
||||
|
||||
// old key gone, new key present
|
||||
_, err = s.GetOidcToken(ctx, "at-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
|
||||
got, err := s.GetOidcToken(ctx, "at-2")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "sub-1", got.Sub)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Update OIDC token by refresh token not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.UpdateOidcTokenByRefreshToken(ctx, repository.UpdateOidcTokenByRefreshTokenParams{
|
||||
RefreshTokenHash_2: "missing",
|
||||
})
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete OIDC token",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{Sub: "sub-1", AccessTokenHash: "at-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.DeleteOidcToken(ctx, "at-1"))
|
||||
|
||||
_, err = s.GetOidcToken(ctx, "at-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete OIDC token by sub",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{Sub: "sub-1", AccessTokenHash: "at-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.DeleteOidcTokenBySub(ctx, "sub-1"))
|
||||
|
||||
_, err = s.GetOidcToken(ctx, "at-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete OIDC token by code hash",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{
|
||||
Sub: "sub-1",
|
||||
AccessTokenHash: "at-1",
|
||||
CodeHash: "code-1",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.DeleteOidcTokenByCodeHash(ctx, "code-1"))
|
||||
|
||||
_, err = s.GetOidcToken(ctx, "at-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete expired OIDC tokens",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
// both expiries past
|
||||
_, err := s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{
|
||||
Sub: "sub-1", AccessTokenHash: "at-1",
|
||||
TokenExpiresAt: 10, RefreshTokenExpiresAt: 10,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
// valid
|
||||
_, err = s.CreateOidcToken(ctx, repository.CreateOidcTokenParams{
|
||||
Sub: "sub-3", AccessTokenHash: "at-3",
|
||||
TokenExpiresAt: 100, RefreshTokenExpiresAt: 100,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
deleted, err := s.DeleteExpiredOidcTokens(ctx, repository.DeleteExpiredOidcTokensParams{
|
||||
TokenExpiresAt: 50,
|
||||
RefreshTokenExpiresAt: 50,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, deleted, 1)
|
||||
|
||||
_, err = s.GetOidcToken(ctx, "at-3")
|
||||
assert.NoError(t, err)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Create and get OIDC user info",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
u, err := s.CreateOidcUserInfo(ctx, repository.CreateOidcUserInfoParams{
|
||||
Sub: "sub-1",
|
||||
Name: "Alice",
|
||||
Email: "alice@example.com",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "sub-1", u.Sub)
|
||||
|
||||
got, err := s.GetOidcUserInfo(ctx, "sub-1")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, u, got)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get OIDC user info not found",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.GetOidcUserInfo(ctx, "missing")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Delete OIDC user info",
|
||||
run: func(t *testing.T, s repository.Store) {
|
||||
_, err := s.CreateOidcUserInfo(ctx, repository.CreateOidcUserInfoParams{Sub: "sub-1"})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, s.DeleteOidcUserInfo(ctx, "sub-1"))
|
||||
|
||||
_, err = s.GetOidcUserInfo(ctx, "sub-1")
|
||||
assert.ErrorIs(t, err, repository.ErrNotFound)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.description, func(t *testing.T) {
|
||||
s := memory.New()
|
||||
test.run(t, s)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/tinyauthapp/tinyauth/internal/repository"
|
||||
)
|
||||
|
||||
func (s *Store) CreateOidcCode(_ context.Context, arg repository.CreateOidcCodeParams) (repository.OidcCode, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
// Enforce sub UNIQUE constraint
|
||||
for _, c := range s.oidcCodes {
|
||||
if c.Sub == arg.Sub {
|
||||
return repository.OidcCode{}, fmt.Errorf("UNIQUE constraint failed: oidc_codes.sub")
|
||||
}
|
||||
}
|
||||
code := repository.OidcCode(arg)
|
||||
s.oidcCodes[arg.CodeHash] = code
|
||||
return code, nil
|
||||
}
|
||||
|
||||
// GetOidcCode is a destructive read: it deletes and returns the code (mirrors SQLite's DELETE...RETURNING).
|
||||
func (s *Store) GetOidcCode(_ context.Context, codeHash string) (repository.OidcCode, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
c, ok := s.oidcCodes[codeHash]
|
||||
if !ok {
|
||||
return repository.OidcCode{}, repository.ErrNotFound
|
||||
}
|
||||
delete(s.oidcCodes, codeHash)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// GetOidcCodeBySub is a destructive read: it deletes and returns the code (mirrors SQLite's DELETE...RETURNING).
|
||||
func (s *Store) GetOidcCodeBySub(_ context.Context, sub string) (repository.OidcCode, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for k, c := range s.oidcCodes {
|
||||
if c.Sub == sub {
|
||||
delete(s.oidcCodes, k)
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
return repository.OidcCode{}, repository.ErrNotFound
|
||||
}
|
||||
|
||||
// GetOidcCodeUnsafe is a non-destructive read (mirrors SQLite's SELECT).
|
||||
func (s *Store) GetOidcCodeUnsafe(_ context.Context, codeHash string) (repository.OidcCode, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
c, ok := s.oidcCodes[codeHash]
|
||||
if !ok {
|
||||
return repository.OidcCode{}, repository.ErrNotFound
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// GetOidcCodeBySubUnsafe is a non-destructive read (mirrors SQLite's SELECT).
|
||||
func (s *Store) GetOidcCodeBySubUnsafe(_ context.Context, sub string) (repository.OidcCode, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
for _, c := range s.oidcCodes {
|
||||
if c.Sub == sub {
|
||||
return c, nil
|
||||
}
|
||||
}
|
||||
return repository.OidcCode{}, repository.ErrNotFound
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcCode(_ context.Context, codeHash string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
delete(s.oidcCodes, codeHash)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcCodeBySub(_ context.Context, sub string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for k, c := range s.oidcCodes {
|
||||
if c.Sub == sub {
|
||||
delete(s.oidcCodes, k)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteExpiredOidcCodes(_ context.Context, expiresAt int64) ([]repository.OidcCode, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
var deleted []repository.OidcCode
|
||||
for k, c := range s.oidcCodes {
|
||||
if c.ExpiresAt < expiresAt {
|
||||
deleted = append(deleted, c)
|
||||
delete(s.oidcCodes, k)
|
||||
}
|
||||
}
|
||||
return deleted, nil
|
||||
}
|
||||
|
||||
func (s *Store) CreateOidcToken(_ context.Context, arg repository.CreateOidcTokenParams) (repository.OidcToken, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
// Enforce sub UNIQUE constraint
|
||||
for _, t := range s.oidcTokens {
|
||||
if t.Sub == arg.Sub {
|
||||
return repository.OidcToken{}, fmt.Errorf("UNIQUE constraint failed: oidc_tokens.sub")
|
||||
}
|
||||
}
|
||||
tok := repository.OidcToken{
|
||||
Sub: arg.Sub,
|
||||
AccessTokenHash: arg.AccessTokenHash,
|
||||
RefreshTokenHash: arg.RefreshTokenHash,
|
||||
CodeHash: arg.CodeHash,
|
||||
Scope: arg.Scope,
|
||||
ClientID: arg.ClientID,
|
||||
TokenExpiresAt: arg.TokenExpiresAt,
|
||||
RefreshTokenExpiresAt: arg.RefreshTokenExpiresAt,
|
||||
Nonce: arg.Nonce,
|
||||
}
|
||||
s.oidcTokens[arg.AccessTokenHash] = tok
|
||||
return tok, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcToken(_ context.Context, accessTokenHash string) (repository.OidcToken, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
t, ok := s.oidcTokens[accessTokenHash]
|
||||
if !ok {
|
||||
return repository.OidcToken{}, repository.ErrNotFound
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcTokenByRefreshToken(_ context.Context, refreshTokenHash string) (repository.OidcToken, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
for _, t := range s.oidcTokens {
|
||||
if t.RefreshTokenHash == refreshTokenHash {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
return repository.OidcToken{}, repository.ErrNotFound
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcTokenBySub(_ context.Context, sub string) (repository.OidcToken, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
for _, t := range s.oidcTokens {
|
||||
if t.Sub == sub {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
return repository.OidcToken{}, repository.ErrNotFound
|
||||
}
|
||||
|
||||
func (s *Store) UpdateOidcTokenByRefreshToken(_ context.Context, arg repository.UpdateOidcTokenByRefreshTokenParams) (repository.OidcToken, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for k, t := range s.oidcTokens {
|
||||
if t.RefreshTokenHash == arg.RefreshTokenHash_2 {
|
||||
delete(s.oidcTokens, k)
|
||||
t.AccessTokenHash = arg.AccessTokenHash
|
||||
t.RefreshTokenHash = arg.RefreshTokenHash
|
||||
t.TokenExpiresAt = arg.TokenExpiresAt
|
||||
t.RefreshTokenExpiresAt = arg.RefreshTokenExpiresAt
|
||||
s.oidcTokens[arg.AccessTokenHash] = t
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
return repository.OidcToken{}, repository.ErrNotFound
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcToken(_ context.Context, accessTokenHash string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
delete(s.oidcTokens, accessTokenHash)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcTokenBySub(_ context.Context, sub string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for k, t := range s.oidcTokens {
|
||||
if t.Sub == sub {
|
||||
delete(s.oidcTokens, k)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcTokenByCodeHash(_ context.Context, codeHash string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for k, t := range s.oidcTokens {
|
||||
if t.CodeHash == codeHash {
|
||||
delete(s.oidcTokens, k)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteExpiredOidcTokens(_ context.Context, arg repository.DeleteExpiredOidcTokensParams) ([]repository.OidcToken, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
var deleted []repository.OidcToken
|
||||
for k, t := range s.oidcTokens {
|
||||
if t.TokenExpiresAt < arg.TokenExpiresAt && t.RefreshTokenExpiresAt < arg.RefreshTokenExpiresAt {
|
||||
deleted = append(deleted, t)
|
||||
delete(s.oidcTokens, k)
|
||||
}
|
||||
}
|
||||
return deleted, nil
|
||||
}
|
||||
|
||||
func (s *Store) CreateOidcUserInfo(_ context.Context, arg repository.CreateOidcUserInfoParams) (repository.OidcUserinfo, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
u := repository.OidcUserinfo(arg)
|
||||
s.oidcUsers[arg.Sub] = u
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcUserInfo(_ context.Context, sub string) (repository.OidcUserinfo, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
u, ok := s.oidcUsers[sub]
|
||||
if !ok {
|
||||
return repository.OidcUserinfo{}, repository.ErrNotFound
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcUserInfo(_ context.Context, sub string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
delete(s.oidcUsers, sub)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package memory
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/tinyauthapp/tinyauth/internal/repository"
|
||||
)
|
||||
|
||||
func (s *Store) CreateSession(_ context.Context, arg repository.CreateSessionParams) (repository.Session, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
sess := repository.Session(arg)
|
||||
s.sessions[arg.UUID] = sess
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
func (s *Store) GetSession(_ context.Context, uuid string) (repository.Session, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
sess, ok := s.sessions[uuid]
|
||||
if !ok {
|
||||
return repository.Session{}, repository.ErrNotFound
|
||||
}
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateSession(_ context.Context, arg repository.UpdateSessionParams) (repository.Session, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
sess, ok := s.sessions[arg.UUID]
|
||||
if !ok {
|
||||
return repository.Session{}, repository.ErrNotFound
|
||||
}
|
||||
sess.Username = arg.Username
|
||||
sess.Email = arg.Email
|
||||
sess.Name = arg.Name
|
||||
sess.Provider = arg.Provider
|
||||
sess.TotpPending = arg.TotpPending
|
||||
sess.OAuthGroups = arg.OAuthGroups
|
||||
sess.Expiry = arg.Expiry
|
||||
sess.OAuthName = arg.OAuthName
|
||||
sess.OAuthSub = arg.OAuthSub
|
||||
s.sessions[arg.UUID] = sess
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteSession(_ context.Context, uuid string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
delete(s.sessions, uuid)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteExpiredSessions(_ context.Context, expiry int64) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
for k, v := range s.sessions {
|
||||
if v.Expiry < expiry {
|
||||
delete(s.sessions, k)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Package memory provides an in-memory implementation of repository.Store for use in tests.
|
||||
package memory
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/tinyauthapp/tinyauth/internal/repository"
|
||||
)
|
||||
|
||||
// Store is a thread-safe in-memory implementation of repository.Store.
|
||||
type Store struct {
|
||||
mu sync.RWMutex
|
||||
sessions map[string]repository.Session
|
||||
oidcCodes map[string]repository.OidcCode
|
||||
oidcTokens map[string]repository.OidcToken
|
||||
oidcUsers map[string]repository.OidcUserinfo
|
||||
}
|
||||
|
||||
// New returns a new empty in-memory Store.
|
||||
func New() repository.Store {
|
||||
return &Store{
|
||||
sessions: make(map[string]repository.Session),
|
||||
oidcCodes: make(map[string]repository.OidcCode),
|
||||
oidcTokens: make(map[string]repository.OidcToken),
|
||||
oidcUsers: make(map[string]repository.OidcUserinfo),
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,22 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
|
||||
package repository
|
||||
|
||||
// Shared model and parameter types for all storage drivers.
|
||||
// sqlc-generated driver packages use these via the conversion layer in their store.go.
|
||||
|
||||
type Session struct {
|
||||
UUID string
|
||||
Username string
|
||||
Email string
|
||||
Name string
|
||||
Provider string
|
||||
TotpPending bool
|
||||
OAuthGroups string
|
||||
Expiry int64
|
||||
CreatedAt int64
|
||||
OAuthName string
|
||||
OAuthSub string
|
||||
}
|
||||
|
||||
type OidcCode struct {
|
||||
Sub string
|
||||
CodeHash string
|
||||
@@ -49,7 +62,7 @@ type OidcUserinfo struct {
|
||||
Address string
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
type CreateSessionParams struct {
|
||||
UUID string
|
||||
Username string
|
||||
Email string
|
||||
@@ -62,3 +75,74 @@ type Session struct {
|
||||
OAuthName string
|
||||
OAuthSub string
|
||||
}
|
||||
|
||||
type UpdateSessionParams struct {
|
||||
Username string
|
||||
Email string
|
||||
Name string
|
||||
Provider string
|
||||
TotpPending bool
|
||||
OAuthGroups string
|
||||
Expiry int64
|
||||
OAuthName string
|
||||
OAuthSub string
|
||||
UUID string
|
||||
}
|
||||
|
||||
type CreateOidcCodeParams struct {
|
||||
Sub string
|
||||
CodeHash string
|
||||
Scope string
|
||||
RedirectURI string
|
||||
ClientID string
|
||||
ExpiresAt int64
|
||||
Nonce string
|
||||
CodeChallenge string
|
||||
}
|
||||
|
||||
type CreateOidcTokenParams struct {
|
||||
Sub string
|
||||
AccessTokenHash string
|
||||
RefreshTokenHash string
|
||||
Scope string
|
||||
ClientID string
|
||||
TokenExpiresAt int64
|
||||
RefreshTokenExpiresAt int64
|
||||
CodeHash string
|
||||
Nonce string
|
||||
}
|
||||
|
||||
type UpdateOidcTokenByRefreshTokenParams struct {
|
||||
AccessTokenHash string
|
||||
RefreshTokenHash string
|
||||
TokenExpiresAt int64
|
||||
RefreshTokenExpiresAt int64
|
||||
RefreshTokenHash_2 string
|
||||
}
|
||||
|
||||
type DeleteExpiredOidcTokensParams struct {
|
||||
TokenExpiresAt int64
|
||||
RefreshTokenExpiresAt int64
|
||||
}
|
||||
|
||||
type CreateOidcUserInfoParams struct {
|
||||
Sub string
|
||||
Name string
|
||||
PreferredUsername string
|
||||
Email string
|
||||
Groups string
|
||||
UpdatedAt int64
|
||||
GivenName string
|
||||
FamilyName string
|
||||
MiddleName string
|
||||
Nickname string
|
||||
Profile string
|
||||
Picture string
|
||||
Website string
|
||||
Gender string
|
||||
Birthdate string
|
||||
Zoneinfo string
|
||||
Locale string
|
||||
PhoneNumber string
|
||||
Address string
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// sqlc v1.31.1
|
||||
|
||||
package repository
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -0,0 +1,3 @@
|
||||
package sqlite
|
||||
|
||||
//go:generate go run github.com/tinyauthapp/tinyauth/gen/sqlc-wrapper -pkg github.com/tinyauthapp/tinyauth/internal/repository/sqlite
|
||||
@@ -0,0 +1,64 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package sqlite
|
||||
|
||||
type OidcCode struct {
|
||||
Sub string
|
||||
CodeHash string
|
||||
Scope string
|
||||
RedirectURI string
|
||||
ClientID string
|
||||
ExpiresAt int64
|
||||
Nonce string
|
||||
CodeChallenge string
|
||||
}
|
||||
|
||||
type OidcToken struct {
|
||||
Sub string
|
||||
AccessTokenHash string
|
||||
RefreshTokenHash string
|
||||
CodeHash string
|
||||
Scope string
|
||||
ClientID string
|
||||
TokenExpiresAt int64
|
||||
RefreshTokenExpiresAt int64
|
||||
Nonce string
|
||||
}
|
||||
|
||||
type OidcUserinfo struct {
|
||||
Sub string
|
||||
Name string
|
||||
PreferredUsername string
|
||||
Email string
|
||||
Groups string
|
||||
UpdatedAt int64
|
||||
GivenName string
|
||||
FamilyName string
|
||||
MiddleName string
|
||||
Nickname string
|
||||
Profile string
|
||||
Picture string
|
||||
Website string
|
||||
Gender string
|
||||
Birthdate string
|
||||
Zoneinfo string
|
||||
Locale string
|
||||
PhoneNumber string
|
||||
Address string
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
UUID string
|
||||
Username string
|
||||
Email string
|
||||
Name string
|
||||
Provider string
|
||||
TotpPending bool
|
||||
OAuthGroups string
|
||||
Expiry int64
|
||||
CreatedAt int64
|
||||
OAuthName string
|
||||
OAuthSub string
|
||||
}
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// sqlc v1.31.1
|
||||
// source: oidc_queries.sql
|
||||
|
||||
package repository
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.30.0
|
||||
// sqlc v1.31.1
|
||||
// source: session_queries.sql
|
||||
|
||||
package repository
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -0,0 +1,209 @@
|
||||
// Code generated by cmd/gen/sqlc-wrapper. DO NOT EDIT.
|
||||
package sqlite
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
|
||||
"github.com/tinyauthapp/tinyauth/internal/repository"
|
||||
)
|
||||
|
||||
// Store wraps *Queries and implements repository.Store.
|
||||
type Store struct {
|
||||
q *Queries
|
||||
}
|
||||
|
||||
// NewStore wraps a *Queries to satisfy repository.Store.
|
||||
func NewStore(q *Queries) repository.Store {
|
||||
return &Store{q: q}
|
||||
}
|
||||
|
||||
var errorMap = map[error]error{
|
||||
sql.ErrNoRows: repository.ErrNotFound,
|
||||
}
|
||||
|
||||
func mapErr(err error) error {
|
||||
for from, to := range errorMap {
|
||||
if errors.Is(err, from) {
|
||||
return to
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Store) CreateOidcCode(ctx context.Context, arg repository.CreateOidcCodeParams) (repository.OidcCode, error) {
|
||||
r, err := s.q.CreateOidcCode(ctx, CreateOidcCodeParams(arg))
|
||||
if err != nil {
|
||||
return repository.OidcCode{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcCode(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) CreateOidcToken(ctx context.Context, arg repository.CreateOidcTokenParams) (repository.OidcToken, error) {
|
||||
r, err := s.q.CreateOidcToken(ctx, CreateOidcTokenParams(arg))
|
||||
if err != nil {
|
||||
return repository.OidcToken{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcToken(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) CreateOidcUserInfo(ctx context.Context, arg repository.CreateOidcUserInfoParams) (repository.OidcUserinfo, error) {
|
||||
r, err := s.q.CreateOidcUserInfo(ctx, CreateOidcUserInfoParams(arg))
|
||||
if err != nil {
|
||||
return repository.OidcUserinfo{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcUserinfo(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) CreateSession(ctx context.Context, arg repository.CreateSessionParams) (repository.Session, error) {
|
||||
r, err := s.q.CreateSession(ctx, CreateSessionParams(arg))
|
||||
if err != nil {
|
||||
return repository.Session{}, mapErr(err)
|
||||
}
|
||||
return repository.Session(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteExpiredOidcCodes(ctx context.Context, expiresAt int64) ([]repository.OidcCode, error) {
|
||||
rows, err := s.q.DeleteExpiredOidcCodes(ctx, expiresAt)
|
||||
if err != nil {
|
||||
return nil, mapErr(err)
|
||||
}
|
||||
out := make([]repository.OidcCode, len(rows))
|
||||
for i, row := range rows {
|
||||
out[i] = repository.OidcCode(row)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteExpiredOidcTokens(ctx context.Context, arg repository.DeleteExpiredOidcTokensParams) ([]repository.OidcToken, error) {
|
||||
rows, err := s.q.DeleteExpiredOidcTokens(ctx, DeleteExpiredOidcTokensParams(arg))
|
||||
if err != nil {
|
||||
return nil, mapErr(err)
|
||||
}
|
||||
out := make([]repository.OidcToken, len(rows))
|
||||
for i, row := range rows {
|
||||
out[i] = repository.OidcToken(row)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (s *Store) DeleteExpiredSessions(ctx context.Context, expiry int64) error {
|
||||
return mapErr(s.q.DeleteExpiredSessions(ctx, expiry))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcCode(ctx context.Context, codeHash string) error {
|
||||
return mapErr(s.q.DeleteOidcCode(ctx, codeHash))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcCodeBySub(ctx context.Context, sub string) error {
|
||||
return mapErr(s.q.DeleteOidcCodeBySub(ctx, sub))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcToken(ctx context.Context, accessTokenHash string) error {
|
||||
return mapErr(s.q.DeleteOidcToken(ctx, accessTokenHash))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcTokenByCodeHash(ctx context.Context, codeHash string) error {
|
||||
return mapErr(s.q.DeleteOidcTokenByCodeHash(ctx, codeHash))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcTokenBySub(ctx context.Context, sub string) error {
|
||||
return mapErr(s.q.DeleteOidcTokenBySub(ctx, sub))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteOidcUserInfo(ctx context.Context, sub string) error {
|
||||
return mapErr(s.q.DeleteOidcUserInfo(ctx, sub))
|
||||
}
|
||||
|
||||
func (s *Store) DeleteSession(ctx context.Context, uuid string) error {
|
||||
return mapErr(s.q.DeleteSession(ctx, uuid))
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcCode(ctx context.Context, codeHash string) (repository.OidcCode, error) {
|
||||
r, err := s.q.GetOidcCode(ctx, codeHash)
|
||||
if err != nil {
|
||||
return repository.OidcCode{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcCode(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcCodeBySub(ctx context.Context, sub string) (repository.OidcCode, error) {
|
||||
r, err := s.q.GetOidcCodeBySub(ctx, sub)
|
||||
if err != nil {
|
||||
return repository.OidcCode{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcCode(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcCodeBySubUnsafe(ctx context.Context, sub string) (repository.OidcCode, error) {
|
||||
r, err := s.q.GetOidcCodeBySubUnsafe(ctx, sub)
|
||||
if err != nil {
|
||||
return repository.OidcCode{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcCode(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcCodeUnsafe(ctx context.Context, codeHash string) (repository.OidcCode, error) {
|
||||
r, err := s.q.GetOidcCodeUnsafe(ctx, codeHash)
|
||||
if err != nil {
|
||||
return repository.OidcCode{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcCode(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcToken(ctx context.Context, accessTokenHash string) (repository.OidcToken, error) {
|
||||
r, err := s.q.GetOidcToken(ctx, accessTokenHash)
|
||||
if err != nil {
|
||||
return repository.OidcToken{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcToken(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcTokenByRefreshToken(ctx context.Context, refreshTokenHash string) (repository.OidcToken, error) {
|
||||
r, err := s.q.GetOidcTokenByRefreshToken(ctx, refreshTokenHash)
|
||||
if err != nil {
|
||||
return repository.OidcToken{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcToken(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcTokenBySub(ctx context.Context, sub string) (repository.OidcToken, error) {
|
||||
r, err := s.q.GetOidcTokenBySub(ctx, sub)
|
||||
if err != nil {
|
||||
return repository.OidcToken{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcToken(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetOidcUserInfo(ctx context.Context, sub string) (repository.OidcUserinfo, error) {
|
||||
r, err := s.q.GetOidcUserInfo(ctx, sub)
|
||||
if err != nil {
|
||||
return repository.OidcUserinfo{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcUserinfo(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) GetSession(ctx context.Context, uuid string) (repository.Session, error) {
|
||||
r, err := s.q.GetSession(ctx, uuid)
|
||||
if err != nil {
|
||||
return repository.Session{}, mapErr(err)
|
||||
}
|
||||
return repository.Session(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateOidcTokenByRefreshToken(ctx context.Context, arg repository.UpdateOidcTokenByRefreshTokenParams) (repository.OidcToken, error) {
|
||||
r, err := s.q.UpdateOidcTokenByRefreshToken(ctx, UpdateOidcTokenByRefreshTokenParams(arg))
|
||||
if err != nil {
|
||||
return repository.OidcToken{}, mapErr(err)
|
||||
}
|
||||
return repository.OidcToken(r), nil
|
||||
}
|
||||
|
||||
func (s *Store) UpdateSession(ctx context.Context, arg repository.UpdateSessionParams) (repository.Session, error) {
|
||||
r, err := s.q.UpdateSession(ctx, UpdateSessionParams(arg))
|
||||
if err != nil {
|
||||
return repository.Session{}, mapErr(err)
|
||||
}
|
||||
return repository.Session(r), nil
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
)
|
||||
|
||||
// ErrNotFound is returned by Store methods when the requested record does not exist.
|
||||
var ErrNotFound = errors.New("not found")
|
||||
|
||||
// Store is the interface that all storage drivers must implement.
|
||||
// The sqlc-generated *Queries struct satisfies this interface for SQLite.
|
||||
// Future drivers (postgres, etc.) must return the shared types defined in this package.
|
||||
type Store interface {
|
||||
// Sessions
|
||||
CreateSession(ctx context.Context, arg CreateSessionParams) (Session, error)
|
||||
GetSession(ctx context.Context, uuid string) (Session, error)
|
||||
UpdateSession(ctx context.Context, arg UpdateSessionParams) (Session, error)
|
||||
DeleteSession(ctx context.Context, uuid string) error
|
||||
DeleteExpiredSessions(ctx context.Context, expiry int64) error
|
||||
|
||||
// OIDC codes
|
||||
CreateOidcCode(ctx context.Context, arg CreateOidcCodeParams) (OidcCode, error)
|
||||
GetOidcCode(ctx context.Context, codeHash string) (OidcCode, error)
|
||||
GetOidcCodeBySub(ctx context.Context, sub string) (OidcCode, error)
|
||||
GetOidcCodeUnsafe(ctx context.Context, codeHash string) (OidcCode, error)
|
||||
GetOidcCodeBySubUnsafe(ctx context.Context, sub string) (OidcCode, error)
|
||||
DeleteOidcCode(ctx context.Context, codeHash string) error
|
||||
DeleteOidcCodeBySub(ctx context.Context, sub string) error
|
||||
DeleteExpiredOidcCodes(ctx context.Context, expiresAt int64) ([]OidcCode, error)
|
||||
|
||||
// OIDC tokens
|
||||
CreateOidcToken(ctx context.Context, arg CreateOidcTokenParams) (OidcToken, error)
|
||||
GetOidcToken(ctx context.Context, accessTokenHash string) (OidcToken, error)
|
||||
GetOidcTokenByRefreshToken(ctx context.Context, refreshTokenHash string) (OidcToken, error)
|
||||
GetOidcTokenBySub(ctx context.Context, sub string) (OidcToken, error)
|
||||
UpdateOidcTokenByRefreshToken(ctx context.Context, arg UpdateOidcTokenByRefreshTokenParams) (OidcToken, error)
|
||||
DeleteOidcToken(ctx context.Context, accessTokenHash string) error
|
||||
DeleteOidcTokenBySub(ctx context.Context, sub string) error
|
||||
DeleteOidcTokenByCodeHash(ctx context.Context, codeHash string) error
|
||||
DeleteExpiredOidcTokens(ctx context.Context, arg DeleteExpiredOidcTokensParams) ([]OidcToken, error)
|
||||
|
||||
// OIDC userinfo
|
||||
CreateOidcUserInfo(ctx context.Context, arg CreateOidcUserInfoParams) (OidcUserinfo, error)
|
||||
GetOidcUserInfo(ctx context.Context, sub string) (OidcUserinfo, error)
|
||||
DeleteOidcUserInfo(ctx context.Context, sub string) error
|
||||
}
|
||||
Reference in New Issue
Block a user