Browse Source

Added documentation FS Session

Quentin Bonaventure 7 years ago
parent
commit
69171b23fd
1 changed files with 69 additions and 12 deletions
  1. 69
    12
      lodel/plugins/filesystem_session/main.py

+ 69
- 12
lodel/plugins/filesystem_session/main.py View File

@@ -8,22 +8,45 @@ import os
8 8
 import pickle
9 9
 import re
10 10
 import time
11
-
11
+from .filesystem_session import FileSystemSession
12 12
 from lodel.context import LodelContext
13
+
14
+
13 15
 LodelContext.expose_modules(globals(), {
14 16
     'lodel.logger': 'logger',
15 17
     'lodel.auth.exceptions': ['ClientAuthenticationFailure'],
16 18
     'lodel.settings': ['Settings']})
17 19
 
18
-from .filesystem_session import FileSystemSession
19
-
20 20
 __sessions = dict()
21 21
 
22 22
 SESSION_TOKENSIZE = 150
23 23
 
24 24
 
25
-## @brief generates a new session token
25
+##
26
+# @brief generates a new session token
27
+#
26 28
 # @return str
29
+#
30
+# @warning The tokensize should absolutely be used as set! os.urandom function
31
+#            takes a number of bytes as a parameter, dividing it by 2 is an
32
+#            extremely dangerous idea as it drastically decrease the token expected 
33
+#            entropy expected from the value set in configs.
34
+# @remarks There is no valid reason for checking the generated token uniqueness:
35
+#        - checking for uniqueness is slow ;
36
+#        - keeping a dict with a few thousand keys of hundred bytes also is
37
+#            memory expensive ;
38
+#        - should the system get distributed while sharing session storage, there
39
+#            would be no reasonable way to efficiently check for uniqueness ;
40
+#        - sessions do have a really short life span, drastically reducing
41
+#            even more an already close to inexistent risk of collision. A 64 bits
42
+#            id would perfectly do the job, or to be really cautious, a 128 bits
43
+#            one (actual size of UUIDs) ;
44
+#        - if we are still willing to ensure uniqueness, then simply salt it
45
+#            with a counter, or a timestamp, and hash the whole thing with a 
46
+#            cryptographically secured method such as sha-2 if we are paranoids
47
+#            and trying to avoid what will never happen, ever ;
48
+#        - sure, two hexadecimal characters is one byte long. Simply go for 
49
+#            bit length, not chars length.
27 50
 def generate_token():
28 51
     token = binascii.hexlify(os.urandom(SESSION_TOKENSIZE//2))
29 52
     if token in __sessions.keys():
@@ -31,9 +54,18 @@ def generate_token():
31 54
     return token.decode('utf-8')
32 55
 
33 56
 
34
-## @brief checks the validity of a given session token
57
+##
58
+# @brief checks the validity of a given session token
59
+#
35 60
 # @param token str
36
-# @throw ClientAuthenticationFailure for invalid or not found session token
61
+# @raise ClientAuthenticationFailure for invalid or not found session token
62
+#
63
+# @remarks It is useless to check the token size, unless urandom you don't
64
+#            trust in PRNG such as urandom.
65
+# @remarks Linear key search...
66
+# @remarks Consider renaming. The "validity of a session token" usually means
67
+#            that it is a active session token and/or that it was actually
68
+#            produced by the application (signed for exemple).
37 69
 def check_token(token):
38 70
     if len(token) != SESSION_TOKENSIZE:
39 71
         raise ClientAuthenticationFailure("Invalid token string")
@@ -49,8 +81,13 @@ def generate_file_path(token):
49 81
 
50 82
 
51 83
 ##
84
+# @brief Retrieve the token from the file system
85
+#
52 86
 # @param filepath str
53 87
 # @return str|None : returns the token or None if no token was found
88
+#
89
+# @remarks What is the purpose of the regex right here? There should be a way
90
+#            to avoid slow operations.
54 91
 def get_token_from_filepath(filepath):
55 92
     token_regex = re.compile(os.path.abspath(os.path.join(Settings.sessions.directory, Settings.sessions.file_template % '(?P<token>.*)')))
56 93
     token_search_result = token_regex.match(filepath)
@@ -59,10 +96,15 @@ def get_token_from_filepath(filepath):
59 96
     return None
60 97
 
61 98
 
62
-## @brief returns the session's last modification timestamp
99
+##
100
+# @brief Returns the session's last modification timestamp
101
+#
63 102
 # @param token str
64 103
 # @return float
65
-# @throw ValueError if the given token doesn't match with an existing session
104
+# @raise ValueError if the given token doesn't match with an existing session
105
+#
106
+# @remarks Consider renaming
107
+# @warning Linear search in array, again. See @ref generate_token().
66 108
 def get_session_last_modified(token):
67 109
     if token in __sessions[token]:
68 110
         return os.stat(__sessions[token]).st_mtime
@@ -70,19 +112,26 @@ def get_session_last_modified(token):
70 112
         raise ValueError("The given token %s doesn't match with an existing session")
71 113
 
72 114
 
73
-## @brief returns the token of a new session
74
-# @return str
115
+##
116
+# @brief Starts a new session and returns a new token
117
+#
118
+# @return str : the new token
75 119
 def start_session():
76 120
     session = FileSystemSession(generate_token())
77 121
     session.path = generate_file_path(session.token)
122
+    
78 123
     with open(session.path, 'wb') as session_file:
79 124
         pickle.dump(session, session_file)
125
+
80 126
     __sessions[session.token] = session.path
81 127
     logger.debug("New session created")
128
+
82 129
     return session.token
83 130
 
84 131
 
85
-## @brief destroys a session given its token
132
+##
133
+# @brief destroys a session given its token
134
+#
86 135
 # @param token str
87 136
 def destroy_session(token):
88 137
     check_token(token)
@@ -93,7 +142,9 @@ def destroy_session(token):
93 142
     logger.debug("Session %s unregistered" % token)
94 143
 
95 144
 
96
-## @brief restores a session's content
145
+##
146
+# @brief Restores a session's content
147
+#
97 148
 # @param token str
98 149
 # @return FileSystemSession|None
99 150
 def restore_session(token):
@@ -128,6 +179,8 @@ def save_session(token, datas):
128 179
 
129 180
 
130 181
 ## @brief session store's garbage collector
182
+#
183
+# @remarks 
131 184
 def gc():
132 185
     # Unregistered files in the session directory
133 186
     session_files_directory = os.path.abspath(Settings.sessions.directory)
@@ -164,8 +217,12 @@ def get_session_value(token, key):
164 217
     return session[key]
165 218
 
166 219
 ##
220
+# @brief deletes a session value
221
+#
167 222
 # @param token str
168 223
 # @param key str
224
+#
225
+# @todo Should we add a save_session at the end of this method?
169 226
 def del_session_value(token, key):
170 227
     session = restore_session(token)
171 228
     if key in session:

Loading…
Cancel
Save