session.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. _, err := s.db.Exec(`INSERT INTO sessions (id, data) VALUES ($1, $2)`, session.ID, session.Data)
  39. if err != nil {
  40. return nil, fmt.Errorf("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 interface{}) error {
  46. query := `UPDATE sessions
  47. SET data = jsonb_set(data, '{%s}', to_jsonb($1::text), true)
  48. WHERE id=$2`
  49. _, err := s.db.Exec(fmt.Sprintf(query, field), value, sessionID)
  50. if err != nil {
  51. return fmt.Errorf("unable to update session field: %v", err)
  52. }
  53. return nil
  54. }
  55. // AppSession returns the given session.
  56. func (s *Storage) AppSession(id string) (*model.Session, error) {
  57. var session model.Session
  58. query := "SELECT id, data FROM sessions WHERE id=$1"
  59. err := s.db.QueryRow(query, id).Scan(
  60. &session.ID,
  61. &session.Data,
  62. )
  63. if err == sql.ErrNoRows {
  64. return nil, fmt.Errorf("session not found: %s", id)
  65. } else if err != nil {
  66. return nil, fmt.Errorf("unable to fetch session: %v", err)
  67. }
  68. return &session, nil
  69. }
  70. // FlushAllSessions removes all sessions from the database.
  71. func (s *Storage) FlushAllSessions() (err error) {
  72. _, err = s.db.Exec(`DELETE FROM user_sessions`)
  73. if err != nil {
  74. return err
  75. }
  76. _, err = s.db.Exec(`DELETE FROM sessions`)
  77. if err != nil {
  78. return err
  79. }
  80. return nil
  81. }
  82. // CleanOldSessions removes sessions older than 30 days.
  83. func (s *Storage) CleanOldSessions() int64 {
  84. query := `DELETE FROM sessions
  85. WHERE id IN (SELECT id FROM sessions WHERE created_at < now() - interval '30 days')`
  86. result, err := s.db.Exec(query)
  87. if err != nil {
  88. return 0
  89. }
  90. n, _ := result.RowsAffected()
  91. return n
  92. }