mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-05-06 04:18:10 +00:00
feat(db): add memory storage driver
removes the sqlite dependency for tests, also brings back the option for users to run zero persistence instances of tinyauth. adds new mapErr fn for sqlc wrapper gen to prevent sql errors from leaking out of the store implementation.
This commit is contained in:
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user