3.28.3: Исправлена проблема с refresh token
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 54s

This commit is contained in:
poignatov
2026-01-25 15:46:24 +03:00
parent ef1d6fb59a
commit fe3721a56f
3 changed files with 37 additions and 8 deletions

View File

@@ -1 +1 @@
3.28.2
3.28.3

View File

@@ -1018,10 +1018,7 @@ func (a *App) refreshTokenHandler(w http.ResponseWriter, r *http.Request) {
return
}
// Delete old refresh token
a.DB.Exec("DELETE FROM refresh_tokens WHERE id = $1", foundTokenID)
// Generate new tokens
// Generate new tokens FIRST before deleting old one to prevent race condition
accessToken, err := a.generateAccessToken(user.ID)
if err != nil {
log.Printf("Error generating access token: %v", err)
@@ -1036,12 +1033,21 @@ func (a *App) refreshTokenHandler(w http.ResponseWriter, r *http.Request) {
return
}
// Store new refresh token
// Store new refresh token FIRST
refreshTokenHash, _ := hashPassword(refreshToken)
a.DB.Exec(`
_, err = a.DB.Exec(`
INSERT INTO refresh_tokens (user_id, token_hash, expires_at)
VALUES ($1, $2, $3)
`, user.ID, refreshTokenHash, nil)
if err != nil {
log.Printf("Error storing new refresh token: %v", err)
sendErrorWithCORS(w, "Error generating token", http.StatusInternalServerError)
return
}
// Delete old refresh token AFTER new one is successfully stored
// This prevents race condition where multiple refresh requests might use the same token
a.DB.Exec("DELETE FROM refresh_tokens WHERE id = $1", foundTokenID)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(TokenResponse{
@@ -2818,6 +2824,29 @@ func (a *App) initAuthDB() error {
a.DB.Exec("CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_id ON refresh_tokens(user_id)")
a.DB.Exec("CREATE INDEX IF NOT EXISTS idx_refresh_tokens_token_hash ON refresh_tokens(token_hash)")
// Apply migration 014: Make refresh tokens permanent (expires_at nullable)
// This allows refresh tokens to never expire
var isNullable string
err = a.DB.QueryRow(`
SELECT is_nullable
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'refresh_tokens'
AND column_name = 'expires_at'
`).Scan(&isNullable)
if err == nil && isNullable == "NO" {
// Column is NOT NULL, need to make it nullable
if _, err := a.DB.Exec("ALTER TABLE refresh_tokens ALTER COLUMN expires_at DROP NOT NULL"); err != nil {
log.Printf("Warning: Failed to apply migration 014 (make expires_at nullable): %v", err)
} else {
log.Printf("Migration 014 applied: refresh_tokens.expires_at is now nullable")
}
} else if err == nil && isNullable == "YES" {
// Migration already applied
log.Printf("Migration 014 already applied (expires_at is nullable), skipping")
}
// If err != nil, column might not exist yet (shouldn't happen, but ignore)
// Add user_id column to all tables if not exists
tables := []string{"projects", "entries", "nodes", "dictionaries", "words", "progress", "configs", "telegram_integrations", "weekly_goals", "tasks"}
for _, table := range tables {

View File

@@ -1,6 +1,6 @@
{
"name": "play-life-web",
"version": "3.28.2",
"version": "3.28.3",
"type": "module",
"scripts": {
"dev": "vite",