reprogl

Форк
0
/
manager.go 
202 строки · 3.8 Кб
1
package session
2

3
import (
4
	"context"
5
	"errors"
6
	"log"
7
	"net/http"
8
	"time"
9

10
	"xelbot.com/reprogl/container"
11
	"xelbot.com/reprogl/security"
12
)
13

14
const (
15
	CookieName    = "session"
16
	CtxKey        = "session.ctx.key"
17
	CsrfCookie    = "csrf_token"
18
	RefererCookie = "after_login"
19

20
	FlashErrorKey   = "fe"
21
	FlashSuccessKey = "fs"
22

23
	OAuthStateKey    = "ostk"
24
	OAuthVerifierKey = "ofk"
25

26
	varnishSessionHeader = "X-Varnish-Session"
27

28
	maxAge = 14 * 24 * time.Hour
29
)
30

31
var (
32
	DecodeError         = errors.New("session: decode error")
33
	EncodedValueTooLong = errors.New("session: the encoded value is too long")
34
	ErrMacInvalid       = errors.New("session: the HMAC is not valid")
35
	Expired             = errors.New("session: expired")
36
	EncryptionError     = errors.New("session: encryption error")
37
	DecryptionError     = errors.New("session: decryption failed")
38
)
39

40
type CookieInterface interface {
41
	Name() string
42
	Path() string
43
	Value() string
44
	Persist() bool
45
}
46

47
func FromRequest(r *http.Request, logger *log.Logger) *Store {
48
	var withError bool
49
	requestData := r.Header.Get(varnishSessionHeader)
50
	if len(requestData) > 0 {
51
		secureCookie := NewSecureCookie(
52
			container.GetConfig().SessionHashKey,
53
			container.GetConfig().SessionBlockKey,
54
		)
55
		data, err := secureCookie.decode(requestData)
56
		if err == nil {
57
			return newStoreWithData(data)
58
		} else {
59
			withError = true
60
			logger.Printf("[AUTH] session: %s error: %s\n", requestData, err.Error())
61
		}
62
	}
63

64
	store := newStore()
65
	if withError {
66
		store.mu.Lock()
67
		store.status = Destroyed
68
		store.mu.Unlock()
69
	}
70

71
	return store
72
}
73

74
func FromContext(ctx context.Context) *Store {
75
	c, ok := ctx.Value(CtxKey).(*Store)
76
	if !ok {
77
		panic("session: no data in context")
78
	}
79

80
	return c
81
}
82

83
func Put(ctx context.Context, key string, value any) {
84
	store := FromContext(ctx)
85

86
	store.mu.Lock()
87
	store.data.values[key] = value
88
	store.setModified()
89
	store.mu.Unlock()
90
}
91

92
func Has(ctx context.Context, key string) bool {
93
	store := FromContext(ctx)
94

95
	store.mu.RLock()
96
	_, exists := store.data.values[key]
97
	store.mu.RUnlock()
98

99
	return exists
100
}
101

102
func Get[T any](ctx context.Context, key string) (T, bool) {
103
	store := FromContext(ctx)
104

105
	store.mu.RLock()
106
	defer store.mu.RUnlock()
107

108
	var result T
109
	var ok bool
110
	if raw, exists := store.data.values[key]; exists {
111
		if result, ok = raw.(T); ok {
112
			return result, true
113
		}
114
	}
115

116
	return result, false
117
}
118

119
func Pop[T any](ctx context.Context, key string) (T, bool) {
120
	store := FromContext(ctx)
121

122
	store.mu.Lock()
123
	defer store.mu.Unlock()
124

125
	var result T
126
	var ok bool
127
	if raw, exists := store.data.values[key]; exists {
128
		if result, ok = raw.(T); ok {
129
			delete(store.data.values, key)
130
			store.setModified()
131

132
			return result, true
133
		}
134
	}
135

136
	return result, false
137
}
138

139
func Remove(ctx context.Context, key string) {
140
	store := FromContext(ctx)
141

142
	store.mu.Lock()
143
	defer store.mu.Unlock()
144

145
	_, exists := store.data.values[key]
146
	if !exists {
147
		return
148
	}
149

150
	delete(store.data.values, key)
151
	store.setModified()
152
}
153

154
func Destroy(ctx context.Context) {
155
	store := FromContext(ctx)
156

157
	store.mu.Lock()
158
	store.status = Destroyed
159
	store.mu.Unlock()
160
}
161

162
func HasIdentity(ctx context.Context) (result bool) {
163
	store := FromContext(ctx)
164

165
	store.mu.RLock()
166
	result = !store.data.identity.IsZero()
167
	store.mu.RUnlock()
168

169
	return
170
}
171

172
func GetIdentity(ctx context.Context) (security.Identity, bool) {
173
	store := FromContext(ctx)
174

175
	store.mu.RLock()
176
	defer store.mu.RUnlock()
177

178
	return store.data.identity, !store.data.identity.IsZero()
179
}
180

181
func SetIdentity(ctx context.Context, identity security.Identity) {
182
	store := FromContext(ctx)
183

184
	store.mu.Lock()
185
	store.data.identity = identity
186
	store.setModified()
187
	store.mu.Unlock()
188
}
189

190
func ClearIdentity(ctx context.Context) {
191
	store := FromContext(ctx)
192

193
	store.mu.Lock()
194
	defer store.mu.Unlock()
195

196
	if !store.data.identity.IsZero() {
197
		return
198
	}
199

200
	store.data.identity = security.Identity{}
201
	store.setModified()
202
}
203

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.