refactor: extract proxy token store

This commit is contained in:
2026-06-13 22:06:07 +02:00
parent 837b99bc58
commit d6f1c37ac3
2 changed files with 69 additions and 63 deletions

View File

@@ -0,0 +1,69 @@
package playback
import (
"crypto/rand"
"encoding/base64"
"fmt"
"sync"
"time"
)
type proxyTokenTarget struct {
targetURL string
referer string
scope string
expiresAt time.Time
}
type proxyTokenStore struct {
mu sync.Mutex
tokens map[string]proxyTokenTarget
}
func newProxyTokenStore() *proxyTokenStore {
return &proxyTokenStore{
tokens: make(map[string]proxyTokenTarget),
}
}
func (s *proxyTokenStore) create(targetURL, referer, scope string, ttl time.Duration, now time.Time) (string, error) {
tokenBytes := make([]byte, 32)
if _, err := rand.Read(tokenBytes); err != nil {
return "", fmt.Errorf("generate proxy token: %w", err)
}
token := base64.RawURLEncoding.EncodeToString(tokenBytes)
s.mu.Lock()
defer s.mu.Unlock()
s.pruneExpiredLocked(now)
s.tokens[token] = proxyTokenTarget{
targetURL: targetURL,
referer: referer,
scope: scope,
expiresAt: now.Add(ttl),
}
return token, nil
}
func (s *proxyTokenStore) resolve(token string, now time.Time) (proxyTokenTarget, error) {
s.mu.Lock()
defer s.mu.Unlock()
target, ok := s.tokens[token]
if !ok {
return proxyTokenTarget{}, fmt.Errorf("invalid proxy token")
}
if !target.expiresAt.After(now) {
delete(s.tokens, token)
return proxyTokenTarget{}, fmt.Errorf("proxy token expired")
}
return target, nil
}
func (s *proxyTokenStore) pruneExpiredLocked(now time.Time) {
for token, target := range s.tokens {
if !target.expiresAt.After(now) {
delete(s.tokens, token)
}
}
}

View File

@@ -3,9 +3,7 @@ package playback
import (
"context"
"crypto/rand"
"database/sql"
"encoding/base64"
"encoding/json"
"fmt"
"io"
@@ -19,7 +17,6 @@ import (
"sort"
"strconv"
"strings"
"sync"
"time"
"github.com/google/uuid"
@@ -38,66 +35,6 @@ type playbackService struct {
type ProxyTokenKey string
type proxyTokenTarget struct {
targetURL string
referer string
scope string
expiresAt time.Time
}
type proxyTokenStore struct {
mu sync.Mutex
tokens map[string]proxyTokenTarget
}
func newProxyTokenStore() *proxyTokenStore {
return &proxyTokenStore{
tokens: make(map[string]proxyTokenTarget),
}
}
func (s *proxyTokenStore) create(targetURL, referer, scope string, ttl time.Duration, now time.Time) (string, error) {
tokenBytes := make([]byte, 32)
if _, err := rand.Read(tokenBytes); err != nil {
return "", fmt.Errorf("generate proxy token: %w", err)
}
token := base64.RawURLEncoding.EncodeToString(tokenBytes)
s.mu.Lock()
defer s.mu.Unlock()
s.pruneExpiredLocked(now)
s.tokens[token] = proxyTokenTarget{
targetURL: targetURL,
referer: referer,
scope: scope,
expiresAt: now.Add(ttl),
}
return token, nil
}
func (s *proxyTokenStore) resolve(token string, now time.Time) (proxyTokenTarget, error) {
s.mu.Lock()
defer s.mu.Unlock()
target, ok := s.tokens[token]
if !ok {
return proxyTokenTarget{}, fmt.Errorf("invalid proxy token")
}
if !target.expiresAt.After(now) {
delete(s.tokens, token)
return proxyTokenTarget{}, fmt.Errorf("proxy token expired")
}
return target, nil
}
func (s *proxyTokenStore) pruneExpiredLocked(now time.Time) {
for token, target := range s.tokens {
if !target.expiresAt.After(now) {
delete(s.tokens, token)
}
}
}
func NewPlaybackService(repo domain.PlaybackRepository, providers []domain.Provider, jikan *jikan.Client, episodes domain.EpisodeService, auditSvc domain.AuditService, proxyTokenKey ProxyTokenKey) domain.PlaybackService {
return &playbackService{
repo: repo,