Exemplo n.º 1
0
	def run_monitor():

		print("starting up backend notifications monitor")

		def monitoring_callback(*args, **kwargs):
			try:
				kwargs['originated_in_database']
				print('==> got notification from database "%s":' % kwargs['signal'])
			except KeyError:
				print('==> received signal from client: "%s"' % kwargs['signal'])
			del kwargs['signal']
			for key in kwargs.keys():
				print('    [%s]: %s' % (key, kwargs[key]))

		gmDispatcher.connect(receiver = monitoring_callback)

		listener = gmBackendListener(conn = gmPG2.get_raw_connection())
		print("listening for the following notifications:")
		print("1) unspecific:")
		for sig in listener.unspecific_notifications:
			print('   - %s' % sig)

		while True:
			pat = gmPersonSearch.ask_for_patient()
			if pat is None:
				break
			print("found patient", pat)
			gmPerson.set_active_patient(patient=pat)
			print("now waiting for notifications, hit <ENTER> to select another patient")
			raw_input()

		print("cleanup")
		listener.shutdown()

		print("shutting down backend notifications monitor")
Exemplo n.º 2
0
	def run_monitor():

		print("starting up backend notifications monitor")

		def monitoring_callback(*args, **kwargs):
			try:
				kwargs['originated_in_database']
				print('==> got notification from database "%s":' % kwargs['signal'])
			except KeyError:
				print('==> received signal from client: "%s"' % kwargs['signal'])
			del kwargs['signal']
			for key in kwargs.keys():
				print('    [%s]: %s' % (key, kwargs[key]))

		gmDispatcher.connect(receiver = monitoring_callback)

		listener = gmBackendListener(conn = gmPG2.get_raw_connection())
		print("listening for the following notifications:")
		print("1) unspecific:")
		for sig in listener.unspecific_notifications:
			print('   - %s' % sig)

		while True:
			pat = gmPersonSearch.ask_for_patient()
			if pat is None:
				break
			print("found patient", pat)
			gmPerson.set_active_patient(patient=pat)
			print("now waiting for notifications, hit <ENTER> to select another patient")
			raw_input()

		print("cleanup")
		listener.shutdown()

		print("shutting down backend notifications monitor")
Exemplo n.º 3
0
 def _worker__export_doc_parts(self, docs=None, cookie=None):
     # this is used as the worker thread payload
     _log.debug('cookie [%s]', cookie)
     conn = gmPG2.get_raw_connection(
         readonly=True, connection_name=threading.current_thread().name)
     parts_list = []
     for soap_doc in docs:
         parts = soap_doc.parts
         if len(parts) == 0:
             continue
         parts_counter = ''
         if len(parts) > 1:
             parts_counter = _(' [part 1 of %s]') % len(parts)
         part = parts[0]
         fname = part.save_to_file(conn=conn)
         if fname is None:
             continue
         tt_header = _('Created: %s%s') % (gmDateTime.pydt_strftime(
             part['date_generated'], '%Y %b %d'), parts_counter)
         tt_footer = gmTools.coalesce(part['doc_comment'], '').strip()
         parts_list.append([fname, part, tt_header, tt_footer])
     conn.close()
     _log.debug('worker finished')
     return (cookie, parts_list)
Exemplo n.º 4
0
def connect_to_database(login_info=None,
                        max_attempts=3,
                        expected_version=None,
                        require_version=True):
    """Display the login dialog and try to log into the backend.

	- up to max_attempts times
	- returns True/False
	"""
    # force programmer to set a valid expected_version
    expected_hash = gmPG2.known_schema_hashes[expected_version]
    client_version = _cfg.get(option=u'client_version')
    global current_db_name
    current_db_name = u'gnumed_v%s' % expected_version

    attempt = 0

    while attempt < max_attempts:

        _log.debug('login attempt %s of %s', (attempt + 1), max_attempts)

        connected = False

        login = login_info
        if login is None:
            _log.info("did not provide a login information")

        # try getting a connection to verify the DSN works
        dsn = gmPG2.make_psycopg2_dsn(database=login.database,
                                      host=login.host,
                                      port=login.port,
                                      user=login.user,
                                      password=login.password)
        try:
            conn = gmPG2.get_raw_connection(dsn=dsn,
                                            verbose=True,
                                            readonly=True)
            connected = True

        except gmPG2.cAuthenticationError, e:
            attempt += 1
            _log.error(u"login attempt failed: %s", e)
            if attempt < max_attempts:
                if (u'host=127.0.0.1' in (u'%s' % e)) or (u'host='
                                                          not in (u'%s' % e)):
                    msg = _(
                        'Unable to connect to database:\n\n'
                        '%s\n\n'
                        "Are you sure you have got a local database installed ?\n"
                        '\n'
                        "Please retry with proper credentials or cancel.\n"
                        '\n'
                        'You may also need to check the PostgreSQL client\n'
                        'authentication configuration in pg_hba.conf. For\n'
                        'details see:\n'
                        '\n'
                        'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL')
                else:
                    msg = _(
                        "Unable to connect to database:\n\n"
                        "%s\n\n"
                        "Please retry with proper credentials or cancel.\n"
                        "\n"
                        'You may also need to check the PostgreSQL client\n'
                        'authentication configuration in pg_hba.conf. For\n'
                        'details see:\n'
                        '\n'
                        'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL')
                msg = msg % e
                msg = regex.sub(
                    r'password=[^\s]+',
                    u'password=%s' % gmTools.u_replacement_character, msg)
                gmGuiHelpersWeb.gm_show_error(msg, _('Connecting to backend'))
            del e
            continue

        except gmPG2.dbapi.OperationalError, e:
            _log.error(u"login attempt failed: %s", e)
            msg = _(
                "Unable to connect to database:\n\n"
                "%s\n\n"
                "Please retry another backend / user / password combination !\n"
            ) % gmPG2.extract_msg_from_pg_exception(e)
            msg = regex.sub(r'password=[^\s]+',
                            u'password=%s' % gmTools.u_replacement_character,
                            msg)
            gmGuiHelpersWeb.gm_show_error(msg, _('Connecting to backend'))
            del e
            continue
Exemplo n.º 5
0
def connect_to_database(max_attempts=3,
                        expected_version=None,
                        require_version=True):
    """Display the login dialog and try to log into the backend.

	- up to max_attempts times
	- returns True/False
	"""
    # force programmer to set a valid expected_version
    expected_hash = gmPG2.known_schema_hashes[expected_version]
    client_version = _cfg.get(option='client_version')
    global current_db_name
    current_db_name = 'gnumed_v%s' % expected_version

    attempt = 0

    dlg = cLoginDialog(None, -1, client_version=client_version)
    dlg.Centre(wx.BOTH)

    while attempt < max_attempts:

        _log.debug('login attempt %s of %s', (attempt + 1), max_attempts)

        connected = False

        dlg.ShowModal()
        login = dlg.panel.GetLoginInfo()
        if login is None:
            _log.info("user cancelled login dialog")
            break

        gmLog2.add_word2hide(login.password)

        # try getting a connection to verify the DSN works
        dsn = gmPG2.make_psycopg2_dsn(database=login.database,
                                      host=login.host,
                                      port=login.port,
                                      user=login.user,
                                      password=login.password)
        try:
            conn = gmPG2.get_raw_connection(dsn=dsn,
                                            verbose=True,
                                            readonly=True)
            connected = True

        except gmPG2.cAuthenticationError as e:
            attempt += 1
            _log.error("login attempt failed: %s", e)
            if attempt < max_attempts:
                if ('host=127.0.0.1' in ('%s' % e)) or ('host='
                                                        not in ('%s' % e)):
                    msg = _(
                        'Unable to connect to database:\n\n'
                        '%s\n\n'
                        "Are you sure you have got a local database installed ?\n"
                        '\n'
                        "Please retry with proper credentials or cancel.\n"
                        '\n'
                        ' (for the public and any new GNUmed data-\n'
                        '  bases the default user name and password\n'
                        '  are {any-doc, any-doc})\n'
                        '\n'
                        'You may also need to check the PostgreSQL client\n'
                        'authentication configuration in pg_hba.conf. For\n'
                        'details see:\n'
                        '\n'
                        'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL')
                else:
                    msg = _(
                        "Unable to connect to database:\n\n"
                        "%s\n\n"
                        "Please retry with proper credentials or cancel.\n"
                        "\n"
                        "For the public and any new GNUmed databases the\n"
                        "default user name and password are {any-doc, any-doc}.\n"
                        "\n"
                        'You may also need to check the PostgreSQL client\n'
                        'authentication configuration in pg_hba.conf. For\n'
                        'details see:\n'
                        '\n'
                        'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL')
                msg = msg % e
                msg = regex.sub(
                    r'password=[^\s]+',
                    'password=%s' % gmTools.u_replacement_character, msg)
                gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
            del e
            continue

        except gmPG2.dbapi.OperationalError as exc:
            _log.exception('login attempt failed')
            gmPG2.log_pg_exception_details(exc)
            msg = _(
                "Unable to connect to database:\n\n"
                "%s\n\n"
                "Please retry another backend / user / password combination !\n"
                "\n"
                " (for the public and any new GNUmed databases\n"
                "  the default user name and password are\n"
                "  {any-doc, any-doc})\n"
                "\n") % exc
            msg = regex.sub(r'password=[^\s]+',
                            'password=%s' % gmTools.u_replacement_character,
                            msg)
            gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
            del exc
            continue

        conn.close()

        # connect was successful
        gmPG2.set_default_login(login=login)
        gmPG2.set_default_client_encoding(
            encoding=dlg.panel.backend_profile.encoding)

        seems_bootstrapped = gmPG2.schema_exists(schema='gm')
        if not seems_bootstrapped:
            _log.error(
                'schema [gm] does not exist - database not bootstrapped ?')
            msg = _('The database you connected to does not seem\n'
                    'to have been boostrapped properly.\n'
                    '\n'
                    'Make sure you have run the GNUmed database\n'
                    'bootstrapper tool to create a new database.\n'
                    '\n'
                    'Further help can be found on the website at\n'
                    '\n'
                    '  http://wiki.gnumed.de\n'
                    '\n'
                    'or on the GNUmed mailing list.')
            gmGuiHelpers.gm_show_error(msg, _('Verifying database'))
            connected = False
            break

        compatible = gmPG2.database_schema_compatible(version=expected_version)
        if compatible or not require_version:
            dlg.panel.save_state()

        if not compatible:
            connected_db_version = gmPG2.get_schema_version()
            msg = msg_generic % (client_version, connected_db_version,
                                 expected_version,
                                 gmTools.coalesce(login.host, '<localhost>'),
                                 login.database, login.user)
            if require_version:
                gmGuiHelpers.gm_show_error(msg + msg_fail,
                                           _('Verifying database version'))
                connected = False
                continue
            gmGuiHelpers.gm_show_info(msg + msg_override,
                                      _('Verifying database version'))

        # FIXME: make configurable
        max_skew = 1  # minutes
        if _cfg.get(option='debug'):
            max_skew = 10
        if not gmPG2.sanity_check_time_skew(tolerance=(max_skew * 60)):
            if _cfg.get(option='debug'):
                gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew,
                                             _('Verifying database settings'))
            else:
                gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew,
                                           _('Verifying database settings'))
                connected = False
                continue

        sanity_level, message = gmPG2.sanity_check_database_settings()
        if sanity_level != 0:
            gmGuiHelpers.gm_show_error((msg_insanity % message),
                                       _('Verifying database settings'))
            if sanity_level == 2:
                connected = False
                continue

        gmExceptionHandlingWidgets.set_is_public_database(login.public_db)
        gmExceptionHandlingWidgets.set_helpdesk(login.helpdesk)

        conn = gmPG2.get_connection(
            verbose=True,
            connection_name='GNUmed-[DbListenerThread]',
            pooled=False)
        listener = gmBackendListener.gmBackendListener(conn=conn)
        break

    dlg.DestroyLater()

    return connected
Exemplo n.º 6
0
    def run_test():

        #-------------------------------
        def dummy(n):
            return float(n) * n / float(1 + n)

        #-------------------------------
        def OnPatientModified():
            global notifies
            notifies += 1
            sys.stdout.flush()
            print(
                "\nBackend says: patient data has been modified (%s. notification)"
                % notifies)

        #-------------------------------
        try:
            n = int(sys.argv[2])
        except Exception:
            print(
                "You can set the number of iterations\nwith the second command line argument"
            )
            n = 100000

        # try loop without backend listener
        print("Looping", n, "times through dummy function")
        i = 0
        t1 = time.time()
        while i < n:
            dummy(i)
            i += 1
        t2 = time.time()
        t_nothreads = t2 - t1
        print("Without backend thread, it took", t_nothreads, "seconds")

        listener = gmBackendListener(conn=gmPG2.get_raw_connection())

        # now try with listener to measure impact
        print("Now in a new shell connect psql to the")
        print("database <gnumed_v9> on localhost, return")
        print("here and hit <enter> to continue.")
        input('hit <enter> when done starting psql')
        print("You now have about 30 seconds to go")
        print("to the psql shell and type")
        print(" notify patient_changed<enter>")
        print("several times.")
        print("This should trigger our backend listening callback.")
        print("You can also try to stop the demo with Ctrl-C !")

        listener.register_callback('patient_changed', OnPatientModified)

        try:
            counter = 0
            while counter < 20:
                counter += 1
                time.sleep(1)
                sys.stdout.flush()
                print('.')
            print("Looping", n, "times through dummy function")
            i = 0
            t1 = time.time()
            while i < n:
                dummy(i)
                i += 1
            t2 = time.time()
            t_threaded = t2 - t1
            print("With backend thread, it took", t_threaded, "seconds")
            print("Difference:", t_threaded - t_nothreads)
        except KeyboardInterrupt:
            print("cancelled by user")

        listener.shutdown()
Exemplo n.º 7
0
	def run_test():

		#-------------------------------
		def dummy(n):
			return float(n)*n/float(1+n)
		#-------------------------------
		def OnPatientModified():
			global notifies
			notifies += 1
			sys.stdout.flush()
			print("\nBackend says: patient data has been modified (%s. notification)" % notifies)
		#-------------------------------
		try:
			n = int(sys.argv[2])
		except:
			print("You can set the number of iterations\nwith the second command line argument")
			n = 100000

		# try loop without backend listener
		print("Looping", n, "times through dummy function")
		i = 0
		t1 = time.time()
		while i < n:
			r = dummy(i)
			i += 1
		t2 = time.time()
		t_nothreads = t2-t1
		print("Without backend thread, it took", t_nothreads, "seconds")

		listener = gmBackendListener(conn = gmPG2.get_raw_connection())

		# now try with listener to measure impact
		print("Now in a new shell connect psql to the")
		print("database <gnumed_v9> on localhost, return")
		print("here and hit <enter> to continue.")
		raw_input('hit <enter> when done starting psql')
		print("You now have about 30 seconds to go")
		print("to the psql shell and type")
		print(" notify patient_changed<enter>")
		print("several times.")
		print("This should trigger our backend listening callback.")
		print("You can also try to stop the demo with Ctrl-C !")

		listener.register_callback('patient_changed', OnPatientModified)

		try:
			counter = 0
			while counter < 20:
				counter += 1
				time.sleep(1)
				sys.stdout.flush()
				print('.', end=' ')
			print("Looping",n,"times through dummy function")
			i = 0
			t1 = time.time()
			while i < n:
				r = dummy(i)
				i += 1
			t2 = time.time()
			t_threaded = t2-t1
			print("With backend thread, it took", t_threaded, "seconds")
			print("Difference:", t_threaded-t_nothreads)
		except KeyboardInterrupt:
			print("cancelled by user")

		listener.shutdown()
		listener.unregister_callback('patient_changed', OnPatientModified)
Exemplo n.º 8
0
def connect_to_database(max_attempts=3, expected_version=None, require_version=True):
    """Display the login dialog and try to log into the backend.

	- up to max_attempts times
	- returns True/False
	"""
    # force programmer to set a valid expected_version
    expected_hash = gmPG2.known_schema_hashes[expected_version]
    client_version = _cfg.get(option=u"client_version")
    global current_db_name
    current_db_name = u"gnumed_v%s" % expected_version

    attempt = 0

    dlg = cLoginDialog(None, -1, client_version=client_version)
    dlg.Centre(wx.BOTH)

    while attempt < max_attempts:

        _log.debug("login attempt %s of %s", (attempt + 1), max_attempts)

        connected = False

        dlg.ShowModal()
        login = dlg.panel.GetLoginInfo()
        if login is None:
            _log.info("user cancelled login dialog")
            break

            # try getting a connection to verify the DSN works
        dsn = gmPG2.make_psycopg2_dsn(
            database=login.database, host=login.host, port=login.port, user=login.user, password=login.password
        )
        try:
            conn = gmPG2.get_raw_connection(dsn=dsn, verbose=True, readonly=True)
            connected = True

        except gmPG2.cAuthenticationError, e:
            attempt += 1
            _log.error(u"login attempt failed: %s", e)
            if attempt < max_attempts:
                if (u"host=127.0.0.1" in (u"%s" % e)) or (u"host=" not in (u"%s" % e)):
                    msg = _(
                        "Unable to connect to database:\n\n"
                        "%s\n\n"
                        "Are you sure you have got a local database installed ?\n"
                        "\n"
                        "Please retry with proper credentials or cancel.\n"
                        "\n"
                        " (for the public and any new GNUmed data-\n"
                        "  bases the default user name and password\n"
                        "  are {any-doc, any-doc})\n"
                        "\n"
                        "You may also need to check the PostgreSQL client\n"
                        "authentication configuration in pg_hba.conf. For\n"
                        "details see:\n"
                        "\n"
                        "wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL"
                    )
                else:
                    msg = _(
                        "Unable to connect to database:\n\n"
                        "%s\n\n"
                        "Please retry with proper credentials or cancel.\n"
                        "\n"
                        "For the public and any new GNUmed databases the\n"
                        "default user name and password are {any-doc, any-doc}.\n"
                        "\n"
                        "You may also need to check the PostgreSQL client\n"
                        "authentication configuration in pg_hba.conf. For\n"
                        "details see:\n"
                        "\n"
                        "wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL"
                    )
                msg = msg % e
                msg = regex.sub(r"password=[^\s]+", u"password=%s" % gmTools.u_replacement_character, msg)
                gmGuiHelpers.gm_show_error(msg, _("Connecting to backend"))
            del e
            continue

        except gmPG2.dbapi.OperationalError, exc:
            exc = gmPG2.make_pg_exception_fields_unicode(exc)
            _log.error(u"login attempt failed: %s", exc)
            msg = (
                _(
                    "Unable to connect to database:\n\n"
                    "%s\n\n"
                    "Please retry another backend / user / password combination !\n"
                    "\n"
                    " (for the public and any new GNUmed databases\n"
                    "  the default user name and password are\n"
                    "  {any-doc, any-doc})\n"
                    "\n"
                )
                % exc.u_pgerror
            )
            # 			) % gmPG2.extract_msg_from_pg_exception(e)
            msg = regex.sub(r"password=[^\s]+", u"password=%s" % gmTools.u_replacement_character, msg)
            gmGuiHelpers.gm_show_error(msg, _("Connecting to backend"))
            del exc
            continue
Exemplo n.º 9
0
def connect_to_database(login_info=None, max_attempts=3, expected_version=None, require_version=True):
    """Display the login dialog and try to log into the backend.

    - up to max_attempts times
    - returns True/False
    """
    from Gnumed.pycommon import gmPG2
    # force programmer to set a valid expected_version
    expected_hash = gmPG2.known_schema_hashes[expected_version]
    client_version = _cfg.get(option = u'client_version')
    global current_db_name
    current_db_name = u'gnumed_v%s' % expected_version

    attempt = 0

    while attempt < max_attempts:

        _log.debug('login attempt %s of %s', (attempt+1), max_attempts)

        connected = False

        login = login_info
        if login is None:
            _log.info("did not provide a login information")

        # try getting a connection to verify the DSN works
        dsn = gmPG2.make_psycopg2_dsn (
            database = login.database,
            host = login.host,
            port = login.port,
            user = login.user,
            password = login.password
        )
        try:
            #conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True)
            conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True)
            connected = True

        except gmPG2.cAuthenticationError, e:
            attempt += 1
            _log.error(u"login attempt failed: %s", e)
            if attempt < max_attempts:
                if (u'host=127.0.0.1' in (u'%s' % e)) or (u'host=' not in (u'%s' % e)):
                    msg = _(
                        'Unable to connect to database:\n\n'
                        '%s\n\n'
                        "Are you sure you have got a local database installed ?\n"
                        '\n'
                        "Please retry with proper credentials or cancel.\n"
                        '\n'
                        'You may also need to check the PostgreSQL client\n'
                        'authentication configuration in pg_hba.conf. For\n'
                        'details see:\n'
                        '\n'
                        'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
                    )
                else:
                    msg = _(
                        "Unable to connect to database:\n\n"
                        "%s\n\n"
                        "Please retry with proper credentials or cancel.\n"
                        "\n"
                        'You may also need to check the PostgreSQL client\n'
                        'authentication configuration in pg_hba.conf. For\n'
                        'details see:\n'
                        '\n'
                        'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
                    )
                msg = msg % e
                msg = re.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
                gmGuiHelpers.gm_show_error (
                    msg,
                    _('Connecting to backend')
                )
            del e
            continue

        except gmPG2.dbapi.OperationalError, e:
            _log.error(u"login attempt failed: %s", e)
            msg = _(
                "Unable to connect to database:\n\n"
                "%s\n\n"
                "Please retry another backend / user / password combination !\n"
            ) % gmPG2.extract_msg_from_pg_exception(e)
            msg = re.sub(r'password=[^\s]+', u'password=%s' % gmTools.u_replacement_character, msg)
            gmGuiHelpers.gm_show_error (
                msg,
                _('Connecting to backend')
            )
            del e
            continue
Exemplo n.º 10
0
def connect_to_database(max_attempts=3, expected_version=None, require_version=True):
	"""Display the login dialog and try to log into the backend.

	- up to max_attempts times
	- returns True/False
	"""
	# force programmer to set a valid expected_version
	expected_hash = gmPG2.known_schema_hashes[expected_version]
	client_version = _cfg.get(option = 'client_version')
	global current_db_name
	current_db_name = 'gnumed_v%s' % expected_version

	attempt = 0

	dlg = cLoginDialog(None, -1, client_version = client_version)
	dlg.Centre(wx.BOTH)

	while attempt < max_attempts:

		_log.debug('login attempt %s of %s', (attempt+1), max_attempts)

		connected = False

		dlg.ShowModal()
		login = dlg.panel.GetLoginInfo()
		if login is None:
			_log.info("user cancelled login dialog")
			break

		gmLog2.add_word2hide(login.password)

		# try getting a connection to verify the DSN works
		dsn = gmPG2.make_psycopg2_dsn (
			database = login.database,
			host = login.host,
			port = login.port,
			user = login.user,
			password = login.password
		)
		try:
			conn = gmPG2.get_raw_connection(dsn = dsn, verbose = True, readonly = True)
			connected = True

		except gmPG2.cAuthenticationError as e:
			attempt += 1
			_log.error("login attempt failed: %s", e)
			if attempt < max_attempts:
				if ('host=127.0.0.1' in ('%s' % e)) or ('host=' not in ('%s' % e)):
					msg = _(
						'Unable to connect to database:\n\n'
						'%s\n\n'
						"Are you sure you have got a local database installed ?\n"
						'\n'
						"Please retry with proper credentials or cancel.\n"
						'\n'
						' (for the public and any new GNUmed data-\n'
						'  bases the default user name and password\n'
						'  are {any-doc, any-doc})\n'
						'\n'
						'You may also need to check the PostgreSQL client\n'
						'authentication configuration in pg_hba.conf. For\n'
						'details see:\n'
						'\n'
						'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
					)
				else:
					msg = _(
						"Unable to connect to database:\n\n"
						"%s\n\n"
						"Please retry with proper credentials or cancel.\n"
						"\n"
						"For the public and any new GNUmed databases the\n"
						"default user name and password are {any-doc, any-doc}.\n"
						"\n"
						'You may also need to check the PostgreSQL client\n'
						'authentication configuration in pg_hba.conf. For\n'
						'details see:\n'
						'\n'
						'wiki.gnumed.de/bin/view/Gnumed/ConfigurePostgreSQL'
					)
				msg = msg % e
				msg = regex.sub(r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg)
				gmGuiHelpers.gm_show_error (
					msg,
					_('Connecting to backend')
				)
			del e
			continue

		except gmPG2.dbapi.OperationalError as exc:
			_log.exception('login attempt failed')
			gmPG2.log_pg_exception_details(exc)
			msg = _(
				"Unable to connect to database:\n\n"
				"%s\n\n"
				"Please retry another backend / user / password combination !\n"
				"\n"
				" (for the public and any new GNUmed databases\n"
				"  the default user name and password are\n"
				"  {any-doc, any-doc})\n"
				"\n"
			) % exc
			msg = regex.sub(r'password=[^\s]+', 'password=%s' % gmTools.u_replacement_character, msg)
			gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
			del exc
			continue

		conn.close()

		# connect was successful
		gmPG2.set_default_login(login = login)
		gmPG2.set_default_client_encoding(encoding = dlg.panel.backend_profile.encoding)

		seems_bootstrapped = gmPG2.schema_exists(schema = 'gm')
		if not seems_bootstrapped:
			_log.error('schema [gm] does not exist - database not bootstrapped ?')
			msg = _(
				'The database you connected to does not seem\n'
				'to have been boostrapped properly.\n'
				'\n'
				'Make sure you have run the GNUmed database\n'
				'bootstrapper tool to create a new database.\n'
				'\n'
				'Further help can be found on the website at\n'
				'\n'
				'  http://wiki.gnumed.de\n'
				'\n'
				'or on the GNUmed mailing list.'
			)
			gmGuiHelpers.gm_show_error(msg, _('Verifying database'))
			connected = False
			break

		compatible = gmPG2.database_schema_compatible(version = expected_version)
		if compatible or not require_version:
			dlg.panel.save_state()

		if not compatible:
			connected_db_version = gmPG2.get_schema_version()
			msg = msg_generic % (
				client_version,
				connected_db_version,
				expected_version,
				gmTools.coalesce(login.host, '<localhost>'),
				login.database,
				login.user
			)
			if require_version:
				gmGuiHelpers.gm_show_error(msg + msg_fail, _('Verifying database version'))
				connected = False
				continue
			gmGuiHelpers.gm_show_info(msg + msg_override, _('Verifying database version'))

		# FIXME: make configurable
		max_skew = 1		# minutes
		if _cfg.get(option = 'debug'):
			max_skew = 10
		if not gmPG2.sanity_check_time_skew(tolerance = (max_skew * 60)):
			if _cfg.get(option = 'debug'):
				gmGuiHelpers.gm_show_warning(msg_time_skew_warn % max_skew, _('Verifying database settings'))
			else:
				gmGuiHelpers.gm_show_error(msg_time_skew_fail % max_skew, _('Verifying database settings'))
				connected = False
				continue

		sanity_level, message = gmPG2.sanity_check_database_settings()
		if sanity_level != 0:
			gmGuiHelpers.gm_show_error((msg_insanity % message), _('Verifying database settings'))
			if sanity_level == 2:
				connected = False
				continue

		gmExceptionHandlingWidgets.set_is_public_database(login.public_db)
		gmExceptionHandlingWidgets.set_helpdesk(login.helpdesk)

		conn = gmPG2.get_connection(verbose = True, connection_name = 'GNUmed-[DbListenerThread]', pooled = False)
		listener = gmBackendListener.gmBackendListener(conn = conn)
		break

	dlg.DestroyLater()

	return connected
Exemplo n.º 11
0
def connect_to_database(max_attempts=3,
                        expected_version=None,
                        require_version=True):
    """Display the login dialog and try to log into the backend.

	- up to max_attempts times
	- returns True/False
	"""
    # force programmer to set a valid expected_version
    gmPG2.known_schema_hashes[expected_version]
    client_version = _cfg.get(option='client_version')
    global current_db_name
    current_db_name = 'gnumed_v%s' % expected_version
    attempt = 0
    dlg = cLoginDialog(None, -1, client_version=client_version)
    dlg.Centre(wx.BOTH)

    while attempt < max_attempts:
        _log.debug('login attempt %s of %s', (attempt + 1), max_attempts)
        connected = False
        dlg.ShowModal()
        login = dlg.panel.GetLoginInfo()
        if login is None:
            _log.info("user cancelled login dialog")
            break

        # obscure unconditionally, it could be a valid password
        gmLog2.add_word2hide(login.password)
        # try getting a connection to verify the parameters do work
        creds = gmConnectionPool.cPGCredentials()
        creds.database = login.database
        creds.host = login.host
        creds.port = login.port
        creds.user = login.user
        creds.password = login.password
        pool = gmConnectionPool.gmConnectionPool()
        pool.credentials = creds
        try:
            conn = gmPG2.get_raw_connection(verbose=True, readonly=True)
            _log.info('successfully connected: %s', conn)
            connected = True

        except gmPG2.cAuthenticationError as exc:
            _log.exception('login attempt failed')
            gmPG2.log_pg_exception_details(exc)
            attempt += 1
            if attempt < max_attempts:
                if ('host=127.0.0.1' in ('%s' % exc)) or ('host='
                                                          not in ('%s' % exc)):
                    msg = msg_auth_error_local
                else:
                    msg = msg_auth_error
                msg = msg % exc
                msg = regex.sub(
                    r'password=[^\s]+',
                    'password=%s' % gmTools.u_replacement_character, msg)
                gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
            del exc
            continue

        except gmPG2.dbapi.OperationalError as exc:
            _log.exception('login attempt failed')
            gmPG2.log_pg_exception_details(exc)
            msg = msg_login_problem_generic % exc
            msg = regex.sub(r'password=[^\s]+',
                            'password=%s' % gmTools.u_replacement_character,
                            msg)
            gmGuiHelpers.gm_show_error(msg, _('Connecting to backend'))
            del exc
            continue

        conn.close()

        if not __database_is_acceptable_for_use(
                require_version=require_version,
                expected_version=expected_version,
                login=login):
            _log.info('database not suitable for use')
            connected = False
            break

        dlg.panel.save_state()
        gmExceptionHandlingWidgets.set_is_public_database(
            _cfg.get(option='is_public_db'))
        gmExceptionHandlingWidgets.set_helpdesk(_cfg.get(option='helpdesk'))
        _log.debug('establishing DB listener connection')
        conn = gmPG2.get_connection(
            verbose=True,
            connection_name='GNUmed-[DbListenerThread]',
            pooled=False)
        gmBackendListener.gmBackendListener(conn=conn)
        break

    dlg.DestroyLater()
    return connected