Browse Source

refactor(storage): avoid using Sprintf to update session fields

Frédéric Guillot 3 months ago
parent
commit
5db66fc279
3 changed files with 25 additions and 22 deletions
  1. 12 11
      internal/storage/session.go
  2. 2 1
      internal/storage/user.go
  3. 11 10
      internal/ui/session/session.go

+ 12 - 11
internal/storage/session.go

@@ -53,36 +53,37 @@ func (s *Storage) createAppSession(session *model.Session) (*model.Session, erro
 	return session, nil
 }
 
-// UpdateAppSessionField updates only one session field.
-func (s *Storage) UpdateAppSessionField(sessionID, field string, value any) error {
+// SetAppSessionTextField sets a text field in the session data.
+func (s *Storage) SetAppSessionTextField(sessionID, field string, value any) error {
 	query := `
 		UPDATE
 			sessions
 		SET
-			data = jsonb_set(data, '{%s}', to_jsonb($1::text), true)
+			data = jsonb_set(data, ARRAY[$2::text], to_jsonb($1::text), true)
 		WHERE
-			id=$2
+			id=$3
 	`
-	_, err := s.db.Exec(fmt.Sprintf(query, field), value, sessionID)
+	_, err := s.db.Exec(query, value, field, sessionID)
 	if err != nil {
-		return fmt.Errorf(`store: unable to update session field: %v`, err)
+		return fmt.Errorf(`store: unable to update session text field %q: %v`, field, err)
 	}
 
 	return nil
 }
 
-func (s *Storage) UpdateAppSessionObjectField(sessionID, field string, value any) error {
+// SetAppSessionJSONField sets a JSON field in the session data.
+func (s *Storage) SetAppSessionJSONField(sessionID, field string, value any) error {
 	query := `
 		UPDATE
 			sessions
 		SET
-			data = jsonb_set(data, '{%s}', $1, true)
+			data = jsonb_set(data, ARRAY[$2::text], $1, true)
 		WHERE
-			id=$2
+			id=$3
 	`
-	_, err := s.db.Exec(fmt.Sprintf(query, field), value, sessionID)
+	_, err := s.db.Exec(query, value, field, sessionID)
 	if err != nil {
-		return fmt.Errorf(`store: unable to update session field: %v`, err)
+		return fmt.Errorf(`store: unable to update session JSON field %q: %v`, field, err)
 	}
 
 	return nil

+ 2 - 1
internal/storage/user.go

@@ -472,7 +472,8 @@ func (s *Storage) UserByField(field, value string) (*model.User, error) {
 // AnotherUserWithFieldExists returns true if a user has the value set for the given field.
 func (s *Storage) AnotherUserWithFieldExists(userID int64, field, value string) bool {
 	var result bool
-	s.db.QueryRow(fmt.Sprintf(`SELECT true FROM users WHERE id <> $1 AND %s=$2 LIMIT 1`, pq.QuoteIdentifier(field)), userID, value).Scan(&result)
+	query := `SELECT true FROM users WHERE id <> $1 AND ` + pq.QuoteIdentifier(field) + `=$2 LIMIT 1`
+	s.db.QueryRow(query, userID, value).Scan(&result)
 	return result
 }
 

+ 11 - 10
internal/ui/session/session.go

@@ -22,53 +22,54 @@ func New(store *storage.Storage, sessionID string) *Session {
 }
 
 func (s *Session) SetLastForceRefresh() {
-	s.store.UpdateAppSessionField(s.sessionID, "last_force_refresh", time.Now().UTC().Unix())
+	s.store.SetAppSessionTextField(s.sessionID, "last_force_refresh", time.Now().UTC().Unix())
 }
 
 func (s *Session) SetOAuth2State(state string) {
-	s.store.UpdateAppSessionField(s.sessionID, "oauth2_state", state)
+	s.store.SetAppSessionTextField(s.sessionID, "oauth2_state", state)
 }
 
 func (s *Session) SetOAuth2CodeVerifier(codeVerfier string) {
-	s.store.UpdateAppSessionField(s.sessionID, "oauth2_code_verifier", codeVerfier)
+	s.store.SetAppSessionTextField(s.sessionID, "oauth2_code_verifier", codeVerfier)
 }
 
 // NewFlashMessage creates a new flash message.
 func (s *Session) NewFlashMessage(message string) {
-	s.store.UpdateAppSessionField(s.sessionID, "flash_message", message)
+	s.store.SetAppSessionTextField(s.sessionID, "flash_message", message)
 }
 
 // FlashMessage returns the current flash message if any.
 func (s *Session) FlashMessage(message string) string {
 	if message != "" {
-		s.store.UpdateAppSessionField(s.sessionID, "flash_message", "")
+		s.store.SetAppSessionTextField(s.sessionID, "flash_message", "")
 	}
 	return message
 }
 
 // NewFlashErrorMessage creates a new flash error message.
 func (s *Session) NewFlashErrorMessage(message string) {
-	s.store.UpdateAppSessionField(s.sessionID, "flash_error_message", message)
+	s.store.SetAppSessionTextField(s.sessionID, "flash_error_message", message)
 }
 
 // FlashErrorMessage returns the last flash error message if any.
 func (s *Session) FlashErrorMessage(message string) string {
 	if message != "" {
-		s.store.UpdateAppSessionField(s.sessionID, "flash_error_message", "")
+		s.store.SetAppSessionTextField(s.sessionID, "flash_error_message", "")
 	}
 	return message
 }
 
 // SetLanguage updates the language field in session.
 func (s *Session) SetLanguage(language string) {
-	s.store.UpdateAppSessionField(s.sessionID, "language", language)
+	s.store.SetAppSessionTextField(s.sessionID, "language", language)
 }
 
 // SetTheme updates the theme field in session.
 func (s *Session) SetTheme(theme string) {
-	s.store.UpdateAppSessionField(s.sessionID, "theme", theme)
+	s.store.SetAppSessionTextField(s.sessionID, "theme", theme)
 }
 
+// SetWebAuthnSessionData sets the WebAuthn session data.
 func (s *Session) SetWebAuthnSessionData(sessionData *model.WebAuthnSession) {
-	s.store.UpdateAppSessionObjectField(s.sessionID, "webauthn_session_data", sessionData)
+	s.store.SetAppSessionJSONField(s.sessionID, "webauthn_session_data", sessionData)
 }