Skip to content

Commit

Permalink
Set basic user connection to shotgrid
Browse files Browse the repository at this point in the history
  • Loading branch information
clement.hector authored and ClementHector committed Feb 7, 2022
1 parent 8606f7a commit 6d52d47
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 14 deletions.
101 changes: 101 additions & 0 deletions openpype/modules/shotgrid/lib/credentials.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import os
import shotgun_api3

try:
from urllib.parse import urlparse
except ImportError:
from urlparse import urlparse


from openpype.lib import OpenPypeSecureRegistry

USERNAME_KEY = "login"
API_KEY_KEY = "password"


def get_shotgrid_hostname(shotgrid_server=None):
if not shotgrid_server:
shotgrid_server = os.environ.get("SHOTGRID_SERVER")

if not shotgrid_server:
return None

if "//" not in shotgrid_server:
shotgrid_server = "//" + shotgrid_server

return urlparse(shotgrid_server).hostname


def _get_shotgrid_secure_key(hostname, key):
"""Secure item key for entered hostname."""
return "/".join(("shotgrid", hostname, key))


def get_credentials(shotgrid_server=None):
output = {USERNAME_KEY: None, API_KEY_KEY: None}
hostname = get_shotgrid_hostname(shotgrid_server)
if not hostname:
return output

username_name = _get_shotgrid_secure_key(hostname, USERNAME_KEY)
api_key_name = _get_shotgrid_secure_key(hostname, API_KEY_KEY)

username_registry = OpenPypeSecureRegistry(username_name)
api_key_registry = OpenPypeSecureRegistry(api_key_name)

output[USERNAME_KEY] = username_registry.get_item(USERNAME_KEY, None)
output[API_KEY_KEY] = api_key_registry.get_item(API_KEY_KEY, None)

return output


def save_credentials(username, api_key, shotgrid_server=None):
hostname = get_shotgrid_hostname(shotgrid_server)
username_name = _get_shotgrid_secure_key(hostname, USERNAME_KEY)
api_key_name = _get_shotgrid_secure_key(hostname, API_KEY_KEY)

# Clear credentials
clear_credentials(shotgrid_server)

username_registry = OpenPypeSecureRegistry(username_name)
api_key_registry = OpenPypeSecureRegistry(api_key_name)

username_registry.set_item(USERNAME_KEY, username)
api_key_registry.set_item(API_KEY_KEY, api_key)


def clear_credentials(shotgrid_server=None):
hostname = get_shotgrid_hostname(shotgrid_server)
username_name = _get_shotgrid_secure_key(hostname, USERNAME_KEY)
api_key_name = _get_shotgrid_secure_key(hostname, API_KEY_KEY)

username_registry = OpenPypeSecureRegistry(username_name)
api_key_registry = OpenPypeSecureRegistry(api_key_name)

current_username = username_registry.get_item(USERNAME_KEY, None)
current_api_key = api_key_registry.get_item(API_KEY_KEY, None)

if current_username is not None:
username_registry.delete_item(USERNAME_KEY)

if current_api_key is not None:
api_key_registry.delete_item(API_KEY_KEY)


def check_credentials(username, api_key, shotgrid_server=None):
if not shotgrid_server:
shotgrid_server = os.environ.get("SHOTGRID_SERVER")

if not shotgrid_server or not username or not api_key:
return False

try:
session = shotgun_api3.Shotgun(
server_url=shotgrid_server, api_key=api_key, api_user=username
)
session.close()

except Exception:
return False

return True
31 changes: 29 additions & 2 deletions openpype/modules/shotgrid/shotgrid_module.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import os
from typing import Optional, Dict, AnyStr, Any
from openpype.modules.shotgrid.lib import credentials
import shotgun_api3

from openpype.modules import PypeModule, ITrayModule, IPluginPaths, ILaunchHookPaths
from openpype.modules import (
PypeModule,
ITrayModule,
IPluginPaths,
ILaunchHookPaths,
)
from openpype.modules.shotgrid.tray.shotgrid_tray import ShotgridTrayWrapper

SHOTGRID_MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
Expand All @@ -16,6 +23,10 @@ class ShotgridModule(PypeModule, ITrayModule, IPluginPaths, ILaunchHookPaths):
def initialize(self, modules_settings: Dict[AnyStr, Any]):
shotgrid_settings = modules_settings.get(self.name, dict())
self.enabled = shotgrid_settings.get("enabled", False)
shotgrid_url = shotgrid_settings.get("shotgrid_server").strip()

self.shotgrid_url = shotgrid_url

self.project_id = shotgrid_settings.get("project_id")

# if self.enabled and not self.project_id:
Expand All @@ -28,7 +39,11 @@ def get_global_environments(self) -> Dict[AnyStr, Any]:
return {"PROJECT_ID": self.project_id}

def get_plugin_paths(self) -> Dict[AnyStr, Any]:
return {"publish": [os.path.join(SHOTGRID_MODULE_DIR, "plugins", "publish")]}
return {
"publish": [
os.path.join(SHOTGRID_MODULE_DIR, "plugins", "publish")
]
}

def get_launch_hook_paths(self) -> AnyStr:
return os.path.join(SHOTGRID_MODULE_DIR, "hooks")
Expand All @@ -44,3 +59,15 @@ def tray_exit(self, *args, **kwargs):

def tray_menu(self, tray_menu):
return self.tray_wrapper.tray_menu(tray_menu)

def set_credentials_to_env(self, username: AnyStr, api_key: AnyStr):
os.environ["SHOTGRID_LOGIN"] = username or ""
os.environ["SHOTGRID_PASSWORD"] = api_key or ""

def create_shotgrid_session(self) -> shotgun_api3.Shotgun:
credentials_ = credentials.get_credentials()
return shotgun_api3.Shotgun(
base_url=self.shotgrid_url,
login=credentials_.get("login"),
password=credentials_.get("password"),
)
128 changes: 117 additions & 11 deletions openpype/modules/shotgrid/tray/credential_dialog.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from typing import Any

from Qt import QtCore, QtWidgets
from Qt import QtCore, QtWidgets, QtGui

from openpype import style
from openpype import resources

import shotgun_api3
from shotgun_api3.shotgun import AuthenticationFault


class CredentialsDialog(QtWidgets.QDialog):
SIZE_W = 300
SIZE_H = 230
SIZE_W = 350
SIZE_H = 150

_module: Any = None
_is_logged: bool = False
Expand All @@ -28,10 +31,15 @@ def __init__(self, module, parent=None):

self._module = module
self._is_logged = False

self.setWindowTitle("OpenPype - Shotgrid Login")

icon = QtGui.QIcon(resources.pype_icon_filepath())
self.setWindowIcon(icon)

self.setWindowFlags(
QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowMinimizeButtonHint
QtCore.Qt.WindowCloseButtonHint
| QtCore.Qt.WindowMinimizeButtonHint
)
self.setMinimumSize(QtCore.QSize(self.SIZE_W, self.SIZE_H))
self.setMaximumSize(QtCore.QSize(self.SIZE_W + 100, self.SIZE_H + 100))
Expand All @@ -43,11 +51,6 @@ def ui_init(self):
self.url_label = QtWidgets.QLabel("Shotgrid URL:")
self.login_label = QtWidgets.QLabel("Login:")
self.password_label = QtWidgets.QLabel("Password:")
# self.url_input = QtWidgets.QLabel()
# self.url_input.setTextInteractionFlags(
# QtCore.Qt.TextBrowserInteraction
# )
# self.url_input.setCursor(QtGui.QCursor(QtCore.Qt.IBeamCursor))

self.url_input = QtWidgets.QLineEdit()
self.url_input.setPlaceholderText("shotgrid url")
Expand All @@ -57,20 +60,123 @@ def ui_init(self):

self.password_input = QtWidgets.QLineEdit()
self.password_input.setPlaceholderText("password")
self.password_input.setEchoMode(QtWidgets.QLineEdit.Password)

self.error_label = QtWidgets.QLabel("")
self.error_label.setWordWrap(True)
self.error_label.hide()

self.input_layout = QtWidgets.QFormLayout()
self.input_layout.setContentsMargins(10, 15, 10, 5)

self.input_layout.addRow(self.url_label, self.url_input)
self.input_layout.addRow(self.login_label, self.login_input)
self.input_layout.addRow(self.password_label, self.password_input)
self.input_layout.addRow(self.error_label)

self.login_button = QtWidgets.QPushButton("Login")
self.login_button.setToolTip("Login into shotgrid instance")
self.login_button.setToolTip("Log in shotgrid instance")
self.login_button.clicked.connect(self._on_shotgrid_login_clicked)

self.logout_button = QtWidgets.QPushButton("Logout")
self.logout_button.setToolTip("Log out shotgrid instance")
self.logout_button.clicked.connect(self._on_shotgrid_logout_clicked)

self.buttons_layout = QtWidgets.QHBoxLayout()
self.buttons_layout.addWidget(self.login_button)

self.main_widget = QtWidgets.QVBoxLayout(self)
self.main_widget.addLayout(self.input_layout)
self.main_widget.addLayout(self.buttons_layout)
self.setLayout(self.main_widget)

def show(self, *args, **kwargs):
super(CredentialsDialog, self).show(*args, **kwargs)
self.fill_ftrack_url()

def fill_ftrack_url(self):
pass
# url = os.getenv("SHOTGRID_SERVER")
# checked_url = self.check_url(url)
# if checked_url == self.ftsite_input.text():
# return

# self.ftsite_input.setText(checked_url or "< Not set >")

# enabled = bool(checked_url)

# self.btn_login.setEnabled(enabled)
# self.btn_ftrack_login.setEnabled(enabled)

# self.api_input.setEnabled(enabled)
# self.user_input.setEnabled(enabled)

# if not url:
# self.btn_advanced.hide()
# self.btn_simple.hide()
# self.btn_ftrack_login.hide()
# self.btn_login.hide()
# self.note_label.hide()
# self.api_input.hide()
# self.user_input.hide()

def _on_shotgrid_login_clicked(self):
login = self.login_input.text().strip()
password = self.password_input.text().strip()
missing = []

if login == "":
missing.append("login")
self._invalid_input(self.login_input)

if password == "":
missing.append("password")
self._invalid_input(self.password_input)

if len(missing) > 0:
self.set_error("You didn't enter {}".format(" and ".join(missing)))
return

if not self.login_with_credentials(login, password):
self._invalid_input(self.user_input)
self._invalid_input(self.api_input)
self.set_error(
"We're unable to sign in to Ftrack with these credentials"
)

try:
sg = shotgun_api3.Shotgun(
self.url_input.text(), login=login, password=password
)

sg.preferences_read()
self._on_login()

except AuthenticationFault as err:
raise AuthenticationFault(err)

except Exception as err:
print(err)

def _on_shotgrid_logout_clicked(self):
pass

def set_error(self, msg):
self.error_label.setText(msg)
self.error_label.show()

def _on_login(self):
print(
f"You are logged into shotgrid with user {self.login_input.text()}"
)
self._is_logged = True
self._close_widget()

def _close_widget(self):
self.hide()

def _valid_input(self, input_widget):
input_widget.setStyleSheet("")

def _invalid_input(self, input_widget):
input_widget.setStyleSheet("border: 1px solid red;")
1 change: 0 additions & 1 deletion openpype/modules/shotgrid/tray/shotgrid_tray.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def show_credential_dialog(self):
self.credentials_dialog.raise_()

def tray_menu(self, tray_menu):
print(type(tray_menu))
menu = QtWidgets.QMenu("Shotgrid", tray_menu)
show_connect_action = QtWidgets.QAction("Connect to Shotgrid", menu)
show_connect_action.triggered.connect(self.show_connect_dialog)
Expand Down

0 comments on commit 6d52d47

Please sign in to comment.