user_session.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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. // UserSessions returns the list of sessions for the given user.
  12. func (s *Storage) UserSessions(userID int64) (model.UserSessions, error) {
  13. query := `SELECT
  14. id, user_id, token, created_at, user_agent, ip
  15. FROM user_sessions
  16. WHERE user_id=$1 ORDER BY id DESC`
  17. rows, err := s.db.Query(query, userID)
  18. if err != nil {
  19. return nil, fmt.Errorf("unable to fetch user sessions: %v", err)
  20. }
  21. defer rows.Close()
  22. var sessions model.UserSessions
  23. for rows.Next() {
  24. var session model.UserSession
  25. err := rows.Scan(
  26. &session.ID,
  27. &session.UserID,
  28. &session.Token,
  29. &session.CreatedAt,
  30. &session.UserAgent,
  31. &session.IP,
  32. )
  33. if err != nil {
  34. return nil, fmt.Errorf("unable to fetch user session row: %v", err)
  35. }
  36. sessions = append(sessions, &session)
  37. }
  38. return sessions, nil
  39. }
  40. // CreateUserSession creates a new sessions.
  41. func (s *Storage) CreateUserSession(username, userAgent, ip string) (sessionID string, userID int64, err error) {
  42. err = s.db.QueryRow("SELECT id FROM users WHERE username = LOWER($1)", username).Scan(&userID)
  43. if err != nil {
  44. return "", 0, fmt.Errorf("unable to fetch user ID: %v", err)
  45. }
  46. token := crypto.GenerateRandomString(64)
  47. query := "INSERT INTO user_sessions (token, user_id, user_agent, ip) VALUES ($1, $2, $3, $4)"
  48. _, err = s.db.Exec(query, token, userID, userAgent, ip)
  49. if err != nil {
  50. return "", 0, fmt.Errorf("unable to create user session: %v", err)
  51. }
  52. return token, userID, nil
  53. }
  54. // UserSessionByToken finds a session by the token.
  55. func (s *Storage) UserSessionByToken(token string) (*model.UserSession, error) {
  56. var session model.UserSession
  57. query := "SELECT id, user_id, token, created_at, user_agent, ip FROM user_sessions WHERE token = $1"
  58. err := s.db.QueryRow(query, token).Scan(
  59. &session.ID,
  60. &session.UserID,
  61. &session.Token,
  62. &session.CreatedAt,
  63. &session.UserAgent,
  64. &session.IP,
  65. )
  66. if err == sql.ErrNoRows {
  67. return nil, nil
  68. } else if err != nil {
  69. return nil, fmt.Errorf("unable to fetch user session: %v", err)
  70. }
  71. return &session, nil
  72. }
  73. // RemoveUserSessionByToken remove a session by using the token.
  74. func (s *Storage) RemoveUserSessionByToken(userID int64, token string) error {
  75. result, err := s.db.Exec(`DELETE FROM user_sessions WHERE user_id=$1 AND token=$2`, userID, token)
  76. if err != nil {
  77. return fmt.Errorf("unable to remove this user session: %v", err)
  78. }
  79. count, err := result.RowsAffected()
  80. if err != nil {
  81. return fmt.Errorf("unable to remove this user session: %v", err)
  82. }
  83. if count != 1 {
  84. return fmt.Errorf("nothing has been removed")
  85. }
  86. return nil
  87. }
  88. // RemoveUserSessionByID remove a session by using the ID.
  89. func (s *Storage) RemoveUserSessionByID(userID, sessionID int64) error {
  90. result, err := s.db.Exec(`DELETE FROM user_sessions WHERE user_id=$1 AND id=$2`, userID, sessionID)
  91. if err != nil {
  92. return fmt.Errorf("unable to remove this user session: %v", err)
  93. }
  94. count, err := result.RowsAffected()
  95. if err != nil {
  96. return fmt.Errorf("unable to remove this user session: %v", err)
  97. }
  98. if count != 1 {
  99. return fmt.Errorf("nothing has been removed")
  100. }
  101. return nil
  102. }
  103. // CleanOldUserSessions removes user sessions older than 30 days.
  104. func (s *Storage) CleanOldUserSessions() int64 {
  105. query := `DELETE FROM user_sessions
  106. WHERE id IN (SELECT id FROM user_sessions WHERE created_at < now() - interval '30 days')`
  107. result, err := s.db.Exec(query)
  108. if err != nil {
  109. return 0
  110. }
  111. n, _ := result.RowsAffected()
  112. return n
  113. }