Преглед на файлове

Merge branch 'session-class' into newlodel

Roland Haroutiounian преди 8 години
родител
ревизия
e294ffec21
променени са 3 файла, в които са добавени 215 реда и са изтрити 88 реда
  1. 112
    0
      lodel/auth/session.py
  2. 87
    0
      plugins/filesystem_session/filesystem_session_store.py
  3. 16
    88
      plugins/filesystem_session/main.py

+ 112
- 0
lodel/auth/session.py Целия файл

@@ -0,0 +1,112 @@
1
+# -*- coding; utf-8 -*-
2
+
3
+from abc import ABC, abstractmethod
4
+from uuid import uuid1
5
+
6
+from lodel.auth.exceptions import AuthenticationError
7
+from lodel.utils.datetime import get_utc_timestamp
8
+
9
+
10
+class SessionStore(ABC):
11
+
12
+    expiration_limit = 900
13
+
14
+    # === ABSTRACT METHODS === #
15
+
16
+    ## @brief Destroys a session
17
+    # @param sid str : session id
18
+    @abstractmethod
19
+    def delete_session(self, sid):
20
+        pass
21
+
22
+    ## @brief Reads a session content
23
+    # @param sid str : session id
24
+    # @return dict
25
+    @abstractmethod
26
+    def read_session(self, sid):
27
+        return {}
28
+
29
+    ## @brief lists all the sessions ids
30
+    # @return list
31
+    @abstractmethod
32
+    def list_all_sessions(self):
33
+        return []
34
+
35
+    ## @brief saves a session to a file
36
+    # @param sid str : session id
37
+    # @param session dict : content to be saved
38
+    @abstractmethod
39
+    def save_session(self, sid, session):
40
+        pass
41
+
42
+    ## @brief checks if a session exists
43
+    # @param sid str : session id
44
+    # @return bool
45
+    @abstractmethod
46
+    def is_session_existing(self, sid):
47
+        return True
48
+
49
+    ## @brief gets a session's last modified timestamp
50
+    # @param sid str: session id
51
+    # @return float
52
+    @abstractmethod
53
+    def get_session_last_modified(self, sid):
54
+        pass
55
+
56
+    # === IMPLEMENTED METHODS === #
57
+
58
+    ## @brief Generates a session unique ID
59
+    # @param cls
60
+    # @return str
61
+    @classmethod
62
+    def generate_new_sid(cls):
63
+        return uuid1()
64
+
65
+    ## @brief Creates a new session
66
+    # @param content dict : session content (default: {})
67
+    # @return str
68
+    def create_new_session(self, content={}):
69
+        sid = self.__class__.generate_new_sid()
70
+        self.save_session(sid, content)
71
+        return sid
72
+
73
+    ## @brief checks if a session has expired
74
+    # @param sid str: session id
75
+    # @return bool
76
+    def has_session_expired(self, sid):
77
+        session_last_modified = self.get_session_last_modified(sid)
78
+        expiration_timestamp = session_last_modified + self.expiration_limit
79
+        now_timestamp = get_utc_timestamp()
80
+        return now_timestamp > expiration_timestamp
81
+
82
+    ## @brief cleans the session store's by destroying the expired sessions
83
+    def clean(self):
84
+        sessions_list = self.list_all_sessions()
85
+        for sid in sessions_list:
86
+            if self.has_session_expired(sid):
87
+                self.delete_session(sid)
88
+
89
+    ## @brief updates a session's content
90
+    # @param sid str : session's id
91
+    # @param content dict : items to update with their new value
92
+    def update_session(self, sid, content):
93
+        session = self.get_session(sid)
94
+        for key, value in content.items():
95
+            if key != 'sid':
96
+                session[key] = value
97
+        self.save_session(sid, session)
98
+
99
+    ## @brief gets a session's content
100
+    # @param sid str : id of the session to read
101
+    # @return dict
102
+    def get_session(self, sid):
103
+        if self.is_session_existing(sid):
104
+            if not self.has_session_expired(sid):
105
+                session = self.read_session(sid)
106
+            else:
107
+                self.delete_session(sid)
108
+                session = {}
109
+        else:
110
+            raise AuthenticationError("No session file found for the sid %s" % sid)
111
+
112
+        return session

+ 87
- 0
plugins/filesystem_session/filesystem_session_store.py Целия файл

@@ -0,0 +1,87 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+import os
4
+import pickle
5
+import re
6
+
7
+from lodel.auth.exceptions import AuthenticationError
8
+from lodel.auth.session import SessionStore
9
+from lodel.settings import Settings
10
+
11
+
12
+class FileSystemSessionStore(SessionStore):
13
+
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.session.directory, file_name_template=Settings.session.file_template, expiration_limit=Settings.session.expiration):
19
+        self.expiration_limit = expiration_limit
20
+        self.base_directory = base_directory
21
+        self.file_name_template = file_name_template
22
+
23
+    # === CRUD === #
24
+
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)
32
+
33
+    ## @brief reads the content of a session
34
+    # @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
+
41
+    ## @brief saves a session to a file
42
+    # @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
+        pickle.dump(session, open(session_file_path, "wb"))
47
+
48
+    # === UTILS === #
49
+    ## @brief returns the session id from the filename
50
+    # @param filename str : session file's name (not the complete path)
51
+    # @return str
52
+    # @raise AuthenticationError : in case the sid could not be found for the given filename
53
+    def filename_to_sid(self,filename):
54
+        sid_regex = self.file_name_template % '(?P<sid>.*)'
55
+        sid_regex_compiled = re.compile(sid_regex)
56
+        sid_searching_result = sid_regex_compiled.match(filename)
57
+        if sid_searching_result is not None:
58
+            return sid_searching_result.groupdict()['sid']
59
+        else:
60
+            raise AuthenticationError('No session id could be found for this filename')
61
+
62
+    ## @brief lists all the session files paths
63
+    # @return list
64
+    def list_all_sessions(self):
65
+        session_files_directory = os.path.abspath(self.base_directory)
66
+        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))]
67
+        return sid_list
68
+
69
+    ## @brief returns the file path for a given session id
70
+    # @param sid str : session id
71
+    # @return str
72
+    def get_session_file_path(self, sid):
73
+        return os.path.join(self.base_directory, self.file_name_template) % sid
74
+
75
+    ## @brief checks if a session exists
76
+    # @param sid str : session id
77
+    # @return bool
78
+    def is_session_existing(self, sid):
79
+        session_file = self.get_session_file_path(sid)
80
+        return os.path.is_file(session_file)
81
+
82
+    ## @brief gets a session's last modified timestamp
83
+    # @param sid str: session id
84
+    # @return float
85
+    def get_session_last_modified(self, sid):
86
+        session_file = self.get_session_file_path(sid)
87
+        return os.stat(session_file).st_mtime

+ 16
- 88
plugins/filesystem_session/main.py Целия файл

@@ -1,58 +1,11 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 
3
-import os
4
-import pickle
5
-import uuid
6
-
7 3
 from lodel.auth.exceptions import AuthenticationError
8 4
 from lodel.plugin import LodelHook
9
-from lodel.settings import Settings
10
-from lodel.utils.datetime import get_utc_timestamp
11
-
12
-SESSION_FILES_BASE_DIR = Settings.sessions.directory
13
-SESSION_FILES_TEMPLATE = Settings.sessions.file_template
14
-SESSION_EXPIRATION_LIMIT = Settings.sessions.expiration
15
-
16
-
17
-## @brief generates a new session id
18
-def generate_new_sid():
19
-    return uuid.uuid1()
20
-
21
-
22
-## @brief gets the session file path, given a session id
23
-# @param sid str : session id
24
-# @return str
25
-def get_session_file_path(sid):
26
-    return os.path.join(SESSION_FILES_BASE_DIR, SESSION_FILES_TEMPLATE) % sid
27
-
28
-
29
-## @brief saves the session content to a session file
30
-# @param sid str: session id
31
-# @param session dict : session content to be saved
32
-def save_session(sid, session):
33
-    session_file_path = get_session_file_path(sid)
34
-    pickle.dump(session, open(session_file_path, "wb"))
35 5
 
6
+from .filesystem_session_store import FileSystemSessionStore
36 7
 
37
-## @brief checks if a session file has expired
38
-# @param sid str : session id
39
-# @return bool
40
-def is_session_expired(sid):
41
-    session_file = get_session_file_path(sid)
42
-    if not os.path.isfile(session_file):
43
-        raise AuthenticationError("No session file found for the sid : %s" % sid)
44
-
45
-    expiration_timestamp = os.stat(session_file).st_mtime + SESSION_EXPIRATION_LIMIT
46
-    now_timestamp = get_utc_timestamp()
47
-    return now_timestamp >= expiration_timestamp
48
-
49
-
50
-## @brief reads a session content
51
-# @param sid str: session id
52
-# @return dict
53
-def get_session_content(sid):
54
-    session_file_path = get_session_file_path(sid)
55
-    return pickle.load(open(session_file_path), 'rb')
8
+session_store = FileSystemSessionStore()
56 9
 
57 10
 
58 11
 ## @brief starts a new session and returns its sid
@@ -61,66 +14,41 @@ def get_session_content(sid):
61 14
 # @return str
62 15
 @LodelHook('session_start')
63 16
 def start_session(caller, payload):
64
-    sid = generate_new_sid()
65
-    session_file = get_session_file_path(sid)
66
-    session = dict()
67
-    for key, value in payload.items():
68
-        session[key] = value
69
-    save_session(sid, session)
70
-    return sid
17
+    return session_store.create_new_session(payload)
71 18
 
72
-## @brief stops a session
19
+
20
+## @brief destroys a session
73 21
 # @param caller *
74 22
 # @param sid str : session id
75 23
 @LodelHook('session_destroy')
76 24
 def stop_session(caller, sid):
77
-    session_file_path = get_session_file_path(sid)
78
-    if os.path.isfile(session_file_path):
79
-        os.unlink(session_file_path)
80
-    else:
81
-        raise AuthenticationError("No session file found for the sid %s" % sid)
25
+    session_store.delete_session(sid)
82 26
 
83 27
 
84 28
 ## @brief reads a session content
85 29
 # @param caller *
86 30
 # @param sid str: session id
31
+# @return dict
87 32
 @LodelHook('session_load')
88 33
 def read_session(caller, sid):
89
-    session_file = get_session_file_path(sid)
90
-    if os.path.isfile(session_file):
91
-        if not is_session_expired(sid):
92
-            session = get_session_content(sid)
93
-        else:
94
-            LodelHook.call_hook('session_stop', __file__, sid)
95
-            session = {}
96
-    else:
97
-        raise AuthenticationError("No session file found for the sid %s" % sid)
98
-    return session
34
+    return session_store.get_session(sid)
99 35
 
100 36
 
101
-## @brief deletes all old session files (expired ones)
37
+## @brief destroys all the old sessions (expired ones)
102 38
 # @param caller *
103 39
 @LodelHook('session_clean')
104 40
 def clean_sessions(caller):
105
-    session_files_path = os.path.abspath(SESSION_FILES_BASE_DIR)
106
-    session_files = [os.path.join(session_files_path, file_object) for file_object in os.listdir(session_files_path) if os.path.isfile(os.path.join(session_files_path, file_object))]
107
-    now_timestamp = get_utc_timestamp()
108
-    for session_file in session_files:
109
-        last_modified = os.stat(session_file).st_mtime
110
-        expiration_timestamp = last_modified + SESSION_EXPIRATION_LIMIT
111
-        if now_timestamp > expiration_timestamp:
112
-            os.unlink(session_file)
41
+    session_store.clean()
42
+
113 43
 
114
-## @brief updates the content session
44
+## @brief updates the content of the session
115 45
 # @param caller *
116
-# @param payload dict: datas to insert/update in the session
46
+# @param payload dict : datas to insert/update in the session
117 47
 @LodelHook('update_session')
118 48
 def update_session_content(caller, payload):
119 49
     if 'sid' in payload:
120 50
         sid = payload['sid']
121
-        session = LodelHook.call_hook('session_load', __file__, sid)
122
-        for key, value in payload.items():
123
-            session[key] = value
124
-        save_session(sid, session)
51
+        del payload['sid']
52
+        session_store.update_session(sid, payload)
125 53
     else:
126
-        raise AuthenticationError("Missing session id in the request")
54
+        raise AuthenticationError("Session Update: Missing sid (session id) in the given payload argument")

Loading…
Отказ
Запис