[GIS] How to access user credentials in database connection

pyqgispythonqgis

I am trying to automate a couple of things when a QGIS plugin is activated:

  1. If Layer A is not in the TOC, add it. This requests username and password to access a PostGIS table using the inbuilt credentials dialog.
  2. If Layer A now exists in the TOC, access the same PostGIS table to run a query using the same user credentials.

Apparently as I'm not storing the password, I can't access it to use in connecting to the database (using psycopg). Is there any way around this? I want to avoid having the user type credentials twice, and also I want to avoid storing the credentials permanently. I have tried to reimplement the QgsCredentialDialog class but that adds so much complexity (e.g. when a connection error is thrown).

What other ways can I add a layer using a non-stored username and password, and access the credentials later to query the same database? The easiest option I can think of is to access the inbuilt credentials dialog request, but I'm not sure how to do that.

EDIT

My implementation of this was to create a function which I call at the point my layer has been added. It then sets my plugin class attributes username and password correctly which I can use in my db query.

def get_credentials(self, lyr):
    connInfo = QgsDataSourceURI(lyr.dataProvider().dataSourceUri()).connectionInfo()
    success, username, password = QgsCredentials.instance().get(connInfo, None, None)
    if success:
        # QgsCredentials.instance().put(connInfo, username, password)
        self.username = username
        self.password = password

Best Answer

QGIS caches the connection credentials inside QgsCredentials based on the connection info. So for a layer lyr do:

connInfo = QgsDataSourceURI( lyr.dataProvider().dataSourceUri() ).connectionInfo()
(success, user, passwd ) = QgsCredentials.instance().get( connInfo, None, None )
# Put the credentials back (for yourself and the provider), as QGIS removes it when you "get" it
if success:
    QgsCredentials.instance().put( connInfo, user, passwd )
Related Question