user_session.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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
  5. import (
  6. "database/sql"
  7. "fmt"
  8. "github.com/miniflux/miniflux/crypto"
  9. "github.com/miniflux/miniflux/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, err error) {
  42. var userID int64
  43. err = s.db.QueryRow("SELECT id FROM users WHERE username = LOWER($1)", username).Scan(&userID)
  44. if err != nil {
  45. return "", fmt.Errorf("unable to fetch UserID: %v", err)
  46. }
  47. token := crypto.GenerateRandomString(64)
  48. query := "INSERT INTO user_sessions (token, user_id, user_agent, ip) VALUES ($1, $2, $3, $4)"
  49. _, err = s.db.Exec(query, token, userID, userAgent, ip)
  50. if err != nil {
  51. return "", fmt.Errorf("unable to create user session: %v", err)
  52. }
  53. s.SetLastLogin(userID)
  54. return token, nil
  55. }
  56. // UserSessionByToken finds a session by the token.
  57. func (s *Storage) UserSessionByToken(token string) (*model.UserSession, error) {
  58. var session model.UserSession
  59. query := "SELECT id, user_id, token, created_at, user_agent, ip FROM user_sessions WHERE token = $1"
  60. err := s.db.QueryRow(query, token).Scan(
  61. &session.ID,
  62. &session.UserID,
  63. &session.Token,
  64. &session.CreatedAt,
  65. &session.UserAgent,
  66. &session.IP,
  67. )
  68. if err == sql.ErrNoRows {
  69. return nil, fmt.Errorf("user session not found: %s", token)
  70. } else if err != nil {
  71. return nil, fmt.Errorf("unable to fetch user session: %v", err)
  72. }
  73. return &session, nil
  74. }
  75. // RemoveUserSessionByToken remove a session by using the token.
  76. func (s *Storage) RemoveUserSessionByToken(userID int64, token string) error {
  77. result, err := s.db.Exec(`DELETE FROM user_sessions WHERE user_id=$1 AND token=$2`, userID, token)
  78. if err != nil {
  79. return fmt.Errorf("unable to remove this user session: %v", err)
  80. }
  81. count, err := result.RowsAffected()
  82. if err != nil {
  83. return fmt.Errorf("unable to remove this user session: %v", err)
  84. }
  85. if count != 1 {
  86. return fmt.Errorf("nothing has been removed")
  87. }
  88. return nil
  89. }
  90. // RemoveUserSessionByID remove a session by using the ID.
  91. func (s *Storage) RemoveUserSessionByID(userID, sessionID int64) error {
  92. result, err := s.db.Exec(`DELETE FROM user_sessions WHERE user_id=$1 AND id=$2`, userID, sessionID)
  93. if err != nil {
  94. return fmt.Errorf("unable to remove this user session: %v", err)
  95. }
  96. count, err := result.RowsAffected()
  97. if err != nil {
  98. return fmt.Errorf("unable to remove this user session: %v", err)
  99. }
  100. if count != 1 {
  101. return fmt.Errorf("nothing has been removed")
  102. }
  103. return nil
  104. }
  105. // CleanOldUserSessions removes user sessions older than 30 days.
  106. func (s *Storage) CleanOldUserSessions() int64 {
  107. query := `DELETE FROM user_sessions
  108. WHERE id IN (SELECT id FROM user_sessions WHERE created_at < now() - interval '30 days')`
  109. result, err := s.db.Exec(query)
  110. if err != nil {
  111. return 0
  112. }
  113. n, _ := result.RowsAffected()
  114. return n
  115. }