Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] SQL: save user name and password via credentials manager #2403

Merged
merged 3 commits into from
Jul 10, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 50 additions & 9 deletions Orange/widgets/data/owsql.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from Orange.data.sql.backend.base import BackendError
from Orange.data.sql.table import SqlTable, LARGE_TABLE, AUTO_DL_LIMIT
from Orange.widgets import gui
from Orange.widgets.credentials import CredentialManager
from Orange.widgets.settings import Setting
from Orange.widgets.utils.itemmodels import PyListModel
from Orange.widgets.widget import OWWidget, Output, Msg
Expand Down Expand Up @@ -47,15 +48,17 @@ class OWSql(OWWidget):
class Outputs:
data = Output("Data", Table, doc="Attribute-valued data set read from the input file.")

settings_version = 2

want_main_area = False
resizing_enabled = False

host = Setting(None)
port = Setting(None)
database = Setting(None)
schema = Setting(None)
username = Setting(None)
password = Setting(None)
username = ""
password = ""
table = Setting(None)
sql = Setting("")
guess_values = Setting(True)
Expand Down Expand Up @@ -94,10 +97,12 @@ def __init__(self):
self.servertext = QLineEdit(box)
self.servertext.setPlaceholderText('Server')
self.servertext.setToolTip('Server')
self.servertext.editingFinished.connect(self._load_credentials)
if self.host:
self.servertext.setText(self.host if not self.port else
'{}:{}'.format(self.host, self.port))
box.layout().addWidget(self.servertext)

self.databasetext = QLineEdit(box)
self.databasetext.setPlaceholderText('Database[/Schema]')
self.databasetext.setToolTip('Database or optionally Database/Schema')
Expand All @@ -109,17 +114,17 @@ def __init__(self):
self.usernametext = QLineEdit(box)
self.usernametext.setPlaceholderText('Username')
self.usernametext.setToolTip('Username')
if self.username:
self.usernametext.setText(self.username)

box.layout().addWidget(self.usernametext)
self.passwordtext = QLineEdit(box)
self.passwordtext.setPlaceholderText('Password')
self.passwordtext.setToolTip('Password')
self.passwordtext.setEchoMode(QLineEdit.Password)
if self.password:
self.passwordtext.setText(self.password)

box.layout().addWidget(self.passwordtext)

self._load_credentials()

tables = gui.hBox(box)
self.tablemodel = TableModel()
self.tablecombo = QComboBox(
Expand Down Expand Up @@ -164,6 +169,25 @@ def __init__(self):
gui.rubber(self.buttonsArea)
QTimer.singleShot(0, self.connect)

def _load_credentials(self):
self._parse_host_port()
cm = self._credential_manager(self.host, self.port)
self.username = cm.username
self.password = cm.password

if self.username:
self.usernametext.setText(self.username)
if self.password:
self.passwordtext.setText(self.password)

def _save_credentials(self):
cm = self._credential_manager(self.host, self.port)
cm.username = self.username
cm.password = self.password

def _credential_manager(self, host, port):
return CredentialManager("SQL Table: {}:{}".format(host, port))

def error(self, id=0, text=""):
super().error(id, text)
err_style = 'QLineEdit {border: 2px solid red;}'
Expand All @@ -180,10 +204,13 @@ def error(self, id=0, text=""):
else:
self.databasetext.setStyleSheet('')

def connect(self):
def _parse_host_port(self):
hostport = self.servertext.text().split(':')
self.host = hostport[0]
self.port = hostport[1] if len(hostport) == 2 else None

def connect(self):
self._parse_host_port()
self.database, _, self.schema = self.databasetext.text().partition('/')
self.username = self.usernametext.text() or None
self.password = self.passwordtext.text() or None
Expand All @@ -199,6 +226,7 @@ def connect(self):
password=self.password
))
self.Error.connection.clear()
self._save_credentials()
self.database_desc = OrderedDict((
("Host", self.host), ("Port", self.port),
("Database", self.database), ("User name", self.username)
Expand Down Expand Up @@ -264,9 +292,12 @@ def get_table(self):
"Specify a table name to materialize the query")
return
try:
with self.backend.execute_sql_query("DROP TABLE IF EXISTS " + self.materialize_table_name):
with self.backend.execute_sql_query("DROP TABLE IF EXISTS " +
self.materialize_table_name):
pass
with self.backend.execute_sql_query("CREATE TABLE " + self.materialize_table_name + " AS " + self.table):
with self.backend.execute_sql_query("CREATE TABLE " +
self.materialize_table_name +
" AS " + self.table):
pass
with self.backend.execute_sql_query("ANALYZE " + self.materialize_table_name):
pass
Expand Down Expand Up @@ -349,6 +380,16 @@ def send_report(self):
self.report_items("Data",
report.describe_data(self.data_desc_table))

@classmethod
def migrate_settings(cls, settings, version):
if version < 2:
# Until Orange version 3.4.4 username and password had been stored
# in Settings.
cm = cls._credential_manager(settings["host"], settings["port"])
cm.username = settings["username"]
cm.password = settings["password"]


if __name__ == "__main__":
a = QApplication(sys.argv)
ow = OWSql()
Expand Down