Refactor the data store a bit
[cascardo/ipsilon.git] / ipsilon / util / user.py
1 #!/usr/bin/python
2 #
3 # Copyright (C) 2013  Simo Sorce <simo@redhat.com>
4 #
5 # see file 'COPYING' for use and warranty information
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 from ipsilon.util.data import UserStore
21 from ipsilon.util.log import Log
22 import cherrypy
23
24
25 class Site(object):
26     def __init__(self, value):
27         # implement lookup of sites id for link/name
28         self.link = value
29         self.name = value
30
31
32 class User(object):
33     def __init__(self, username):
34         if username is None:
35             self.name = None
36             self._userdata = dict()
37         else:
38             self._userdata = self._get_user_data(username)
39             self.name = username
40
41     def _get_user_data(self, username):
42         store = UserStore()
43         return store.load_options('users', username)
44
45     def reset(self):
46         self.name = None
47         self._userdata = dict()
48
49     @property
50     def is_anonymous(self):
51         if self.name:
52             return False
53         return True
54
55     @property
56     def is_admin(self):
57         if 'is_admin' in self._userdata:
58             if str(self._userdata['is_admin']) == '1':
59                 return True
60         return False
61
62     @is_admin.setter
63     def is_admin(self, value):
64         if value is True:
65             self._userdata['is_admin'] = '1'
66         else:
67             self._userdata['is_admin'] = '0'
68
69     @property
70     def fullname(self):
71         if 'fullname' in self._userdata:
72             return self._userdata['fullname']
73         else:
74             return self.name
75
76     @fullname.setter
77     def fullname(self, value):
78         self._userdata['fullname'] = value
79
80     @property
81     def email(self):
82         if 'email' in self._userdata:
83             return self._userdata['email']
84         else:
85             return None
86
87     @property
88     def sites(self):
89         if 'sites' in self._userdata:
90             d = []
91             for site in self._userdata['sites']:
92                 d.append(Site(site))
93         else:
94             return []
95
96     @sites.setter
97     def sites(self):
98         # TODO: implement setting sites via the user object ?
99         raise AttributeError
100
101
102 class UserSession(Log):
103     def __init__(self):
104         self.user = self.get_data('user', 'name')
105         self.userattrs = self.get_user_attrs()
106
107     def get_user(self):
108         return User(self.user)
109
110     def remote_login(self):
111         if cherrypy.request.login:
112             self.login(cherrypy.request.login)
113         else:
114             self.nuke_data('user')
115
116     def login(self, username, userattrs=None):
117         if self.user == username:
118             return
119
120         # REMOTE_USER changed, replace user
121         self.nuke_data('user')
122         self.save_data('user', 'name', username)
123         self.user = username
124
125         # Save additional data provided by the login manager
126         self.nuke_data('userattrs')
127         if userattrs:
128             self.save_user_attrs(userattrs)
129
130         cherrypy.log('LOGIN SUCCESSFUL: %s' % username)
131
132     def logout(self, user):
133         if user is not None:
134             if not type(user) is User:
135                 raise TypeError
136             # Completely reset user data
137             cherrypy.log.error('%s %s' % (user.name, user.fullname))
138             user.reset()
139
140         # Destroy current session in all cases
141         cherrypy.lib.sessions.expire()
142
143     def get_user_attrs(self):
144         userattrs = dict()
145         if 'userattrs' in cherrypy.session:
146             userattrs = cherrypy.session['userattrs']
147         return userattrs
148
149     def save_user_attrs(self, userattrs):
150         cherrypy.session['userattrs'] = userattrs
151         cherrypy.session.save()
152         self._debug('Saved user attrs')
153         self.userattrs = userattrs
154
155     def save_data(self, facility, name, data):
156         """ Save named data in the session so it can be retrieved later """
157         if facility not in cherrypy.session:
158             cherrypy.session[facility] = dict()
159         cherrypy.session[facility][name] = data
160         cherrypy.session.save()
161         self._debug('Saved session data named [%s:%s]' % (facility, name))
162
163     def get_data(self, facility, name):
164         """ Get named data in the session if available """
165         if facility not in cherrypy.session:
166             return None
167         if name not in cherrypy.session[facility]:
168             return None
169         return cherrypy.session[facility][name]
170
171     def nuke_data(self, facility, name=None):
172         if facility not in cherrypy.session:
173             return
174         if name:
175             if name not in cherrypy.session[facility]:
176                 return
177             cherrypy.session[facility][name] = None
178             del cherrypy.session[facility][name]
179             self._debug('Nuked session data named [%s:%s]' % (facility, name))
180         else:
181             del cherrypy.session[facility]
182             self._debug('Nuked session facility [%s]' % (facility,))
183         cherrypy.session.save()