session.go 2.9 KB

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