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 v2 or later (details at http://www.gnu.org)"
10
11
12
13 import sys, os.path, logging, re as regex
14
15
16
17 import wx
18
19
20
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
98
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
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_v%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
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
195 gmPG2.set_default_login(login = login)
196 gmPG2.set_default_client_encoding(encoding = dlg.panel.backend_profile.encoding)
197
198 seems_bootstrapped = gmPG2.schema_exists(schema = 'gm')
199 if not seems_bootstrapped:
200 _log.error('schema [gm] does not exist - database not bootstrapped ?')
201 msg = _(
202 'The database you connected to does not seem\n'
203 'to have been boostrapped properly.\n'
204 '\n'
205 'Make sure you have run the GNUmed database\n'
206 'bootstrapper tool to create a new database.\n'
207 '\n'
208 'Further help can be found on the website at\n'
209 '\n'
210 ' http://wiki.gnumed.de\n'
211 '\n'
212 'or on the GNUmed mailing list.'
213 )
214 gmGuiHelpers.gm_show_error(msg, _('Verifying database'))
215 connected = False
216 break
217
218 compatible = gmPG2.database_schema_compatible(version = expected_version)
219 if compatible or not require_version:
220 dlg.panel.save_state()
221
222 if not compatible:
223 connected_db_version = gmPG2.get_schema_version()
224 msg = msg_generic % (
225 client_version,
226 connected_db_version,
227 expected_version,
228 gmTools.coalesce(login.host, '<localhost>'),
229 login.database,
230 login.user
231 )
232 if require_version:
233 gmGuiHelpers.gm_show_error(msg + msg_fail, _('Verifying database version'))
234 connected = False
235 continue
236 gmGuiHelpers.gm_show_info(msg + msg_override, _('Verifying database version'))
237
238
239 max_skew = 1
240 if _cfg.get(option = 'debug'):
241 max_skew = 10
242 if not gmPG2.sanity_check_time_skew(tolerance = (max_skew * 60)):
243 if _cfg.get(option = 'debug'):
244 gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings'))
245 else:
246 gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings'))
247 connected = False
248 continue
249
250 sanity_level, message = gmPG2.sanity_check_database_settings()
251 if sanity_level != 0:
252 gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings'))
253 if sanity_level == 2:
254 connected = False
255 continue
256
257 gmExceptionHandlingWidgets.set_is_public_database(login.public_db)
258 gmExceptionHandlingWidgets.set_helpdesk(login.helpdesk)
259
260 listener = gmBackendListener.gmBackendListener(conn = conn)
261 break
262
263 dlg.Destroy()
264
265 return connected
266
268 if procedure is None:
269 procedure = _('<restricted procedure>')
270
271
272 if dbo_password is None:
273 dbo_password = wx.GetPasswordFromUser (
274 message = _("""
275 [%s]
276
277 This is a restricted procedure. We need the
278 current password for the GNUmed database owner.
279
280 Please enter the current password for <%s>:""") % (
281 procedure,
282 dbo_account
283 ),
284 caption = procedure
285 )
286 if dbo_password == '':
287 return None
288
289
290 login = gmPG2.get_default_login()
291 dsn = gmPG2.make_psycopg2_dsn (
292 database = login.database,
293 host = login.host,
294 port = login.port,
295 user = dbo_account,
296 password = dbo_password
297 )
298 try:
299 conn = gmPG2.get_connection (
300 dsn = dsn,
301 readonly = False,
302 verbose = True,
303 pooled = False
304 )
305 except:
306 _log.exception('cannot connect')
307 gmGuiHelpers.gm_show_error (
308 aMessage = _('Cannot connect as the GNUmed database owner <%s>.') % dbo_account,
309 aTitle = procedure
310 )
311 gmPG2.log_database_access(action = u'failed to connect as database owner for [%s]' % procedure)
312 return None
313
314 return conn
315
317
318 title = _(u'Changing GNUmed database owner password')
319
320 dbo_account = wx.GetTextFromUser (
321 message = _(u"Enter the account name of the GNUmed database owner:"),
322 caption = title,
323 default_value = u''
324 )
325
326 if dbo_account.strip() == u'':
327 return False
328
329 dbo_conn = get_dbowner_connection (
330 procedure = title,
331 dbo_account = dbo_account
332 )
333 if dbo_conn is None:
334 return False
335
336 dbo_pwd_new_1 = wx.GetPasswordFromUser (
337 message = _(u"Enter the NEW password for the GNUmed database owner:"),
338 caption = title
339 )
340 if dbo_pwd_new_1.strip() == u'':
341 return False
342
343 dbo_pwd_new_2 = wx.GetPasswordFromUser (
344 message = _(u"""Enter the NEW password for the GNUmed database owner, again.
345
346 (This will protect you from typos.)
347 """),
348 caption = title
349 )
350 if dbo_pwd_new_2.strip() == u'':
351 return False
352
353 if dbo_pwd_new_1 != dbo_pwd_new_2:
354 return False
355
356 cmd = u"""ALTER ROLE "%s" ENCRYPTED PASSWORD '%s';""" % (
357 dbo_account,
358 dbo_pwd_new_2
359 )
360 gmPG2.run_rw_queries(link_obj = dbo_conn, queries = [{'cmd': cmd}], end_tx = True)
361
362 return True
363
366
368 """cLoginDialog - window holding cLoginPanel"""
369
370 - def __init__(self, parent, id, title=_("Welcome to the"), client_version=u'*** unknown ***'):
377
379 """GUI panel class that interactively gets Postgres login parameters.
380
381 It features combo boxes which "remember" any number of
382 previously entered settings.
383 """
384 - def __init__(self, parent, id,
385 pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.TAB_TRAVERSAL,
386 isDialog = 0, client_version = u'*** unknown ***'):
387 """Create login panel.
388
389 isDialog: if this panel is the main panel of a dialog, the panel will
390 resize the dialog automatically to display everything neatly
391 if isDialog is set to True
392 """
393 wx.Panel.__init__(self, parent, id, pos, size, style)
394 self.parent = parent
395
396
397
398 self.cancelled = True
399
400
401 self.isDialog = isDialog
402
403 self.topsizer = wx.BoxSizer(wx.VERTICAL)
404
405
406 paths = gmTools.gmPaths(app_name = u'gnumed', wx = wx)
407 bitmap = os.path.join(paths.system_app_data_dir, 'bitmaps', 'gnumedlogo.png')
408 try:
409 png = wx.Image(bitmap, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
410 bmp = wx.StaticBitmap(self, -1, png, wx.Point(10, 10), wx.Size(png.GetWidth(), png.GetHeight()))
411 self.topsizer.Add (
412 bmp,
413 proportion = 0,
414 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL,
415 border = 10
416 )
417 except:
418 self.topsizer.Add (
419 wx.StaticText (
420 self,
421 -1,
422 label = _("Cannot find image") + bitmap,
423 style = wx.ALIGN_CENTRE
424 ),
425 proportion = 0,
426 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL,
427 border = 10
428 )
429
430 paramsbox_caption = _('"%s" (version %s)') % (gmSurgery.gmCurrentPractice().active_workplace, client_version)
431
432
433 self.paramsbox = wx.StaticBox( self, -1, paramsbox_caption, style = wx.ALIGN_CENTRE_HORIZONTAL)
434 self.paramsboxsizer = wx.StaticBoxSizer( self.paramsbox, wx.VERTICAL )
435 self.paramsbox.SetForegroundColour(wx.Colour(35, 35, 142))
436 self.paramsbox.SetFont(wx.Font(
437 pointSize = 12,
438 family = wx.SWISS,
439 style = wx.NORMAL,
440 weight = wx.BOLD,
441 underline = False
442 ))
443 self.pboxgrid = wx.FlexGridSizer(5, 2, 5, 5)
444 self.pboxgrid.AddGrowableCol(1)
445
446
447 label = wx.StaticText( self, -1, _('Log into'), wx.DefaultPosition, wx.DefaultSize, 0)
448 label.SetForegroundColour(wx.Colour(35, 35, 142))
449 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
450 self.__backend_profiles = self.__get_backend_profiles()
451 self._CBOX_profile = wx.ComboBox (
452 self,
453 -1,
454 self.__backend_profiles.keys()[0],
455 wx.DefaultPosition,
456 size = wx.Size(150,-1),
457 choices = self.__backend_profiles.keys(),
458 style = wx.CB_READONLY
459 )
460 self.pboxgrid.Add (self._CBOX_profile, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
461
462
463 label = wx.StaticText( self, -1, _("Username"), wx.DefaultPosition, wx.DefaultSize, 0 )
464 label.SetForegroundColour(wx.Colour(35, 35, 142))
465 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
466 self.__previously_used_accounts = self.__get_previously_used_accounts()
467 self._CBOX_user = wx.ComboBox (
468 self,
469 -1,
470 self.__previously_used_accounts[0],
471 wx.DefaultPosition,
472 wx.Size(150,-1),
473 self.__previously_used_accounts,
474 wx.CB_DROPDOWN
475 )
476 self.pboxgrid.Add( self._CBOX_user, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
477
478
479 label = wx.StaticText( self, -1, _("Password"), wx.DefaultPosition, wx.DefaultSize, 0 )
480 label.SetForegroundColour(wx.Colour(35, 35, 142))
481 self.pboxgrid.Add( label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
482 self.pwdentry = wx.TextCtrl( self, 1, '', wx.DefaultPosition, wx.Size(80,-1), wx.TE_PASSWORD )
483
484 self.pwdentry.SetFocus()
485 self.pboxgrid.Add( self.pwdentry, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
486
487
488 label = wx.StaticText(self, -1, _('Options'), wx.DefaultPosition, wx.DefaultSize, 0)
489 label.SetForegroundColour(wx.Colour(35, 35, 142))
490 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
491 self._CHBOX_debug = wx.CheckBox(self, -1, _('&Debug mode'))
492 self._CHBOX_debug.SetToolTipString(_('Check this to run GNUmed client in debugging mode.'))
493 self.pboxgrid.Add(self._CHBOX_debug, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
494
495
496 label = wx.StaticText(self, -1, '', wx.DefaultPosition, wx.DefaultSize, 0)
497 label.SetForegroundColour(wx.Colour(35, 35, 142))
498 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
499 self._CHBOX_slave = wx.CheckBox(self, -1, _('Enable &remote control'))
500 self._CHBOX_slave.SetToolTipString(_('Check this to run GNUmed client in slave mode for remote control.'))
501 self.pboxgrid.Add(self._CHBOX_slave, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
502
503
504
505
506
507
508
509
510
511
512
513
514
515 self.button_gridsizer = wx.GridSizer(1,3,0,0)
516
517
518
519 ID_BUTTON_LOGIN = wx.NewId()
520 button_login_ok = wx.Button(self, ID_BUTTON_LOGIN, _("&Ok"), wx.DefaultPosition, wx.DefaultSize, 0 )
521 button_login_ok.SetToolTip(wx.ToolTip(_("Proceed with login.")) )
522 button_login_ok.SetDefault()
523
524
525
526
527 ID_BUTTON_CANCEL = wx.NewId()
528 button_cancel = wx.Button(self, ID_BUTTON_CANCEL, _("&Cancel"), wx.DefaultPosition, wx.DefaultSize, 0 )
529 button_cancel.SetToolTip(wx.ToolTip(_("Cancel Login.")) )
530
531
532
533 ID_BUTTON_HELP = wx.NewId()
534 button_help = wx.Button(self, ID_BUTTON_HELP, _("&Help"), wx.DefaultPosition, wx.DefaultSize, 0 )
535 button_help.SetToolTip(wx.ToolTip(_("Help for login screen")))
536
537
538
539 self.button_gridsizer.Add (button_help,0,wx.EXPAND|wx.ALL,5)
540 self.button_gridsizer.Add (button_login_ok,0,wx.EXPAND|wx.ALL,5)
541 self.button_gridsizer.Add (button_cancel,0,wx.EXPAND|wx.ALL,5)
542
543 self.paramsboxsizer.Add(self.pboxgrid, 1, wx.GROW|wx.ALL, 10)
544 self.topsizer.Add(self.paramsboxsizer, 1, wx.GROW|wx.ALL, 10)
545 self.topsizer.Add( self.button_gridsizer, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
546
547 self.__load_state()
548
549 self.SetAutoLayout(True)
550 self.SetSizer( self.topsizer)
551 self.topsizer.Fit( self )
552 if self.isDialog:
553 self.topsizer.SetSizeHints(parent)
554
555 wx.EVT_BUTTON(self, ID_BUTTON_HELP, self.OnHelp)
556 wx.EVT_BUTTON(self, ID_BUTTON_LOGIN, self.__on_login_button_pressed)
557 wx.EVT_BUTTON(self, ID_BUTTON_CANCEL, self.OnCancel)
558
559
560
561
563
564 accounts = gmTools.coalesce (
565 _cfg.get (
566 group = u'backend',
567 option = u'logins',
568 source_order = [
569 (u'explicit', u'extend'),
570 (u'user', u'extend'),
571 (u'workbase', u'extend')
572 ]
573 ),
574 ['any-doc']
575 )
576
577
578 return accounts
579
581 """Get server profiles from the configuration files.
582
583 1) from system-wide file
584 2) from user file
585
586 Profiles in the user file which have the same name
587 as a profile in the system file will override the
588 system file.
589 """
590
591 src_order = [
592 (u'explicit', u'extend'),
593 (u'system', u'extend'),
594 (u'user', u'extend'),
595 (u'workbase', u'extend')
596 ]
597
598 profile_names = gmTools.coalesce (
599 _cfg.get(group = u'backend', option = u'profiles', source_order = src_order),
600 []
601 )
602
603
604 src_order = [
605 (u'explicit', u'return'),
606 (u'workbase', u'return'),
607 (u'user', u'return'),
608 (u'system', u'return')
609 ]
610
611 profiles = {}
612
613 for profile_name in profile_names:
614
615
616 profile = cBackendProfile()
617 profile_section = 'profile %s' % profile_name
618
619 profile.name = profile_name
620 profile.host = gmTools.coalesce(_cfg.get(profile_section, u'host', src_order), u'').strip()
621 port = gmTools.coalesce(_cfg.get(profile_section, u'port', src_order), 5432)
622 try:
623 profile.port = int(port)
624 if profile.port < 1024:
625 raise ValueError('refusing to use priviledged port (< 1024)')
626 except ValueError:
627 _log.warning('invalid port definition: [%s], skipping profile [%s]', port, profile_name)
628 continue
629 profile.database = gmTools.coalesce(_cfg.get(profile_section, u'database', src_order), u'').strip()
630 if profile.database == u'':
631 _log.warning('database name not specified, skipping profile [%s]', profile_name)
632 continue
633 profile.encoding = gmTools.coalesce(_cfg.get(profile_section, u'encoding', src_order), u'UTF8')
634 profile.public_db = bool(_cfg.get(profile_section, u'public/open access', src_order))
635 profile.helpdesk = _cfg.get(profile_section, u'help desk', src_order)
636
637 label = u'%s (%s@%s)' % (profile_name, profile.database, profile.host)
638 profiles[label] = profile
639
640
641
642 if not (_cfg.get(option = 'debug') or current_db_name.endswith('_devel')):
643 profiles2remove = []
644 for label in profiles:
645 if profiles[label].database != current_db_name:
646 profiles2remove.append(label)
647 for label in profiles2remove:
648 del profiles[label]
649
650 if len(profiles) == 0:
651 host = u'publicdb.gnumed.de'
652 label = u'public GNUmed database (%s@%s)' % (current_db_name, host)
653 profiles[label] = cBackendProfile()
654 profiles[label].name = label
655 profiles[label].host = host
656 profiles[label].port = 5432
657 profiles[label].database = current_db_name
658 profiles[label].encoding = u'UTF8'
659 profiles[label].public_db = True
660 profiles[label].helpdesk = u'http://wiki.gnumed.de'
661
662 return profiles
663
665
666 src_order = [
667 (u'explicit', u'return'),
668 (u'user', u'return'),
669 ]
670
671 self._CBOX_user.SetValue (
672 gmTools.coalesce (
673 _cfg.get(u'preferences', u'login', src_order),
674 self.__previously_used_accounts[0]
675 )
676 )
677
678 last_used_profile_label = _cfg.get(u'preferences', u'profile', src_order)
679 if last_used_profile_label in self.__backend_profiles.keys():
680 self._CBOX_profile.SetValue(last_used_profile_label)
681 else:
682 self._CBOX_profile.SetValue(self.__backend_profiles.keys()[0])
683
684 self._CHBOX_debug.SetValue(_cfg.get(option = 'debug'))
685 self._CHBOX_slave.SetValue(_cfg.get(option = 'slave'))
686
705
706
707
709 """convenience function for compatibility with gmLoginInfo.LoginInfo"""
710 if not self.cancelled:
711
712
713 profile = self.__backend_profiles[self._CBOX_profile.GetValue().encode('utf8').strip()]
714 _log.debug(u'backend profile "%s" selected', profile.name)
715 _log.debug(u' details: <%s> on %s@%s:%s (%s, %s)',
716 self._CBOX_user.GetValue(),
717 profile.database,
718 profile.host,
719 profile.port,
720 profile.encoding,
721 gmTools.bool2subst(profile.public_db, u'public', u'private')
722 )
723 _log.debug(u' helpdesk: "%s"', profile.helpdesk)
724 login = gmLoginInfo.LoginInfo (
725 user = self._CBOX_user.GetValue(),
726 password = self.pwdentry.GetValue(),
727 host = profile.host,
728 database = profile.database,
729 port = profile.port
730 )
731 login.public_db = profile.public_db
732 login.helpdesk = profile.helpdesk
733 return login
734
735 return None
736
737
738
740 praxis = gmSurgery.gmCurrentPractice()
741 wx.MessageBox(_(
742 """GNUmed main login screen
743
744 USER:
745 name of the GNUmed user
746 PASSWORD
747 password for this user
748
749 button OK:
750 proceed with login
751 button OPTIONS:
752 set advanced options
753 button CANCEL:
754 abort login and quit GNUmed client
755 button HELP:
756 this help screen
757
758 For assistance on using GNUmed please contact:
759 %s""") % praxis.helpdesk)
760
761
789
791 self.cancelled = True
792 self.parent.Close()
793
794
795
796
797 if __name__ == "__main__":
798
799 if len(sys.argv) < 2:
800 sys.exit()
801
802 if sys.argv[1] != 'test':
803 sys.exit()
804
805
806 sys.exit()
807
808 from Gnumed.pycommon import gmI18N
809
810 logging.basicConfig(level = logging.DEBUG)
811
812 gmI18N.activate_locale()
813 gmI18N.install_domain(domain='gnumed')
814
815
817 app = wx.PyWidgetTester(size = (300,400))
818
819
820
821 dlg = cLoginDialog(None, -1)
822 dlg.ShowModal()
823
824 lp = dlg.panel.GetLoginInfo()
825 if lp is None:
826 wx.MessageBox(_("Dialog was cancelled by user"))
827 else:
828 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()))
829 dlg.Destroy()
830
831
832
833