Răsfoiți Sursa

Handle the case when application session is expired and not user session

Frédéric Guillot 7 ani în urmă
părinte
comite
7897d8a8ad
5 a modificat fișierele cu 62 adăugiri și 29 ștergeri
  1. 1 1
      model/app_session.go
  2. 36 12
      storage/session.go
  3. 16 7
      ui/middleware.go
  4. 8 8
      ui/session/session.go
  5. 1 1
      ui/ui.go

+ 1 - 1
model/app_session.go

@@ -18,7 +18,7 @@ type SessionData struct {
 	FlashMessage       string `json:"flash_message"`
 	FlashErrorMessage  string `json:"flash_error_message"`
 	Language           string `json:"language"`
-	Theme              string `json:"Theme"`
+	Theme              string `json:"theme"`
 	PocketRequestToken string `json:"pocket_request_token"`
 }
 

+ 36 - 12
storage/session.go

@@ -12,24 +12,48 @@ import (
 	"miniflux.app/model"
 )
 
-// CreateSession creates a new session.
-func (s *Storage) CreateSession() (*model.Session, error) {
+// CreateAppSessionWithUserPrefs creates a new application session with the given user preferences.
+func (s *Storage) CreateAppSessionWithUserPrefs(userID int64) (*model.Session, error) {
+	user, err := s.UserByID(userID)
+	if err != nil {
+		return nil, err
+	}
+
 	session := model.Session{
-		ID:   crypto.GenerateRandomString(32),
-		Data: &model.SessionData{CSRF: crypto.GenerateRandomString(64)},
+		ID: crypto.GenerateRandomString(32),
+		Data: &model.SessionData{
+			CSRF:     crypto.GenerateRandomString(64),
+			Theme:    user.Theme,
+			Language: user.Language,
+		},
 	}
 
-	query := "INSERT INTO sessions (id, data) VALUES ($1, $2)"
-	_, err := s.db.Exec(query, session.ID, session.Data)
+	return s.createAppSession(&session)
+}
+
+// CreateAppSession creates a new application session.
+func (s *Storage) CreateAppSession() (*model.Session, error) {
+	session := model.Session{
+		ID: crypto.GenerateRandomString(32),
+		Data: &model.SessionData{
+			CSRF: crypto.GenerateRandomString(64),
+		},
+	}
+
+	return s.createAppSession(&session)
+}
+
+func (s *Storage) createAppSession(session *model.Session) (*model.Session, error) {
+	_, err := s.db.Exec(`INSERT INTO sessions (id, data) VALUES ($1, $2)`, session.ID, session.Data)
 	if err != nil {
-		return nil, fmt.Errorf("unable to create session: %v", err)
+		return nil, fmt.Errorf("unable to create app session: %v", err)
 	}
 
-	return &session, nil
+	return session, nil
 }
 
-// UpdateSessionField updates only one session field.
-func (s *Storage) UpdateSessionField(sessionID, field string, value interface{}) error {
+// UpdateAppSessionField updates only one session field.
+func (s *Storage) UpdateAppSessionField(sessionID, field string, value interface{}) error {
 	query := `UPDATE sessions
 		SET data = jsonb_set(data, '{%s}', to_jsonb($1::text), true)
 		WHERE id=$2`
@@ -42,8 +66,8 @@ func (s *Storage) UpdateSessionField(sessionID, field string, value interface{})
 	return nil
 }
 
-// Session returns the given session.
-func (s *Storage) Session(id string) (*model.Session, error) {
+// AppSession returns the given session.
+func (s *Storage) AppSession(id string) (*model.Session, error) {
 	var session model.Session
 
 	query := "SELECT id, data FROM sessions WHERE id=$1"

+ 16 - 7
ui/middleware.go

@@ -61,12 +61,21 @@ func (m *middleware) handleAppSession(next http.Handler) http.Handler {
 		session := m.getAppSessionValueFromCookie(r)
 
 		if session == nil {
-			logger.Debug("[UI:AppSession] Session not found")
-
-			session, err = m.store.CreateSession()
-			if err != nil {
-				html.ServerError(w, r, err)
-				return
+			if (request.IsAuthenticated(r)) {
+				userID := request.UserID(r)
+				logger.Debug("[UI:AppSession] Cookie expired but user #%d is logged: creating a new session", userID)
+				session, err = m.store.CreateAppSessionWithUserPrefs(userID)
+				if err != nil {
+					html.ServerError(w, r, err)
+					return
+				}
+			} else {
+				logger.Debug("[UI:AppSession] Session not found, creating a new one")
+				session, err = m.store.CreateAppSession()
+				if err != nil {
+					html.ServerError(w, r, err)
+					return
+				}
 			}
 
 			http.SetCookie(w, cookie.New(cookie.CookieSessionID, session.ID, m.cfg.IsHTTPS, m.cfg.BasePath()))
@@ -104,7 +113,7 @@ func (m *middleware) getAppSessionValueFromCookie(r *http.Request) *model.Sessio
 		return nil
 	}
 
-	session, err := m.store.Session(cookieValue)
+	session, err := m.store.AppSession(cookieValue)
 	if err != nil {
 		logger.Error("[UI:AppSession] %v", err)
 		return nil

+ 8 - 8
ui/session/session.go

@@ -18,49 +18,49 @@ type Session struct {
 // NewOAuth2State generates a new OAuth2 state and stores the value into the database.
 func (s *Session) NewOAuth2State() string {
 	state := crypto.GenerateRandomString(32)
-	s.store.UpdateSessionField(s.sessionID, "oauth2_state", state)
+	s.store.UpdateAppSessionField(s.sessionID, "oauth2_state", state)
 	return state
 }
 
 // NewFlashMessage creates a new flash message.
 func (s *Session) NewFlashMessage(message string) {
-	s.store.UpdateSessionField(s.sessionID, "flash_message", message)
+	s.store.UpdateAppSessionField(s.sessionID, "flash_message", message)
 }
 
 // FlashMessage returns the current flash message if any.
 func (s *Session) FlashMessage(message string) string {
 	if message != "" {
-		s.store.UpdateSessionField(s.sessionID, "flash_message", "")
+		s.store.UpdateAppSessionField(s.sessionID, "flash_message", "")
 	}
 	return message
 }
 
 // NewFlashErrorMessage creates a new flash error message.
 func (s *Session) NewFlashErrorMessage(message string) {
-	s.store.UpdateSessionField(s.sessionID, "flash_error_message", message)
+	s.store.UpdateAppSessionField(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.UpdateSessionField(s.sessionID, "flash_error_message", "")
+		s.store.UpdateAppSessionField(s.sessionID, "flash_error_message", "")
 	}
 	return message
 }
 
 // SetLanguage updates the language field in session.
 func (s *Session) SetLanguage(language string) {
-	s.store.UpdateSessionField(s.sessionID, "language", language)
+	s.store.UpdateAppSessionField(s.sessionID, "language", language)
 }
 
 // SetTheme updates the theme field in session.
 func (s *Session) SetTheme(theme string) {
-	s.store.UpdateSessionField(s.sessionID, "theme", theme)
+	s.store.UpdateAppSessionField(s.sessionID, "theme", theme)
 }
 
 // SetPocketRequestToken updates Pocket Request Token.
 func (s *Session) SetPocketRequestToken(requestToken string) {
-	s.store.UpdateSessionField(s.sessionID, "pocket_request_token", requestToken)
+	s.store.UpdateAppSessionField(s.sessionID, "pocket_request_token", requestToken)
 }
 
 // New returns a new session handler.

+ 1 - 1
ui/ui.go

@@ -22,8 +22,8 @@ func Serve(router *mux.Router, cfg *config.Config, store *storage.Storage, pool
 	handler := &handler{router, cfg, store, template.NewEngine(cfg, router), pool, feedHandler}
 
 	uiRouter := router.NewRoute().Subrouter()
-	uiRouter.Use(middleware.handleAppSession)
 	uiRouter.Use(middleware.handleUserSession)
+	uiRouter.Use(middleware.handleAppSession)
 
 	// Static assets.
 	uiRouter.HandleFunc("/stylesheets/{name}.css", handler.showStylesheet).Name("stylesheet").Methods("GET")