-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsessionStore.go
More file actions
146 lines (116 loc) · 3.92 KB
/
Copy pathsessionStore.go
File metadata and controls
146 lines (116 loc) · 3.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package sessions
import (
"github.com/emillis/cacheMachine"
"github.com/emillis/idGen"
"net/http"
"sync"
"time"
)
//===========[INTERFACES]====================================================================================================
type Cookie interface {
Cookie(string) (*http.Cookie, error)
}
type ISession[TValue any] interface {
Uid() string
SetUid(uid string)
Value() TValue
Key() string
SetKey(k string)
SetValue(v TValue)
LastModified() time.Time
UpdateLastModified()
}
//===========[STRUCTURES]===============================================================================================
//Unexported session store where all the related sessions will be cached
type sessionStore[TValue any] struct {
//Every pointer to a Session structure will be stored here
_sessions cacheMachine.Cache[string, *Session[TValue]]
//Only purpose of this cache is to store pointers to Sessions that were modified. This cache is going to be used only
//for updating the database where instead of saving the entire cache, only the modified ones will be updated
_modifiedSessions cacheMachine.Cache[string, *Session[TValue]]
//When checking for UID existence, possible unique ID will be stored here until determined that it's indeed unique
_tmpUidStore cacheMachine.Cache[string, struct{}]
//DefaultKey is the default key used in key:value pairs such as cookie.Name
Requirements Requirements
mx sync.RWMutex
}
//SessionStore is exported access point to all the cached sessions
type SessionStore[TValue any] struct {
sessionStore[TValue]
}
//New creates new session in this store with the Value supplied and returns pointer to it
func (ss *SessionStore[TValue]) New(data TValue) ISession[TValue] {
uid := generateUid(ss)
s := &Session[TValue]{session[TValue]{
Uid: uid,
mx: sync.RWMutex{},
store: ss,
Value: data,
}}
ss._sessions.AddWithTimeout(uid, s, ss.Requirements.Timeout)
ss._modifiedSessions.Add(uid, s)
return s
}
//Get returns Session based on the UID provided
func (ss *SessionStore[TValue]) Get(uid string) ISession[TValue] {
if e := ss._sessions.GetEntry(uid); e == nil {
return nil
} else {
return e.Value()
}
}
//GetFromCookie returns session if UID was specified in the http.Request cookies
func (ss *SessionStore[TValue]) GetFromCookie(c Cookie) ISession[TValue] {
if c == nil {
return nil
}
cookie, err := c.Cookie(ss.Requirements.DefaultKey)
if err != nil {
return nil
}
s, exist := ss._sessions.Get(cookie.Value)
if !exist {
return nil
}
return s
}
//Remove removes session based on the uid supplied
func (ss *SessionStore[TValue]) Remove(uid string) {
ss._sessions.Remove(uid)
ss._modifiedSessions.Remove(uid)
}
//Exist checks whether supplied uid exist in the cache
func (ss *SessionStore[TValue]) Exist(uid string) bool {
return ss._sessions.Exist(uid)
}
//===========[FUNCTIONALITY]====================================================================================================
//Generates and returns new unique UID
func generateUid[TValue any](ss *SessionStore[TValue]) string {
for {
newUid := idGen.Random(&idGen.Config{Length: 99})
if doesUidExist(ss, newUid) {
continue
}
return newUid
}
}
//doesUidExist checks the cache and db whether the uid already exist
func doesUidExist[TValue any](ss *SessionStore[TValue], uid string) bool {
return ss._sessions.Exist(uid) || ss._tmpUidStore.Exist(uid) || ss.Requirements.UidExist(uid)
}
//New initiates and returns a pointer to SessionStore
func New[TValue any](r *Requirements) *SessionStore[TValue] {
if r == nil {
r = &defaultRequirements
} else {
r = makeRequirementsReasonable(r)
}
s := &SessionStore[TValue]{sessionStore[TValue]{
_sessions: cacheMachine.New[string, *Session[TValue]](nil),
_modifiedSessions: cacheMachine.New[string, *Session[TValue]](nil),
_tmpUidStore: cacheMachine.New[string, struct{}](nil),
Requirements: *r,
mx: sync.RWMutex{},
}}
return s
}