user_session.go 3.9 KB

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