Package Gnumed :: Package wxpython :: Module gmAuthWidgets
[frames] | no frames]

Source Code for Module Gnumed.wxpython.gmAuthWidgets

  1  """GNUmed authentication widgets. 
  2   
  3  This module contains widgets and GUI 
  4  functions for authenticating users. 
  5  """ 
  6  #================================================================ 
  7  __version__ = "$Revision: 1.45 $" 
  8  __author__ = "karsten.hilbert@gmx.net, H.Herb, H.Berger, R.Terry" 
  9  __license__ = "GPL (details at http://www.gnu.org)" 
 10   
 11   
 12  # stdlib 
 13  import sys, os.path, cPickle, zlib, logging, re as regex 
 14   
 15   
 16  # 3rd party 
 17  import wx 
 18   
 19   
 20  # GNUmed 
 21  if __name__ == '__main__': 
 22          sys.path.insert(0, '../../') 
 23  from Gnumed.pycommon import gmLoginInfo, gmPG2, gmBackendListener, gmTools, gmCfg2, gmI18N 
 24  from Gnumed.business import gmSurgery 
 25  from Gnumed.wxpython import gmGuiHelpers, gmExceptionHandlingWidgets 
 26   
 27   
 28  _log = logging.getLogger('gm.ui') 
 29  _log.info(__version__) 
 30  _cfg = gmCfg2.gmCfgData() 
 31   
 32  try: 
 33          _('dummy-no-need-to-translate-but-make-epydoc-happy') 
 34  except NameError: 
 35          _ = lambda x:x 
 36   
 37   
 38  msg_generic = _(""" 
 39  GNUmed database version mismatch. 
 40   
 41  This database version cannot be used with this client: 
 42   
 43   client version: %s 
 44   database version detected: %s 
 45   database version needed: %s 
 46   
 47  Currently connected to database: 
 48   
 49   host: %s 
 50   database: %s 
 51   user: %s 
 52  """) 
 53   
 54  msg_time_skew_fail = _("""\ 
 55  The server and client clocks are off 
 56  by more than %s minutes ! 
 57   
 58  You must fix the time settings before 
 59  you can use this database with this 
 60  client. 
 61   
 62  You may have to contact your 
 63  administrator for help.""") 
 64   
 65  msg_time_skew_warn = _("""\ 
 66  The server and client clocks are off 
 67  by more than %s minutes ! 
 68   
 69  You should fix the time settings. 
 70  Otherwise clinical data may appear to 
 71  have been entered at the wrong time. 
 72   
 73  You may have to contact your 
 74  administrator for help.""") 
 75   
 76  msg_insanity = _(""" 
 77  There is a serious problem with the database settings: 
 78   
 79  %s 
 80   
 81  You may have to contact your administrator for help.""") 
 82   
 83  msg_fail = _(""" 
 84  You must connect to a different database in order 
 85  to use the GNUmed client. You may have to contact 
 86  your administrator for help.""") 
 87   
 88  msg_override = _(""" 
 89  The client will, however, continue to start up because 
 90  you are running a development/test version of GNUmed. 
 91   
 92  There may be schema related errors. Please report and/or 
 93  fix them. Do not rely on this database to work properly 
 94  in all cases !""") 
 95   
 96  #================================================================ 
 97  # convenience functions 
 98  #---------------------------------------------------------------- 
99 -def connect_to_database(max_attempts=3, expected_version=None, require_version=True):
100 """Display the login dialog and try to log into the backend. 101 102 - up to max_attempts times 103 - returns True/False 104 """ 105 # force programmer to set a valid expected_version 106 expected_hash = gmPG2.known_schema_hashes[expected_version] 107 client_version = _cfg.get(option = u'client_version') 108 global current_db_name 109 current_db_name = u'gnumed_%s' % expected_version 110 111 attempt = 0 112 113 dlg = cLoginDialog(None, -1, client_version = client_version) 114 dlg.Centre(wx.BOTH) 115 116 while attempt < max_attempts: 117 118 _log.debug('login attempt %s of %s', (attempt+1), max_attempts) 119 120 connected = False 121 122 dlg.ShowModal() 123 login = dlg.panel.GetLoginInfo() 124 if login is None: 125 _log.info("user cancelled login dialog") 126 break 127 128 # try getting a connection to verify the DSN works 129 dsn = gmPG2.make_psycopg2_dsn ( 130 database = login.database, 131 host = login.host, 132 port = login.port, 133 user = login.user, 134 password = login.password 135 ) 136 try: 137 conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True) 138 connected = True 139 140 except gmPG2.cAuthenticationError, e: 141 attempt += 1 142 _log.error(u"login attempt failed: %s", e) 143 if attempt < max_attempts: 144 if (u'host=127.0.0.1' in (u'%s' % e)) or (u'host=' not in (u'%s' % e)): 145 msg = _( 146 'Unable to connect to database:\n\n' 147 '%s\n\n' 148 "Are you sure you have got a local database installed ?\n" 149 '\n' 150 "Please retry with proper credentials or cancel.\n" 151 '\n' 152 'You may also need to check the PostgreSQL client\n' 153 'authentication configuration in pg_hba.conf. For\n' 154 'details see:\n' 155 '\n' 156 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL' 157 ) 158 else: 159 msg = _( 160 "Unable to connect to database:\n\n" 161 "%s\n\n" 162 "Please retry with proper credentials or cancel.\n" 163 "\n" 164 'You may also need to check the PostgreSQL client\n' 165 'authentication configuration in pg_hba.conf. For\n' 166 'details see:\n' 167 '\n' 168 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL' 169 ) 170 msg = msg % e 171 msg = regex.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg) 172 gmGuiHelpers.gm_show_error ( 173 msg, 174 _('Connecting to backend') 175 ) 176 del e 177 continue 178 179 except gmPG2.dbapi.OperationalError, e: 180 _log.error(u"login attempt failed: %s", e) 181 msg = _( 182 "Unable to connect to database:\n\n" 183 "%s\n\n" 184 "Please retry another backend / user / password combination !\n" 185 ) % gmPG2.extract_msg_from_pg_exception(e) 186 msg = regex.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg) 187 gmGuiHelpers.gm_show_error ( 188 msg, 189 _('Connecting to backend') 190 ) 191 del e 192 continue 193 194 # connect was successful 195 gmPG2.set_default_login(login = login) 196 gmPG2.set_default_client_encoding(encoding = dlg.panel.backend_profile.encoding) 197 198 compatible = gmPG2.database_schema_compatible(version = expected_version) 199 if compatible or not require_version: 200 dlg.panel.save_state() 201 202 if not compatible: 203 connected_db_version = gmPG2.get_schema_version() 204 msg = msg_generic % ( 205 client_version, 206 connected_db_version, 207 expected_version, 208 gmTools.coalesce(login.host, '<localhost>'), 209 login.database, 210 login.user 211 ) 212 if require_version: 213 gmGuiHelpers.gm_show_error(msg + msg_fail, _('Verifying database version')) 214 connected = False 215 continue 216 gmGuiHelpers.gm_show_info(msg + msg_override, _('Verifying database version')) 217 218 # FIXME: make configurable 219 max_skew = 1 # minutes 220 if _cfg.get(option = 'debug'): 221 max_skew = 10 222 if not gmPG2.sanity_check_time_skew(tolerance = (max_skew * 60)): 223 if _cfg.get(option = 'debug'): 224 gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings')) 225 else: 226 gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings')) 227 connected = False 228 continue 229 230 sanity_level, message = gmPG2.sanity_check_database_settings() 231 if sanity_level != 0: 232 gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings')) 233 if sanity_level == 2: 234 connected = False 235 continue 236 237 gmExceptionHandlingWidgets.set_is_public_database(login.public_db) 238 gmExceptionHandlingWidgets.set_helpdesk(login.helpdesk) 239 240 listener = gmBackendListener.gmBackendListener(conn = conn) 241 break 242 243 dlg.Destroy() 244 245 return connected
246 #================================================================
247 -def get_dbowner_connection(procedure=None, dbo_password=None):
248 if procedure is None: 249 procedure = _('<restricted procedure>') 250 251 # 1) get password for gm-dbo 252 if dbo_password is None: 253 pwd_gm_dbo = wx.GetPasswordFromUser ( 254 message = _(""" 255 [%s] 256 257 This is a restricted procedure. We need the 258 password for the GNUmed database owner. 259 260 Please enter the password for <gm-dbo>:""") % procedure, 261 caption = procedure 262 ) 263 if pwd_gm_dbo == '': 264 return None 265 else: 266 pwd_gm_dbo = dbo_password 267 268 # 2) connect as gm-dbo 269 login = gmPG2.get_default_login() 270 dsn = gmPG2.make_psycopg2_dsn(database=login.database, host=login.host, port=login.port, user='gm-dbo', password=pwd_gm_dbo) 271 try: 272 conn = gmPG2.get_connection(dsn=dsn, readonly=False, verbose=True, pooled=False) 273 except: 274 _log.exception('cannot connect') 275 gmGuiHelpers.gm_show_error ( 276 aMessage = _('Cannot connect as the GNUmed database owner <gm-dbo>.'), 277 aTitle = procedure 278 ) 279 return None 280 281 return conn
282 #================================================================
283 -class cBackendProfile:
284 pass
285 #================================================================
286 -class cLoginDialog(wx.Dialog):
287 """cLoginDialog - window holding cLoginPanel""" 288 289 icon_serpent='x\xdae\x8f\xb1\x0e\x83 \x10\x86w\x9f\xe2\x92\x1blb\xf2\x07\x96\xeaH:0\xd6\ 290 \xc1\x85\xd5\x98N5\xa5\xef?\xf5N\xd0\x8a\xdcA\xc2\xf7qw\x84\xdb\xfa\xb5\xcd\ 291 \xd4\xda;\xc9\x1a\xc8\xb6\xcd<\xb5\xa0\x85\x1e\xeb\xbc\xbc7b!\xf6\xdeHl\x1c\ 292 \x94\x073\xec<*\xf7\xbe\xf7\x99\x9d\xb21~\xe7.\xf5\x1f\x1c\xd3\xbdVlL\xc2\ 293 \xcf\xf8ye\xd0\x00\x90\x0etH \x84\x80B\xaa\x8a\x88\x85\xc4(U\x9d$\xfeR;\xc5J\ 294 \xa6\x01\xbbt9\xceR\xc8\x81e_$\x98\xb9\x9c\xa9\x8d,y\xa9t\xc8\xcf\x152\xe0x\ 295 \xe9$\xf5\x07\x95\x0cD\x95t:\xb1\x92\xae\x9cI\xa8~\x84\x1f\xe0\xa3ec' 296
297 - def __init__(self, parent, id, title=_("Welcome to the"), client_version=u'*** unknown ***'):
298 wx.Dialog.__init__(self, parent, id, title) 299 self.panel = cLoginPanel(self, -1, isDialog=1, client_version = client_version) 300 self.Fit() # needed for Windoze. 301 self.Centre() 302 303 # set window icon 304 icon_bmp_data = wx.BitmapFromXPMData(cPickle.loads(zlib.decompress(self.icon_serpent))) 305 icon = wx.EmptyIcon() 306 icon.CopyFromBitmap(icon_bmp_data) 307 self.SetIcon(icon)
308 #================================================================
309 -class cLoginPanel(wx.Panel):
310 """GUI panel class that interactively gets Postgres login parameters. 311 312 It features combo boxes which "remember" any number of 313 previously entered settings. 314 """
315 - def __init__(self, parent, id, 316 pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.TAB_TRAVERSAL, 317 isDialog = 0, client_version = u'*** unknown ***'):
318 """Create login panel. 319 320 isDialog: if this panel is the main panel of a dialog, the panel will 321 resize the dialog automatically to display everything neatly 322 if isDialog is set to True 323 """ 324 wx.Panel.__init__(self, parent, id, pos, size, style) 325 self.parent = parent 326 327 #True if dialog was cancelled by user 328 #if the dialog is closed manually, login should be cancelled 329 self.cancelled = True 330 331 # True if this panel is displayed within a dialog (will resize the dialog automatically then) 332 self.isDialog = isDialog 333 334 self.topsizer = wx.BoxSizer(wx.VERTICAL) 335 336 # find bitmap 337 paths = gmTools.gmPaths(app_name = u'gnumed', wx = wx) 338 bitmap = os.path.join(paths.system_app_data_dir, 'bitmaps', 'gnumedlogo.png') 339 try: 340 png = wx.Image(bitmap, wx.BITMAP_TYPE_PNG).ConvertToBitmap() 341 bmp = wx.StaticBitmap(self, -1, png, wx.Point(10, 10), wx.Size(png.GetWidth(), png.GetHeight())) 342 self.topsizer.Add ( 343 bmp, 344 proportion = 0, 345 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 346 border = 10 347 ) 348 except: 349 self.topsizer.Add ( 350 wx.StaticText ( 351 self, 352 -1, 353 label = _("Cannot find image") + bitmap, 354 style = wx.ALIGN_CENTRE 355 ), 356 proportion = 0, 357 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 358 border = 10 359 ) 360 361 paramsbox_caption = _('"%s" (version %s)') % (gmSurgery.gmCurrentPractice().active_workplace, client_version) 362 363 # FIXME: why doesn't this align in the centre ? 364 self.paramsbox = wx.StaticBox( self, -1, paramsbox_caption, style = wx.ALIGN_CENTRE_HORIZONTAL) 365 self.paramsboxsizer = wx.StaticBoxSizer( self.paramsbox, wx.VERTICAL ) 366 self.paramsbox.SetForegroundColour(wx.Colour(35, 35, 142)) 367 self.paramsbox.SetFont(wx.Font( 368 pointSize = 12, 369 family = wx.SWISS, 370 style = wx.NORMAL, 371 weight = wx.BOLD, 372 underline = False 373 )) 374 self.pboxgrid = wx.FlexGridSizer(5, 2, 5, 5) 375 self.pboxgrid.AddGrowableCol(1) 376 377 # PROFILE COMBO 378 label = wx.StaticText( self, -1, _('Log into'), wx.DefaultPosition, wx.DefaultSize, 0) 379 label.SetForegroundColour(wx.Colour(35, 35, 142)) 380 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) 381 self.__backend_profiles = self.__get_backend_profiles() 382 self._CBOX_profile = wx.ComboBox ( 383 self, 384 -1, 385 self.__backend_profiles.keys()[0], 386 wx.DefaultPosition, 387 size = wx.Size(150,-1), 388 choices = self.__backend_profiles.keys(), 389 style = wx.CB_READONLY 390 ) 391 self.pboxgrid.Add (self._CBOX_profile, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) 392 393 # USER NAME COMBO 394 label = wx.StaticText( self, -1, _("Username"), wx.DefaultPosition, wx.DefaultSize, 0 ) 395 label.SetForegroundColour(wx.Colour(35, 35, 142)) 396 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) 397 self.__previously_used_accounts = self.__get_previously_used_accounts() 398 self._CBOX_user = wx.ComboBox ( 399 self, 400 -1, 401 self.__previously_used_accounts[0], 402 wx.DefaultPosition, 403 wx.Size(150,-1), 404 self.__previously_used_accounts, 405 wx.CB_DROPDOWN 406 ) 407 self.pboxgrid.Add( self._CBOX_user, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) 408 409 #PASSWORD TEXT ENTRY 410 label = wx.StaticText( self, -1, _("Password"), wx.DefaultPosition, wx.DefaultSize, 0 ) 411 label.SetForegroundColour(wx.Colour(35, 35, 142)) 412 self.pboxgrid.Add( label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) 413 self.pwdentry = wx.TextCtrl( self, 1, '', wx.DefaultPosition, wx.Size(80,-1), wx.TE_PASSWORD ) 414 # set focus on password entry 415 self.pwdentry.SetFocus() 416 self.pboxgrid.Add( self.pwdentry, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) 417 418 # --debug checkbox 419 label = wx.StaticText(self, -1, _('Options'), wx.DefaultPosition, wx.DefaultSize, 0) 420 label.SetForegroundColour(wx.Colour(35, 35, 142)) 421 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) 422 self._CHBOX_debug = wx.CheckBox(self, -1, _('&Debug mode')) 423 self._CHBOX_debug.SetToolTipString(_('Check this to run GNUmed client in debugging mode.')) 424 self.pboxgrid.Add(self._CHBOX_debug, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) 425 426 # --slave checkbox 427 label = wx.StaticText(self, -1, '', wx.DefaultPosition, wx.DefaultSize, 0) 428 label.SetForegroundColour(wx.Colour(35, 35, 142)) 429 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5) 430 self._CHBOX_slave = wx.CheckBox(self, -1, _('Enable &remote control')) 431 self._CHBOX_slave.SetToolTipString(_('Check this to run GNUmed client in slave mode for remote control.')) 432 self.pboxgrid.Add(self._CHBOX_slave, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5) 433 434 #---------------------------------------------------------------------- 435 #new button code inserted rterry 06Sept02 436 #button order re-arraged to make it consistant with usual dialog format 437 #in most operating systems ie btns ok and cancel are standard and 438 #in that order 439 #ie Order is now help, ok and cancel 440 #The order of creation is the tab order 441 #login-ok button automatically is the default when tabbing (or <enter>) 442 #from password 443 #this eliminates the heavy border when you use the default 444 #?is the default word needed for any other reason? 445 #---------------------------------------------------------------------- 446 self.button_gridsizer = wx.GridSizer(1,3,0,0) 447 #--------------------- 448 #3:create login ok button 449 #--------------------- 450 ID_BUTTON_LOGIN = wx.NewId() 451 button_login_ok = wx.Button(self, ID_BUTTON_LOGIN, _("&Ok"), wx.DefaultPosition, wx.DefaultSize, 0 ) 452 button_login_ok.SetToolTip(wx.ToolTip(_("Proceed with login.")) ) 453 button_login_ok.SetDefault() 454 455 #--------------------- 456 #3:create cancel button 457 #--------------------- 458 ID_BUTTON_CANCEL = wx.NewId() 459 button_cancel = wx.Button(self, ID_BUTTON_CANCEL, _("&Cancel"), wx.DefaultPosition, wx.DefaultSize, 0 ) 460 button_cancel.SetToolTip(wx.ToolTip(_("Cancel Login.")) ) 461 #--------------------- 462 #2:create Help button 463 #--------------------- 464 ID_BUTTON_HELP = wx.NewId() 465 button_help = wx.Button(self, ID_BUTTON_HELP, _("&Help"), wx.DefaultPosition, wx.DefaultSize, 0 ) 466 button_help.SetToolTip(wx.ToolTip(_("Help for login screen"))) 467 #---------------------------- 468 #Add buttons to the gridsizer 469 #---------------------------- 470 self.button_gridsizer.Add (button_help,0,wx.EXPAND|wx.ALL,5) 471 self.button_gridsizer.Add (button_login_ok,0,wx.EXPAND|wx.ALL,5) 472 self.button_gridsizer.Add (button_cancel,0,wx.EXPAND|wx.ALL,5) 473 474 self.paramsboxsizer.Add(self.pboxgrid, 1, wx.GROW|wx.ALL, 10) 475 self.topsizer.Add(self.paramsboxsizer, 1, wx.GROW|wx.ALL, 10) 476 self.topsizer.Add( self.button_gridsizer, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 ) 477 478 self.__load_state() 479 480 self.SetAutoLayout(True) 481 self.SetSizer( self.topsizer) 482 self.topsizer.Fit( self ) 483 if self.isDialog: 484 self.topsizer.SetSizeHints(parent) 485 486 wx.EVT_BUTTON(self, ID_BUTTON_HELP, self.OnHelp) 487 wx.EVT_BUTTON(self, ID_BUTTON_LOGIN, self.__on_login_button_pressed) 488 wx.EVT_BUTTON(self, ID_BUTTON_CANCEL, self.OnCancel)
489 490 #---------------------------------------------------------- 491 # internal helper methods 492 #----------------------------------------------------------
494 495 accounts = gmTools.coalesce ( 496 _cfg.get ( 497 group = u'backend', 498 option = u'logins', 499 source_order = [ 500 (u'explicit', u'extend'), 501 (u'user', u'extend'), 502 (u'workbase', u'extend') 503 ] 504 ), 505 ['any-doc'] 506 ) 507 # FIXME: make unique 508 509 return accounts
510 #----------------------------------------------------
511 - def __get_backend_profiles(self):
512 """Get server profiles from the configuration files. 513 514 1) from system-wide file 515 2) from user file 516 517 Profiles in the user file which have the same name 518 as a profile in the system file will override the 519 system file. 520 """ 521 # find active profiles 522 src_order = [ 523 (u'explicit', u'extend'), 524 (u'system', u'extend'), 525 (u'user', u'extend'), 526 (u'workbase', u'extend') 527 ] 528 529 profile_names = gmTools.coalesce ( 530 _cfg.get(group = u'backend', option = u'profiles', source_order = src_order), 531 [] 532 ) 533 534 # find data for active profiles 535 src_order = [ 536 (u'explicit', u'return'), 537 (u'workbase', u'return'), 538 (u'user', u'return'), 539 (u'system', u'return') 540 ] 541 542 profiles = {} 543 544 for profile_name in profile_names: 545 # FIXME: once the profile has been found always use the corresponding source ! 546 # FIXME: maybe not or else we cannot override parts of the profile 547 profile = cBackendProfile() 548 profile_section = 'profile %s' % profile_name 549 550 profile.name = profile_name 551 profile.host = gmTools.coalesce(_cfg.get(profile_section, u'host', src_order), u'').strip() 552 port = gmTools.coalesce(_cfg.get(profile_section, u'port', src_order), 5432) 553 try: 554 profile.port = int(port) 555 if profile.port < 1024: 556 raise ValueError('refusing to use priviledged port (< 1024)') 557 except ValueError: 558 _log.warning('invalid port definition: [%s], skipping profile [%s]', port, profile_name) 559 continue 560 profile.database = gmTools.coalesce(_cfg.get(profile_section, u'database', src_order), u'').strip() 561 if profile.database == u'': 562 _log.warning('database name not specified, skipping profile [%s]', profile_name) 563 continue 564 profile.encoding = gmTools.coalesce(_cfg.get(profile_section, u'encoding', src_order), u'UTF8') 565 profile.public_db = bool(_cfg.get(profile_section, u'public/open access', src_order)) 566 profile.helpdesk = _cfg.get(profile_section, u'help desk', src_order) 567 568 label = u'%s (%s@%s)' % (profile_name, profile.database, profile.host) 569 profiles[label] = profile 570 571 # sort out profiles with incompatible database versions if not --debug 572 # NOTE: this essentially hardcodes the database name in production ... 573 if not (_cfg.get(option = 'debug') or current_db_name.endswith('_devel')): 574 profiles2remove = [] 575 for label in profiles: 576 if profiles[label].database != current_db_name: 577 profiles2remove.append(label) 578 for label in profiles2remove: 579 del profiles[label] 580 581 if len(profiles) == 0: 582 host = u'salaam.homeunix.com' 583 label = u'public GNUmed database (%s@%s)' % (current_db_name, host) 584 profiles[label] = cBackendProfile() 585 profiles[label].name = label 586 profiles[label].host = host 587 profiles[label].port = 5432 588 profiles[label].database = current_db_name 589 profiles[label].encoding = u'UTF8' 590 profiles[label].public_db = True 591 profiles[label].helpdesk = u'http://wiki.gnumed.de' 592 593 return profiles
594 #----------------------------------------------------------
595 - def __load_state(self):
596 597 src_order = [ 598 (u'explicit', u'return'), 599 (u'user', u'return'), 600 ] 601 602 self._CBOX_user.SetValue ( 603 gmTools.coalesce ( 604 _cfg.get(u'preferences', u'login', src_order), 605 self.__previously_used_accounts[0] 606 ) 607 ) 608 609 last_used_profile_label = _cfg.get(u'preferences', u'profile', src_order) 610 if last_used_profile_label in self.__backend_profiles.keys(): 611 self._CBOX_profile.SetValue(last_used_profile_label) 612 else: 613 self._CBOX_profile.SetValue(self.__backend_profiles.keys()[0]) 614 615 self._CHBOX_debug.SetValue(_cfg.get(option = 'debug')) 616 self._CHBOX_slave.SetValue(_cfg.get(option = 'slave'))
617 #----------------------------------------------------
618 - def save_state(self):
619 """Save parameter settings to standard configuration file""" 620 prefs_name = _cfg.get(option = 'user_preferences_file') 621 _log.debug(u'saving login preferences in [%s]', prefs_name) 622 623 gmCfg2.set_option_in_INI_file ( 624 filename = prefs_name, 625 group = 'preferences', 626 option = 'login', 627 value = self._CBOX_user.GetValue() 628 ) 629 630 gmCfg2.set_option_in_INI_file ( 631 filename = prefs_name, 632 group = 'preferences', 633 option = 'profile', 634 value = self._CBOX_profile.GetValue() 635 )
636 ############################################################################# 637 # Retrieve current settings from user interface widgets 638 #############################################################################
639 - def GetLoginInfo(self):
640 """convenience function for compatibility with gmLoginInfo.LoginInfo""" 641 if not self.cancelled: 642 # FIXME: do not assume conf file is latin1 ! 643 #profile = self.__backend_profiles[self._CBOX_profile.GetValue().encode('latin1').strip()] 644 profile = self.__backend_profiles[self._CBOX_profile.GetValue().encode('utf8').strip()] 645 _log.debug(u'backend profile "%s" selected', profile.name) 646 _log.debug(u' details: <%s> on %s@%s:%s (%s, %s)', 647 self._CBOX_user.GetValue(), 648 profile.database, 649 profile.host, 650 profile.port, 651 profile.encoding, 652 gmTools.bool2subst(profile.public_db, u'public', u'private') 653 ) 654 _log.debug(u' helpdesk: "%s"', profile.helpdesk) 655 login = gmLoginInfo.LoginInfo ( 656 user = self._CBOX_user.GetValue(), 657 password = self.pwdentry.GetValue(), 658 host = profile.host, 659 database = profile.database, 660 port = profile.port 661 ) 662 login.public_db = profile.public_db 663 login.helpdesk = profile.helpdesk 664 return login 665 666 return None
667 #---------------------------- 668 # event handlers 669 #----------------------------
670 - def OnHelp(self, event):
671 praxis = gmSurgery.gmCurrentPractice() 672 wx.MessageBox(_( 673 """GNUmed main login screen 674 675 USER: 676 name of the GNUmed user 677 PASSWORD 678 password for this user 679 680 button OK: 681 proceed with login 682 button OPTIONS: 683 set advanced options 684 button CANCEL: 685 abort login and quit GNUmed client 686 button HELP: 687 this help screen 688 689 For assistance on using GNUmed please contact: 690 %s""") % praxis.helpdesk)
691 692 #----------------------------
693 - def __on_login_button_pressed(self, event):
694 695 root_logger = logging.getLogger() 696 if self._CHBOX_debug.GetValue(): 697 _log.info('debug mode enabled') 698 _cfg.set_option(option = 'debug', value = True) 699 root_logger.setLevel(logging.DEBUG) 700 else: 701 _log.info('debug mode disabled') 702 _cfg.set_option(option = 'debug', value = False) 703 if _cfg.get(option = '--quiet', source_order = [('cli', 'return')]): 704 root_logger.setLevel(logging.ERROR) 705 else: 706 root_logger.setLevel(logging.WARNING) 707 708 if self._CHBOX_slave.GetValue(): 709 _log.info('slave mode enabled') 710 _cfg.set_option(option = 'slave', value = True) 711 else: 712 _log.info('slave mode disabled') 713 _cfg.set_option(option = 'slave', value = False) 714 715 self.backend_profile = self.__backend_profiles[self._CBOX_profile.GetValue().encode('latin1').strip()] 716 # self.user = self._CBOX_user.GetValue().strip() 717 # self.password = self.GetPassword() 718 self.cancelled = False 719 self.parent.Close()
720 #----------------------------
721 - def OnCancel(self, event):
722 self.cancelled = True 723 self.parent.Close()
724 725 #================================================================ 726 # main 727 #---------------------------------------------------------------- 728 if __name__ == "__main__": 729 730 if len(sys.argv) < 2: 731 sys.exit() 732 733 if sys.argv[1] != 'test': 734 sys.exit() 735 736 # we don't have tests yet 737 sys.exit() 738 739 from Gnumed.pycommon import gmI18N 740 741 logging.basicConfig(level = logging.DEBUG) 742 743 gmI18N.activate_locale() 744 gmI18N.install_domain(domain='gnumed') 745 #----------------------------------------------- 746 #-----------------------------------------------
747 - def test():
748 app = wx.PyWidgetTester(size = (300,400)) 749 #show the login panel in a main window 750 # app.SetWidget(cLoginPanel, -1) 751 #and pop the login dialog up modally 752 dlg = cLoginDialog(None, -1) #, png_bitmap = 'bitmaps/gnumedlogo.png') 753 dlg.ShowModal() 754 #demonstration how to access the login dialog values 755 lp = dlg.panel.GetLoginInfo() 756 if lp is None: 757 wx.MessageBox(_("Dialog was cancelled by user")) 758 else: 759 wx.MessageBox(_("You tried to log in as [%s] with password [%s].\nHost:%s, DB: %s, Port: %s") % (lp.GetUser(),lp.GetPassword(),lp.GetHost(),lp.GetDatabase(),lp.GetPort())) 760 dlg.Destroy()
761 # app.MainLoop() 762 763 #================================================================ 764