|
@@ -4,86 +4,106 @@ import os
|
4
|
4
|
import pickle
|
5
|
5
|
import re
|
6
|
6
|
|
7
|
|
-from lodel.auth.exceptions import AuthenticationError
|
8
|
|
-from lodel.auth.session import SessionStore
|
|
7
|
+from lodel.auth.session import LodelSession
|
9
|
8
|
from lodel.settings import Settings
|
10
|
9
|
|
11
|
10
|
|
12
|
|
-class FileSystemSessionStore(SessionStore):
|
|
11
|
+class FileSystemSession(LodelSession):
|
13
|
12
|
|
14
|
|
- ## @brief instanciates a FileSystemSessionStore
|
15
|
|
- # @param base_directory str : path to the base directory containing the session files (default: session.directory param of the settings)
|
16
|
|
- # @param file_name_template str : template for the session files name (default : session.file_template param of the settings)
|
17
|
|
- # @param expiration_limit int : duration of a session validity without any action made (defaut : session.expiration param of the settings)
|
18
|
|
- def __init__(self, base_directory=Settings.sessions.directory, file_name_template=Settings.sessions.file_template, expiration_limit=Settings.sessions.expiration):
|
19
|
|
- self.expiration_limit = expiration_limit
|
20
|
|
- self.base_directory = base_directory
|
21
|
|
- self.file_name_template = file_name_template
|
|
13
|
+ __sessions = {}
|
22
|
14
|
|
23
|
|
- # === CRUD === #
|
|
15
|
+ EXPIRATION_LIMIT = Settings.sessions.expiration
|
|
16
|
+ BASE_DIRECTORY = Settings.sessions.directory
|
|
17
|
+ FILENAME_TEMPLATE = Settings.sessions.file_template
|
24
|
18
|
|
25
|
|
- ## @brief delete a session
|
26
|
|
- # @param sid str : id of the session to be deleted
|
27
|
|
- def delete_session(self, sid):
|
28
|
|
- if self.is_session_existing(sid):
|
29
|
|
- os.unlink(self.get_session_file_path(sid))
|
30
|
|
- else:
|
31
|
|
- raise AuthenticationError("No session file found for the sid %s" % sid)
|
|
19
|
+ def __init__(self):
|
|
20
|
+ self.path = None # Is initialized in the store method
|
|
21
|
+ super().__init__()
|
32
|
22
|
|
33
|
|
- ## @brief reads the content of a session
|
|
23
|
+ ## @brief stores the session
|
|
24
|
+ def store(self):
|
|
25
|
+ self.path = self.__class__.generate_session_file_name(self.sid)
|
|
26
|
+ self.save()
|
|
27
|
+
|
|
28
|
+ ## @brief registers the session in the active sessions list
|
|
29
|
+ def register_session(self):
|
|
30
|
+ self.__class__.__sessions[self.sid] = self.path
|
|
31
|
+
|
|
32
|
+ ## @brief saves the session
|
|
33
|
+ # @todo security
|
|
34
|
+ def save(self):
|
|
35
|
+ with open(self.path, 'wb') as session_file:
|
|
36
|
+ pickle.dump(self, session_file)
|
|
37
|
+
|
|
38
|
+ ## @brief loads a session
|
34
|
39
|
# @param sid str : session id
|
35
|
|
- def read_session(self, sid):
|
36
|
|
- session_file_path = self.get_session_file_path(sid)
|
37
|
|
- with open(session_file_path, 'rb') as session_file:
|
38
|
|
- session_content = pickle.load(session_file)
|
39
|
|
- return session_content
|
|
40
|
+ # @return FileSystemSession
|
|
41
|
+ @classmethod
|
|
42
|
+ def load(cls, sid):
|
|
43
|
+ if sid in cls.__sessions.keys():
|
|
44
|
+ session_file_path = cls.__sessions[sid]
|
|
45
|
+ with open(session_file_path, 'rb') as session_file:
|
|
46
|
+ session = pickle.load(session_file)
|
|
47
|
+ return session
|
|
48
|
+ return None
|
40
|
49
|
|
41
|
|
- ## @brief saves a session to a file
|
|
50
|
+ ## @brief cleans the session store
|
|
51
|
+ # @todo add more checks
|
|
52
|
+ @classmethod
|
|
53
|
+ def clean(cls):
|
|
54
|
+ # unregistered files in the session directory (if any)
|
|
55
|
+ session_dir_files = cls.list_all_session_files()
|
|
56
|
+ for session_dir_file in session_dir_files:
|
|
57
|
+ sid = cls.filename_to_sid(session_dir_file)
|
|
58
|
+ if sid is None or sid not in cls.__sessions.keys():
|
|
59
|
+ os.unlink(session_dir_file)
|
|
60
|
+ # registered sessions
|
|
61
|
+ for sid in cls.__sessions.keys():
|
|
62
|
+ if cls.is_expired(sid):
|
|
63
|
+ cls.destroy(sid)
|
|
64
|
+
|
|
65
|
+ ## @brief gets the last modified date of a session
|
42
|
66
|
# @param sid str : session id
|
43
|
|
- # @param session dict : content to be saved
|
44
|
|
- def save_session(self, sid, session):
|
45
|
|
- session_file_path = self.get_session_file_path(sid)
|
46
|
|
- with open(session_file_path, 'wb') as session_file:
|
47
|
|
- pickle.dump(session, session_file)
|
|
67
|
+ @classmethod
|
|
68
|
+ def get_last_modified(cls, sid):
|
|
69
|
+ return os.stat(cls.__sessions[sid]).st_mtime
|
48
|
70
|
|
|
71
|
+ ## @brief lists all the files contained in the session directory
|
|
72
|
+ # @return list
|
|
73
|
+ @classmethod
|
|
74
|
+ def list_all_session_files(cls):
|
|
75
|
+ session_files_directory = os.abspath(cls.BASE_DIRECTORY)
|
|
76
|
+ files_list = [file_path for file_path in os.listdir(session_files_directory) if os.path.isfile(os.path.join(session_files_directory, file_path))]
|
|
77
|
+ return files_list
|
49
|
78
|
|
50
|
|
- # === UTILS === #
|
51
|
79
|
## @brief returns the session id from the filename
|
52
|
|
- # @param filename str : session file's name (not the complete path)
|
|
80
|
+ # @param filename str : session file's name
|
53
|
81
|
# @return str
|
54
|
|
- # @raise AuthenticationError : in case the sid could not be found for the given filename
|
55
|
|
- def filename_to_sid(self,filename):
|
56
|
|
- sid_regex = self.file_name_template % '(?P<sid>.*)'
|
57
|
|
- sid_regex_compiled = re.compile(sid_regex)
|
58
|
|
- sid_searching_result = sid_regex_compiled.match(filename)
|
|
82
|
+ @classmethod
|
|
83
|
+ def filename_to_sid(cls, filename):
|
|
84
|
+ sid_regex = re.compile(cls.FILENAME_TEMPLATE % '(?P<sid>.*)')
|
|
85
|
+ sid_searching_result = sid_regex.match(filename)
|
59
|
86
|
if sid_searching_result is not None:
|
60
|
87
|
return sid_searching_result.groupdict()['sid']
|
61
|
|
- else:
|
62
|
|
- raise AuthenticationError('No session id could be found for this filename')
|
|
88
|
+ return None
|
63
|
89
|
|
64
|
|
- ## @brief lists all the session files paths
|
65
|
|
- # @return list
|
66
|
|
- def list_all_sessions(self):
|
67
|
|
- session_files_directory = os.path.abspath(self.base_directory)
|
68
|
|
- sid_list = [self.filename_to_sid(file_object) for file_object in os.listdir(session_files_directory) if os.path.isfile(os.path.join(session_files_directory, file_object))]
|
69
|
|
- return sid_list
|
|
90
|
+ ## @brief deletes a session's informations
|
|
91
|
+ @classmethod
|
|
92
|
+ def delete_session(cls, sid):
|
|
93
|
+ if os.path.isfile(cls.__sessions[sid]):
|
|
94
|
+ # Deletes the session file
|
|
95
|
+ os.unlink(cls.__sessions[sid])
|
70
|
96
|
|
71
|
|
- ## @brief returns the file path for a given session id
|
|
97
|
+ ## @brief generates session file name
|
72
|
98
|
# @param sid str : session id
|
73
|
99
|
# @return str
|
74
|
|
- def get_session_file_path(self, sid):
|
75
|
|
- return os.path.join(self.base_directory, self.file_name_template) % sid
|
|
100
|
+ @classmethod
|
|
101
|
+ def generate_session_file_name(cls, sid):
|
|
102
|
+ return os.path.join(cls.BASE_DIRECTORY, cls.FILENAME_TEMPLATE) % sid
|
76
|
103
|
|
77
|
104
|
## @brief checks if a session exists
|
78
|
|
- # @param sid str : session id
|
79
|
|
- # @return bool
|
80
|
|
- def is_session_existing(self, sid):
|
81
|
|
- session_file = self.get_session_file_path(sid)
|
82
|
|
- return os.path.is_file(session_file)
|
83
|
|
-
|
84
|
|
- ## @brief gets a session's last modified timestamp
|
85
|
105
|
# @param sid str: session id
|
86
|
|
- # @return float
|
87
|
|
- def get_session_last_modified(self, sid):
|
88
|
|
- session_file = self.get_session_file_path(sid)
|
89
|
|
- return os.stat(session_file).st_mtime
|
|
106
|
+ # @return bool
|
|
107
|
+ @classmethod
|
|
108
|
+ def exists(cls, sid):
|
|
109
|
+ return cls.is_registered(sid) and (os.path.isfile(cls.__sessions[sid]))
|