1
2 """GNUmed authentication widgets.
3
4 This module contains widgets and GUI
5 functions for authenticating users.
6 """
7
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
14 import os.path
15 import logging
16 import re as regex
17
18
19
20 import wx
21
22
23
24 if __name__ == '__main__':
25 sys.path.insert(0, '../../')
26 from Gnumed.pycommon import gmLoginInfo
27 from Gnumed.pycommon import gmPG2
28 from Gnumed.pycommon import gmConnectionPool
29 from Gnumed.pycommon import gmBackendListener
30 from Gnumed.pycommon import gmTools
31 from Gnumed.pycommon import gmCfg2
32 from Gnumed.pycommon import gmI18N
33 from Gnumed.pycommon import gmLog2
34
35 from Gnumed.business import gmPraxis
36
37 from Gnumed.wxpython import gmGuiHelpers
38 from Gnumed.wxpython import gmExceptionHandlingWidgets
39
40
41 _log = logging.getLogger('gm.ui')
42 _cfg = gmCfg2.gmCfgData()
43
44
45 msg_generic = _("""
46 GNUmed database version mismatch.
47
48 This database version cannot be used with this client:
49
50 client version: %s
51 database version detected: %s
52 database version needed: %s
53
54 Currently connected to database:
55
56 host: %s
57 database: %s
58 user: %s
59 """)
60
61 msg_time_skew_fail = _("""\
62 The server and client clocks are off
63 by more than %s minutes !
64
65 You must fix the time settings before
66 you can use this database with this
67 client.
68
69 You may have to contact your
70 administrator for help.""")
71
72 msg_time_skew_warn = _("""\
73 The server and client clocks are off
74 by more than %s minutes !
75
76 You should fix the time settings.
77 Otherwise clinical data may appear to
78 have been entered at the wrong time.
79
80 You may have to contact your
81 administrator for help.""")
82
83 msg_insanity = _("""
84 There is a serious problem with the database settings:
85
86 %s
87
88 You may have to contact your administrator for help.""")
89
90 msg_fail = _("""
91 You must connect to a different database in order
92 to use the GNUmed client. You may have to contact
93 your administrator for help.""")
94
95 msg_override = _("""
96 The client will, however, continue to start up because
97 you are running a development/test version of GNUmed.
98
99 There may be schema related errors. Please report and/or
100 fix them. Do not rely on this database to work properly
101 in all cases !""")
102
103
104
105
107 """Display the login dialog and try to log into the backend.
108
109 - up to max_attempts times
110 - returns True/False
111 """
112
113 expected_hash = gmPG2.known_schema_hashes[expected_version]
114 client_version = _cfg.get(option = 'client_version')
115 global current_db_name
116 current_db_name = 'gnumed_v%s' % expected_version
117
118 attempt = 0
119
120 dlg = cLoginDialog(None, -1, client_version = client_version)
121 dlg.Centre(wx.BOTH)
122
123 while attempt < max_attempts:
124
125 _log.debug('login attempt %s of %s', (attempt+1), max_attempts)
126
127 connected = False
128
129 dlg.ShowModal()
130 login = dlg.panel.GetLoginInfo()
131 if login is None:
132 _log.info("user cancelled login dialog")
133 break
134
135 gmLog2.add_word2hide(login.password)
136
137
138 creds = gmConnectionPool.cPGCredentials()
139 creds.database = login.database
140 creds.host = login.host
141 creds.port = login.port
142 creds.user = login.user
143 creds.password = login.password
144 pool = gmConnectionPool.gmConnectionPool()
145 pool.credentials = creds
146 try:
147 conn = gmPG2.get_raw_connection(verbose = True, readonly = True)
148 connected = True
149
150 except gmPG2.cAuthenticationError as e:
151 attempt += 1
152 _log.error("login attempt failed: %s", e)
153 if attempt < max_attempts:
154 if ('host=127.0.0.1' in ('%s' % e)) or ('host=' not in ('%s' % e)):
155 msg = _(
156 'Unable to connect to database:\n\n'
157 '%s\n\n'
158 "Are you sure you have got a local database installed ?\n"
159 '\n'
160 "Please retry with proper credentials or cancel.\n"
161 '\n'
162 ' (for the public and any new GNUmed data-\n'
163 ' bases the default user name and password\n'
164 ' are {any-doc, any-doc})\n'
165 '\n'
166 'You may also need to check the PostgreSQL client\n'
167 'authentication configuration in pg_hba.conf. For\n'
168 'details see:\n'
169 '\n'
170 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
171 )
172 else:
173 msg = _(
174 "Unable to connect to database:\n\n"
175 "%s\n\n"
176 "Please retry with proper credentials or cancel.\n"
177 "\n"
178 "For the public and any new GNUmed databases the\n"
179 "default user name and password are {any-doc, any-doc}.\n"
180 "\n"
181 'You may also need to check the PostgreSQL client\n'
182 'authentication configuration in pg_hba.conf. For\n'
183 'details see:\n'
184 '\n'
185 'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
186 )
187 msg = msg % e
188 msg = regex.sub(r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg)
189 gmGuiHelpers.gm_show_error (
190 msg,
191 _('Connecting to backend')
192 )
193 del e
194 continue
195
196 except gmPG2.dbapi.OperationalError as exc:
197 _log.exception('login attempt failed')
198 gmPG2.log_pg_exception_details(exc)
199 msg = _(
200 "Unable to connect to database:\n\n"
201 "%s\n\n"
202 "Please retry another backend / user / password combination !\n"
203 "\n"
204 " (for the public and any new GNUmed databases\n"
205 " the default user name and password are\n"
206 " {any-doc, any-doc})\n"
207 "\n"
208 ) % exc
209 msg = regex.sub(r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg)
210 gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
211 del exc
212 continue
213
214 conn.close()
215
216 seems_bootstrapped = gmPG2.schema_exists(schema = 'gm')
217 if not seems_bootstrapped:
218 _log.error('schema [gm] does not exist - database not bootstrapped ?')
219 msg = _(
220 'The database you connected to does not seem\n'
221 'to have been boostrapped properly.\n'
222 '\n'
223 'Make sure you have run the GNUmed database\n'
224 'bootstrapper tool to create a new database.\n'
225 '\n'
226 'Further help can be found on the website at\n'
227 '\n'
228 ' http://wiki.gnumed.de\n'
229 '\n'
230 'or on the GNUmed mailing list.'
231 )
232 gmGuiHelpers.gm_show_error(msg, _('Verifying database'))
233 connected = False
234 break
235
236 compatible = gmPG2.database_schema_compatible(version = expected_version)
237 if compatible or not require_version:
238 dlg.panel.save_state()
239
240 if not compatible:
241 connected_db_version = gmPG2.get_schema_version()
242 msg = msg_generic % (
243 client_version,
244 connected_db_version,
245 expected_version,
246 gmTools.coalesce(login.host, '<localhost>'),
247 login.database,
248 login.user
249 )
250 if require_version:
251 gmGuiHelpers.gm_show_error(msg + msg_fail, _('Verifying database version'))
252 connected = False
253 continue
254 gmGuiHelpers.gm_show_info(msg + msg_override, _('Verifying database version'))
255
256
257 max_skew = 1
258 if _cfg.get(option = 'debug'):
259 max_skew = 10
260 if not gmPG2.sanity_check_time_skew(tolerance = (max_skew * 60)):
261 if _cfg.get(option = 'debug'):
262 gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings'))
263 else:
264 gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings'))
265 connected = False
266 continue
267
268 sanity_level, message = gmPG2.sanity_check_database_settings()
269 if sanity_level != 0:
270 gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings'))
271 if sanity_level == 2:
272 connected = False
273 continue
274
275 gmExceptionHandlingWidgets.set_is_public_database(_cfg.get(option = 'is_public_db'))
276 gmExceptionHandlingWidgets.set_helpdesk(_cfg.get(option = 'helpdesk'))
277
278 conn = gmPG2.get_connection(verbose = True, connection_name = 'GNUmed-[DbListenerThread]', pooled = False)
279 listener = gmBackendListener.gmBackendListener(conn = conn)
280 break
281
282 dlg.DestroyLater()
283
284 return connected
285
286
288 if procedure is None:
289 procedure = _('<restricted procedure>')
290
291
292 if dbo_password is None:
293 dbo_password = wx.GetPasswordFromUser (
294 message = _("""
295 [%s]
296
297 This is a restricted procedure. We need the
298 current password for the GNUmed database owner.
299
300 Please enter the current password for <%s>:""") % (
301 procedure,
302 dbo_account
303 ),
304 caption = procedure
305 )
306 if dbo_password == '':
307 return None
308
309 gmLog2.add_word2hide(dbo_password)
310
311
312 pool = gmConnectionPool.gmConnectionPool()
313 conn = None
314 try:
315 conn = pool.get_dbowner_connection (
316 readonly = False,
317 verbose = True,
318 dbo_password = dbo_password,
319 dbo_account = dbo_account
320 )
321 except Exception:
322 _log.exception('cannot connect')
323 gmGuiHelpers.gm_show_error (
324 aMessage = _('Cannot connect as the GNUmed database owner <%s>.') % dbo_account,
325 aTitle = procedure
326 )
327 gmPG2.log_database_access(action = 'failed to connect as database owner for [%s]' % procedure)
328 return conn
329
330
332
333 title = _('Changing GNUmed database owner password')
334
335 dbo_account = wx.GetTextFromUser (
336 message = _("Enter the account name of the GNUmed database owner:"),
337 caption = title,
338 default_value = ''
339 )
340
341 if dbo_account.strip() == '':
342 return False
343
344 dbo_conn = get_dbowner_connection (
345 procedure = title,
346 dbo_account = dbo_account
347 )
348 if dbo_conn is None:
349 return False
350
351 dbo_pwd_new_1 = wx.GetPasswordFromUser (
352 message = _("Enter the NEW password for the GNUmed database owner:"),
353 caption = title
354 )
355 if dbo_pwd_new_1.strip() == '':
356 return False
357
358 gmLog2.add_word2hide(dbo_pwd_new_1)
359
360 dbo_pwd_new_2 = wx.GetPasswordFromUser (
361 message = _("""Enter the NEW password for the GNUmed database owner, again.
362
363 (This will protect you from typos.)
364 """),
365 caption = title
366 )
367 if dbo_pwd_new_2.strip() == '':
368 return False
369
370 if dbo_pwd_new_1 != dbo_pwd_new_2:
371 return False
372
373
374
375 """ On Mon, Mar 13, 2017 at 12:19:22PM -0400, Tom Lane wrote:
376 > Date: Mon, 13 Mar 2017 12:19:22 -0400
377 > From: Tom Lane <tgl@sss.pgh.pa.us>
378 > To: Adrian Klaver <adrian.klaver@aklaver.com>
379 > cc: Schmid Andreas <Andreas.Schmid@bd.so.ch>,
380 > "'pgsql-general@postgresql.org'" <pgsql-general@postgresql.org>
381 > Subject: Re: [GENERAL] createuser: How to specify a database to connect to
382 >
383 > Adrian Klaver <adrian.klaver@aklaver.com> writes:
384 > > On 03/13/2017 08:52 AM, Tom Lane wrote:
385 > >> If by "history" you're worried about the server-side statement log, this
386 > >> is merest fantasy: the createuser program is not magic, it just constructs
387 > >> and sends a CREATE USER command for you. You'd actually be more secure
388 > >> using psql, where (if you're superuser) you could shut off log_statement
389 > >> for your session first.
390 >
391 > > There is a difference though:
392 >
393 > > psql> CREATE USER:
394 >
395 > > postgres-2017-03-13 09:03:27.147 PDT-0LOG: statement: create user
396 > > dummy_user with login password '1234';
397 >
398 > Well, what you're supposed to do is
399 >
400 > postgres=# create user dummy_user;
401 > postgres=# \password dummy_user
402 > Enter new password:
403 > Enter it again:
404 > postgres=#
405 >
406 > which will result in sending something like
407 >
408 > ALTER USER dummy_user PASSWORD 'md5c5e9567bc40082671d02c654260e0e09'
409 >
410 > You can additionally protect that by wrapping it into one transaction
411 > (if you have a setup where the momentary existence of the role without a
412 > password would be problematic) and/or shutting off logging beforehand.
413 """
414
415
416 cmd = """ALTER ROLE "%s" ENCRYPTED PASSWORD '%s';""" % (
417 dbo_account,
418 dbo_pwd_new_2
419 )
420 gmPG2.run_rw_queries(link_obj = dbo_conn, queries = [{'cmd': cmd}], end_tx = True)
421 return True
422
423
426
427
429 """cLoginDialog - window holding cLoginPanel"""
430
431 - def __init__(self, parent, id, title = _("Welcome to"), client_version = '*** unknown ***'):
438
439
441 """GUI panel class that interactively gets Postgres login parameters.
442
443 It features combo boxes which "remember" any number of
444 previously entered settings.
445 """
446 - def __init__(self, parent, id,
447 pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.TAB_TRAVERSAL,
448 isDialog = 0, client_version = '*** unknown ***'):
449 """Create login panel.
450
451 isDialog: if this panel is the main panel of a dialog, the panel will
452 resize the dialog automatically to display everything neatly
453 if isDialog is set to True
454 """
455 wx.Panel.__init__(self, parent, id, pos, size, style)
456 self.parent = parent
457
458
459
460 self.cancelled = True
461
462
463 self.isDialog = isDialog
464
465 self.topsizer = wx.BoxSizer(wx.VERTICAL)
466
467
468 paths = gmTools.gmPaths(app_name = 'gnumed', wx = wx)
469 bitmap = os.path.join(paths.system_app_data_dir, 'bitmaps', 'gnumedlogo.png')
470 try:
471 png = wx.Image(bitmap, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
472 bmp = wx.StaticBitmap(self, -1, png, wx.Point(10, 10), wx.Size(png.GetWidth(), png.GetHeight()))
473 self.topsizer.Add (
474 bmp,
475 proportion = 0,
476 flag = wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_CENTER_HORIZONTAL|wx.ALL,
477 border = 10
478 )
479 except Exception:
480 self.topsizer.Add (
481 wx.StaticText (
482 self,
483 -1,
484 label = _("Cannot find image") + bitmap,
485 style = wx.ALIGN_CENTRE
486 ),
487 proportion = 0,
488 flag = wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL,
489 border = 10
490 )
491
492 paramsbox_caption = _('Workplace "%s" (version %s)') % (gmPraxis.gmCurrentPraxisBranch().active_workplace, client_version)
493
494
495 self.paramsbox = wx.StaticBox( self, -1, paramsbox_caption, style = wx.ALIGN_CENTRE_HORIZONTAL)
496 self.paramsboxsizer = wx.StaticBoxSizer( self.paramsbox, wx.VERTICAL )
497 self.paramsbox.SetForegroundColour(wx.Colour(35, 35, 142))
498 self.paramsbox.SetFont(wx.Font(
499 pointSize = 12,
500 family = wx.SWISS,
501 style = wx.NORMAL,
502 weight = wx.BOLD,
503 underline = False
504 ))
505 self.pboxgrid = wx.FlexGridSizer(5, 2, 5, 5)
506 self.pboxgrid.AddGrowableCol(1)
507
508
509 label = wx.StaticText( self, -1, _('Log into'), wx.DefaultPosition, wx.DefaultSize, 0)
510 label.SetForegroundColour(wx.Colour(35, 35, 142))
511 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
512 self.__backend_profiles = self.__get_backend_profiles()
513 self._CBOX_profile = wx.ComboBox (
514 self,
515 -1,
516 list(self.__backend_profiles.keys())[0],
517 wx.DefaultPosition,
518 size = wx.Size(550,-1),
519 choices = list(self.__backend_profiles.keys()),
520 style = wx.CB_READONLY
521 )
522 self.pboxgrid.Add (self._CBOX_profile, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
523
524
525 label = wx.StaticText( self, -1, _("Username"), wx.DefaultPosition, wx.DefaultSize, 0 )
526 label.SetForegroundColour(wx.Colour(35, 35, 142))
527 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
528 self.__previously_used_accounts = self.__get_previously_used_accounts()
529 self._CBOX_user = wx.ComboBox (
530 self,
531 -1,
532 self.__previously_used_accounts[0],
533 wx.DefaultPosition,
534 wx.Size(150,-1),
535 self.__previously_used_accounts,
536 wx.CB_DROPDOWN
537 )
538 self.pboxgrid.Add( self._CBOX_user, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
539
540
541 label = wx.StaticText( self, -1, _("Password"), wx.DefaultPosition, wx.DefaultSize, 0 )
542 label.SetForegroundColour(wx.Colour(35, 35, 142))
543 self.pboxgrid.Add( label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
544 self.pwdentry = wx.TextCtrl( self, 1, '', wx.DefaultPosition, wx.Size(80,-1), wx.TE_PASSWORD )
545
546 self.pwdentry.SetFocus()
547 self.pboxgrid.Add( self.pwdentry, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
548
549
550 label = wx.StaticText(self, -1, _('Options'), wx.DefaultPosition, wx.DefaultSize, 0)
551 label.SetForegroundColour(wx.Colour(35, 35, 142))
552 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
553 self._CHBOX_debug = wx.CheckBox(self, -1, _('&Debug mode'))
554 self._CHBOX_debug.SetToolTip(_('Check this to run GNUmed client in debugging mode.'))
555 self.pboxgrid.Add(self._CHBOX_debug, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
556
557
558 label = wx.StaticText(self, -1, '', wx.DefaultPosition, wx.DefaultSize, 0)
559 label.SetForegroundColour(wx.Colour(35, 35, 142))
560 self.pboxgrid.Add(label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)
561 self._CHBOX_slave = wx.CheckBox(self, -1, _('Enable &remote control'))
562 self._CHBOX_slave.SetToolTip(_('Check this to run GNUmed client in slave mode for remote control.'))
563 self.pboxgrid.Add(self._CHBOX_slave, 0, wx.GROW | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 5)
564
565
566
567
568
569
570
571
572
573
574
575
576
577 self.button_gridsizer = wx.GridSizer(1,3,0,0)
578
579
580
581 ID_BUTTON_LOGIN = wx.NewId()
582 button_login_ok = wx.Button(self, ID_BUTTON_LOGIN, _("&Ok"), wx.DefaultPosition, wx.DefaultSize, 0 )
583 button_login_ok.SetToolTip(wx.ToolTip(_("Proceed with login.")) )
584 button_login_ok.SetDefault()
585
586
587
588
589 ID_BUTTON_CANCEL = wx.NewId()
590 button_cancel = wx.Button(self, ID_BUTTON_CANCEL, _("&Cancel"), wx.DefaultPosition, wx.DefaultSize, 0 )
591 button_cancel.SetToolTip(wx.ToolTip(_("Cancel Login.")) )
592
593
594
595 ID_BUTTON_HELP = wx.NewId()
596 button_help = wx.Button(self, ID_BUTTON_HELP, _("&Help"), wx.DefaultPosition, wx.DefaultSize, 0 )
597 button_help.SetToolTip(wx.ToolTip(_("Help for login screen")))
598
599
600
601 self.button_gridsizer.Add (button_help,0,wx.EXPAND|wx.ALL,5)
602 self.button_gridsizer.Add (button_login_ok,0,wx.EXPAND|wx.ALL,5)
603 self.button_gridsizer.Add (button_cancel,0,wx.EXPAND|wx.ALL,5)
604
605 self.paramsboxsizer.Add(self.pboxgrid, 1, wx.GROW|wx.ALL, 10)
606 self.topsizer.Add(self.paramsboxsizer, 1, wx.GROW|wx.ALL, 10)
607 self.topsizer.Add( self.button_gridsizer, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5 )
608
609 self.__load_state()
610
611 self.SetAutoLayout(True)
612 self.SetSizer( self.topsizer)
613 self.topsizer.Fit( self )
614 if self.isDialog:
615 self.topsizer.SetSizeHints(parent)
616
617 button_help.Bind(wx.EVT_BUTTON, self.OnHelp)
618 button_login_ok.Bind(wx.EVT_BUTTON, self.__on_login_button_pressed)
619 button_cancel.Bind(wx.EVT_BUTTON, self.OnCancel)
620
621
622
623
624
625
626
628
629 accounts = gmTools.coalesce (
630 _cfg.get (
631 group = 'backend',
632 option = 'logins',
633 source_order = [
634 ('explicit', 'extend'),
635 ('user', 'extend'),
636 ('workbase', 'extend')
637 ]
638 ),
639 ['any-doc']
640 )
641
642
643 return accounts
644
646 """Get server profiles from the configuration files.
647
648 1) from system-wide file
649 2) from user file
650
651 Profiles in the user file which have the same name
652 as a profile in the system file will override the
653 system file.
654 """
655
656 src_order = [
657 ('explicit', 'extend'),
658 ('system', 'extend'),
659 ('user', 'extend'),
660 ('workbase', 'extend')
661 ]
662
663 profile_names = gmTools.coalesce (
664 _cfg.get(group = 'backend', option = 'profiles', source_order = src_order),
665 []
666 )
667
668
669 src_order = [
670 ('explicit', 'return'),
671 ('workbase', 'return'),
672 ('user', 'return'),
673 ('system', 'return')
674 ]
675
676 profiles = {}
677
678 for profile_name in profile_names:
679
680
681 profile = cBackendProfile()
682 profile_section = 'profile %s' % profile_name
683
684 profile.name = profile_name
685 profile.host = gmTools.coalesce(_cfg.get(profile_section, 'host', src_order), '').strip()
686 port = gmTools.coalesce(_cfg.get(profile_section, 'port', src_order), 5432)
687 try:
688 profile.port = int(port)
689 if profile.port < 1024:
690 raise ValueError('refusing to use priviledged port (< 1024)')
691 except ValueError:
692 _log.warning('invalid port definition: [%s], skipping profile [%s]', port, profile_name)
693 continue
694 profile.database = gmTools.coalesce(_cfg.get(profile_section, 'database', src_order), '').strip()
695 if profile.database == '':
696 _log.warning('database name not specified, skipping profile [%s]', profile_name)
697 continue
698 profile.encoding = gmTools.coalesce(_cfg.get(profile_section, 'encoding', src_order), 'UTF8')
699 profile.public_db = bool(_cfg.get(profile_section, 'public/open access', src_order))
700 profile.helpdesk = _cfg.get(profile_section, 'help desk', src_order)
701
702 label = '%s (%s@%s)' % (profile_name, profile.database, profile.host)
703 profiles[label] = profile
704
705
706
707 if not (_cfg.get(option = 'debug') or current_db_name.endswith('_devel')):
708 profiles2remove = []
709 for label in profiles:
710 if profiles[label].database != current_db_name:
711 profiles2remove.append(label)
712 for label in profiles2remove:
713 del profiles[label]
714
715 if len(profiles) == 0:
716 host = 'publicdb.gnumed.de'
717 label = 'public GNUmed database (%s@%s)' % (current_db_name, host)
718 profiles[label] = cBackendProfile()
719 profiles[label].name = label
720 profiles[label].host = host
721 profiles[label].port = 5432
722 profiles[label].database = current_db_name
723 profiles[label].encoding = 'UTF8'
724 profiles[label].public_db = True
725 profiles[label].helpdesk = 'http://wiki.gnumed.de'
726
727 return profiles
728
730
731 src_order = [
732 ('explicit', 'return'),
733 ('user', 'return'),
734 ]
735
736 self._CBOX_user.SetValue (
737 gmTools.coalesce (
738 _cfg.get('preferences', 'login', src_order),
739 self.__previously_used_accounts[0]
740 )
741 )
742
743 last_used_profile_label = _cfg.get('preferences', 'profile', src_order)
744 if last_used_profile_label in self.__backend_profiles.keys():
745 self._CBOX_profile.SetValue(last_used_profile_label)
746 else:
747 self._CBOX_profile.SetValue(list(self.__backend_profiles.keys())[0])
748
749 self._CHBOX_debug.SetValue(_cfg.get(option = 'debug'))
750 self._CHBOX_slave.SetValue(_cfg.get(option = 'slave'))
751
770
771
772
774 """convenience function for compatibility with gmLoginInfo.LoginInfo"""
775 if self.cancelled:
776 return None
777
778
779 profile = self.__backend_profiles[self._CBOX_profile.GetValue().strip()]
780 _log.info('backend profile "%s" selected', profile.name)
781 _log.info(' details: <%s> on %s@%s:%s (%s, %s)',
782 self._CBOX_user.GetValue(),
783 profile.database,
784 profile.host,
785 profile.port,
786 profile.encoding,
787 gmTools.bool2subst(profile.public_db, 'public', 'private')
788 )
789 _log.info(' helpdesk: "%s"', profile.helpdesk)
790 login = gmLoginInfo.LoginInfo (
791 user = self._CBOX_user.GetValue(),
792 password = self.pwdentry.GetValue(),
793 host = profile.host,
794 database = profile.database,
795 port = profile.port
796 )
797 _cfg.set_option (
798 option = 'is_public_db',
799 value = profile.public_db
800 )
801 _cfg.set_option (
802 option = 'helpdesk',
803 value = profile.helpdesk
804 )
805 _cfg.set_option (
806 option = 'backend_profile',
807 value = profile.name
808 )
809 return login
810
811
812
814 praxis = gmPraxis.gmCurrentPraxisBranch()
815 wx.MessageBox(_(
816 """Unable to connect to the database ?
817
818 "PostgreSQL: FATAL: password authentication failed ..."
819
820 The default user name and password are {any-doc, any-doc}
821 for the public and any new GNUmed databases.
822
823 "... could not connect to server ..."
824
825 Mostly this is a case of new users who did not yet install
826 or configure a PostgreSQL server and/or a GNUmed database
827 of their own, which you must do before you can connect to
828 anything other than the public demonstration database, see
829
830 http://wiki.gnumed.de/bin/view/Gnumed/GmManualServerInstall
831
832 For assistance on using GNUmed please consult the wiki:
833
834 http://wiki.gnumed.de/bin/view/Gnumed/GnumedManual
835
836 For more help than the above, please contact:
837
838 GNUmed Development List <gnumed-bugs@gnu.org>
839
840 For local assistance please contact:
841
842 %s""") % praxis.helpdesk,
843 caption = _('HELP for GNUmed main login screen'))
844
845
873
877
878
879
880
881 if __name__ == "__main__":
882
883 if len(sys.argv) < 2:
884 sys.exit()
885
886 if sys.argv[1] != 'test':
887 sys.exit()
888
889
890 sys.exit()
891
892 from Gnumed.pycommon import gmI18N
893
894 logging.basicConfig(level = logging.DEBUG)
895
896 gmI18N.activate_locale()
897 gmI18N.install_domain(domain='gnumed')
898
899
901 app = wx.PyWidgetTester(size = (300,400))
902
903
904
905 dlg = cLoginDialog(None, -1)
906 dlg.ShowModal()
907
908 lp = dlg.panel.GetLoginInfo()
909 if lp is None:
910 wx.MessageBox(_("Dialog was cancelled by user"))
911 else:
912 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()))
913 dlg.DestroyLater()
914
915
916
917