1 """GNUmed authentication widgets.
2
3 This module contains widgets and GUI
4 functions for authenticating users.
5 """
6
7 __author__ = "karsten.hilbert@gmx.net, H.Herb, H.Berger, R.Terry"
8 __license__ = "GPL v2 or later (details at http://www.gnu.org)"
9
10
11
12 import sys
13 import os.path
14 import logging
15 import re as regex
16
17
18
19 import wx
20
21
22
23 if __name__ == '__main__':
24 sys.path.insert(0, '../../')
25 from Gnumed.pycommon import gmLoginInfo
26 from Gnumed.pycommon import gmPG2
27 from Gnumed.pycommon import gmBackendListener
28 from Gnumed.pycommon import gmTools
29 from Gnumed.pycommon import gmCfg2
30 from Gnumed.pycommon import gmI18N
31
32 from Gnumed.business import gmSurgery
33
34 from Gnumed.wxpython import gmGuiHelpers
35 from Gnumed.wxpython import gmExceptionHandlingWidgets
36
37
38 _log = logging.getLogger('gm.ui')
39 _cfg = gmCfg2.gmCfgData()
40
41 try:
42 _('dummy-no-need-to-translate-but-make-epydoc-happy')
43 except NameError:
44 _ = lambda x:x
45
46
47 msg_generic = _("""
48 GNUmed database version mismatch.
49
50 This database version cannot be used with this client:
51
52 client version: %s
53 database version detected: %s
54 database version needed: %s
55
56 Currently connected to database:
57
58 host: %s
59 database: %s
60 user: %s
61 """)
62
63 msg_time_skew_fail = _("""\
64 The server and client clocks are off
65 by more than %s minutes !
66
67 You must fix the time settings before
68 you can use this database with this
69 client.
70
71 You may have to contact your
72 administrator for help.""")
73
74 msg_time_skew_warn = _("""\
75 The server and client clocks are off
76 by more than %s minutes !
77
78 You should fix the time settings.
79 Otherwise clinical data may appear to
80 have been entered at the wrong time.
81
82 You may have to contact your
83 administrator for help.""")
84
85 msg_insanity = _("""
86 There is a serious problem with the database settings:
87
88 %s
89
90 You may have to contact your administrator for help.""")
91
92 msg_fail = _("""
93 You must connect to a different database in order
94 to use the GNUmed client. You may have to contact
95 your administrator for help.""")
96
97 msg_override = _("""
98 The client will, however, continue to start up because
99 you are running a development/test version of GNUmed.
100
101 There may be schema related errors. Please report and/or
102 fix them. Do not rely on this database to work properly
103 in all cases !""")
104
105
106
107
109 """Display the login dialog and try to log into the backend.
110
111 - up to max_attempts times
112 - returns True/False
113 """
114
115 expected_hash = gmPG2.known_schema_hashes[expected_version]
116 client_version = _cfg.get(option = u'client_version')
117 global current_db_name
118 current_db_name = u'gnumed_v%s' % expected_version
119
120 attempt = 0
121
122 dlg = cLoginDialog(None, -1, client_version = client_version)
123 dlg.Centre(wx.BOTH)
124
125 while attempt < max_attempts:
126
127 _log.debug('login attempt %s of %s', (attempt+1), max_attempts)
128
129 connected = False
130
131 dlg.ShowModal()
132 login = dlg.panel.GetLoginInfo()
133 if login is None:
134 _log.info("user cancelled login dialog")
135 break
136
137
138 dsn = gmPG2.make_psycopg2_dsn (
139 database = login.database,
140 host = login.host,
141 port = login.port,
142 user = login.user,
143 password = login.password
144 )
145 try:
146 conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True)
147 connected = True
148
149 except gmPG2.cAuthenticationError, e:
150 attempt += 1
151 _log.error(u"login attempt failed: %s", e)
152 if attempt < max_attempts:
153 if (u'host=127.0.0.1' in (u'%s' % e)) or (u'host=' not in (u'%s' % e)):
154 msg = _(
155 'Unable to connect to database:\n\n'
156 '%s\n\n'
157 "Are you sure you have got a local database installed ?\n"
158 '\n'
159 "Please retry with proper credentials or cancel.\n"
160 '\n'
161 'You may also need to check the PostgreSQL client\n'
162 'authentication configuration in pg_hba.conf. For\n'
163 'details see:\n'
164 '\n'
165 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
166 )
167 else:
168 msg = _(
169 "Unable to connect to database:\n\n"
170 "%s\n\n"
171 "Please retry with proper credentials or cancel.\n"
172 "\n"
173 'You may also need to check the PostgreSQL client\n'
174 'authentication configuration in pg_hba.conf. For\n'
175 'details see:\n'
176 '\n'
177 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
178 )
179 msg = msg % e
180 msg = regex.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
181 gmGuiHelpers.gm_show_error (
182 msg,
183 _('Connecting to backend')
184 )
185 del e
186 continue
187
188 except gmPG2.dbapi.OperationalError, e:
189 _log.error(u"login attempt failed: %s", e)
190 msg = _(
191 "Unable to connect to database:\n\n"
192 "%s\n\n"
193 "Please retry another backend / user / password combination !\n"
194 ) % gmPG2.extract_msg_from_pg_exception(e)
195 msg = regex.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
196 gmGuiHelpers.gm_show_error (
197 msg,
198 _('Connecting to backend')
199 )
200 del e
201 continue
202
203
204 gmPG2.set_default_login(login = login)
205 gmPG2.set_default_client_encoding(encoding = dlg.panel.backend_profile.encoding)
206
207 seems_bootstrapped = gmPG2.schema_exists(schema = 'gm')
208 if not seems_bootstrapped:
209 _log.error('schema [gm] does not exist - database not bootstrapped ?')
210 msg = _(
211 'The database you connected to does not seem\n'
212 'to have been boostrapped properly.\n'
213 '\n'
214 'Make sure you have run the GNUmed database\n'
215 'bootstrapper tool to create a new database.\n'
216 '\n'
217 'Further help can be found on the website at\n'
218 '\n'
219 ' http://wiki.gnumed.de\n'
220 '\n'
221 'or on the GNUmed mailing list.'
222 )
223 gmGuiHelpers.gm_show_error(msg, _('Verifying database'))
224 connected = False
225 break
226
227 compatible = gmPG2.database_schema_compatible(version = expected_version)
228 if compatible or not require_version:
229 dlg.panel.save_state()
230
231 if not compatible:
232 connected_db_version = gmPG2.get_schema_version()
233 msg = msg_generic % (
234 client_version,
235 connected_db_version,
236 expected_version,
237 gmTools.coalesce(login.host, '<localhost>'),
238 login.database,
239 login.user
240 )
241 if require_version:
242 gmGuiHelpers.gm_show_error(msg + msg_fail, _('Verifying database version'))
243 connected = False
244 continue
245 gmGuiHelpers.gm_show_info(msg + msg_override, _('Verifying database version'))
246
247
248 max_skew = 1
249 if _cfg.get(option = 'debug'):
250 max_skew = 10
251 if not gmPG2.sanity_check_time_skew(tolerance = (max_skew * 60)):
252 if _cfg.get(option = 'debug'):
253 gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings'))
254 else:
255 gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings'))
256 connected = False
257 continue
258
259 sanity_level, message = gmPG2.sanity_check_database_settings()
260 if sanity_level != 0:
261 gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings'))
262 if sanity_level == 2:
263 connected = False
264 continue
265
266 gmExceptionHandlingWidgets.set_is_public_database(login.public_db)
267 gmExceptionHandlingWidgets.set_helpdesk(login.helpdesk)
268
269 listener = gmBackendListener.gmBackendListener(conn = conn)
270 break
271
272 dlg.Destroy()
273
274 return connected
275
277 if procedure is None:
278 procedure = _('<restricted procedure>')
279
280
281 if dbo_password is None:
282 dbo_password = wx.GetPasswordFromUser (
283 message = _("""
284 [%s]
285
286 This is a restricted procedure. We need the
287 current password for the GNUmed database owner.
288
289 Please enter the current password for <%s>:""") % (
290 procedure,
291 dbo_account
292 ),
293 caption = procedure
294 )
295 if dbo_password == '':
296 return None
297
298
299 login = gmPG2.get_default_login()
300 dsn = gmPG2.make_psycopg2_dsn (
301 database = login.database,
302 host = login.host,
303 port = login.port,
304 user = dbo_account,
305 password = dbo_password
306 )
307 try:
308 conn = gmPG2.get_connection (
309 dsn = dsn,
310 readonly = False,
311 verbose = True,
312 pooled = False
313 )
314 except:
315 _log.exception('cannot connect')
316 gmGuiHelpers.gm_show_error (
317 aMessage = _('Cannot connect as the GNUmed database owner <%s>.') % dbo_account,
318 aTitle = procedure
319 )
320 gmPG2.log_database_access(action = u'failed to connect as database owner for [%s]' % procedure)
321 return None
322
323 return conn
324
326
327 title = _(u'Changing GNUmed database owner password')
328
329 dbo_account = wx.GetTextFromUser (
330 message = _(u"Enter the account name of the GNUmed database owner:"),
331 caption = title,
332 default_value = u''
333 )
334
335 if dbo_account.strip() == u'':
336 return False
337
338 dbo_conn = get_dbowner_connection (
339 procedure = title,
340 dbo_account = dbo_account
341 )
342 if dbo_conn is None:
343 return False
344
345 dbo_pwd_new_1 = wx.GetPasswordFromUser (
346 message = _(u"Enter the NEW password for the GNUmed database owner:"),
347 caption = title
348 )
349 if dbo_pwd_new_1.strip() == u'':
350 return False
351
352 dbo_pwd_new_2 = wx.GetPasswordFromUser (
353 message = _(u"""Enter the NEW password for the GNUmed database owner, again.
354
355 (This will protect you from typos.)
356 """),
357 caption = title
358 )
359 if dbo_pwd_new_2.strip() == u'':
360 return False
361
362 if dbo_pwd_new_1 != dbo_pwd_new_2:
363 return False
364
365 cmd = u"""ALTER ROLE "%s" ENCRYPTED PASSWORD '%s';""" % (
366 dbo_account,
367 dbo_pwd_new_2
368 )
369 gmPG2.run_rw_queries(link_obj = dbo_conn, queries = [{'cmd': cmd}], end_tx = True)
370
371 return True
372
375
377 """cLoginDialog - window holding cLoginPanel"""
378
379 - def __init__(self, parent, id, title=_("Welcome to the"), client_version=u'*** unknown ***'):
386
388 """GUI panel class that interactively gets Postgres login parameters.
389
390 It features combo boxes which "remember" any number of
391 previously entered settings.
392 """
393 - def __init__(self, parent, id,
394 pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.TAB_TRAVERSAL,
395 isDialog = 0, client_version = u'*** unknown ***'):
396 """Create login panel.
397
398 isDialog: if this panel is the main panel of a dialog, the panel will
399 resize the dialog automatically to display everything neatly
400 if isDialog is set to True
401 """
402 wx.Panel.__init__(self, parent, id, pos, size, style)
403 self.parent = parent
404
405
406
407 self.cancelled = True
408
409
410 self.isDialog = isDialog
411
412 self.topsizer = wx.BoxSizer(wx.VERTICAL)
413
414
415 paths = gmTools.gmPaths(app_name = u'gnumed', wx = wx)
416 bitmap = os.path.join(paths.system_app_data_dir, 'bitmaps', 'gnumedlogo.png')
417 try:
418 png = wx.Image(bitmap, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
419 bmp = wx.StaticBitmap(self, -1, png, wx.Point(10, 10), wx.Size(png.GetWidth(), png.GetHeight()))
420 self.topsizer.Add (
421 bmp,
422 proportion = 0,
423 flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALL,
424 border = 10
425 )
426 except:
427 self.topsizer.Add (
428 wx.StaticText (
429 self,
430 -1,
431 label = _("Cannot find image") + bitmap,
432 style = wx.ALIGN_CENTRE
433 ),
434 proportion = 0,
435 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL,
436 border = 10
437 )
438
439 paramsbox_caption = _('"%s" (version %s)') % (gmSurgery.gmCurrentPractice().active_workplace, client_version)
440
441
442 self.paramsbox = wx.StaticBox( self, -1, paramsbox_caption, style = wx.ALIGN_CENTRE_HORIZONTAL)
443 self.paramsboxsizer = wx.StaticBoxSizer( self.paramsbox, wx.VERTICAL )
444 self.paramsbox.SetForegroundColour(wx.Colour(35, 35, 142))
445 self.paramsbox.SetFont(wx.Font(
446 pointSize = 12,
447 family = wx.SWISS,
448 style = wx.NORMAL,
449 weight = wx.BOLD,
450 underline = False
451 ))
452 self.pboxgrid = wx.FlexGridSizer(5, 2, 5, 5)
453 self.pboxgrid.AddGrowableCol(1)
454
455
456 label = wx.StaticText( self, -1, _('Log into'), wx.DefaultPosition, wx.DefaultSize, 0)
457 label.SetForegroundColour(wx.Colour(35, 35, 142))
458 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
459 self.__backend_profiles = self.__get_backend_profiles()
460 self._CBOX_profile = wx.ComboBox (
461 self,
462 -1,
463 self.__backend_profiles.keys()[0],
464 wx.DefaultPosition,
465 size = wx.Size(550,-1),
466 choices = self.__backend_profiles.keys(),
467 style = wx.CB_READONLY
468 )
469 self.pboxgrid.Add (self._CBOX_profile, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
470
471
472 label = wx.StaticText( self, -1, _("Username"), wx.DefaultPosition, wx.DefaultSize, 0 )
473 label.SetForegroundColour(wx.Colour(35, 35, 142))
474 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
475 self.__previously_used_accounts = self.__get_previously_used_accounts()
476 self._CBOX_user = wx.ComboBox (
477 self,
478 -1,
479 self.__previously_used_accounts[0],
480 wx.DefaultPosition,
481 wx.Size(150,-1),
482 self.__previously_used_accounts,
483 wx.CB_DROPDOWN
484 )
485 self.pboxgrid.Add( self._CBOX_user, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
486
487
488 label = wx.StaticText( self, -1, _("Password"), 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.pwdentry = wx.TextCtrl( self, 1, '', wx.DefaultPosition, wx.Size(80,-1), wx.TE_PASSWORD )
492
493 self.pwdentry.SetFocus()
494 self.pboxgrid.Add( self.pwdentry, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
495
496
497 label = wx.StaticText(self, -1, _('Options'), wx.DefaultPosition, wx.DefaultSize, 0)
498 label.SetForegroundColour(wx.Colour(35, 35, 142))
499 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
500 self._CHBOX_debug = wx.CheckBox(self, -1, _('&Debug mode'))
501 self._CHBOX_debug.SetToolTipString(_('Check this to run GNUmed client in debugging mode.'))
502 self.pboxgrid.Add(self._CHBOX_debug, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
503
504
505 label = wx.StaticText(self, -1, '', wx.DefaultPosition, wx.DefaultSize, 0)
506 label.SetForegroundColour(wx.Colour(35, 35, 142))
507 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
508 self._CHBOX_slave = wx.CheckBox(self, -1, _('Enable &remote control'))
509 self._CHBOX_slave.SetToolTipString(_('Check this to run GNUmed client in slave mode for remote control.'))
510 self.pboxgrid.Add(self._CHBOX_slave, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
511
512
513
514
515
516
517
518
519
520
521
522
523
524 self.button_gridsizer = wx.GridSizer(1,3,0,0)
525
526
527
528 ID_BUTTON_LOGIN = wx.NewId()
529 button_login_ok = wx.Button(self, ID_BUTTON_LOGIN, _("&Ok"), wx.DefaultPosition, wx.DefaultSize, 0 )
530 button_login_ok.SetToolTip(wx.ToolTip(_("Proceed with login.")) )
531 button_login_ok.SetDefault()
532
533
534
535
536 ID_BUTTON_CANCEL = wx.NewId()
537 button_cancel = wx.Button(self, ID_BUTTON_CANCEL, _("&Cancel"), wx.DefaultPosition, wx.DefaultSize, 0 )
538 button_cancel.SetToolTip(wx.ToolTip(_("Cancel Login.")) )
539
540
541
542 ID_BUTTON_HELP = wx.NewId()
543 button_help = wx.Button(self, ID_BUTTON_HELP, _("&Help"), wx.DefaultPosition, wx.DefaultSize, 0 )
544 button_help.SetToolTip(wx.ToolTip(_("Help for login screen")))
545
546
547
548 self.button_gridsizer.Add (button_help,0,wx.EXPAND|wx.ALL,5)
549 self.button_gridsizer.Add (button_login_ok,0,wx.EXPAND|wx.ALL,5)
550 self.button_gridsizer.Add (button_cancel,0,wx.EXPAND|wx.ALL,5)
551
552 self.paramsboxsizer.Add(self.pboxgrid, 1, wx.GROW|wx.ALL, 10)
553 self.topsizer.Add(self.paramsboxsizer, 1, wx.GROW|wx.ALL, 10)
554 self.topsizer.Add( self.button_gridsizer, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
555
556 self.__load_state()
557
558 self.SetAutoLayout(True)
559 self.SetSizer( self.topsizer)
560 self.topsizer.Fit( self )
561 if self.isDialog:
562 self.topsizer.SetSizeHints(parent)
563
564 wx.EVT_BUTTON(self, ID_BUTTON_HELP, self.OnHelp)
565 wx.EVT_BUTTON(self, ID_BUTTON_LOGIN, self.__on_login_button_pressed)
566 wx.EVT_BUTTON(self, ID_BUTTON_CANCEL, self.OnCancel)
567
568
569
570
572
573 accounts = gmTools.coalesce (
574 _cfg.get (
575 group = u'backend',
576 option = u'logins',
577 source_order = [
578 (u'explicit', u'extend'),
579 (u'user', u'extend'),
580 (u'workbase', u'extend')
581 ]
582 ),
583 ['any-doc']
584 )
585
586
587 return accounts
588
590 """Get server profiles from the configuration files.
591
592 1) from system-wide file
593 2) from user file
594
595 Profiles in the user file which have the same name
596 as a profile in the system file will override the
597 system file.
598 """
599
600 src_order = [
601 (u'explicit', u'extend'),
602 (u'system', u'extend'),
603 (u'user', u'extend'),
604 (u'workbase', u'extend')
605 ]
606
607 profile_names = gmTools.coalesce (
608 _cfg.get(group = u'backend', option = u'profiles', source_order = src_order),
609 []
610 )
611
612
613 src_order = [
614 (u'explicit', u'return'),
615 (u'workbase', u'return'),
616 (u'user', u'return'),
617 (u'system', u'return')
618 ]
619
620 profiles = {}
621
622 for profile_name in profile_names:
623
624
625 profile = cBackendProfile()
626 profile_section = 'profile %s' % profile_name
627
628 profile.name = profile_name
629 profile.host = gmTools.coalesce(_cfg.get(profile_section, u'host', src_order), u'').strip()
630 port = gmTools.coalesce(_cfg.get(profile_section, u'port', src_order), 5432)
631 try:
632 profile.port = int(port)
633 if profile.port < 1024:
634 raise ValueError('refusing to use priviledged port (< 1024)')
635 except ValueError:
636 _log.warning('invalid port definition: [%s], skipping profile [%s]', port, profile_name)
637 continue
638 profile.database = gmTools.coalesce(_cfg.get(profile_section, u'database', src_order), u'').strip()
639 if profile.database == u'':
640 _log.warning('database name not specified, skipping profile [%s]', profile_name)
641 continue
642 profile.encoding = gmTools.coalesce(_cfg.get(profile_section, u'encoding', src_order), u'UTF8')
643 profile.public_db = bool(_cfg.get(profile_section, u'public/open access', src_order))
644 profile.helpdesk = _cfg.get(profile_section, u'help desk', src_order)
645
646 label = u'%s (%s@%s)' % (profile_name, profile.database, profile.host)
647 profiles[label] = profile
648
649
650
651 if not (_cfg.get(option = 'debug') or current_db_name.endswith('_devel')):
652 profiles2remove = []
653 for label in profiles:
654 if profiles[label].database != current_db_name:
655 profiles2remove.append(label)
656 for label in profiles2remove:
657 del profiles[label]
658
659 if len(profiles) == 0:
660 host = u'publicdb.gnumed.de'
661 label = u'public GNUmed database (%s@%s)' % (current_db_name, host)
662 profiles[label] = cBackendProfile()
663 profiles[label].name = label
664 profiles[label].host = host
665 profiles[label].port = 5432
666 profiles[label].database = current_db_name
667 profiles[label].encoding = u'UTF8'
668 profiles[label].public_db = True
669 profiles[label].helpdesk = u'http://wiki.gnumed.de'
670
671 return profiles
672
674
675 src_order = [
676 (u'explicit', u'return'),
677 (u'user', u'return'),
678 ]
679
680 self._CBOX_user.SetValue (
681 gmTools.coalesce (
682 _cfg.get(u'preferences', u'login', src_order),
683 self.__previously_used_accounts[0]
684 )
685 )
686
687 last_used_profile_label = _cfg.get(u'preferences', u'profile', src_order)
688 if last_used_profile_label in self.__backend_profiles.keys():
689 self._CBOX_profile.SetValue(last_used_profile_label)
690 else:
691 self._CBOX_profile.SetValue(self.__backend_profiles.keys()[0])
692
693 self._CHBOX_debug.SetValue(_cfg.get(option = 'debug'))
694 self._CHBOX_slave.SetValue(_cfg.get(option = 'slave'))
695
714
715
716
718 """convenience function for compatibility with gmLoginInfo.LoginInfo"""
719 if self.cancelled:
720 return None
721
722
723
724 profile = self.__backend_profiles[self._CBOX_profile.GetValue().encode('utf8').strip()]
725 _log.info(u'backend profile "%s" selected', profile.name)
726 _log.info(u' details: <%s> on %s@%s:%s (%s, %s)',
727 self._CBOX_user.GetValue(),
728 profile.database,
729 profile.host,
730 profile.port,
731 profile.encoding,
732 gmTools.bool2subst(profile.public_db, u'public', u'private')
733 )
734 _log.info(u' helpdesk: "%s"', profile.helpdesk)
735 login = gmLoginInfo.LoginInfo (
736 user = self._CBOX_user.GetValue(),
737 password = self.pwdentry.GetValue(),
738 host = profile.host,
739 database = profile.database,
740 port = profile.port
741 )
742 login.public_db = profile.public_db
743 login.helpdesk = profile.helpdesk
744 login.backend_profile = profile.name
745 return login
746
747
748
750 praxis = gmSurgery.gmCurrentPractice()
751 wx.MessageBox(_(
752 """GNUmed main login screen
753
754 Welcome to the GNUmed client. Shown are the current
755 "Workplace" and (version).
756
757 You may select to log into a public database with username
758 and password {any-doc, any-doc}. Any other database
759 (including a local one) must first be separately installed
760 before you can log in.
761
762 For assistance on using GNUmed please consult the wiki:
763
764 http://wiki.gnumed.de/bin/view/Gnumed/GnumedManual
765
766 and to install a local database see:
767
768 http://wiki.gnumed.de/bin/view/Gnumed/GmManualServerInstall
769
770 For more help than the above, please contact:
771
772 GNUmed Development List <gnumed-bugs@gnu.org>
773
774 For local assistance please contact:
775
776 %s""") % praxis.helpdesk)
777
778
806
808 self.cancelled = True
809 self.parent.Close()
810
811
812
813
814 if __name__ == "__main__":
815
816 if len(sys.argv) < 2:
817 sys.exit()
818
819 if sys.argv[1] != 'test':
820 sys.exit()
821
822
823 sys.exit()
824
825 from Gnumed.pycommon import gmI18N
826
827 logging.basicConfig(level = logging.DEBUG)
828
829 gmI18N.activate_locale()
830 gmI18N.install_domain(domain='gnumed')
831
832
834 app = wx.PyWidgetTester(size = (300,400))
835
836
837
838 dlg = cLoginDialog(None, -1)
839 dlg.ShowModal()
840
841 lp = dlg.panel.GetLoginInfo()
842 if lp is None:
843 wx.MessageBox(_("Dialog was cancelled by user"))
844 else:
845 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()))
846 dlg.Destroy()
847
848
849
850