session.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
  2. // SPDX-License-Identifier: Apache-2.0
  3. package storage // import "miniflux.app/v2/internal/storage"
  4. import (
  5. "crypto/rand"
  6. "database/sql"
  7. "fmt"
  8. "miniflux.app/v2/internal/model"
  9. )
  10. // CreateAppSessionWithUserPrefs creates a new application session with the given user preferences.
  11. func (s *Storage) CreateAppSessionWithUserPrefs(userID int64) (*model.Session, error) {
  12. user, err := s.UserByID(userID)
  13. if err != nil {
  14. return nil, err
  15. }
  16. session := model.Session{
  17. ID: rand.Text(),
  18. Data: &model.SessionData{
  19. CSRF: rand.Text(),
  20. Theme: user.Theme,
  21. Language: user.Language,
  22. },
  23. }
  24. return s.createAppSession(&session)
  25. }
  26. // CreateAppSession creates a new application session.
  27. func (s *Storage) CreateAppSession() (*model.Session, error) {
  28. session := model.Session{
  29. ID: rand.Text(),
  30. Data: &model.SessionData{
  31. CSRF: rand.Text(),
  32. },
  33. }
  34. return s.createAppSession(&session)
  35. }
  36. func (s *Storage) createAppSession(session *model.Session) (*model.Session, error) {
  37. query := `INSERT INTO sessions (id, data) VALUES ($1, $2)`
  38. _, err := s.db.Exec(query, session.ID, session.Data)
  39. if err != nil {
  40. return nil, fmt.Errorf(`store: unable to create app session: %v`, err)
  41. }
  42. return session, nil
  43. }
  44. // UpdateAppSessionField updates only one session field.
  45. func (s *Storage) UpdateAppSessionField(sessionID, field string, value any) error {
  46. query := `
  47. UPDATE
  48. sessions
  49. SET
  50. data = jsonb_set(data, '{%s}', to_jsonb($1::text), true)
  51. WHERE
  52. id=$2
  53. `
  54. _, err := s.db.Exec(fmt.Sprintf(query, field), value, sessionID)
  55. if err != nil {
  56. return fmt.Errorf(`store: unable to update session field: %v`, err)
  57. }
  58. return nil
  59. }
  60. func (s *Storage) UpdateAppSessionObjectField(sessionID, field string, value interface{}) error {
  61. query := `
  62. UPDATE
  63. sessions
  64. SET
  65. data = jsonb_set(data, '{%s}', $1, true)
  66. WHERE
  67. id=$2
  68. `
  69. _, err := s.db.Exec(fmt.Sprintf(query, field), value, sessionID)
  70. if err != nil {
  71. return fmt.Errorf(`store: unable to update session field: %v`, err)
  72. }
  73. return nil
  74. }
  75. // AppSession returns the given session.
  76. func (s *Storage) AppSession(id string) (*model.Session, error) {
  77. var session model.Session
  78. query := "SELECT id, data FROM sessions WHERE id=$1"
  79. err := s.db.QueryRow(query, id).Scan(
  80. &session.ID,
  81. &session.Data,
  82. )
  83. switch {
  84. case err == sql.ErrNoRows:
  85. return nil, fmt.Errorf(`store: session not found: %s`, id)
  86. case err != nil:
  87. return nil, fmt.Errorf(`store: unable to fetch session: %v`, err)
  88. default:
  89. return &session, nil
  90. }
  91. }
  92. // FlushAllSessions removes all sessions from the database.
  93. func (s *Storage) FlushAllSessions() (err error) {
  94. _, err = s.db.Exec(`DELETE FROM user_sessions`)
  95. if err != nil {
  96. return err
  97. }
  98. _, err = s.db.Exec(`DELETE FROM sessions`)
  99. if err != nil {
  100. return err
  101. }
  102. return nil
  103. }
  104. // CleanOldSessions removes sessions older than specified days.
  105. func (s *Storage) CleanOldSessions(days int) int64 {
  106. query := `
  107. DELETE FROM
  108. sessions
  109. WHERE
  110. created_at < now() - $1::interval
  111. `
  112. result, err := s.db.Exec(query, fmt.Sprintf("%d days", days))
  113. if err != nil {
  114. return 0
  115. }
  116. n, _ := result.RowsAffected()
  117. return n
  118. }