appier 1.31.4__py2.py3-none-any.whl → 1.32.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- appier/__init__.py +333 -52
- appier/amqp.py +29 -30
- appier/api.py +214 -212
- appier/asgi.py +54 -55
- appier/async_neo.py +46 -35
- appier/async_old.py +55 -42
- appier/asynchronous.py +7 -13
- appier/base.py +1762 -1429
- appier/bus.py +51 -52
- appier/cache.py +99 -84
- appier/common.py +9 -11
- appier/component.py +17 -19
- appier/compress.py +25 -28
- appier/config.py +96 -73
- appier/controller.py +9 -15
- appier/crypt.py +25 -21
- appier/data.py +73 -57
- appier/defines.py +191 -226
- appier/exceptions.py +103 -63
- appier/execution.py +94 -88
- appier/export.py +90 -88
- appier/extra.py +6 -13
- appier/extra_neo.py +8 -11
- appier/extra_old.py +18 -16
- appier/geo.py +57 -47
- appier/git.py +101 -90
- appier/graph.py +23 -24
- appier/http.py +520 -398
- appier/legacy.py +373 -180
- appier/log.py +90 -97
- appier/meta.py +42 -42
- appier/mock.py +32 -34
- appier/model.py +793 -681
- appier/model_a.py +208 -183
- appier/mongo.py +183 -107
- appier/observer.py +39 -31
- appier/part.py +23 -24
- appier/preferences.py +44 -47
- appier/queuing.py +78 -96
- appier/redisdb.py +40 -35
- appier/request.py +227 -175
- appier/scheduler.py +13 -18
- appier/serialize.py +37 -31
- appier/session.py +161 -147
- appier/settings.py +2 -11
- appier/smtp.py +53 -49
- appier/storage.py +39 -33
- appier/structures.py +50 -45
- appier/test/__init__.py +2 -11
- appier/test/base.py +111 -108
- appier/test/cache.py +28 -35
- appier/test/config.py +10 -19
- appier/test/crypt.py +3 -12
- appier/test/data.py +3 -12
- appier/test/exceptions.py +8 -17
- appier/test/export.py +16 -33
- appier/test/graph.py +27 -60
- appier/test/http.py +42 -54
- appier/test/legacy.py +20 -30
- appier/test/log.py +14 -35
- appier/test/mock.py +27 -123
- appier/test/model.py +79 -91
- appier/test/part.py +5 -14
- appier/test/preferences.py +5 -13
- appier/test/queuing.py +29 -37
- appier/test/request.py +61 -73
- appier/test/serialize.py +12 -23
- appier/test/session.py +10 -19
- appier/test/smtp.py +8 -14
- appier/test/structures.py +20 -24
- appier/test/typesf.py +14 -28
- appier/test/util.py +480 -438
- appier/typesf.py +251 -171
- appier/util.py +578 -407
- appier/validation.py +280 -143
- {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/METADATA +6 -1
- appier-1.32.0.dist-info/RECORD +86 -0
- appier-1.31.4.dist-info/RECORD +0 -86
- {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/LICENSE +0 -0
- {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/WHEEL +0 -0
- {appier-1.31.4.dist-info → appier-1.32.0.dist-info}/top_level.txt +0 -0
appier/session.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
# Hive Appier Framework
|
|
5
|
-
# Copyright (c) 2008-
|
|
5
|
+
# Copyright (c) 2008-2024 Hive Solutions Lda.
|
|
6
6
|
#
|
|
7
7
|
# This file is part of Hive Appier Framework.
|
|
8
8
|
#
|
|
@@ -22,16 +22,7 @@
|
|
|
22
22
|
__author__ = "João Magalhães <joamag@hive.pt>"
|
|
23
23
|
""" The author(s) of the module """
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
""" The version of the module """
|
|
27
|
-
|
|
28
|
-
__revision__ = "$LastChangedRevision$"
|
|
29
|
-
""" The revision number of the module """
|
|
30
|
-
|
|
31
|
-
__date__ = "$LastChangedDate$"
|
|
32
|
-
""" The last change date of the module """
|
|
33
|
-
|
|
34
|
-
__copyright__ = "Copyright (c) 2008-2022 Hive Solutions Lda."
|
|
25
|
+
__copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
|
|
35
26
|
""" The copyright for the module """
|
|
36
27
|
|
|
37
28
|
__license__ = "Apache License, Version 2.0"
|
|
@@ -53,10 +44,11 @@ from . import legacy
|
|
|
53
44
|
from . import redisdb
|
|
54
45
|
from . import exceptions
|
|
55
46
|
|
|
56
|
-
|
|
57
|
-
""" The default expire time
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
EXPIRE_TIME = datetime.timedelta(days=31)
|
|
48
|
+
""" The default expire time to be used in new sessions
|
|
49
|
+
in case no expire time is provided to the creation of
|
|
50
|
+
the session instance """
|
|
51
|
+
|
|
60
52
|
|
|
61
53
|
class Session(object):
|
|
62
54
|
"""
|
|
@@ -68,15 +60,9 @@ class Session(object):
|
|
|
68
60
|
"""
|
|
69
61
|
|
|
70
62
|
def __init__(
|
|
71
|
-
self,
|
|
72
|
-
name = "session",
|
|
73
|
-
expire = None,
|
|
74
|
-
sid = None,
|
|
75
|
-
address = None,
|
|
76
|
-
growing = True
|
|
63
|
+
self, name="session", expire=EXPIRE_TIME, sid=None, address=None, growing=True
|
|
77
64
|
):
|
|
78
65
|
object.__init__(self)
|
|
79
|
-
if expire == None: expire = datetime.timedelta(days = EXPIRE_TIME_DAYS)
|
|
80
66
|
self.sid = sid if sid else self._gen_sid()
|
|
81
67
|
self.name = name
|
|
82
68
|
self.address = address
|
|
@@ -96,11 +82,11 @@ class Session(object):
|
|
|
96
82
|
return self.data_t.__getitem__(key)
|
|
97
83
|
|
|
98
84
|
def __setitem__(self, key, value):
|
|
99
|
-
self.mark(extend
|
|
85
|
+
self.mark(extend=self.growing)
|
|
100
86
|
self.data_t.__setitem__(key, value)
|
|
101
87
|
|
|
102
88
|
def __delitem__(self, key):
|
|
103
|
-
self.mark(extend
|
|
89
|
+
self.mark(extend=self.growing)
|
|
104
90
|
self.data_t.__delitem__(key)
|
|
105
91
|
|
|
106
92
|
def __iter__(self):
|
|
@@ -117,15 +103,15 @@ class Session(object):
|
|
|
117
103
|
|
|
118
104
|
def __getstate__(self):
|
|
119
105
|
return dict(
|
|
120
|
-
sid
|
|
121
|
-
name
|
|
122
|
-
address
|
|
123
|
-
create
|
|
124
|
-
modify
|
|
125
|
-
duration
|
|
126
|
-
expire
|
|
127
|
-
growing
|
|
128
|
-
dirty
|
|
106
|
+
sid=self.sid,
|
|
107
|
+
name=self.name,
|
|
108
|
+
address=self.address,
|
|
109
|
+
create=self.create,
|
|
110
|
+
modify=self.modify,
|
|
111
|
+
duration=self.duration,
|
|
112
|
+
expire=self.expire,
|
|
113
|
+
growing=self.growing,
|
|
114
|
+
dirty=self.dirty,
|
|
129
115
|
)
|
|
130
116
|
|
|
131
117
|
def __setstate__(self, state):
|
|
@@ -138,7 +124,7 @@ class Session(object):
|
|
|
138
124
|
"duration",
|
|
139
125
|
"expire",
|
|
140
126
|
"growing",
|
|
141
|
-
"dirty"
|
|
127
|
+
"dirty",
|
|
142
128
|
):
|
|
143
129
|
value = state.get(name, None)
|
|
144
130
|
setattr(self, name, value)
|
|
@@ -149,7 +135,7 @@ class Session(object):
|
|
|
149
135
|
return cls(*args, **kwargs)
|
|
150
136
|
|
|
151
137
|
@classmethod
|
|
152
|
-
def get_s(cls, sid, request
|
|
138
|
+
def get_s(cls, sid, request=None):
|
|
153
139
|
return cls()
|
|
154
140
|
|
|
155
141
|
@classmethod
|
|
@@ -198,8 +184,9 @@ class Session(object):
|
|
|
198
184
|
def iteritems(self):
|
|
199
185
|
return self.items()
|
|
200
186
|
|
|
201
|
-
def pop(self, key, default
|
|
202
|
-
if not key in self:
|
|
187
|
+
def pop(self, key, default=None):
|
|
188
|
+
if not key in self:
|
|
189
|
+
return default
|
|
203
190
|
value = self[key]
|
|
204
191
|
del self[key]
|
|
205
192
|
return value
|
|
@@ -207,16 +194,18 @@ class Session(object):
|
|
|
207
194
|
def start(self):
|
|
208
195
|
pass
|
|
209
196
|
|
|
210
|
-
def flush(self, request
|
|
211
|
-
self.mark(dirty
|
|
197
|
+
def flush(self, request=None):
|
|
198
|
+
self.mark(dirty=False)
|
|
212
199
|
|
|
213
|
-
def mark(self, dirty
|
|
200
|
+
def mark(self, dirty=True, extend=False):
|
|
214
201
|
self.dirty = dirty
|
|
215
|
-
if extend:
|
|
202
|
+
if extend:
|
|
203
|
+
self.extend()
|
|
216
204
|
|
|
217
|
-
def extend(self, duration
|
|
205
|
+
def extend(self, duration=None):
|
|
218
206
|
duration = duration or self.duration
|
|
219
|
-
if not duration:
|
|
207
|
+
if not duration:
|
|
208
|
+
return
|
|
220
209
|
self.modify = time.time()
|
|
221
210
|
self.duration = duration
|
|
222
211
|
self.expire = self.modify + duration
|
|
@@ -225,13 +214,15 @@ class Session(object):
|
|
|
225
214
|
|
|
226
215
|
def is_expired(self):
|
|
227
216
|
has_expire = hasattr(self, "expire")
|
|
228
|
-
if not has_expire:
|
|
217
|
+
if not has_expire:
|
|
218
|
+
return False
|
|
229
219
|
|
|
230
220
|
current = time.time()
|
|
231
221
|
return current >= self.expire
|
|
232
222
|
|
|
233
223
|
def is_dirty(self):
|
|
234
|
-
if not hasattr(self, "dirty"):
|
|
224
|
+
if not hasattr(self, "dirty"):
|
|
225
|
+
return True
|
|
235
226
|
return self.dirty
|
|
236
227
|
|
|
237
228
|
def is_loaded(self):
|
|
@@ -240,35 +231,41 @@ class Session(object):
|
|
|
240
231
|
def ensure(self, *args, **kwargs):
|
|
241
232
|
return self
|
|
242
233
|
|
|
243
|
-
def get(self, key, default
|
|
244
|
-
try:
|
|
245
|
-
|
|
234
|
+
def get(self, key, default=None):
|
|
235
|
+
try:
|
|
236
|
+
value = self.__getitem__(key)
|
|
237
|
+
except KeyError:
|
|
238
|
+
value = default
|
|
246
239
|
return value
|
|
247
240
|
|
|
248
241
|
def set(self, key, value):
|
|
249
242
|
self.__setitem__(key, value)
|
|
250
243
|
|
|
251
|
-
def delete(self, key, force
|
|
252
|
-
if not force and not key in self:
|
|
244
|
+
def delete(self, key, force=False):
|
|
245
|
+
if not force and not key in self:
|
|
246
|
+
return
|
|
253
247
|
self.__delitem__(key)
|
|
254
248
|
|
|
255
|
-
def get_t(self, key, default
|
|
256
|
-
try:
|
|
257
|
-
|
|
249
|
+
def get_t(self, key, default=None):
|
|
250
|
+
try:
|
|
251
|
+
value = self.data_t[key]
|
|
252
|
+
except KeyError:
|
|
253
|
+
value = default
|
|
258
254
|
return value
|
|
259
255
|
|
|
260
256
|
def set_t(self, key, value):
|
|
261
257
|
self.data_t[key] = value
|
|
262
258
|
|
|
263
|
-
def delete_t(self, key, force
|
|
264
|
-
if not force and not key in self.data_t:
|
|
259
|
+
def delete_t(self, key, force=False):
|
|
260
|
+
if not force and not key in self.data_t:
|
|
261
|
+
return
|
|
265
262
|
del self.data_t[key]
|
|
266
263
|
|
|
267
264
|
def timeout(self):
|
|
268
265
|
current = time.time()
|
|
269
266
|
return self.expire - current
|
|
270
267
|
|
|
271
|
-
def set_transient(self, value
|
|
268
|
+
def set_transient(self, value=True):
|
|
272
269
|
"""
|
|
273
270
|
Marks the current session as transient only meaning
|
|
274
271
|
that all of the operations will be made in memory
|
|
@@ -290,8 +287,10 @@ class Session(object):
|
|
|
290
287
|
return token
|
|
291
288
|
|
|
292
289
|
def _to_seconds(self, delta):
|
|
293
|
-
return (
|
|
294
|
-
(delta.seconds + delta.days * 24 * 3600) * 10
|
|
290
|
+
return (
|
|
291
|
+
delta.microseconds + (delta.seconds + delta.days * 24 * 3600) * 10**6
|
|
292
|
+
) / 10**6
|
|
293
|
+
|
|
295
294
|
|
|
296
295
|
class MockSession(Session):
|
|
297
296
|
"""
|
|
@@ -301,18 +300,15 @@ class MockSession(Session):
|
|
|
301
300
|
with the pre-defined standard operations.
|
|
302
301
|
"""
|
|
303
302
|
|
|
304
|
-
def __init__(self, request, name
|
|
305
|
-
Session.__init__(self, name
|
|
303
|
+
def __init__(self, request, name="mock", *args, **kwargs):
|
|
304
|
+
Session.__init__(self, name=name, *args, **kwargs)
|
|
306
305
|
self.request = request
|
|
307
306
|
self.setter = None
|
|
308
307
|
|
|
309
308
|
def __setitem__(self, key, value):
|
|
310
309
|
if self.transient:
|
|
311
310
|
return Session.__setitem__(self, key, value)
|
|
312
|
-
session = self.ensure(
|
|
313
|
-
sid = self.sid,
|
|
314
|
-
address = self.address
|
|
315
|
-
)
|
|
311
|
+
session = self.ensure(sid=self.sid, address=self.address)
|
|
316
312
|
return session.__setitem__(key, value)
|
|
317
313
|
|
|
318
314
|
def __setstate__(self, state):
|
|
@@ -323,7 +319,8 @@ class MockSession(Session):
|
|
|
323
319
|
return False
|
|
324
320
|
|
|
325
321
|
def ensure(self, *args, **kwargs):
|
|
326
|
-
if self.transient:
|
|
322
|
+
if self.transient:
|
|
323
|
+
return self
|
|
327
324
|
self._ensure_names(kwargs)
|
|
328
325
|
session_c = self.request.session_c
|
|
329
326
|
session = session_c.new(*args, **kwargs)
|
|
@@ -333,11 +330,12 @@ class MockSession(Session):
|
|
|
333
330
|
|
|
334
331
|
def _ensure_names(self, kwargs):
|
|
335
332
|
for name in ("sid", "address"):
|
|
336
|
-
if name in kwargs:
|
|
333
|
+
if name in kwargs:
|
|
334
|
+
continue
|
|
337
335
|
kwargs[name] = getattr(self, name)
|
|
338
336
|
|
|
339
|
-
class DataSession(Session):
|
|
340
337
|
|
|
338
|
+
class DataSession(Session):
|
|
341
339
|
def __init__(self, *args, **kwargs):
|
|
342
340
|
Session.__init__(self, *args, **kwargs)
|
|
343
341
|
self.data = {}
|
|
@@ -346,16 +344,18 @@ class DataSession(Session):
|
|
|
346
344
|
return Session.__len__(self) + self.data.__len__()
|
|
347
345
|
|
|
348
346
|
def __getitem__(self, key):
|
|
349
|
-
try:
|
|
350
|
-
|
|
347
|
+
try:
|
|
348
|
+
return self.data.__getitem__(key)
|
|
349
|
+
except KeyError:
|
|
350
|
+
return Session.__getitem__(self, key)
|
|
351
351
|
|
|
352
352
|
def __setitem__(self, key, value):
|
|
353
|
-
self.mark(extend
|
|
353
|
+
self.mark(extend=self.growing)
|
|
354
354
|
return self.data.__setitem__(key, value)
|
|
355
355
|
|
|
356
356
|
def __delitem__(self, key):
|
|
357
357
|
try:
|
|
358
|
-
self.mark(extend
|
|
358
|
+
self.mark(extend=self.growing)
|
|
359
359
|
return self.data.__delitem__(key)
|
|
360
360
|
except KeyError:
|
|
361
361
|
return Session.__delitem__(self, key)
|
|
@@ -364,14 +364,11 @@ class DataSession(Session):
|
|
|
364
364
|
return self._merged.__iter__()
|
|
365
365
|
|
|
366
366
|
def __contains__(self, item):
|
|
367
|
-
return Session.__contains__(self, item) or
|
|
368
|
-
self.data.__contains__(item)
|
|
367
|
+
return Session.__contains__(self, item) or self.data.__contains__(item)
|
|
369
368
|
|
|
370
369
|
def __getstate__(self):
|
|
371
370
|
state = Session.__getstate__(self)
|
|
372
|
-
state.update(
|
|
373
|
-
data = self.data
|
|
374
|
-
)
|
|
371
|
+
state.update(data=self.data)
|
|
375
372
|
return state
|
|
376
373
|
|
|
377
374
|
def __setstate__(self, state):
|
|
@@ -396,22 +393,24 @@ class DataSession(Session):
|
|
|
396
393
|
|
|
397
394
|
@property
|
|
398
395
|
def _merged(self):
|
|
399
|
-
if not self.data_t:
|
|
400
|
-
|
|
396
|
+
if not self.data_t:
|
|
397
|
+
return self.data
|
|
398
|
+
if not self.data:
|
|
399
|
+
return self.data_t
|
|
401
400
|
merged = dict()
|
|
402
401
|
merged.update(self.data_t)
|
|
403
402
|
merged.update(self.data)
|
|
404
403
|
return merged
|
|
405
404
|
|
|
406
|
-
class MemorySession(DataSession):
|
|
407
405
|
|
|
406
|
+
class MemorySession(DataSession):
|
|
408
407
|
SESSIONS = {}
|
|
409
408
|
""" Global static sessions map where all the
|
|
410
409
|
(in-memory) session instances are going to be
|
|
411
410
|
stored to be latter retrieved """
|
|
412
411
|
|
|
413
|
-
def __init__(self, name
|
|
414
|
-
DataSession.__init__(self, name
|
|
412
|
+
def __init__(self, name="session", *args, **kwargs):
|
|
413
|
+
DataSession.__init__(self, name=name, *args, **kwargs)
|
|
415
414
|
self["sid"] = self.sid
|
|
416
415
|
|
|
417
416
|
@classmethod
|
|
@@ -421,13 +420,15 @@ class MemorySession(DataSession):
|
|
|
421
420
|
return session
|
|
422
421
|
|
|
423
422
|
@classmethod
|
|
424
|
-
def get_s(cls, sid, request
|
|
423
|
+
def get_s(cls, sid, request=None):
|
|
425
424
|
state = cls.SESSIONS.get(sid, None)
|
|
426
|
-
if not state:
|
|
425
|
+
if not state:
|
|
426
|
+
return state
|
|
427
427
|
session = cls.__new__(cls)
|
|
428
428
|
session.__setstate__(state)
|
|
429
429
|
is_expired = session.is_expired()
|
|
430
|
-
if is_expired:
|
|
430
|
+
if is_expired:
|
|
431
|
+
cls.expire(sid)
|
|
431
432
|
session = None if is_expired else session
|
|
432
433
|
return session
|
|
433
434
|
|
|
@@ -447,6 +448,7 @@ class MemorySession(DataSession):
|
|
|
447
448
|
def empty(cls):
|
|
448
449
|
cls.SESSIONS.empty()
|
|
449
450
|
|
|
451
|
+
|
|
450
452
|
class FileSession(DataSession):
|
|
451
453
|
"""
|
|
452
454
|
Shelve based file system session engine that store the
|
|
@@ -463,24 +465,28 @@ class FileSession(DataSession):
|
|
|
463
465
|
result of opening a file in shelve mode, this is a global
|
|
464
466
|
object and only one instance should exist per process """
|
|
465
467
|
|
|
466
|
-
def __init__(self, name
|
|
467
|
-
DataSession.__init__(self, name
|
|
468
|
+
def __init__(self, name="file", *args, **kwargs):
|
|
469
|
+
DataSession.__init__(self, name=name, *args, **kwargs)
|
|
468
470
|
self["sid"] = self.sid
|
|
469
471
|
|
|
470
472
|
@classmethod
|
|
471
473
|
def new(cls, *args, **kwargs):
|
|
472
|
-
if cls.SHELVE == None:
|
|
474
|
+
if cls.SHELVE == None:
|
|
475
|
+
cls.open()
|
|
473
476
|
session = cls(*args, **kwargs)
|
|
474
477
|
cls.SHELVE[session.sid] = session
|
|
475
478
|
return session
|
|
476
479
|
|
|
477
480
|
@classmethod
|
|
478
|
-
def get_s(cls, sid, request
|
|
479
|
-
if cls.SHELVE == None:
|
|
481
|
+
def get_s(cls, sid, request=None):
|
|
482
|
+
if cls.SHELVE == None:
|
|
483
|
+
cls.open()
|
|
480
484
|
session = cls.SHELVE.get(sid, None)
|
|
481
|
-
if not session:
|
|
485
|
+
if not session:
|
|
486
|
+
return session
|
|
482
487
|
is_expired = session.is_expired()
|
|
483
|
-
if is_expired:
|
|
488
|
+
if is_expired:
|
|
489
|
+
cls.expire(sid)
|
|
484
490
|
session = None if is_expired else session
|
|
485
491
|
return session
|
|
486
492
|
|
|
@@ -497,37 +503,37 @@ class FileSession(DataSession):
|
|
|
497
503
|
return cls.SHELVE
|
|
498
504
|
|
|
499
505
|
@classmethod
|
|
500
|
-
def open(cls, file_path
|
|
506
|
+
def open(cls, file_path="session.shelve"):
|
|
501
507
|
base_path = config.conf("APPIER_BASE_PATH", "")
|
|
502
508
|
base_path = config.conf("SESSION_FILE_PATH", base_path)
|
|
503
|
-
if base_path and not os.path.exists(base_path):
|
|
509
|
+
if base_path and not os.path.exists(base_path):
|
|
510
|
+
os.makedirs(base_path)
|
|
504
511
|
base_path = os.path.expanduser(base_path)
|
|
505
512
|
base_path = os.path.abspath(base_path)
|
|
506
513
|
base_path = os.path.normpath(base_path)
|
|
507
514
|
file_path = os.path.join(base_path, file_path)
|
|
508
|
-
cls.SHELVE = shelve.open(
|
|
509
|
-
file_path,
|
|
510
|
-
protocol = 2,
|
|
511
|
-
writeback = True
|
|
512
|
-
)
|
|
515
|
+
cls.SHELVE = shelve.open(file_path, protocol=2, writeback=True)
|
|
513
516
|
cls.gc()
|
|
514
517
|
|
|
515
518
|
@classmethod
|
|
516
519
|
def close(cls):
|
|
517
|
-
if not cls.SHELVE:
|
|
520
|
+
if not cls.SHELVE:
|
|
521
|
+
return
|
|
518
522
|
cls.SHELVE.close()
|
|
519
523
|
cls.SHELVE = None
|
|
520
524
|
|
|
521
525
|
@classmethod
|
|
522
526
|
def empty(cls):
|
|
523
|
-
for sid in cls.SHELVE:
|
|
527
|
+
for sid in cls.SHELVE:
|
|
528
|
+
del cls.SHELVE[sid]
|
|
524
529
|
|
|
525
530
|
@classmethod
|
|
526
531
|
def gc(cls):
|
|
527
532
|
for sid in cls.SHELVE:
|
|
528
533
|
session = cls.SHELVE.get(sid, None)
|
|
529
534
|
is_expired = session.is_expired()
|
|
530
|
-
if is_expired:
|
|
535
|
+
if is_expired:
|
|
536
|
+
cls.expire(sid)
|
|
531
537
|
|
|
532
538
|
@classmethod
|
|
533
539
|
def db_type(cls):
|
|
@@ -539,12 +545,13 @@ class FileSession(DataSession):
|
|
|
539
545
|
def db_secure(cls):
|
|
540
546
|
return cls.db_type() == "dbm"
|
|
541
547
|
|
|
542
|
-
def flush(self, request
|
|
543
|
-
if not self.is_dirty():
|
|
544
|
-
|
|
545
|
-
self.
|
|
548
|
+
def flush(self, request=None, secure=None):
|
|
549
|
+
if not self.is_dirty():
|
|
550
|
+
return
|
|
551
|
+
self.mark(dirty=False)
|
|
552
|
+
self.sync(secure=secure)
|
|
546
553
|
|
|
547
|
-
def sync(self, secure
|
|
554
|
+
def sync(self, secure=None):
|
|
548
555
|
cls = self.__class__
|
|
549
556
|
if secure == None:
|
|
550
557
|
secure = cls.db_secure()
|
|
@@ -554,8 +561,8 @@ class FileSession(DataSession):
|
|
|
554
561
|
else:
|
|
555
562
|
cls.SHELVE.sync()
|
|
556
563
|
|
|
557
|
-
class RedisSession(DataSession):
|
|
558
564
|
|
|
565
|
+
class RedisSession(DataSession):
|
|
559
566
|
REDIS = None
|
|
560
567
|
""" Global shelve object reference should reflect the
|
|
561
568
|
result of opening a file in shelve mode, this is a global
|
|
@@ -565,32 +572,32 @@ class RedisSession(DataSession):
|
|
|
565
572
|
""" The serializer to be used for the values contained in
|
|
566
573
|
the session (used on top of the class) """
|
|
567
574
|
|
|
568
|
-
def __init__(self, name
|
|
569
|
-
DataSession.__init__(self, name
|
|
575
|
+
def __init__(self, name="redis", *args, **kwargs):
|
|
576
|
+
DataSession.__init__(self, name=name, *args, **kwargs)
|
|
570
577
|
self["sid"] = self.sid
|
|
571
578
|
|
|
572
579
|
@classmethod
|
|
573
580
|
def new(cls, *args, **kwargs):
|
|
574
|
-
if cls.REDIS == None:
|
|
581
|
+
if cls.REDIS == None:
|
|
582
|
+
cls.open()
|
|
575
583
|
session = cls(*args, **kwargs)
|
|
576
584
|
data = cls.SERIALIZER.dumps(session)
|
|
577
585
|
timeout = session.timeout()
|
|
578
586
|
timeout = int(timeout)
|
|
579
|
-
cls.REDIS.setex(
|
|
580
|
-
session.sid,
|
|
581
|
-
value = data,
|
|
582
|
-
time = timeout
|
|
583
|
-
)
|
|
587
|
+
cls.REDIS.setex(session.sid, value=data, time=timeout)
|
|
584
588
|
return session
|
|
585
589
|
|
|
586
590
|
@classmethod
|
|
587
|
-
def get_s(cls, sid, request
|
|
588
|
-
if cls.REDIS == None:
|
|
591
|
+
def get_s(cls, sid, request=None):
|
|
592
|
+
if cls.REDIS == None:
|
|
593
|
+
cls.open()
|
|
589
594
|
data = cls.REDIS.get(sid)
|
|
590
|
-
if not data:
|
|
595
|
+
if not data:
|
|
596
|
+
return data
|
|
591
597
|
session = cls.SERIALIZER.loads(data)
|
|
592
598
|
is_expired = session.is_expired()
|
|
593
|
-
if is_expired:
|
|
599
|
+
if is_expired:
|
|
600
|
+
cls.expire(sid)
|
|
594
601
|
session = None if is_expired else session
|
|
595
602
|
return session
|
|
596
603
|
|
|
@@ -600,18 +607,22 @@ class RedisSession(DataSession):
|
|
|
600
607
|
|
|
601
608
|
@classmethod
|
|
602
609
|
def count(cls):
|
|
603
|
-
if cls.REDIS == None:
|
|
610
|
+
if cls.REDIS == None:
|
|
611
|
+
cls.open()
|
|
604
612
|
return cls.REDIS.dbsize()
|
|
605
613
|
|
|
606
614
|
@classmethod
|
|
607
615
|
def all(cls):
|
|
608
|
-
if cls.REDIS == None:
|
|
616
|
+
if cls.REDIS == None:
|
|
617
|
+
cls.open()
|
|
609
618
|
sessions = dict()
|
|
610
619
|
sids = cls.REDIS.keys()
|
|
611
620
|
for sid in sids:
|
|
612
621
|
data = cls.REDIS.get(sid)
|
|
613
|
-
try:
|
|
614
|
-
|
|
622
|
+
try:
|
|
623
|
+
session = cls.SERIALIZER.loads(data)
|
|
624
|
+
except Exception:
|
|
625
|
+
continue
|
|
615
626
|
sessions[sid] = session
|
|
616
627
|
return sessions
|
|
617
628
|
|
|
@@ -621,21 +632,20 @@ class RedisSession(DataSession):
|
|
|
621
632
|
|
|
622
633
|
@classmethod
|
|
623
634
|
def empty(cls):
|
|
624
|
-
if cls.REDIS == None:
|
|
635
|
+
if cls.REDIS == None:
|
|
636
|
+
cls.open()
|
|
625
637
|
cls.REDIS.flushdb()
|
|
626
638
|
|
|
627
|
-
def flush(self, request
|
|
628
|
-
if not self.is_dirty():
|
|
629
|
-
|
|
639
|
+
def flush(self, request=None):
|
|
640
|
+
if not self.is_dirty():
|
|
641
|
+
return
|
|
642
|
+
self.mark(dirty=False)
|
|
630
643
|
cls = self.__class__
|
|
631
644
|
data = cls.SERIALIZER.dumps(self)
|
|
632
645
|
timeout = self.timeout()
|
|
633
646
|
timeout = int(timeout)
|
|
634
|
-
cls.REDIS.setex(
|
|
635
|
-
|
|
636
|
-
value = data,
|
|
637
|
-
time = timeout
|
|
638
|
-
)
|
|
647
|
+
cls.REDIS.setex(self.sid, value=data, time=timeout)
|
|
648
|
+
|
|
639
649
|
|
|
640
650
|
class ClientSession(DataSession):
|
|
641
651
|
"""
|
|
@@ -655,20 +665,22 @@ class ClientSession(DataSession):
|
|
|
655
665
|
""" The limit (in bytes) of a cookie to be properly handled
|
|
656
666
|
by most of the modern web browsers """
|
|
657
667
|
|
|
658
|
-
def __init__(self, name
|
|
659
|
-
DataSession.__init__(self, name
|
|
668
|
+
def __init__(self, name="client", *args, **kwargs):
|
|
669
|
+
DataSession.__init__(self, name=name, *args, **kwargs)
|
|
660
670
|
self["sid"] = self.sid
|
|
661
671
|
|
|
662
672
|
@classmethod
|
|
663
|
-
def get_s(cls, sid, request
|
|
673
|
+
def get_s(cls, sid, request=None):
|
|
664
674
|
data_b64 = request.cookies.get("session", None)
|
|
665
|
-
if not data_b64:
|
|
675
|
+
if not data_b64:
|
|
676
|
+
return None
|
|
666
677
|
data = base64.b64decode(data_b64)
|
|
667
678
|
data = zlib.decompress(data)
|
|
668
679
|
data = cls._verify(data, request)
|
|
669
680
|
session = cls.SERIALIZER.loads(data)
|
|
670
681
|
is_expired = session.is_expired()
|
|
671
|
-
if is_expired:
|
|
682
|
+
if is_expired:
|
|
683
|
+
cls.expire(sid)
|
|
672
684
|
session = None if is_expired else session
|
|
673
685
|
return session
|
|
674
686
|
|
|
@@ -689,21 +701,22 @@ class ClientSession(DataSession):
|
|
|
689
701
|
expected = hmac.new(secret, data).hexdigest()
|
|
690
702
|
expected = legacy.bytes(expected)
|
|
691
703
|
valid = digest == expected
|
|
692
|
-
if not valid:
|
|
693
|
-
message
|
|
694
|
-
)
|
|
704
|
+
if not valid:
|
|
705
|
+
raise exceptions.SecurityError(message="Invalid signature for message")
|
|
695
706
|
return data
|
|
696
707
|
|
|
697
708
|
@classmethod
|
|
698
709
|
def _secret(cls, request):
|
|
699
710
|
owner = request.owner
|
|
700
|
-
if not hasattr(owner, "secret"):
|
|
711
|
+
if not hasattr(owner, "secret"):
|
|
712
|
+
return None
|
|
701
713
|
return owner.secret
|
|
702
714
|
|
|
703
|
-
def flush(self, request
|
|
715
|
+
def flush(self, request=None):
|
|
704
716
|
cls = self.__class__
|
|
705
|
-
if not self.is_dirty():
|
|
706
|
-
|
|
717
|
+
if not self.is_dirty():
|
|
718
|
+
return
|
|
719
|
+
self.mark(dirty=False)
|
|
707
720
|
cls = self.__class__
|
|
708
721
|
data = cls.SERIALIZER.dumps(self)
|
|
709
722
|
data = cls._sign(data, request)
|
|
@@ -711,7 +724,8 @@ class ClientSession(DataSession):
|
|
|
711
724
|
data_b64 = base64.b64encode(data)
|
|
712
725
|
data_b64 = legacy.str(data_b64)
|
|
713
726
|
valid = len(data_b64) <= cls.COOKIE_LIMIT
|
|
714
|
-
if not valid:
|
|
715
|
-
|
|
716
|
-
|
|
727
|
+
if not valid:
|
|
728
|
+
raise exceptions.OperationalError(
|
|
729
|
+
message="Session payload size over cookie limit"
|
|
730
|
+
)
|
|
717
731
|
request.set_cookie = "session=%s" % data_b64
|
appier/settings.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
# Hive Appier Framework
|
|
5
|
-
# Copyright (c) 2008-
|
|
5
|
+
# Copyright (c) 2008-2024 Hive Solutions Lda.
|
|
6
6
|
#
|
|
7
7
|
# This file is part of Hive Appier Framework.
|
|
8
8
|
#
|
|
@@ -22,16 +22,7 @@
|
|
|
22
22
|
__author__ = "João Magalhães <joamag@hive.pt>"
|
|
23
23
|
""" The author(s) of the module """
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
""" The version of the module """
|
|
27
|
-
|
|
28
|
-
__revision__ = "$LastChangedRevision$"
|
|
29
|
-
""" The revision number of the module """
|
|
30
|
-
|
|
31
|
-
__date__ = "$LastChangedDate$"
|
|
32
|
-
""" The last change date of the module """
|
|
33
|
-
|
|
34
|
-
__copyright__ = "Copyright (c) 2008-2022 Hive Solutions Lda."
|
|
25
|
+
__copyright__ = "Copyright (c) 2008-2024 Hive Solutions Lda."
|
|
35
26
|
""" The copyright for the module """
|
|
36
27
|
|
|
37
28
|
__license__ = "Apache License, Version 2.0"
|