feat: 实现内存 UserRepository(测试用)
This commit is contained in:
120
backend/internal/store/user_mem.go
Normal file
120
backend/internal/store/user_mem.go
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
package store
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MemUserRepository 基于内存的 UserRepository 实现(测试用)。
|
||||||
|
type MemUserRepository struct {
|
||||||
|
mu sync.RWMutex
|
||||||
|
users map[string]*User // id -> user
|
||||||
|
byUsername map[string]string // username -> id
|
||||||
|
refreshTokens map[string]string // tokenHash -> userID
|
||||||
|
tokenExpiry map[string]time.Time // tokenHash -> expiresAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMemUserRepository 创建 MemUserRepository。
|
||||||
|
func NewMemUserRepository() *MemUserRepository {
|
||||||
|
return &MemUserRepository{
|
||||||
|
users: make(map[string]*User),
|
||||||
|
byUsername: make(map[string]string),
|
||||||
|
refreshTokens: make(map[string]string),
|
||||||
|
tokenExpiry: make(map[string]time.Time),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MemUserRepository) Create(_ context.Context, username, passwordHash string) (string, error) {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
if _, exists := r.byUsername[username]; exists {
|
||||||
|
return "", ErrUsernameTaken
|
||||||
|
}
|
||||||
|
|
||||||
|
id := uuid.New().String()
|
||||||
|
now := time.Now()
|
||||||
|
user := &User{
|
||||||
|
ID: id,
|
||||||
|
Username: username,
|
||||||
|
PasswordHash: passwordHash,
|
||||||
|
CreatedAt: now,
|
||||||
|
UpdatedAt: now,
|
||||||
|
}
|
||||||
|
r.users[id] = user
|
||||||
|
r.byUsername[username] = id
|
||||||
|
return id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MemUserRepository) FindByUsername(_ context.Context, username string) (*User, error) {
|
||||||
|
r.mu.RLock()
|
||||||
|
defer r.mu.RUnlock()
|
||||||
|
|
||||||
|
id, ok := r.byUsername[username]
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrUserNotFound
|
||||||
|
}
|
||||||
|
u := r.users[id]
|
||||||
|
copy := *u
|
||||||
|
return ©, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MemUserRepository) FindByID(_ context.Context, id string) (*User, error) {
|
||||||
|
r.mu.RLock()
|
||||||
|
defer r.mu.RUnlock()
|
||||||
|
|
||||||
|
u, ok := r.users[id]
|
||||||
|
if !ok {
|
||||||
|
return nil, ErrUserNotFound
|
||||||
|
}
|
||||||
|
copy := *u
|
||||||
|
return ©, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MemUserRepository) SaveRefreshToken(_ context.Context, userID, tokenHash string, expiresAt time.Time) error {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
r.refreshTokens[tokenHash] = userID
|
||||||
|
r.tokenExpiry[tokenHash] = expiresAt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MemUserRepository) FindRefreshToken(_ context.Context, tokenHash string) (string, error) {
|
||||||
|
r.mu.RLock()
|
||||||
|
defer r.mu.RUnlock()
|
||||||
|
|
||||||
|
userID, ok := r.refreshTokens[tokenHash]
|
||||||
|
if !ok {
|
||||||
|
return "", ErrRefreshTokenNotFound
|
||||||
|
}
|
||||||
|
if time.Now().After(r.tokenExpiry[tokenHash]) {
|
||||||
|
return "", ErrRefreshTokenNotFound
|
||||||
|
}
|
||||||
|
return userID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MemUserRepository) DeleteRefreshToken(_ context.Context, tokenHash string) error {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
delete(r.refreshTokens, tokenHash)
|
||||||
|
delete(r.tokenExpiry, tokenHash)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *MemUserRepository) DeleteUserRefreshTokens(_ context.Context, userID string) error {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
for hash, uid := range r.refreshTokens {
|
||||||
|
if uid == userID {
|
||||||
|
delete(r.refreshTokens, hash)
|
||||||
|
delete(r.tokenExpiry, hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user