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