|
@@ -1,14 +1,123 @@
|
1
|
1
|
#-*- Coding: utf-8 -*-
|
2
|
2
|
|
3
|
3
|
import copy
|
|
4
|
+import sys
|
|
5
|
+import warnings
|
4
|
6
|
|
5
|
7
|
from lodel.settings import Settings
|
6
|
8
|
from lodel import logger
|
7
|
9
|
from lodel.plugin.hooks import LodelHook
|
8
|
10
|
from lodel.plugin import SessionHandlerPlugin as SessionHandler
|
9
|
11
|
|
|
12
|
+##@brief Class designed to handle sessions and its datas
|
|
13
|
+class LodelSession(object):
|
|
14
|
+
|
|
15
|
+ ##@brief Try to restore or to create a session
|
|
16
|
+ #@param token None | mixed : If None no session will be loaded nor created
|
|
17
|
+ #restore an existing session
|
|
18
|
+ #@throw ClientAuthenticationFailure if a session restore fails
|
|
19
|
+ def __init__(self, token = None):
|
|
20
|
+ ##@brief Stores the session token
|
|
21
|
+ self.__token = token
|
|
22
|
+ ##@brief Stores the session datas
|
|
23
|
+ self.__datas = dict()
|
|
24
|
+ if token is not None:
|
|
25
|
+ self.restore(token)
|
|
26
|
+
|
|
27
|
+ ##@brief A token reference checker to ensure token deletion at the end of
|
|
28
|
+ #a session
|
|
29
|
+ #@warning Cause maybe a performance issue !
|
|
30
|
+ def __token_checker(self):
|
|
31
|
+ refcount = sys.getrefcount(self.__token)
|
|
32
|
+ if refcount > 1:
|
|
33
|
+ warnings.warn("More than one reference to the session token \
|
|
34
|
+exists !")
|
|
35
|
+
|
|
36
|
+ ##@brief Property. Equals True if a session is started else False
|
|
37
|
+ @property
|
|
38
|
+ def started(self):
|
|
39
|
+ res = self.__token is None
|
|
40
|
+ if res:
|
|
41
|
+ self.__token_checker()
|
|
42
|
+ return res
|
|
43
|
+
|
|
44
|
+ ##@brief Property that ensure ro acces to sessions datas
|
|
45
|
+ @property
|
|
46
|
+ def datas(self):
|
|
47
|
+ return copy.copy(self.__datas)
|
|
48
|
+
|
|
49
|
+ ##@brief Return the session token
|
|
50
|
+ def retrieve_token(self):
|
|
51
|
+ # DO NOT COPY THE TOKEN TO ENSURE THAT NOT MORE THAN ONE REFERENCE TO
|
|
52
|
+ # IT EXISTS
|
|
53
|
+ return self.__token
|
|
54
|
+
|
|
55
|
+ ##@brief Late restore of a session
|
|
56
|
+ #@param token mixed : the session token
|
|
57
|
+ #@throw ClientAuthenticationError if a session was allready started
|
|
58
|
+ #@throw ClientAuthenticationFailure if no session exists with this token
|
|
59
|
+ def restore(self, token):
|
|
60
|
+ if self.started:
|
|
61
|
+ raise ClientAuthenticationError("Trying to restore a session, but \
|
|
62
|
+a session is allready started !!!")
|
|
63
|
+ self.__datas = SessionHandler.restore(token)
|
|
64
|
+ return self.datas
|
|
65
|
+
|
|
66
|
+ ##@brief Save the current session state
|
|
67
|
+ def save(self):
|
|
68
|
+ if not self.started:
|
|
69
|
+ raise ClientAuthenticationError(
|
|
70
|
+ "Trying to save a non started session")
|
|
71
|
+ SessionHandler.save(self.__token)
|
|
72
|
+
|
|
73
|
+ ##@brief Destroy a session
|
|
74
|
+ def destroy(self):
|
|
75
|
+ if not self.started:
|
|
76
|
+ logger.debug("Destroying a session that is not started")
|
|
77
|
+ SessionHandler.destroy(self.__token)
|
|
78
|
+ self.__token = None
|
|
79
|
+ self.__datas = dict()
|
|
80
|
+
|
|
81
|
+ ##@brief Destructor
|
|
82
|
+ def __del__(self):
|
|
83
|
+ del(self.__token)
|
|
84
|
+ del(self.__datas)
|
|
85
|
+
|
|
86
|
+ ##@brief Implements setter for dict access to instance
|
|
87
|
+ #@todo Custom exception throwing
|
|
88
|
+ def __setitem__(self, key, value):
|
|
89
|
+ self.__init_session() #Start the sesssion
|
|
90
|
+ self.__datas[key] = value
|
|
91
|
+
|
|
92
|
+ ##@brief Implements destructor for dict access to instance
|
|
93
|
+ #@todo Custom exception throwing
|
|
94
|
+ def __delitem__(self, key):
|
|
95
|
+ if not self.started:
|
|
96
|
+ raise ClientAuthenticationError(
|
|
97
|
+ "Data read access to a non started session is not possible")
|
|
98
|
+ del(self.__datas[key])
|
|
99
|
+
|
|
100
|
+ ##@brief Implements getter for dict acces to instance
|
|
101
|
+ #@todo Custom exception throwing
|
|
102
|
+ def __getitem__(self, key):
|
|
103
|
+ if not self.started:
|
|
104
|
+ raise ClientAuthenticationError(
|
|
105
|
+ "Data read access to a non started session is not possible")
|
|
106
|
+ return self.__datas[key]
|
|
107
|
+
|
|
108
|
+ ##@brief Start a new session
|
|
109
|
+ #@note start a new session only if no session started yet
|
|
110
|
+ def __init_session(self):
|
|
111
|
+ if self.__token is not None:
|
|
112
|
+ return
|
|
113
|
+ self.__token = SessionHandler.start()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
|
10
|
117
|
##@brief Client metaclass designed to implements container accessor on
|
11
|
118
|
#Client Class
|
|
119
|
+#
|
|
120
|
+#@todo Maybe we can delete this metaclass....
|
12
|
121
|
class ClientMetaclass(type):
|
13
|
122
|
|
14
|
123
|
SESSION_ID_NAME = '__SESSION_ID__'
|
|
@@ -27,11 +136,14 @@ class ClientMetaclass(type):
|
27
|
136
|
self.__session[SESSION_ID_NAME] = SessionHandler.start_session()
|
28
|
137
|
self.__session[key] = value
|
29
|
138
|
|
|
139
|
+ def __token(self):
|
|
140
|
+ return None if SESSION_ID_NAME not in self.__sessions else self.__session[SESSION_ID_NAME]
|
|
141
|
+
|
30
|
142
|
##@brief Return a copy of sessions infos
|
31
|
143
|
def session_dump(self):
|
|
144
|
+ #first set all sessions values
|
|
145
|
+ SessionHandler.save_session(self.__session)
|
32
|
146
|
return copy.copy(self.__session)
|
33
|
|
-
|
34
|
|
-
|
35
|
147
|
|
36
|
148
|
|
37
|
149
|
##@brief Abstract singleton class designed to handle client informations
|
|
@@ -55,6 +167,10 @@ class Client(object, metaclass = ClientMetaclass):
|
55
|
167
|
#- password typle contains (LeObjectChild, FieldName)
|
56
|
168
|
_infos_fields = None
|
57
|
169
|
|
|
170
|
+ ##@brief Constant that stores the session key that stores authentication
|
|
171
|
+ #informations
|
|
172
|
+ _AUTH_DATANAME = '__auth_user_infos'
|
|
173
|
+
|
58
|
174
|
|
59
|
175
|
##@brief Constructor
|
60
|
176
|
#@param ui_instance Lodel2Ui child class instance
|
|
@@ -79,6 +195,8 @@ class Client(object, metaclass = ClientMetaclass):
|
79
|
195
|
self.__user = None
|
80
|
196
|
##@brief Stores the session handler
|
81
|
197
|
Client._instance = self
|
|
198
|
+ ##@brief Stores LodelSession instance
|
|
199
|
+ self.__session = LodelSession(token)
|
82
|
200
|
logger.debug("New client : %s" % self)
|
83
|
201
|
|
84
|
202
|
##@brief Attempt to restore a session given a session token
|
|
@@ -87,11 +205,13 @@ class Client(object, metaclass = ClientMetaclass):
|
87
|
205
|
#@throw ClientAuthenticationFailure if token is not valid or not
|
88
|
206
|
#existing
|
89
|
207
|
def _restore_session(self, token):
|
90
|
|
- res = self._session_handler.restore_session(token)
|
91
|
|
- if res is False:
|
92
|
|
- raise ClientAuthenticationFailure(client = self,
|
93
|
|
- msg = "Invalid or not existing session token provided")
|
94
|
|
- pass
|
|
208
|
+ return self.__session.restore(token)
|
|
209
|
+
|
|
210
|
+ ##@brief Return the current session token or None
|
|
211
|
+ #@return A session token or None
|
|
212
|
+ @classmethod
|
|
213
|
+ def session_token(cls):
|
|
214
|
+ return self.__session.retrieve_token()
|
95
|
215
|
|
96
|
216
|
##@brief Try to authenticate a user with a login and a password
|
97
|
217
|
#@param login str : provided login
|
|
@@ -216,5 +336,7 @@ login EmClass '%s' and password EmClass '%s'. Abording..." % (
|
216
|
336
|
#@return None
|
217
|
337
|
def __set_authenticated(self, leo, uid):
|
218
|
338
|
self.__user = {'classname': leo.__name__, 'uid': uid, 'leoclass': leo}
|
|
339
|
+ #Store auth infos in session
|
|
340
|
+ self.__session[self.__class__._AUTH_DATANAME] = copy.copy(self.__user)
|
219
|
341
|
|
220
|
342
|
|