accounts.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 ################################################################################
3 #
4 # Copyright Airbus Group SAS 2015
5 # All rigths reserved.
6 #
7 # File Name : accounts.py
8 # Authors : Martin Matignon
9 #
10 # If you find any bug or if you have any question please contact
11 # Adolfo Suarez Roos <adolfo.suarez@airbus.com>
12 # Martin Matignon <martin.matignon.external@airbus.com>
13 #
14 #
15 ################################################################################
16 
17 import rospy
18 import os
19 import base64
20 from xml.etree import ElementTree
21 
22 from python_qt_binding.QtCore import *
23 
24 from airbus_cobot_gui.pkg_dir import airbus_cobot_gui_dir
25 
26 from airbus_cobot_gui.exception import CobotGuiException
27 
28 ## @class Privilege
29 ## @brief Class for difine different levels of user access.
30 class Privilege:
31 
32  NONE = -1
33  OPERATOR = 0
34  MAINTENANCE = 1
35  EXPERT = 2
36  DEVELOPER = 3
37 
38  TOSTR = {NONE : 'none',
39  OPERATOR : 'operator',
40  MAINTENANCE: 'maintenance',
41  EXPERT : 'expert',
42  DEVELOPER : 'developer'}
43 
44  TOLEVEL = {'none' : NONE,
45  'operator' : OPERATOR,
46  'maintenance': MAINTENANCE,
47  'expert' : EXPERT,
48  'developer' : DEVELOPER}
49 
50 class User(object):
51 
52  UNKNOWN = 'Unknown'
53  NONE = UNKNOWN
54 
55  def __init__(self, userid = None, privilege = Privilege.NONE):
56 
57  self.userid = userid or ''
58  self.created = ''
59  self.modified = ''
60  self.connected = ''
61  self.privilege = privilege
62  self.password = ''
63  self.encoded = False
64 
65  if userid is not None:
66  self.connected = rospy.get_time()
67 
68  def init(self, userid, privilege):
69  self.connected = rospy.get_time()
70  self.userid = userid
71  self.privilege = privilege
72 
73  def set_password(self, password, encode = True):
74 
75  if encode:
76  self.password = base64.b64encode(password)
77  else:
78  self.password = password
79 
80  self.encoded = encode
81 
82  def get_password(self, decode = False):
83 
84  if decode:
85  return base64.b64decode(self.password)
86  else:
87  return self.password
88 
89  def __str__(self):
90  return 'User[%s,%s]'%(self.userid, Privilege.TOSTR[self.privilege])
91 
92 class UserAccountCommunicate(QObject):
93 
94  def __init__(self):
95  """! The constructor."""
96  QObject.__init__(self)
97 
98  self._user = User()
99 
100  def update(self, user):
101  """! Set user informations and call at callbacks the new connection.
102  @param userinfo: user connected information.
103  @type userinfo: User.
104  """
105  self._user = user
106  self.emit(SIGNAL('userAccountChanged'), self._user)
107 
109  """! Get current user informations.
110  @return userinfo: user informations.
111  @type userinfo: User.
112  """
113  return self._user
114 
115 #Global instance
116 GUserAccountCommunicate = UserAccountCommunicate()
117 
119 
120  db_dir = airbus_cobot_gui_dir('resources','accounts','accounts_init.db')
121 
122  xmlstr = """<?xml version='1.0' encoding='utf8'?>
123 <accounts>
124  <user id="mmn">
125  <created>22-05-2014</created>
126  <modified>23-05-2014</modified>
127  <privilege>developer</privilege>
128  <password>YXRpMDA2</password>
129  </user>
130  <user id="martin">
131  <created>22-05-2014</created>
132  <modified>23-05-2014</modified>
133  <privilege>operator</privilege>
134  <password>YXRpMDA2</password>
135  </user>
136 </accounts>"""
137 
138  xmlencode = base64.encodestring(xmlstr)
139 
140  with open(os.path.join(db_dir),'w') as f_db:
141  f_db.write(xmlencode)
142 
144 
145  db_dir = airbus_cobot_gui_dir('resources','accounts','accounts_root.db')
146 
147  xmlstr = """<?xml version='1.0' encoding='utf8'?>
148 <accounts>
149 </accounts>"""
150 
151  xmlencode = base64.encodestring(xmlstr)
152 
153  with open(os.path.join(db_dir),'w') as f_db:
154  f_db.write(xmlencode)
155 
156 
157 def indent(elem, level=0):
158 
159  i = "\n" + level*" "
160  if len(elem):
161  if not elem.text or not elem.text.strip():
162  elem.text = i + " "
163  if not elem.tail or not elem.tail.strip():
164  elem.tail = i
165  for elem in elem:
166  indent(elem, level+1)
167  if not elem.tail or not elem.tail.strip():
168  elem.tail = i
169  else:
170  if level and (not elem.tail or not elem.tail.strip()):
171  elem.tail = i
172 
173 setattr(ElementTree, 'indent', indent)
174 
175 ## @package: accounts
176 ##
177 ## @version 4.0
178 ## @author Matignon Martin
179 ## @date Last modified 22/05/2014
180 
181 ## @class UserAccounts
182 ## @brief Manage user accounts file
184  """ Manage user account file xml:
185  - Get user list
186  - Find user account,
187  - Add user account,
188  - Modif user account,
189  - Remove user account.
190  """
191 
192  ACCOUNTS_FILENAME = 'accounts.db'
193 
194  #Primary keys
195  USER = 'user'
196  PRIVILEGE = 'privilege'
197  PASSWORD = 'password'
198  #Keys
199  UID = 'id'
200  CREATED = 'created'
201  MODIFIED = 'modified'
202 
203  USER_STR_ITEM = """<user id="%s">
204  <created>%s</created>
205  <modified>%s</modified>
206  <privilege>%s</privilege>
207  <password>%s</password>
208  </user>"""
209 
210  def __init__(self):
211  """Constructor"""
212 
213  self.accounts_dir = airbus_cobot_gui_dir('resources','accounts')
214 
215  with open(os.path.join(self.accounts_dir,self.ACCOUNTS_FILENAME),'r') as \
216  file_encode:
217  accounts_encode = file_encode.read()
218 
219  try:
220  accounts_decode = base64.decodestring(accounts_encode)
221  except Exception as e:
222  raise CobotGuiException('The user accounts file is corrupted "%s"!'%str(e))
223 
224  self.accounts_xml = None
225 
226  try:
227  self.accounts_xml = ElementTree.fromstring(accounts_decode)
228  except Exception as e:
229  raise CobotGuiException('UserAccountsManager.__init__() raised with exception "%s"'%e)
230  finally:
231  self._xml_file_generator()
232 
233 
234  def update(self):
235 
236  xmlstr = ElementTree.tostring(self.accounts_xml,
237  encoding='utf8',
238  method='xml')
239 
240  xmlencode = base64.encodestring(xmlstr)
241 
242  with open(os.path.join(self.accounts_dir,self.ACCOUNTS_FILENAME),'w') as \
243  f_accounts:
244  f_accounts.write(xmlencode)
245 
246  from shutil import copyfile
247  #Create backup file for the rescue mode
248  copyfile(os.path.join(self.accounts_dir,self.ACCOUNTS_FILENAME),
249  os.path.join(self.accounts_dir,'backup','accounts_back.db'))
250 
251  self._xml_file_generator()
252 
254 
255  xmlstr = ElementTree.tostring(self.accounts_xml,
256  encoding='utf8',
257  method='xml')
258  with open(os.path.join(self.accounts_dir,'accounts.xml'),'w') as \
259  f_accounts_xml:
260  f_accounts_xml.write(xmlstr)
261 
262  def resolve_path(self, userid):
263  return './%s[@%s="%s"]'%(self.USER, self.UID, userid)
264 
265  def user_list(self):
266  """Read and get user(s) id list registered in user accounts file
267  @return: user_list: user(s) id list.
268  @type user_list: array string.
269  """
270  user_list = []
271 
272  for user in self.accounts_xml:
273  user_list.append(user.attrib[self.UID])
274 
275  return user_list
276 
277  def find(self, userid):
278  """Read and get user account information
279 
280  @param: userid: user id.
281  @type userid: str.
282 
283  @return: userinfo: user informations.
284  @type userinfo: C{User}.
285  """
286 
287  user_account = self.accounts_xml.find(self.resolve_path(userid))
288 
289  if user_account is None:
290  rospy.logerr('User "%s" not found !'%userid)
291  return None
292 
293  userinfo = User()
294  userinfo.userid = userid
295  userinfo.created = user_account.find(self.CREATED).text
296  userinfo.modified = user_account.find(self.MODIFIED).text
297  userinfo.privilege = Privilege.TOLEVEL[user_account.find(self.PRIVILEGE).text]
298  userinfo.password = user_account.find(self.PASSWORD).text
299  userinfo.encoded = True
300 
301  return userinfo
302 
303  def add(self, userinfo):
304  """Add new user account in "accounts.db" file.
305 
306  @param: userinfo: user informations.
307  @type userinfo: C{User}.
308  """
309 
310  user_account = self.accounts_xml.find(self.resolve_path(userinfo.userid))
311 
312  if user_account is not None:
313  raise CobotGuiException('Do not add the user id "%s" is already used !'
314  %userinfo.userid)
315 
316  user_str = self.USER_STR_ITEM%(userinfo.userid,
317  str(rospy.get_rostime()),
318  str(rospy.get_rostime()),
319  Privilege.TOSTR[userinfo.privilege],
320  userinfo.password)
321 
322  try:
323 
324  user_xml = ElementTree.fromstring(user_str)
325  self.accounts_xml.append(user_xml)
326  ElementTree.indent(self.accounts_xml)
327  self.update()
328 
329  except Exception as e:
330  raise CobotGuiException('Do not add the user id "%s" because %s !'
331  %(userinfo.userid, str(e)))
332 
333  def modif(self, usersource, usermodifed):
334  """Update user informations.
335 
336  @param: usersource: current user informations.
337  @type usersource: C{User}.
338 
339  @param: usermodifed: new user informations.
340  @type usermodifed: C{User}.
341 
342  """
343 
344  if usersource.userid != usermodifed.userid:
345  raise CobotGuiException("Change user id not allowed !")
346 
347  user_account = self.accounts_xml.find(self.resolve_path(usersource.userid))
348 
349  if user_account is None:
350  raise CobotGuiException('Invalid user id "%s" is not found !'
351  %usersource.userid)
352 
353  if usersource.password != user_account.find(self.PASSWORD).text:
354  raise CobotGuiException('Invalid password from user id "%s" !'
355  %usersource.userid)
356  else:
357  user_account.find(self.MODIFIED).text = str(rospy.get_rostime())
358  user_account.find(self.PASSWORD).text = usermodifed.password
359  user_account.find(self.PRIVILEGE).text = Privilege.TOSTR[usermodifed.privilege]
360 
361  try:
362  self.update()
363  except Exception as e:
364  raise CobotGuiException(str(e))
365 
366  def remove(self, userinfo):
367  """Remove user account.
368 
369  @param: userinfo: user informations.
370  @type userinfo: C{User}.
371  """
372 
373  user_account = self.accounts_xml.find(self.resolve_path(userinfo.userid))
374 
375  try:
376  self.accounts_xml.remove(user_account)
377  except:
378  raise CobotGuiException('Connot removed user id "%s" is not registered !'
379  %userinfo.userid)
380  try:
381  self.update()
382  except Exception as e:
383  raise CobotGuiException(str(e))
384 
385 if __name__ == '__main__':
386 
387  print Privilege.LEVEL[Privilege.NONE]
388  print Privilege.LEVEL[Privilege.OPERATOR]
389  print Privilege.LEVEL[Privilege.MAINTENANCE]
390  print Privilege.LEVEL[Privilege.EXPERT]
391  print Privilege.LEVEL[Privilege.DEVELOPER]
392 
393 # rospy.init_node('user_accounts_db')
394 #
395 # user_accounts_db = UserAccounts()
396 #
397 # user_accounts_db.remove(User('mmn2'))
398 # user_accounts_db.remove(User('mmn3'))
399 # user_accounts_db.remove(User('mmn4'))
400 # user_accounts_db.remove(User('mmn5'))
401 
402 # try:
403 # user_accounts_db.remove(User('martin'))
404 # except:
405 # pass
406 #
407 # mmn = User('martin')
408 # mmn.set_password('ati006', True)
409 # mmn.privilege = 'operator'
410 #
411 # user_accounts_db.add(mmn)
412 #
413 # mmn_src = User('martin')
414 # mmn_src.set_password('ati006', True)
415 # mmn_src.privilege = 'optirun'
416 #
417 # mmn_modif = User('martin')
418 # mmn_modif.set_password('martin', True)
419 # mmn_modif.privilege = 'operator'
420 #
421 # user_accounts_db.modif(mmn_src, mmn_modif)
422 
423 
424 # print user_accounts_db.user_list()
425 #
426 # mmn = user_accounts_db.find('Roberto')
427 #
428 # if mmn is not None:
429 # print mmn.userid
430 # print mmn.created
431 # print mmn.modified
432 # print mmn.privilege
433 # print mmn.password
434 #
435 # user_x = User()
436 #
437 # user_x.userid = 'Titi'
438 # user_x.privilege = 'operator'
439 # user_x.password = base64.b64encode('totototo')
440 #
441 # try:
442 # user_accounts_db.add(user_x)
443 # except Exception as e:
444 # print e
445 
446 #End of file
447 
def get_current_user_account
Get current user informations.
Definition: accounts.py:108
def update
Set user informations and call at callbacks the new connection.
Definition: accounts.py:100
Class for difine different levels of user access.
Definition: accounts.py:30


airbus_cobot_gui
Author(s):
autogenerated on Thu Dec 17 2015 11:42:05