Ver Fonte

Use SQL transaction when creating user sessions

Frédéric Guillot há 5 anos atrás
pai
commit
60a7362327
4 ficheiros alterados com 27 adições e 11 exclusões
  1. 23 7
      storage/user_session.go
  2. 2 2
      ui/login_check.go
  3. 1 1
      ui/middleware.go
  4. 1 1
      ui/oauth2_callback.go

+ 23 - 7
storage/user_session.go

@@ -55,21 +55,37 @@ func (s *Storage) UserSessions(userID int64) (model.UserSessions, error) {
 	return sessions, nil
 }
 
-// CreateUserSession creates a new sessions.
-func (s *Storage) CreateUserSession(username, userAgent, ip string) (sessionID string, userID int64, err error) {
-	query := `SELECT id FROM users WHERE username = LOWER($1)`
-	err = s.db.QueryRow(query, username).Scan(&userID)
+// CreateUserSessionFromUsername creates a new user session.
+func (s *Storage) CreateUserSessionFromUsername(username, userAgent, ip string) (sessionID string, userID int64, err error) {
+	token := crypto.GenerateRandomString(64)
+
+	tx, err := s.db.Begin()
+	if err != nil {
+		return "", 0, fmt.Errorf(`store: unable to start transaction: %v`, err)
+	}
+
+	err = tx.QueryRow(`SELECT id FROM users WHERE username = LOWER($1)`, username).Scan(&userID)
 	if err != nil {
+		tx.Rollback()
 		return "", 0, fmt.Errorf(`store: unable to fetch user ID: %v`, err)
 	}
 
-	token := crypto.GenerateRandomString(64)
-	query = `INSERT INTO user_sessions (token, user_id, user_agent, ip) VALUES ($1, $2, $3, $4)`
-	_, err = s.db.Exec(query, token, userID, userAgent, ip)
+	_, err = tx.Exec(
+		`INSERT INTO user_sessions (token, user_id, user_agent, ip) VALUES ($1, $2, $3, $4)`,
+		token,
+		userID,
+		userAgent,
+		ip,
+	)
 	if err != nil {
+		tx.Rollback()
 		return "", 0, fmt.Errorf(`store: unable to create user session: %v`, err)
 	}
 
+	if err := tx.Commit(); err != nil {
+		return "", 0, fmt.Errorf(`store: unable to commit transaction: %v`, err)
+	}
+
 	return token, userID, nil
 }
 

+ 2 - 2
ui/login_check.go

@@ -1,4 +1,4 @@
-package ui  // import "miniflux.app/ui"
+package ui // import "miniflux.app/ui"
 
 import (
 	"net/http"
@@ -35,7 +35,7 @@ func (h *handler) checkLogin(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	sessionToken, userID, err := h.store.CreateUserSession(authForm.Username, r.UserAgent(), clientIP)
+	sessionToken, userID, err := h.store.CreateUserSessionFromUsername(authForm.Username, r.UserAgent(), clientIP)
 	if err != nil {
 		html.ServerError(w, r, err)
 		return

+ 1 - 1
ui/middleware.go

@@ -204,7 +204,7 @@ func (m *middleware) handleAuthProxy(next http.Handler) http.Handler {
 			}
 		}
 
-		sessionToken, _, err := m.store.CreateUserSession(user.Username, r.UserAgent(), clientIP)
+		sessionToken, _, err := m.store.CreateUserSessionFromUsername(user.Username, r.UserAgent(), clientIP)
 		if err != nil {
 			html.ServerError(w, r, err)
 			return

+ 1 - 1
ui/oauth2_callback.go

@@ -114,7 +114,7 @@ func (h *handler) oauth2Callback(w http.ResponseWriter, r *http.Request) {
 		}
 	}
 
-	sessionToken, _, err := h.store.CreateUserSession(user.Username, r.UserAgent(), clientIP)
+	sessionToken, _, err := h.store.CreateUserSessionFromUsername(user.Username, r.UserAgent(), clientIP)
 	if err != nil {
 		html.ServerError(w, r, err)
 		return