From 39a1c2768cf0d2fa028418598a90ae7edfb53cac Mon Sep 17 00:00:00 2001 From: Jakub Trllo Date: Tue, 13 Nov 2018 11:05:15 +0100 Subject: [PATCH] Login without GUI --- pype/ftrack/Login/login_dialog_ui.py | 304 ++++++++++++ .../Login/templatesforcode/login_dialogue.py | 198 -------- .../templatesforcode/login_dialogue_usage.py | 196 -------- .../Login/templatesforcode/login_setup.py | 442 ------------------ pype/ftrack/login_dialog.py | 223 +-------- 5 files changed, 322 insertions(+), 1041 deletions(-) create mode 100644 pype/ftrack/Login/login_dialog_ui.py delete mode 100644 pype/ftrack/Login/templatesforcode/login_dialogue.py delete mode 100644 pype/ftrack/Login/templatesforcode/login_dialogue_usage.py delete mode 100644 pype/ftrack/Login/templatesforcode/login_setup.py diff --git a/pype/ftrack/Login/login_dialog_ui.py b/pype/ftrack/Login/login_dialog_ui.py new file mode 100644 index 0000000000..00d0c5ae5f --- /dev/null +++ b/pype/ftrack/Login/login_dialog_ui.py @@ -0,0 +1,304 @@ +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/Login/templatesforcode/login_dialogue.py b/pype/ftrack/Login/templatesforcode/login_dialogue.py deleted file mode 100644 index ba0315cabf..0000000000 --- a/pype/ftrack/Login/templatesforcode/login_dialogue.py +++ /dev/null @@ -1,198 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '..\CODE\github\pypeclub\pype-setup\temp\pype_project_settins_ui\login_dialogue.ui' -# -# Created by: PyQt5 UI code generator 5.7.1 -# -# WARNING! All changes made in this file will be lost! - -import sys -from PyQt5 import QtCore, QtGui, QtWidgets - -from app import style - - - - -class Login_Dialog_ui(object): - - SIZE_W = 250 - SIZE_H = 300 - - def __init__(self): - super(Login_Dialog_ui, self).__init__() - self.Dialog = QtWidgets.QDialog() - self.Dialog.setStyleSheet(style.load_stylesheet()) - self.Dialog.setObjectName("Dialog") - self.Dialog.resize(self.SIZE_W, self.SIZE_H) - self.Dialog.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H)) - self.verticalLayoutWidget = QtWidgets.QWidget(self.Dialog) - self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, self.SIZE_W + 1, self.SIZE_H + 1)) - self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") - self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) - self.verticalLayout.setContentsMargins(10, 5, 10, 5) - self.verticalLayout.setObjectName("verticalLayout") - - font = QtGui.QFont() - font.setFamily("DejaVu Sans Condensed") - font.setPointSize(9) - font.setBold(True) - font.setWeight(50) - font.setKerning(True) - - sizePolicy = QtWidgets.QSizePolicy( - QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - - if self.ftracksite: - self.site_label = QtWidgets.QLabel(self.verticalLayoutWidget) - sizePolicy.setHeightForWidth(self.site_label.sizePolicy().hasHeightForWidth()) - self.site_label.setSizePolicy(sizePolicy) - self.site_label.setMinimumSize(QtCore.QSize(150, 28)) - self.site_label.setFont(font) - self.site_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.site_label.setTextFormat(QtCore.Qt.RichText) - # self.site_label.setAlignment(QtCore.Qt.AlignCenter) - self.site_label.setObjectName("site_label") - self.verticalLayout.addWidget(self.site_label) - - self.site_input = QtWidgets.QLineEdit(self.verticalLayoutWidget) - self.site_input.setEnabled(True) - self.site_input.setFrame(True) - self.site_input.setFrame(True) - self.site_input.setReadOnly(True) - self.site_input.setObjectName("site_input") - self.verticalLayout.addWidget(self.site_input) - - self.user_label = QtWidgets.QLabel(self.verticalLayoutWidget) - sizePolicy.setHeightForWidth(self.user_label.sizePolicy().hasHeightForWidth()) - self.user_label.setSizePolicy(sizePolicy) - self.user_label.setMinimumSize(QtCore.QSize(150, 28)) - self.user_label.setFont(font) - self.user_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.user_label.setTextFormat(QtCore.Qt.RichText) - # self.user_label.setAlignment(QtCore.Qt.AlignCenter) - self.user_label.setObjectName("user_label") - self.verticalLayout.addWidget(self.user_label) - - self.user_input = QtWidgets.QLineEdit(self.verticalLayoutWidget) - self.user_input.setEnabled(True) - self.user_input.setFrame(True) - self.user_input.setObjectName("user_input") - self.verticalLayout.addWidget(self.user_input) - - self.api_label = QtWidgets.QLabel(self.verticalLayoutWidget) - sizePolicy.setHeightForWidth(self.api_label.sizePolicy().hasHeightForWidth()) - self.api_label.setSizePolicy(sizePolicy) - self.api_label.setMinimumSize(QtCore.QSize(150, 28)) - self.api_label.setFont(font) - self.api_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.api_label.setTextFormat(QtCore.Qt.RichText) - # self.api_label.setAlignment(QtCore.Qt.AlignCenter) - self.api_label.setObjectName("api_label") - self.verticalLayout.addWidget(self.api_label) - - self.api_input = QtWidgets.QLineEdit(self.verticalLayoutWidget) - self.api_input.setEnabled(True) - self.api_input.setFrame(True) - self.api_input.setObjectName("api_input") - self.verticalLayout.addWidget(self.api_input) - - spacerItem = QtWidgets.QSpacerItem( - 20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem) - - - # button.setToolTip('This is an example button') - # button.move(100,70) - self.btn_ftrack = QtWidgets.QPushButton("Login", self.verticalLayoutWidget) - self.btn_ftrack.resize(10,10) - # self.btn_ftrack.move(100,70) - self.verticalLayout.addWidget(self.btn_ftrack) - - self.buttonBox = QtWidgets.QDialogButtonBox(self.verticalLayoutWidget) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons( - QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok) - self.buttonBox.setObjectName("buttonBox") - self.verticalLayout.addWidget(self.buttonBox) - - self.retranslateUi(self.Dialog) - self.buttonBox.accepted.connect(self.execute) - self.buttonBox.rejected.connect(self.Dialog.reject) - QtCore.QMetaObject.connectSlotsByName(self.Dialog) - self.Dialog.setTabOrder(self.user_input, self.api_input) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", self.ui_title)) - self.site_label.setText(_translate("Dialog", "FTrack URL:")) - if self.ftracksite: - self.site_input.setText(_translate("Dialog", self.ftracksite)) - self.user_label.setText(_translate("Dialog", "Username:")) - self.user_input.setPlaceholderText(_translate("Dialog", "user.name")) - self.api_label.setText(_translate("Dialog", "API Key:")) - self.api_input.setPlaceholderText(_translate("Dialog", "eg.:")) - - def show(self): - self.Dialog.show() - - -class Login_Dialog(Login_Dialog_ui): - def __init__(self, ui_title="Dialog", ftracksite=None): - self.ui_title = ui_title - self.ftracksite = ftracksite - super(Login_Dialog, self).__init__() - self.user_input.textChanged.connect(self._user_changed) - self.api_input.textChanged.connect(self._api_changed) - - def _user_changed(self): - self.user_input.setStyleSheet("") - - def _api_changed(self): - self.api_input.setStyleSheet("") - # print(self.passw_input.text()) - - def _invalid_input(self,entity): - entity.setStyleSheet("border: 1px solid red;") - - def _check_credentials(self): - logged = False - - user = self.user_input.text() - api = self.api_input.text() - - if user == "": - self._invalid_input(self.user_input) - elif True: - # IF user exist - pass - - if api == "": - self._invalid_input(self.api_input) - elif True: - # IF is api ok exist - Session creation - pass - - if logged is True: - self.close() - - def execute(self): - self._check_credentials() - - -def getApp(): - return QtWidgets.QApplication(sys.argv) - -def main(): - app = QtWidgets.QApplication(sys.argv) - ui = Login_Dialog("Ftrack Login","pype") - ui.show() - sys.exit(app.exec_()) - - -if __name__ == "__main__": - main() - -main() diff --git a/pype/ftrack/Login/templatesforcode/login_dialogue_usage.py b/pype/ftrack/Login/templatesforcode/login_dialogue_usage.py deleted file mode 100644 index ac6e986bef..0000000000 --- a/pype/ftrack/Login/templatesforcode/login_dialogue_usage.py +++ /dev/null @@ -1,196 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '..\CODE\github\pypeclub\pype-setup\temp\pype_project_settins_ui\login_dialogue.ui' -# -# Created by: PyQt5 UI code generator 5.7.1 -# -# WARNING! All changes made in this file will be lost! - -import sys -from PyQt5 import QtCore, QtGui, QtWidgets - -from app import style - - -class Login_Dialog_ui(object): - - SIZE_W = 250 - SIZE_H = 300 - - def __init__(self): - super(Login_Dialog_ui, self).__init__() - self.Dialog = QtWidgets.QDialog() - self.Dialog.setStyleSheet(style.load_stylesheet()) - self.Dialog.setObjectName("Dialog") - self.Dialog.resize(self.SIZE_W, self.SIZE_H) - self.Dialog.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H)) - self.verticalLayoutWidget = QtWidgets.QWidget(self.Dialog) - self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, self.SIZE_W + 1, self.SIZE_H + 1)) - self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") - self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget) - self.verticalLayout.setContentsMargins(10, 5, 10, 5) - self.verticalLayout.setObjectName("verticalLayout") - - font = QtGui.QFont() - font.setFamily("DejaVu Sans Condensed") - font.setPointSize(9) - font.setBold(True) - font.setWeight(50) - font.setKerning(True) - - sizePolicy = QtWidgets.QSizePolicy( - QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - - if self.ftracksite: - self.site_label = QtWidgets.QLabel(self.verticalLayoutWidget) - sizePolicy.setHeightForWidth(self.site_label.sizePolicy().hasHeightForWidth()) - self.site_label.setSizePolicy(sizePolicy) - self.site_label.setMinimumSize(QtCore.QSize(150, 28)) - self.site_label.setFont(font) - self.site_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.site_label.setTextFormat(QtCore.Qt.RichText) - # self.site_label.setAlignment(QtCore.Qt.AlignCenter) - self.site_label.setObjectName("site_label") - self.verticalLayout.addWidget(self.site_label) - - self.site_input = QtWidgets.QLineEdit(self.verticalLayoutWidget) - self.site_input.setEnabled(True) - self.site_input.setFrame(True) - self.site_input.setFrame(True) - self.site_input.setReadOnly(True) - self.site_input.setObjectName("site_input") - self.verticalLayout.addWidget(self.site_input) - - self.user_label = QtWidgets.QLabel(self.verticalLayoutWidget) - sizePolicy.setHeightForWidth(self.user_label.sizePolicy().hasHeightForWidth()) - self.user_label.setSizePolicy(sizePolicy) - self.user_label.setMinimumSize(QtCore.QSize(150, 28)) - self.user_label.setFont(font) - self.user_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.user_label.setTextFormat(QtCore.Qt.RichText) - # self.user_label.setAlignment(QtCore.Qt.AlignCenter) - self.user_label.setObjectName("user_label") - self.verticalLayout.addWidget(self.user_label) - - self.user_input = QtWidgets.QLineEdit(self.verticalLayoutWidget) - self.user_input.setEnabled(True) - self.user_input.setFrame(True) - self.user_input.setObjectName("user_input") - self.verticalLayout.addWidget(self.user_input) - - self.api_label = QtWidgets.QLabel(self.verticalLayoutWidget) - sizePolicy.setHeightForWidth(self.api_label.sizePolicy().hasHeightForWidth()) - self.api_label.setSizePolicy(sizePolicy) - self.api_label.setMinimumSize(QtCore.QSize(150, 28)) - self.api_label.setFont(font) - self.api_label.setCursor(QtGui.QCursor(QtCore.Qt.ArrowCursor)) - self.api_label.setTextFormat(QtCore.Qt.RichText) - # self.api_label.setAlignment(QtCore.Qt.AlignCenter) - self.api_label.setObjectName("api_label") - self.verticalLayout.addWidget(self.api_label) - - self.api_input = QtWidgets.QLineEdit(self.verticalLayoutWidget) - self.api_input.setEnabled(True) - self.api_input.setFrame(True) - self.api_input.setObjectName("api_input") - self.verticalLayout.addWidget(self.api_input) - - spacerItem = QtWidgets.QSpacerItem( - 20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.verticalLayout.addItem(spacerItem) - - - # button.setToolTip('This is an example button') - # button.move(100,70) - self.btn_ftrack = QtWidgets.QPushButton("Login", self.verticalLayoutWidget) - self.btn_ftrack.resize(10,10) - # self.btn_ftrack.move(100,70) - self.verticalLayout.addWidget(self.btn_ftrack) - - self.buttonBox = QtWidgets.QDialogButtonBox(self.verticalLayoutWidget) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons( - QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok) - self.buttonBox.setObjectName("buttonBox") - self.verticalLayout.addWidget(self.buttonBox) - - self.retranslateUi(self.Dialog) - self.buttonBox.accepted.connect(self.execute) - self.buttonBox.rejected.connect(self.Dialog.reject) - QtCore.QMetaObject.connectSlotsByName(self.Dialog) - self.Dialog.setTabOrder(self.user_input, self.api_input) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", self.ui_title)) - self.site_label.setText(_translate("Dialog", "FTrack URL:")) - if self.ftracksite: - self.site_input.setText(_translate("Dialog", self.ftracksite)) - self.user_label.setText(_translate("Dialog", "Username:")) - self.user_input.setPlaceholderText(_translate("Dialog", "user.name")) - self.api_label.setText(_translate("Dialog", "API Key:")) - self.api_input.setPlaceholderText(_translate("Dialog", "eg.:")) - - def show(self): - self.Dialog.show() - - -class Login_Dialog(Login_Dialog_ui): - def __init__(self, ui_title="Dialog", ftracksite=None): - self.ui_title = ui_title - self.ftracksite = ftracksite - super(Login_Dialog, self).__init__() - self.user_input.textChanged.connect(self._user_changed) - self.api_input.textChanged.connect(self._api_changed) - - def _user_changed(self): - self.user_input.setStyleSheet("") - - def _api_changed(self): - self.api_input.setStyleSheet("") - # print(self.passw_input.text()) - - def _invalid_input(self,entity): - entity.setStyleSheet("border: 1px solid red;") - - def _check_credentials(self): - logged = False - - user = self.user_input.text() - api = self.api_input.text() - - if user == "": - self._invalid_input(self.user_input) - elif True: - # IF user exist - pass - - if api == "": - self._invalid_input(self.api_input) - elif True: - # IF is api ok exist - Session creation - pass - - if logged is True: - self.close() - - def execute(self): - self._check_credentials() - - -def getApp(): - return QtWidgets.QApplication(sys.argv) - -def main(): - app = getApp() - ui = Login_Dialog("Ftrack Login","pype") - ui.show() - sys.exit(app.exec_()) - - -if __name__ == "__main__": - main() - -main() diff --git a/pype/ftrack/Login/templatesforcode/login_setup.py b/pype/ftrack/Login/templatesforcode/login_setup.py deleted file mode 100644 index 6ebae672fa..0000000000 --- a/pype/ftrack/Login/templatesforcode/login_setup.py +++ /dev/null @@ -1,442 +0,0 @@ -import os -import sys -import login_tools -from PyQt5 import QtCore -import requests - - -class FtrackLogin(object): - - # loginSignal = QtCore.pyqtSignal(object, object, object) - # - # def __init__(self): - # self.username = None - # self.apiKey = None - # self.url = "https://pype.ftrackapp.com" - # - # self._login_server_thread = None - # self.loginSignal.connect(self.loginWithCredentials) - # self.login() - # - # def login(self): - # '''Login using stored credentials or ask user for them.''' - # - # credentials = self._get_credentials() - # if credentials: - # # Try to login. - # self.loginWithCredentials( - # credentials['server_url'], - # credentials['api_user'], - # credentials['api_key'] - # ) - # - # def setup_session(self): - # try: - # session = ftrack_api.session() - # except Exception as e: - # return False - # return session - # - # def report_session_setup_error(self, error): - # msg = ( - # u'\nAn error occured while starting ftrack: {0}.'.format(error) - # ) - # print(msg) - # # self.loginError.emit(msg) - # - # def _get_credentials(self): - # data = {'server_url':self.url, - # 'api_user':self.username, - # 'api_key':self.apiKey - # } - # return data - # - # def _save_credentials(self, url, username, apiKey): - # self.url = url - # self.username = username - # self.apiKey = apiKey - # - # def loginWithCredentials(self, url, username, apiKey): - # url = url.strip('/ ') - # - # if not url: - # self.loginError.emit( - # '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.logger.exception('Error reaching server url.') - # self.loginError.emit( - # 'The server URL you provided could not be reached.' - # ) - # return - # - # if ( - # result.status_code != 200 or 'FTRACK_VERSION' not in result.headers - # ): - # self.loginError.emit( - # '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 - # - # # Set environment variables supported by the old API. - # os.environ['FTRACK_SERVER'] = url - # os.environ['LOGNAME'] = username - # os.environ['FTRACK_APIKEY'] = apiKey - # - # # Set environment variables supported by the new API. - # os.environ['FTRACK_API_USER'] = username - # os.environ['FTRACK_API_KEY'] = apiKey - # - # # Login using the new ftrack API. - # try: - # self._session = self._setup_session() - # except Exception as error: - # self.logger.exception(u'Error during login.:') - # self._report_session_setup_error(error) - # return - # - # # Store credentials since login was successful. - # self._save_credentials(url, username, apiKey) - # - # # Verify storage scenario before starting. - # if 'storage_scenario' in self._session.server_information: - # storage_scenario = self._session.server_information.get( - # 'storage_scenario' - # ) - # if storage_scenario is None: - # # Hide login overlay at this time since it will be deleted - # self.logger.debug('Storage scenario is not configured.') - # scenario_widget = _scenario_widget.ConfigureScenario( - # self._session - # ) - # scenario_widget.configuration_completed.connect( - # self.location_configuration_finished - # ) - # self.setCentralWidget(scenario_widget) - # self.focus() - # return - - - - - - - - - - - - - - - - - - - - - - - - - - - loginError = QtCore.pyqtSignal(object) - - #: Signal when event received via ftrack's event hub. - eventHubSignal = QtCore.pyqtSignal(object) - - # Login signal. - loginSignal = QtCore.pyqtSignal(object, object, object) - - def __init__(self, *args, **kwargs): - - # self.logger = logging.getLogger( - # __name__ + '.' + self.__class__.__name__ - # ) - - self._login_server_thread = None - - self._login_overlay = None - self.loginSignal.connect(self.loginWithCredentials) - self.login() - - - def _onConnectTopicEvent(self, event): - '''Generic callback for all ftrack.connect events. - - .. note:: - Events not triggered by the current logged in user will be dropped. - - ''' - if event['topic'] != 'ftrack.connect': - return - - self._routeEvent(event) - - def logout(self): - '''Clear stored credentials and quit Connect.''' - self._clear_qsettings() - config = ftrack_connect.ui.config.read_json_config() - - config['accounts'] = [] - ftrack_connect.ui.config.write_json_config(config) - - QtWidgets.qApp.quit() - - def _clear_qsettings(self): - '''Remove credentials from QSettings.''' - settings = QtCore.QSettings() - settings.remove('login') - - def _get_credentials(self): - '''Return a dict with API credentials from storage.''' - credentials = None - - # Read from json config file. - json_config = ftrack_connect.ui.config.read_json_config() - if json_config: - try: - data = json_config['accounts'][0] - credentials = { - 'server_url': data['server_url'], - 'api_user': data['api_user'], - 'api_key': data['api_key'] - } - except Exception: - self.logger.debug( - u'No credentials were found in config: {0}.'.format( - json_config - ) - ) - - # Fallback on old QSettings. - if not json_config and not credentials: - settings = QtCore.QSettings() - server_url = settings.value('login/server', None) - api_user = settings.value('login/username', None) - api_key = settings.value('login/apikey', None) - - if not None in (server_url, api_user, api_key): - credentials = { - 'server_url': server_url, - 'api_user': api_user, - 'api_key': api_key - } - - return credentials - - def _save_credentials(self, server_url, api_user, api_key): - '''Save API credentials to storage.''' - # Clear QSettings since they should not be used any more. - self._clear_qsettings() - - # Save the credentials. - json_config = ftrack_connect.ui.config.read_json_config() - - if not json_config: - json_config = {} - - # Add a unique id to the config that can be used to identify this - # machine. - if not 'id' in json_config: - json_config['id'] = str(uuid.uuid4()) - - json_config['accounts'] = [{ - 'server_url': server_url, - 'api_user': api_user, - 'api_key': api_key - }] - - ftrack_connect.ui.config.write_json_config(json_config) - - def login(self): - '''Login using stored credentials or ask user for them.''' - credentials = self._get_credentials() - self.showLoginWidget() - - if credentials: - # Try to login. - self.loginWithCredentials( - credentials['server_url'], - credentials['api_user'], - credentials['api_key'] - ) - - def showLoginWidget(self): - '''Show the login widget.''' - self._login_overlay = ftrack_connect.ui.widget.overlay.CancelOverlay( - self.loginWidget, - message='Signing in' - ) - - self._login_overlay.hide() - self.setCentralWidget(self.loginWidget) - self.loginWidget.login.connect(self._login_overlay.show) - self.loginWidget.login.connect(self.loginWithCredentials) - self.loginError.connect(self.loginWidget.loginError.emit) - self.loginError.connect(self._login_overlay.hide) - self.focus() - - # Set focus on the login widget to remove any focus from its child - # widgets. - self.loginWidget.setFocus() - self._login_overlay.hide() - - def _setup_session(self): - '''Setup a new python API session.''' - if hasattr(self, '_hub_thread'): - self._hub_thread.quit() - - plugin_paths = os.environ.get( - 'FTRACK_EVENT_PLUGIN_PATH', '' - ).split(os.pathsep) - - plugin_paths.extend(self.pluginHookPaths) - - try: - session = ftrack_connect.session.get_shared_session( - plugin_paths=plugin_paths - ) - except Exception as error: - raise ftrack_connect.error.ParseError(error) - - # Listen to events using the new API event hub. This is required to - # allow reconfiguring the storage scenario. - self._hub_thread = _event_hub_thread.NewApiEventHubThread() - self._hub_thread.start(session) - - ftrack_api._centralized_storage_scenario.register_configuration( - session - ) - - return session - - def _report_session_setup_error(self, error): - '''Format error message and emit loginError.''' - msg = ( - u'\nAn error occured while starting ftrack-connect: {0}.' - u'\nPlease check log file for more informations.' - u'\nIf the error persists please send the log file to:' - u' support@ftrack.com'.format(error) - - ) - self.loginError.emit(msg) - - def loginWithCredentials(self, url, username, apiKey): - '''Connect to *url* with *username* and *apiKey*. - - loginError will be emitted if this fails. - - ''' - # Strip all leading and preceeding occurances of slash and space. - url = url.strip('/ ') - - if not url: - self.loginError.emit( - '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.logger.exception('Error reaching server url.') - self.loginError.emit( - 'The server URL you provided could not be reached.' - ) - return - - if ( - result.status_code != 200 or 'FTRACK_VERSION' not in result.headers - ): - self.loginError.emit( - '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 - - # Set environment variables supported by the old API. - os.environ['FTRACK_SERVER'] = url - os.environ['LOGNAME'] = username - os.environ['FTRACK_APIKEY'] = apiKey - - # Set environment variables supported by the new API. - os.environ['FTRACK_API_USER'] = username - os.environ['FTRACK_API_KEY'] = apiKey - - # Login using the new ftrack API. - try: - self._session = self._setup_session() - except Exception as error: - self.logger.exception(u'Error during login.:') - self._report_session_setup_error(error) - return - - # Store credentials since login was successful. - self._save_credentials(url, username, apiKey) - - # Verify storage scenario before starting. - if 'storage_scenario' in self._session.server_information: - storage_scenario = self._session.server_information.get( - 'storage_scenario' - ) - if storage_scenario is None: - # Hide login overlay at this time since it will be deleted - self.logger.debug('Storage scenario is not configured.') - scenario_widget = _scenario_widget.ConfigureScenario( - self._session - ) - - self.setCentralWidget(scenario_widget) - self.focus() - return diff --git a/pype/ftrack/login_dialog.py b/pype/ftrack/login_dialog.py index 2a69f92f69..f6e3b33478 100644 --- a/pype/ftrack/login_dialog.py +++ b/pype/ftrack/login_dialog.py @@ -1,205 +1,38 @@ import sys import requests -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt5 import QtCore, QtWidgets from app import style from . import credentials, login_tools -class Login_Dialog_ui(QtWidgets.QWidget): - - SIZE_W = 300 - SIZE_H = 230 +class Login_Dialog(QtCore.QObject): 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): + def run(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 + except: + print("Environment variable 'FTRACK_SERVER' is not set.") - 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") + self.url = checkUrl(url) + self.open_ftrack() def open_ftrack(self): - url = self.ftsite_input.text() - self.loginWithCredentials(url,None,None) + self.loginWithCredentials(self.url,None,None) def checkUrl(self, url): url = url.strip('/ ') if not url: - self.setError() + print("Url is empty!") return if not 'http' in url: @@ -213,26 +46,23 @@ class Login_Dialog_ui(QtWidgets.QWidget): 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.' - ) + print('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.' - ) + 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: - self.setError( + print( 'You need to specify a valid server URL, ' 'for example https://server-name.ftrackapp.com' ) @@ -249,18 +79,14 @@ class Login_Dialog_ui(QtWidgets.QWidget): 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.' - ) + print('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.' - ) + 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. @@ -281,23 +107,10 @@ class Login_Dialog_ui(QtWidgets.QWidget): 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() + app = QtWidgets.QApplication(sys.argv) + applogin = Login_Dialog() + applogin.run() sys.exit(app.exec_())