From f345a40bff06b2aedd5b0ba74d0690267143fbd2 Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 13 Nov 2018 16:36:58 +0100 Subject: [PATCH] Able to log in and run server --- pype/ftrack/Login/login_dialog_ui.py | 304 --------------------------- pype/ftrack/__init__.py | 1 + pype/ftrack/credentials.py | 6 +- pype/ftrack/login_dialog.py | 229 ++++++++++++++++++-- pype/ftrack/login_dialog_noui.py | 120 +++++++++++ 5 files changed, 334 insertions(+), 326 deletions(-) delete mode 100644 pype/ftrack/Login/login_dialog_ui.py create mode 100644 pype/ftrack/login_dialog_noui.py diff --git a/pype/ftrack/Login/login_dialog_ui.py b/pype/ftrack/Login/login_dialog_ui.py deleted file mode 100644 index 00d0c5ae5f..0000000000 --- a/pype/ftrack/Login/login_dialog_ui.py +++ /dev/null @@ -1,304 +0,0 @@ -import sys -import requests -import PyQt5 -from Qt.PyQt5 import QtCore, QtGui, QtWidgets -from app import style -from . import credentials, login_tools - - -class Login_Dialog_ui(QtWidgets.QWidget): - - SIZE_W = 300 - SIZE_H = 230 - - loginSignal = QtCore.pyqtSignal(object, object, object) - _login_server_thread = None - inputs = [] - buttons = [] - labels = [] - - def __init__(self): - - super().__init__() - self.loginSignal.connect(self.loginWithCredentials) - self._translate = QtCore.QCoreApplication.translate - - self.font = QtGui.QFont() - self.font.setFamily("DejaVu Sans Condensed") - self.font.setPointSize(9) - self.font.setBold(True) - self.font.setWeight(50) - self.font.setKerning(True) - - self.resize(self.SIZE_W, self.SIZE_H) - self.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H)) - self.setStyleSheet(style.load_stylesheet()) - - self.setLayout(self._main()) - self.setWindowTitle('FTrack Login') - - self.show() - - def _main(self): - self.main = QtWidgets.QVBoxLayout() - self.main.setObjectName("main") - - self.form = QtWidgets.QFormLayout() - self.form.setContentsMargins(10, 15, 10, 5) - self.form.setObjectName("form") - - self.ftsite_label = QtWidgets.QLabel("FTrack URL:") - self.ftsite_label.setFont(self.font) - self.ftsite_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.ftsite_label.setTextFormat(QtCore.Qt.RichText) - self.ftsite_label.setObjectName("user_label") - - self.ftsite_input = QtWidgets.QLineEdit() - self.ftsite_input.setEnabled(True) - self.ftsite_input.setFrame(True) - self.ftsite_input.setEnabled(False) - self.ftsite_input.setReadOnly(True) - self.ftsite_input.setObjectName("ftsite_input") - - self.user_label = QtWidgets.QLabel("Username:") - self.user_label.setFont(self.font) - self.user_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.user_label.setTextFormat(QtCore.Qt.RichText) - self.user_label.setObjectName("user_label") - - self.user_input = QtWidgets.QLineEdit() - self.user_input.setEnabled(True) - self.user_input.setFrame(True) - self.user_input.setObjectName("user_input") - self.user_input.setPlaceholderText(self._translate("main","user.name")) - self.user_input.textChanged.connect(self._user_changed) - - self.api_label = QtWidgets.QLabel("API Key:") - self.api_label.setFont(self.font) - self.api_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.api_label.setTextFormat(QtCore.Qt.RichText) - self.api_label.setObjectName("api_label") - - self.api_input = QtWidgets.QLineEdit() - self.api_input.setEnabled(True) - self.api_input.setFrame(True) - self.api_input.setObjectName("api_input") - self.api_input.setPlaceholderText(self._translate("main","e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")) - self.api_input.textChanged.connect(self._api_changed) - - self.error_label = QtWidgets.QLabel("") - self.error_label.setFont(self.font) - self.error_label.setTextFormat(QtCore.Qt.RichText) - self.error_label.setObjectName("error_label") - self.error_label.setWordWrap(True); - self.error_label.hide() - - self.form.addRow(self.ftsite_label, self.ftsite_input) - self.form.addRow(self.user_label, self.user_input) - self.form.addRow(self.api_label,self.api_input) - self.form.addRow(self.error_label) - - self.btnGroup = QtWidgets.QHBoxLayout() - self.btnGroup.addStretch(1) - self.btnGroup.setObjectName("btnGroup") - - self.btnEnter = QtWidgets.QPushButton("Login") - self.btnEnter.setToolTip('Set Username and API Key with entered values') - self.btnEnter.clicked.connect(self.enter_credentials) - - self.btnClose = QtWidgets.QPushButton("Close") - self.btnClose.setToolTip('Close this window') - self.btnClose.clicked.connect(self._close_widget) - - self.btnFtrack = QtWidgets.QPushButton("Ftrack") - self.btnFtrack.setToolTip('Open browser for Login to Ftrack') - self.btnFtrack.clicked.connect(self.open_ftrack) - - self.btnGroup.addWidget(self.btnFtrack) - self.btnGroup.addWidget(self.btnEnter) - self.btnGroup.addWidget(self.btnClose) - - self.main.addLayout(self.form) - self.main.addLayout(self.btnGroup) - - self.inputs.append(self.api_input) - self.inputs.append(self.user_input) - self.inputs.append(self.ftsite_input) - - self.enter_site() - return self.main - - def enter_site(self): - try: - # # TESTING - # url = ".ftrackapp.com" - url = os.getenv('FTRACK_SERVER') - newurl = self.checkUrl(url) - - if newurl is None: - self.btnEnter.setEnabled(False) - self.btnFtrack.setEnabled(False) - for input in self.inputs: - input.setEnabled(False) - newurl = url - - self.ftsite_input.setText(newurl) - - except: - self.setError("FTRACK_SERVER is not set in templates") - self.btnEnter.setEnabled(False) - self.btnFtrack.setEnabled(False) - for input in self.inputs: - input.setEnabled(False) - - def setError(self, msg): - self.error_label.setText(msg) - self.error_label.show() - - def _user_changed(self): - self.user_input.setStyleSheet("") - - def _api_changed(self): - self.api_input.setStyleSheet("") - - def _invalid_input(self,entity): - entity.setStyleSheet("border: 1px solid red;") - - def enter_credentials(self): - user = self.user_input.text().strip() - api = self.api_input.text().strip() - msg = "You didn't enter " - missing = [] - if user == "": - missing.append("Username") - self._invalid_input(self.user_input) - - if api == "": - missing.append("API Key") - self._invalid_input(self.api_input) - - if len(missing) > 0: - self.setError("{0} {1}".format(msg, " and ".join(missing))) - return - - verification = credentials._check_credentials(user, api) - - if verification: - credentials._save_credentials(username, apiKey) - credentials._set_env(username, apiKey) - self._close_widget() - else: - self._invalid_input(self.user_input) - self._invalid_input(self.api_input) - self.setError("We're unable to connect to Ftrack with these credentials") - - def open_ftrack(self): - url = self.ftsite_input.text() - self.loginWithCredentials(url,None,None) - - def checkUrl(self, url): - url = url.strip('/ ') - - if not url: - self.setError() - return - - if not 'http' in url: - if url.endswith('ftrackapp.com'): - url = 'https://' + url - else: - url = 'https://{0}.ftrackapp.com'.format(url) - try: - result = requests.get( - url, - allow_redirects=False # Old python API will not work with redirect. - ) - except requests.exceptions.RequestException: - self.setError( - 'The server URL set in Templates could not be reached.' - ) - return - - - if ( - result.status_code != 200 or 'FTRACK_VERSION' not in result.headers - ): - self.setError( - 'The server URL set in Templates is not a valid ftrack server.' - ) - return - return url - - def loginWithCredentials(self, url, username, apiKey): - url = url.strip('/ ') - - if not url: - self.setError( - 'You need to specify a valid server URL, ' - 'for example https://server-name.ftrackapp.com' - ) - return - - if not 'http' in url: - if url.endswith('ftrackapp.com'): - url = 'https://' + url - else: - url = 'https://{0}.ftrackapp.com'.format(url) - try: - result = requests.get( - url, - allow_redirects=False # Old python API will not work with redirect. - ) - except requests.exceptions.RequestException: - self.setError( - 'The server URL you provided could not be reached.' - ) - return - - - if ( - result.status_code != 200 or 'FTRACK_VERSION' not in result.headers - ): - self.setError( - 'The server URL you provided is not a valid ftrack server.' - ) - return - - # If there is an existing server thread running we need to stop it. - if self._login_server_thread: - self._login_server_thread.quit() - self._login_server_thread = None - - # If credentials are not properly set, try to get them using a http - # server. - if not username or not apiKey: - self._login_server_thread = login_tools.LoginServerThread() - self._login_server_thread.loginSignal.connect(self.loginSignal) - self._login_server_thread.start(url) - return - - verification = credentials._check_credentials(user, api) - - if verification is True: - credentials._save_credentials(username, apiKey) - credentials._set_env(username, apiKey) - self._close_widget() - - - def _close_widget(self): - sys.exit(app.exec_()) - - -class Login_Dialog(Login_Dialog_ui): - def __init__(self): - super(Login_Dialog, self).__init__() - - -def getApp(): - return QtWidgets.QApplication(sys.argv) - -def run_login(): - app = getApp() - ui = Login_Dialog() - ui.show() - sys.exit(app.exec_()) diff --git a/pype/ftrack/__init__.py b/pype/ftrack/__init__.py index e69de29bb2..8b13789179 100644 --- a/pype/ftrack/__init__.py +++ b/pype/ftrack/__init__.py @@ -0,0 +1 @@ + diff --git a/pype/ftrack/credentials.py b/pype/ftrack/credentials.py index 74b0b298ab..3efad41997 100644 --- a/pype/ftrack/credentials.py +++ b/pype/ftrack/credentials.py @@ -7,6 +7,10 @@ import appdirs config_path = os.path.normpath(appdirs.user_data_dir('pype-app','pype')) config_name = 'ftrack_cred.toml' fpath = os.path.join(config_path, config_name) +folder = os.path.dirname(fpath) + +if not os.path.isdir(folder): + os.makedirs(folder) def _get_credentials(): @@ -53,9 +57,9 @@ def _check_credentials(username=None, apiKey=None): try: session = ftrack_api.Session() + session.close() except Exception as e: print(e) return False - session.close() return True diff --git a/pype/ftrack/login_dialog.py b/pype/ftrack/login_dialog.py index f6e3b33478..4dd8a8dca3 100644 --- a/pype/ftrack/login_dialog.py +++ b/pype/ftrack/login_dialog.py @@ -1,38 +1,205 @@ import sys +import os import requests -from PyQt5 import QtCore, QtWidgets +from PyQt5 import QtCore, QtGui, QtWidgets from app import style from . import credentials, login_tools -class Login_Dialog(QtCore.QObject): +class Login_Dialog_ui(QtWidgets.QWidget): + + SIZE_W = 300 + SIZE_H = 230 loginSignal = QtCore.pyqtSignal(object, object, object) _login_server_thread = None + inputs = [] + buttons = [] + labels = [] def __init__(self): + super().__init__() self.loginSignal.connect(self.loginWithCredentials) self._translate = QtCore.QCoreApplication.translate - def run(self): + self.font = QtGui.QFont() + self.font.setFamily("DejaVu Sans Condensed") + self.font.setPointSize(9) + self.font.setBold(True) + self.font.setWeight(50) + self.font.setKerning(True) + + self.resize(self.SIZE_W, self.SIZE_H) + self.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H)) + self.setStyleSheet(style.load_stylesheet()) + + self.setLayout(self._main()) + self.setWindowTitle('FTrack Login') + + self.show() + + def _main(self): + self.main = QtWidgets.QVBoxLayout() + self.main.setObjectName("main") + + self.form = QtWidgets.QFormLayout() + self.form.setContentsMargins(10, 15, 10, 5) + self.form.setObjectName("form") + + self.ftsite_label = QtWidgets.QLabel("FTrack URL:") + self.ftsite_label.setFont(self.font) + self.ftsite_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) + self.ftsite_label.setTextFormat(QtCore.Qt.RichText) + self.ftsite_label.setObjectName("user_label") + + self.ftsite_input = QtWidgets.QLineEdit() + self.ftsite_input.setEnabled(True) + self.ftsite_input.setFrame(True) + self.ftsite_input.setEnabled(False) + self.ftsite_input.setReadOnly(True) + self.ftsite_input.setObjectName("ftsite_input") + + self.user_label = QtWidgets.QLabel("Username:") + self.user_label.setFont(self.font) + self.user_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) + self.user_label.setTextFormat(QtCore.Qt.RichText) + self.user_label.setObjectName("user_label") + + self.user_input = QtWidgets.QLineEdit() + self.user_input.setEnabled(True) + self.user_input.setFrame(True) + self.user_input.setObjectName("user_input") + self.user_input.setPlaceholderText(self._translate("main","user.name")) + self.user_input.textChanged.connect(self._user_changed) + + self.api_label = QtWidgets.QLabel("API Key:") + self.api_label.setFont(self.font) + self.api_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) + self.api_label.setTextFormat(QtCore.Qt.RichText) + self.api_label.setObjectName("api_label") + + self.api_input = QtWidgets.QLineEdit() + self.api_input.setEnabled(True) + self.api_input.setFrame(True) + self.api_input.setObjectName("api_input") + self.api_input.setPlaceholderText(self._translate("main","e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")) + self.api_input.textChanged.connect(self._api_changed) + + self.error_label = QtWidgets.QLabel("") + self.error_label.setFont(self.font) + self.error_label.setTextFormat(QtCore.Qt.RichText) + self.error_label.setObjectName("error_label") + self.error_label.setWordWrap(True); + self.error_label.hide() + + self.form.addRow(self.ftsite_label, self.ftsite_input) + self.form.addRow(self.user_label, self.user_input) + self.form.addRow(self.api_label,self.api_input) + self.form.addRow(self.error_label) + + self.btnGroup = QtWidgets.QHBoxLayout() + self.btnGroup.addStretch(1) + self.btnGroup.setObjectName("btnGroup") + + self.btnEnter = QtWidgets.QPushButton("Login") + self.btnEnter.setToolTip('Set Username and API Key with entered values') + self.btnEnter.clicked.connect(self.enter_credentials) + + self.btnClose = QtWidgets.QPushButton("Close") + self.btnClose.setToolTip('Close this window') + self.btnClose.clicked.connect(self._close_widget) + + self.btnFtrack = QtWidgets.QPushButton("Ftrack") + self.btnFtrack.setToolTip('Open browser for Login to Ftrack') + self.btnFtrack.clicked.connect(self.open_ftrack) + + self.btnGroup.addWidget(self.btnFtrack) + self.btnGroup.addWidget(self.btnEnter) + self.btnGroup.addWidget(self.btnClose) + + self.main.addLayout(self.form) + self.main.addLayout(self.btnGroup) + + self.inputs.append(self.api_input) + self.inputs.append(self.user_input) + self.inputs.append(self.ftsite_input) + + self.enter_site() + return self.main + + def enter_site(self): try: url = os.getenv('FTRACK_SERVER') - return - except: - print("Environment variable 'FTRACK_SERVER' is not set.") + newurl = self.checkUrl(url) - self.url = checkUrl(url) - self.open_ftrack() + if newurl is None: + self.btnEnter.setEnabled(False) + self.btnFtrack.setEnabled(False) + for input in self.inputs: + input.setEnabled(False) + newurl = url + + self.ftsite_input.setText(newurl) + + except Exception as e: + self.setError("FTRACK_SERVER is not set in templates") + self.setError(str(e)) + self.btnEnter.setEnabled(False) + self.btnFtrack.setEnabled(False) + for input in self.inputs: + input.setEnabled(False) + + def setError(self, msg): + self.error_label.setText(msg) + self.error_label.show() + + def _user_changed(self): + self.user_input.setStyleSheet("") + + def _api_changed(self): + self.api_input.setStyleSheet("") + + def _invalid_input(self,entity): + entity.setStyleSheet("border: 1px solid red;") + + def enter_credentials(self): + user = self.user_input.text().strip() + api = self.api_input.text().strip() + msg = "You didn't enter " + missing = [] + if user == "": + missing.append("Username") + self._invalid_input(self.user_input) + + if api == "": + missing.append("API Key") + self._invalid_input(self.api_input) + + if len(missing) > 0: + self.setError("{0} {1}".format(msg, " and ".join(missing))) + return + + verification = credentials._check_credentials(user, api) + + if verification: + credentials._save_credentials(username, apiKey) + credentials._set_env(username, apiKey) + self._close_widget() + else: + self._invalid_input(self.user_input) + self._invalid_input(self.api_input) + self.setError("We're unable to connect to Ftrack with these credentials") def open_ftrack(self): - self.loginWithCredentials(self.url,None,None) + url = self.ftsite_input.text() + self.loginWithCredentials(url,None,None) def checkUrl(self, url): url = url.strip('/ ') if not url: - print("Url is empty!") + self.setError() return if not 'http' in url: @@ -46,23 +213,26 @@ class Login_Dialog(QtCore.QObject): allow_redirects=False # Old python API will not work with redirect. ) except requests.exceptions.RequestException: - print('The server URL set in Templates could not be reached.') + self.setError( + 'The server URL set in Templates could not be reached.' + ) return if ( result.status_code != 200 or 'FTRACK_VERSION' not in result.headers ): - print('The server URL set in Templates is not a valid ftrack server.') + self.setError( + 'The server URL set in Templates is not a valid ftrack server.' + ) return - return url def loginWithCredentials(self, url, username, apiKey): url = url.strip('/ ') if not url: - print( + self.setError( 'You need to specify a valid server URL, ' 'for example https://server-name.ftrackapp.com' ) @@ -79,14 +249,18 @@ class Login_Dialog(QtCore.QObject): allow_redirects=False # Old python API will not work with redirect. ) except requests.exceptions.RequestException: - print('The server URL you provided could not be reached.') + self.setError( + 'The server URL you provided could not be reached.' + ) return if ( result.status_code != 200 or 'FTRACK_VERSION' not in result.headers ): - print('The server URL you provided is not a valid ftrack server.') + self.setError( + 'The server URL you provided is not a valid ftrack server.' + ) return # If there is an existing server thread running we need to stop it. @@ -102,15 +276,28 @@ class Login_Dialog(QtCore.QObject): self._login_server_thread.start(url) return - verification = credentials._check_credentials(user, api) + verification = credentials._check_credentials(username, apiKey) if verification is True: credentials._save_credentials(username, apiKey) credentials._set_env(username, apiKey) + self._close_widget() + def _close_widget(self): + self.close() + + +class Login_Dialog(Login_Dialog_ui): + def __init__(self): + super(Login_Dialog, self).__init__() + + +def getApp(): + return QtWidgets.QApplication(sys.argv) + def run_login(): - app = QtWidgets.QApplication(sys.argv) - applogin = Login_Dialog() - applogin.run() - sys.exit(app.exec_()) + app = getApp() + ui = Login_Dialog() + ui.show() + app.exec_() diff --git a/pype/ftrack/login_dialog_noui.py b/pype/ftrack/login_dialog_noui.py new file mode 100644 index 0000000000..5df2c62daf --- /dev/null +++ b/pype/ftrack/login_dialog_noui.py @@ -0,0 +1,120 @@ +import os +import sys +import requests +import argparse +from pprint import pprint +from PyQt5 import QtCore, QtWidgets +from app import style +from . import credentials, login_tools + + +class Login_Dialog(QtWidgets.QWidget): + + loginSignal = QtCore.pyqtSignal(object, object, object) + _login_server_thread = None + + def __init__(self): + super().__init__() + self.loginSignal.connect(self.loginWithCredentials) + + def run(self): + try: + url = os.getenv('FTRACK_SERVER') + except: + print("Environment variable 'FTRACK_SERVER' is not set.") + return + + self.url = self.checkUrl(url) + self.open_ftrack() + + def open_ftrack(self): + self.loginWithCredentials(self.url, None, None) + + def checkUrl(self, url): + url = url.strip('/ ') + + if not url: + print("Url is empty!") + return + + if not 'http' in url: + if url.endswith('ftrackapp.com'): + url = 'https://' + url + else: + url = 'https://{0}.ftrackapp.com'.format(url) + try: + result = requests.get( + url, + allow_redirects=False # Old python API will not work with redirect. + ) + except requests.exceptions.RequestException: + print('The server URL set in Templates could not be reached.') + return + + + if ( + result.status_code != 200 or 'FTRACK_VERSION' not in result.headers + ): + print('The server URL set in Templates is not a valid ftrack server.') + return + + return url + + def loginWithCredentials(self, url, username, apiKey): + url = url.strip('/ ') + if not url: + print( + 'You need to specify a valid server URL, ' + 'for example https://server-name.ftrackapp.com' + ) + return + + if not 'http' in url: + if url.endswith('ftrackapp.com'): + url = 'https://' + url + else: + url = 'https://{0}.ftrackapp.com'.format(url) + try: + result = requests.get( + url, + allow_redirects=False # Old python API will not work with redirect. + ) + except requests.exceptions.RequestException: + print('The server URL you provided could not be reached.') + return + + + if ( + result.status_code != 200 or 'FTRACK_VERSION' not in result.headers + ): + print('The server URL you provided is not a valid ftrack server.') + return + + # If there is an existing server thread running we need to stop it. + if self._login_server_thread: + self._login_server_thread.quit() + self._login_server_thread = None + + # If credentials are not properly set, try to get them using a http + # server. + if not username or not apiKey: + self._login_server_thread = login_tools.LoginServerThread() + self._login_server_thread.loginSignal.connect(self.loginSignal) + self._login_server_thread.start(url) + + verification = credentials._check_credentials(username, apiKey) + + if verification is True: + credentials._save_credentials(username, apiKey) + credentials._set_env(username, apiKey) + self.close() + + +def run_login(): + app = QtWidgets.QApplication(sys.argv) + applogin = Login_Dialog() + applogin.run() + app.exec_() + +if __name__ == '__main__': + run_login()