Files
Agent-System/internal/auth/session.go
T
weichen d8c445bfd5 feat(auth): persist sessions and accounts via PostgresAuthStore
Add PgStore with hashed token sessions, IAM bootstrap, and store factory wiring; remove in-memory token map and allow_dev_switch from login payload.
2026-09-13 02:50:22 +00:00

78 lines
2.0 KiB
Go

package auth
import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"time"
)
var errSessionNotFound = errors.New("session not found or expired")
const (
defaultIdleSessionTTL = 24 * time.Hour
defaultAbsoluteSessionTTL = 7 * 24 * time.Hour
)
// SessionMeta 创建会话时的客户端元数据(可选)。
type SessionMeta struct {
IPHash string
UserAgent string
}
// SessionStore 持久化或内存会话存储。
type SessionStore interface {
CreateSession(ctx context.Context, userID int64, tokenHash string, meta SessionMeta) error
ResolveUserID(ctx context.Context, tokenHash string) (int64, error)
TouchSession(ctx context.Context, tokenHash string) error
RevokeByTokenHash(ctx context.Context, tokenHash string) error
RevokeAllForUser(ctx context.Context, userID int64) error
}
// HashToken 将会话 token 转为存储用 SHA-256 十六进制摘要。
func HashToken(token string) string {
sum := sha256.Sum256([]byte(token))
return hex.EncodeToString(sum[:])
}
// MemorySessionStore 进程内 token 映射(仅 dev/stub fallback)。
type MemorySessionStore struct {
tokens map[string]int64
}
func NewMemorySessionStore() *MemorySessionStore {
return &MemorySessionStore{tokens: make(map[string]int64)}
}
func (s *MemorySessionStore) CreateSession(_ context.Context, userID int64, tokenHash string, _ SessionMeta) error {
s.tokens[tokenHash] = userID
return nil
}
func (s *MemorySessionStore) ResolveUserID(_ context.Context, tokenHash string) (int64, error) {
userID, ok := s.tokens[tokenHash]
if !ok {
return 0, errSessionNotFound
}
return userID, nil
}
func (s *MemorySessionStore) TouchSession(_ context.Context, _ string) error {
return nil
}
func (s *MemorySessionStore) RevokeByTokenHash(_ context.Context, tokenHash string) error {
delete(s.tokens, tokenHash)
return nil
}
func (s *MemorySessionStore) RevokeAllForUser(_ context.Context, userID int64) error {
for tok, uid := range s.tokens {
if uid == userID {
delete(s.tokens, tok)
}
}
return nil
}