191 lines
4.3 KiB
Go
191 lines
4.3 KiB
Go
package session
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/fossyy/filekeeper/logger"
|
|
"github.com/fossyy/filekeeper/types"
|
|
"net/http"
|
|
"strconv"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/fossyy/filekeeper/utils"
|
|
)
|
|
|
|
type Session struct {
|
|
ID string
|
|
Values map[string]interface{}
|
|
CreateTime time.Time
|
|
mu sync.Mutex
|
|
}
|
|
|
|
type SessionInfo struct {
|
|
SessionID string
|
|
Browser string
|
|
Version string
|
|
OS string
|
|
OSVersion string
|
|
IP string
|
|
Location string
|
|
AccessAt string
|
|
}
|
|
|
|
type UserStatus string
|
|
type SessionNotFoundError struct{}
|
|
|
|
const (
|
|
Authorized UserStatus = "authorized"
|
|
Unauthorized UserStatus = "unauthorized"
|
|
InvalidSession UserStatus = "invalid_session"
|
|
)
|
|
|
|
var GlobalSessionStore = make(map[string]*Session)
|
|
var UserSessionInfoList = make(map[string]map[string]*SessionInfo)
|
|
var log *logger.AggregatedLogger
|
|
|
|
func init() {
|
|
log = logger.Logger()
|
|
|
|
ticker := time.NewTicker(time.Minute)
|
|
go func() {
|
|
for {
|
|
<-ticker.C
|
|
currentTime := time.Now()
|
|
cacheClean := 0
|
|
cleanID := utils.GenerateRandomString(10)
|
|
log.Info(fmt.Sprintf("Cache cleanup [Session] [%s] initiated at %02d:%02d:%02d", cleanID, currentTime.Hour(), currentTime.Minute(), currentTime.Second()))
|
|
|
|
for _, data := range GlobalSessionStore {
|
|
data.mu.Lock()
|
|
if currentTime.Sub(data.CreateTime) > time.Hour*24*7 {
|
|
RemoveSessionInfo(data.Values["user"].(types.User).Email, data.ID)
|
|
delete(GlobalSessionStore, data.ID)
|
|
cacheClean++
|
|
}
|
|
data.mu.Unlock()
|
|
}
|
|
|
|
log.Info(fmt.Sprintf("Cache cleanup [Session] [%s] completed: %d entries removed. Finished at %s", cleanID, cacheClean, time.Since(currentTime)))
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (e *SessionNotFoundError) Error() string {
|
|
return "session not found"
|
|
}
|
|
|
|
func Get(id string) (*Session, error) {
|
|
if session, ok := GlobalSessionStore[id]; ok {
|
|
return session, nil
|
|
}
|
|
return nil, &SessionNotFoundError{}
|
|
}
|
|
|
|
func Create() *Session {
|
|
id := utils.GenerateRandomString(128)
|
|
session := &Session{
|
|
ID: id,
|
|
Values: make(map[string]interface{}),
|
|
}
|
|
GlobalSessionStore[id] = session
|
|
return session
|
|
}
|
|
|
|
func (s *Session) Delete() {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
delete(GlobalSessionStore, s.ID)
|
|
}
|
|
|
|
func (s *Session) Save(w http.ResponseWriter) {
|
|
maxAge, _ := strconv.Atoi(utils.Getenv("SESSION_MAX_AGE"))
|
|
http.SetCookie(w, &http.Cookie{
|
|
Name: utils.Getenv("SESSION_NAME"),
|
|
Value: s.ID,
|
|
MaxAge: maxAge,
|
|
Path: "/",
|
|
})
|
|
}
|
|
|
|
func (s *Session) Destroy(w http.ResponseWriter) {
|
|
http.SetCookie(w, &http.Cookie{
|
|
Name: utils.Getenv("SESSION_NAME"),
|
|
Value: "",
|
|
MaxAge: -1,
|
|
})
|
|
}
|
|
|
|
func AddSessionInfo(email string, sessionInfo *SessionInfo) {
|
|
if _, ok := UserSessionInfoList[email]; !ok {
|
|
UserSessionInfoList[email] = make(map[string]*SessionInfo)
|
|
}
|
|
|
|
UserSessionInfoList[email][sessionInfo.SessionID] = sessionInfo
|
|
}
|
|
|
|
func RemoveSessionInfo(email string, id string) {
|
|
if userSessions, ok := UserSessionInfoList[email]; ok {
|
|
if _, ok := userSessions[id]; ok {
|
|
delete(userSessions, id)
|
|
if len(userSessions) == 0 {
|
|
delete(UserSessionInfoList, email)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func RemoveAllSessions(email string) {
|
|
sessionInfos := UserSessionInfoList[email]
|
|
for _, sessionInfo := range sessionInfos {
|
|
delete(GlobalSessionStore, sessionInfo.SessionID)
|
|
}
|
|
delete(UserSessionInfoList, email)
|
|
}
|
|
|
|
func GetSessionInfo(email string, id string) *SessionInfo {
|
|
if userSession, ok := UserSessionInfoList[email]; ok {
|
|
if sessionInfo, ok := userSession[id]; ok {
|
|
return sessionInfo
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (sessionInfo *SessionInfo) UpdateAccessTime() {
|
|
currentTime := time.Now()
|
|
formattedTime := currentTime.Format("01-02-2006")
|
|
sessionInfo.AccessAt = formattedTime
|
|
}
|
|
|
|
func GetSession(r *http.Request) (UserStatus, types.User, string) {
|
|
cookie, err := r.Cookie("Session")
|
|
if err != nil {
|
|
return Unauthorized, types.User{}, ""
|
|
}
|
|
|
|
storeSession, ok := GlobalSessionStore[cookie.Value]
|
|
if !ok {
|
|
return InvalidSession, types.User{}, ""
|
|
}
|
|
|
|
val := storeSession.Values["user"]
|
|
var userSession = types.User{}
|
|
userSession, ok = val.(types.User)
|
|
if !ok {
|
|
return Unauthorized, types.User{}, ""
|
|
}
|
|
|
|
return Authorized, userSession, cookie.Value
|
|
}
|
|
|
|
func GetSessions(email string) []*SessionInfo {
|
|
if sessions, ok := UserSessionInfoList[email]; ok {
|
|
result := make([]*SessionInfo, 0, len(sessions))
|
|
for _, sessionInfo := range sessions {
|
|
result = append(result, sessionInfo)
|
|
}
|
|
return result
|
|
}
|
|
return nil
|
|
}
|