restapi_auth.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package httpservers
  2. import (
  3. "github.com/OliveTin/OliveTin/internal/config"
  4. "github.com/OliveTin/OliveTin/internal/filehelper"
  5. log "github.com/sirupsen/logrus"
  6. "gopkg.in/yaml.v3"
  7. "os"
  8. "path/filepath"
  9. "sync"
  10. "time"
  11. )
  12. var sessionStorageMutex sync.Mutex
  13. type UserSession struct {
  14. Username string
  15. Expiry int64
  16. }
  17. type SessionProvider struct {
  18. Sessions map[string]*UserSession
  19. }
  20. type SessionStorage struct {
  21. Providers map[string]*SessionProvider
  22. }
  23. var (
  24. sessionStorage *SessionStorage
  25. )
  26. func registerSessionProviders() {
  27. sessionStorage = &SessionStorage{
  28. Providers: make(map[string]*SessionProvider),
  29. }
  30. registerSessionProvider("local")
  31. registerSessionProvider("oauth2")
  32. }
  33. func registerSessionProvider(provider string) {
  34. sessionStorage.Providers[provider] = &SessionProvider{
  35. Sessions: make(map[string]*UserSession),
  36. }
  37. }
  38. func deleteLocalUserSession(provider string, sid string) {
  39. sessionStorageMutex.Lock()
  40. deleteLocalUserSessionBatch(provider, sid)
  41. sessionStorageMutex.Unlock()
  42. saveUserSessions()
  43. }
  44. func deleteLocalUserSessionBatch(provider string, sid string) {
  45. log.WithFields(log.Fields{
  46. "sid": sid,
  47. "provider": provider,
  48. }).Debug("Deleting user session")
  49. if _, ok := sessionStorage.Providers[provider]; !ok {
  50. return
  51. }
  52. delete(sessionStorage.Providers[provider].Sessions, sid)
  53. }
  54. func registerUserSession(provider string, sid string, username string) {
  55. sessionStorageMutex.Lock()
  56. sessionStorage.Providers[provider].Sessions[sid] = &UserSession{
  57. Username: username,
  58. Expiry: time.Now().Unix() + 31556952, // 1 year
  59. }
  60. sessionStorageMutex.Unlock()
  61. saveUserSessions()
  62. }
  63. func saveUserSessions() {
  64. sessionStorageMutex.Lock()
  65. defer sessionStorageMutex.Unlock()
  66. filename := filepath.Join(cfg.GetDir(), "sessions.db.yaml")
  67. out, err := yaml.Marshal(sessionStorage)
  68. if err != nil {
  69. log.WithFields(log.Fields{
  70. "error": err,
  71. }).Errorf("Failed to marshal session data to %v", filename)
  72. return
  73. }
  74. filehelper.WriteFile(filename, out)
  75. }
  76. func loadUserSessions() {
  77. registerSessionProviders()
  78. filename := filepath.Join(cfg.GetDir(), "sessions.db.yaml")
  79. if _, err := os.Stat(filename); os.IsNotExist(err) {
  80. return
  81. }
  82. data, err := os.ReadFile(filename)
  83. if err != nil {
  84. log.WithFields(log.Fields{
  85. "error": err,
  86. }).Errorf("Failed to read %v", filename)
  87. return
  88. }
  89. err = yaml.Unmarshal(data, &sessionStorage)
  90. if err != nil {
  91. log.WithFields(log.Fields{
  92. "error": err,
  93. }).Error("Failed to unmarshal sessions.local.db")
  94. return
  95. }
  96. deleteExpiredSessions()
  97. }
  98. func deleteExpiredSessions() {
  99. sessionStorageMutex.Lock()
  100. for provider, sessions := range sessionStorage.Providers {
  101. for sid, session := range sessions.Sessions {
  102. if session.Expiry < time.Now().Unix() {
  103. deleteLocalUserSessionBatch(provider, sid)
  104. }
  105. }
  106. }
  107. sessionStorageMutex.Unlock()
  108. saveUserSessions()
  109. }
  110. func getUserFromSession(providerName string, sid string) *config.LocalUser {
  111. provider, ok := sessionStorage.Providers[providerName]
  112. if !ok {
  113. log.WithFields(log.Fields{
  114. "provider": providerName,
  115. }).Warnf("Provider not found")
  116. return nil
  117. }
  118. session, ok := provider.Sessions[sid]
  119. if !ok {
  120. log.WithFields(log.Fields{
  121. "sid": sid,
  122. "provider": providerName,
  123. }).Warnf("Stale session")
  124. return nil
  125. }
  126. user := cfg.FindUserByUsername(session.Username)
  127. if user == nil {
  128. log.WithFields(log.Fields{
  129. "sid": sid,
  130. "provider": providerName,
  131. }).Warnf("User not found")
  132. return nil
  133. }
  134. return user
  135. }