def authenticate(options): """ Authenticates using the command line arguments or user input. :param options: OptionParser instance with values shotgun_host, shotgun_script_key and shotgun_script_name :returns: An authenticated ShotgunUser instance. """ # now authenticate to shotgun sg_auth = ShotgunAuthenticator() shotgun_host = options.shotgun_host or os.environ.get("SHOTGUN_HOST") if shotgun_host: script_name = options.shotgun_script_name or os.environ.get("SHOTGUN_SCRIPT_NAME") script_key = options.shotgun_script_key or os.environ.get("SHOTGUN_SCRIPT_KEY") if script_name is None or script_key is None: logger.error("Need to provide, host, script name and script key! Run with -h for more info.") return 2 logger.info("Connecting to %s using script user %s..." % (options.shotgun_host, script_name)) sg_user = sg_auth.create_script_user(script_name, script_key, shotgun_host) else: logger.info("Connect to any Shotgun site to collect AppStore keys.") # get user, prompt if necessary sg_user = sg_auth.get_user() # Make sure our session is not out of date. sg_user.refresh_credentials() return sg_user
def test_create_session_user(self, get_global_root, generate_session_token_mock, server_caps_mock): """ Makes sure that create_session_user does correct input validation. :param generate_session_token_mock: Mocked so we can skip communicating with the Shotgun server. """ generate_session_token_mock.return_value = "session_token" get_global_root.return_value = os.path.join(self.tank_temp, "session_cache") # No login should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(TestDefaultManager()).create_session_user("", "session_token") # No password or session token should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(TestDefaultManager()).create_session_user("login") # Passing a password should generate a session token user = ShotgunAuthenticator(TestDefaultManager()).create_session_user( "login", password="******", host="https://host.shotgunstudio.com" ) self.assertEquals(generate_session_token_mock.call_count, 1) self.assertEquals(user.impl.get_session_token(), "session_token") connection = user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token")
def authenticate(options): """ Authenticates using the command line arguments or user input. :param options: OptionParser instance with values shotgun_host, shotgun_script_key and shotgun_script_name :returns: An authenticated ShotgunUser instance. """ # now authenticate to shotgun sg_auth = ShotgunAuthenticator() if options.shotgun_host: script_name = options.shotgun_script_name script_key = options.shotgun_script_key if script_name is None or script_key is None: logger.error("Need to provide, host, script name and script key! Run with -h for more info.") return 2 logger.info("Connecting to %s using script user %s..." % (options.shotgun_host, script_name)) sg_user = sg_auth.create_script_user(script_name, script_key, options.shotgun_host) else: logger.info("Connect to any Shotgun site to collect AppStore keys.") # get user, prompt if necessary sg_user = sg_auth.get_user() # Make sure our session is not out of date. sg_user.refresh_credentials() return sg_user
def test_create_session_user(self, get_global_root, generate_session_token_mock, server_caps_mock): """ Makes sure that create_session_user does correct input validation. :param generate_session_token_mock: Mocked so we can skip communicating with the Shotgun server. """ generate_session_token_mock.return_value = "session_token" get_global_root.return_value = os.path.join(self.tank_temp, "session_cache") # No login should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(TestDefaultManager()).create_session_user( "", "session_token") # No password or session token should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator( TestDefaultManager()).create_session_user("login") # Passing a password should generate a session token user = ShotgunAuthenticator(TestDefaultManager()).create_session_user( "login", password="******", host="https://host.shotgunstudio.com") self.assertEquals(generate_session_token_mock.call_count, 1) self.assertEquals(user.impl.get_session_token(), "session_token") connection = user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token")
def test_create_script_user(self, server_caps_mock): """ Makes sure that create_script_user does correct input validation. """ # No script name should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(TestDefaultManager()).create_script_user("", "api_key") # No script key should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(TestDefaultManager()).create_script_user("api_script", "") # With valid values it should work user = ShotgunAuthenticator(TestDefaultManager()).create_script_user( "api_script", "api_key", "https://host.shotgunstudio.com", None ) connection = user.create_sg_connection() self.assertEqual(connection.config.script_name, "api_script") self.assertEqual(connection.config.api_key, "api_key")
def test_create_script_user(self, server_caps_mock): """ Makes sure that create_script_user does correct input validation. """ # No script name should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(CustomDefaultManager()).create_script_user("", "api_key") # No script key should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(CustomDefaultManager()).create_script_user("api_script", "") # With valid values it should work user = ShotgunAuthenticator(CustomDefaultManager()).create_script_user( "api_script", "api_key", "https://host.shotgunstudio.com", None ) connection = user.create_sg_connection() self.assertEqual(connection.config.script_name, "api_script") self.assertEqual(connection.config.api_key, "api_key")
def setUp(self): super(TestSerialize, self).setUp() # params used in creating contexts self.kws = {} self.kws["tk"] = self.tk self.kws["project"] = self.project self.kws["entity"] = self.shot self.kws["step"] = self.step self.kws["task"] = {"id": 45, "type": "Task"} self._user = ShotgunAuthenticator().create_script_user( "script_user", "script_key", "https://abc.shotgunstudio.com")
def test_serialize_without_user(self): """ Make sure the user is not serialized and not restored. """ tank.set_authenticated_user(self._user) ctx = context.Context(**self.kws) ctx_str = tank.Context.serialize(ctx) # Change the current user to make sure that the deserialize operation doesn't # change it back to the original user. other_user = ShotgunAuthenticator().create_script_user( "script_user", "script_key", "https://abc.shotgunstudio.com") tank.set_authenticated_user(other_user) # The unserialized context shouldn't have changed the current user. tank.Context.deserialize(ctx_str) self._assert_same_user(tank.get_authenticated_user(), other_user)
def test_get_current_user_uses_session(self, get_authenticated_user_mock, find_one_mock): """ When we are session based, the get_current_user method should return user associated to the session. """ find_one_mock.return_value = {"login": "******"} get_authenticated_user_mock.return_value = ShotgunAuthenticator( ).create_session_user(host="host", login="******", session_token="session_token", http_proxy=None) try: # Clear the cache so that get_current_user can work. Path cache is being updated by # TankTestBase.setUp which calls get_current_user when nothing is authenticated yet # so we need to uncache the value for the test current_user = tank.util.login.g_shotgun_current_user_cache tank.util.login.g_shotgun_current_user_cache = "unknown" user = login.get_current_user(self.tk) self.assertEqual(user["login"], "tk-user") finally: # Make sure we end up back in the original state of so new side effects are # introduced in the tests. tank.util.login.g_shotgun_current_user_cache = current_user
def main(): """ Main entry point for script. Handles argument parsing and validation and then calls the script payload. """ usage = "%prog [options] source_path target_path" desc = "Builds a standard toolkit plugin structure ready for testing and deploy" epilog = """ Details and Examples -------------------- In its simplest form, just provide a source and target folder for the build. > python build_plugin.py ~/dev/tk-maya/plugins/basic /tmp/maya-plugin For automated build setups, you can provide a specific shotgun API script name and and corresponding script key: > python build_plugin.py --shotgun-host='https://mysite.shotgunstudio.com' --shotgun-script-name='plugin_build' --shotgun-script-key='<script-key-here>' ~/dev/tk-maya/plugins/basic /tmp/maya-plugin By default, the build script will use the latest app store core for its bootstrapping. If you want to use a specific core for the bootstrap, this can be specified via the --bootstrap-core-uri option: > python build_plugin.py --bootstrap-core-uri='sgtk:descriptor:dev?path=~/dev/tk-core' ~/dev/tk-maya/plugins/basic /tmp/maya-plugin For information about the various descriptors that can be used, see http://developer.shotgunsoftware.com/tk-core/descriptor """ parser = OptionParserLineBreakingEpilog(usage=usage, description=desc, epilog=epilog) parser.add_option("-d", "--debug", default=False, action="store_true", help="Enable debug logging") parser.add_option( "-b", "--buildable", default=False, action="store_true", help= ("Don't cull config files as part of the build process. Enabling this setting " "means that the built plugin can be used as a source for another build." )) parser.add_option( "-c", "--bootstrap-core-uri", default=None, action="store", help= ("Specify which version of core to be used by the bootstrap process. " "If not specified, defaults to the most recently released core.")) group = optparse.OptionGroup( parser, "Shotgun Authentication", "In order to download content from the Toolkit app store, the script will need to authenticate " "against any shotgun site. By default, it will use the toolkit authentication APIs stored " "credentials, and if such are not found, it will prompt for site, username and password." ) group.add_option("-s", "--shotgun-host", default=None, action="store", help="Shotgun host to authenticate with.") group.add_option("-n", "--shotgun-script-name", default=None, action="store", help="Script to use to authenticate with the given host.") group.add_option( "-k", "--shotgun-script-key", default=None, action="store", help="Script key to use to authenticate with the given host.") parser.add_option_group(group) # parse cmd line (options, remaining_args) = parser.parse_args() logger.info("Welcome to the Toolkit plugin builder.") logger.info("") if options.debug: LogManager().global_debug = True if options.bootstrap_core_uri: bootstrap_core_uri = options.bootstrap_core_uri else: # default bootstrap_core_uri = None if len(remaining_args) != 2: parser.print_help() return 2 # get paths source_path = remaining_args[0] target_path = remaining_args[1] # convert any env vars and tildes source_path = os.path.expanduser(os.path.expandvars(source_path)) target_path = os.path.expanduser(os.path.expandvars(target_path)) # now authenticate to shotgun sg_auth = ShotgunAuthenticator() if options.shotgun_host: script_name = options.shotgun_script_name script_key = options.shotgun_script_key if script_name is None or script_key is None: logger.error( "Need to provide, host, script name and script key! Run with -h for more info." ) return 2 logger.info("Connecting to %s using script user %s..." % (options.shotgun_host, script_name)) sg_user = sg_auth.create_script_user(script_name, script_key, options.shotgun_host) else: # get user, prompt if necessary sg_user = sg_auth.get_user() sg_connection = sg_user.create_sg_connection() # make sure we are properly connected try: sg_connection.find_one("HumanUser", []) except Exception, e: logger.error("Could not communicate with Shotgun: %s" % e) return 3
def test_create_session_user(self, get_global_root, generate_session_token_mock, server_caps_mock): """ Makes sure that create_session_user does correct input validation. :param generate_session_token_mock: Mocked so we can skip communicating with the Shotgun server. """ generate_session_token_mock.return_value = "session_token" get_global_root.return_value = os.path.join(self.tank_temp, "session_cache") # No login should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(CustomDefaultManager()).create_session_user( "", "session_token") # No password or session token should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator( CustomDefaultManager()).create_session_user("login") # Passing a password should generate a session token session_user = ShotgunAuthenticator( CustomDefaultManager()).create_session_user( "login", password="******", host="https://host.shotgunstudio.com") self.assertIsInstance(session_user, user.ShotgunUser) self.assertNotIsInstance(session_user, user.ShotgunWebUser) self.assertNotIsInstance(session_user, user.ShotgunSamlUser) self.assertEqual(generate_session_token_mock.call_count, 1) self.assertEqual(session_user.impl.get_session_token(), "session_token") connection = session_user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token") # Passing invalid session_metadata will result in a regular ShotgunUser session_user = ShotgunAuthenticator( CustomDefaultManager())._create_session_user( "login", password="******", host="https://host.shotgunstudio.com", session_metadata="invalid session_metadata") self.assertIsInstance(session_user, user.ShotgunUser) self.assertNotIsInstance(session_user, user.ShotgunWebUser) self.assertNotIsInstance(session_user, user.ShotgunSamlUser) self.assertEqual(generate_session_token_mock.call_count, 2) self.assertEqual(session_user.impl.get_session_token(), "session_token") connection = session_user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token") # Passing valid session_metadata will result in a ShotgunWebUser session_user = ShotgunAuthenticator( CustomDefaultManager())._create_session_user( "login", password="******", host="https://host.shotgunstudio.com", session_metadata=valid_web_session_metadata) self.assertIsInstance(session_user, user.ShotgunWebUser) self.assertNotIsInstance(session_user, user.ShotgunSamlUser) self.assertEqual(generate_session_token_mock.call_count, 3) self.assertEqual(session_user.impl.get_session_token(), "session_token") connection = session_user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token") # Passing valid session_metadata will result in a ShotgunSamlUser session_user = ShotgunAuthenticator( CustomDefaultManager())._create_session_user( "login", password="******", host="https://host.shotgunstudio.com", session_metadata=valid_sso_session_metadata) self.assertIsInstance(session_user, user.ShotgunSamlUser) self.assertEqual(generate_session_token_mock.call_count, 4) self.assertEqual(session_user.impl.get_session_token(), "session_token") connection = session_user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token")
def test_get_default_user(self, generate_session_token_mock): """ Makes sure get_default_user handles all the edge cases. :param generate_session_token_mock: Mocked so we can skip communicating with the Shotgun server. """ generate_session_token_mock.return_value = "session_token" class TestWithUserDefaultManager(CustomDefaultManager): def get_host(self): return "https://unique_host.shotgunstudio.com" def get_user_credentials(self): return self.user dm = TestWithUserDefaultManager() # Make sure missing the api_script throws. dm.user = {"api_key": "api_key"} with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(dm).get_default_user() # Make sure missing the api_key throws. dm.user = {"api_script": "api_script"} with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(dm).get_default_user() # Make sure missing password or session_token throws. dm.user = {"login": "******"} with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(dm).get_default_user() # Make sure missing login throws. dm.user = {"password": "******"} with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(dm).get_default_user() # Make sure missing login throws. dm.user = {"session_token": "session_token"} with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(dm).get_default_user() # If we can't determine the user time, it should throw. dm.user = {"alien_user": "******"} with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(dm).get_default_user() # Test when the credentials are properly set up dm.user = {"api_script": "api_script", "api_key": "api_key"} self.assertIsInstance( ShotgunAuthenticator(dm).get_default_user().impl, user_impl.ScriptUser) dm.user = {"login": "******", "session_token": "session_token"} default_user = ShotgunAuthenticator(dm).get_default_user() self.assertIsInstance(default_user, user.ShotgunUser) self.assertNotIsInstance(default_user, user.ShotgunWebUser) self.assertNotIsInstance(default_user, user.ShotgunSamlUser) self.assertIsInstance(default_user.impl, user_impl.SessionUser) dm.user = {"login": "******", "password": "******"} default_user = ShotgunAuthenticator(dm).get_default_user() self.assertIsInstance(default_user, user.ShotgunUser) self.assertNotIsInstance(default_user, user.ShotgunWebUser) self.assertNotIsInstance(default_user, user.ShotgunSamlUser) self.assertIsInstance(default_user.impl, user_impl.SessionUser) dm.user = { "login": "******", "password": "******", "session_metadata": "invalid session_metadata" } default_user = ShotgunAuthenticator(dm).get_default_user() self.assertIsInstance(default_user, user.ShotgunUser) self.assertNotIsInstance(default_user, user.ShotgunWebUser) self.assertNotIsInstance(default_user, user.ShotgunSamlUser) self.assertIsInstance(default_user.impl, user_impl.SessionUser) dm.user = { "login": "******", "password": "******", "session_metadata": valid_web_session_metadata } default_user = ShotgunAuthenticator(dm).get_default_user() self.assertIsInstance(default_user, user.ShotgunWebUser) self.assertNotIsInstance(default_user, user.ShotgunSamlUser) self.assertIsInstance(default_user.impl, user_impl.SessionUser) dm.user = { "login": "******", "password": "******", "session_metadata": valid_sso_session_metadata } default_user = ShotgunAuthenticator(dm).get_default_user() self.assertIsInstance(default_user, user.ShotgunSamlUser) self.assertIsInstance(default_user.impl, user_impl.SessionUser)
def main(): """ Main entry point for script. Handles argument parsing and validation and then calls the script payload. """ usage = "%prog [options] source_path target_path" desc = "Builds a standard toolkit plugin structure ready for testing and deploy" epilog = """ Details and Examples -------------------- In its simplest form, just provide a source and target folder for the build. > python build_plugin.py ~/dev/tk-maya/plugins/basic /tmp/maya-plugin For automated build setups, you can provide a specific shotgun API script name and and corresponding script key: > python build_plugin.py --shotgun-host='https://mysite.shotgunstudio.com' --shotgun-script-name='plugin_build' --shotgun-script-key='<script-key-here>' ~/dev/tk-maya/plugins/basic /tmp/maya-plugin By default, the build script will use the latest app store core for its bootstrapping. If you want to use a specific core for the bootstrap, this can be specified via the --bootstrap-core-uri option: > python build_plugin.py --bootstrap-core-uri='sgtk:descriptor:dev?path=~/dev/tk-core' ~/dev/tk-maya/plugins/basic /tmp/maya-plugin For information about the various descriptors that can be used, see http://developer.shotgunsoftware.com/tk-core/descriptor """ parser = OptionParserLineBreakingEpilog(usage=usage, description=desc, epilog=epilog) parser.add_option( "-d", "--debug", default=False, action="store_true", help="Enable debug logging" ) parser.add_option( "-b", "--buildable", default=False, action="store_true", help=("Don't cull config files as part of the build process. Enabling this setting " "means that the built plugin can be used as a source for another build.") ) parser.add_option( "-c", "--bootstrap-core-uri", default=None, action="store", help=("Specify which version of core to be used by the bootstrap process. " "If not specified, defaults to the most recently released core.") ) group = optparse.OptionGroup( parser, "Shotgun Authentication", "In order to download content from the Toolkit app store, the script will need to authenticate " "against any shotgun site. By default, it will use the toolkit authentication APIs stored " "credentials, and if such are not found, it will prompt for site, username and password." ) group.add_option( "-s", "--shotgun-host", default=None, action="store", help="Shotgun host to authenticate with." ) group.add_option( "-n", "--shotgun-script-name", default=None, action="store", help="Script to use to authenticate with the given host." ) group.add_option( "-k", "--shotgun-script-key", default=None, action="store", help="Script key to use to authenticate with the given host." ) parser.add_option_group(group) # parse cmd line (options, remaining_args) = parser.parse_args() logger.info("Welcome to the Toolkit plugin builder.") logger.info("") if options.debug: LogManager().global_debug = True if options.bootstrap_core_uri: bootstrap_core_uri = options.bootstrap_core_uri else: # default bootstrap_core_uri = None if len(remaining_args) != 2: parser.print_help() return 2 # get paths source_path = remaining_args[0] target_path = remaining_args[1] # convert any env vars and tildes source_path = os.path.expanduser(os.path.expandvars(source_path)) target_path = os.path.expanduser(os.path.expandvars(target_path)) # now authenticate to shotgun sg_auth = ShotgunAuthenticator() if options.shotgun_host: script_name = options.shotgun_script_name script_key = options.shotgun_script_key if script_name is None or script_key is None: logger.error("Need to provide, host, script name and script key! Run with -h for more info.") return 2 logger.info("Connecting to %s using script user %s..." % (options.shotgun_host, script_name)) sg_user = sg_auth.create_script_user(script_name, script_key, options.shotgun_host) else: # get user, prompt if necessary sg_user = sg_auth.get_user() sg_connection = sg_user.create_sg_connection() # make sure we are properly connected try: sg_connection.find_one("HumanUser", []) except Exception, e: logger.error("Could not communicate with Shotgun: %s" % e) return 3
def test_create_session_user(self, get_global_root, generate_session_token_mock, server_caps_mock): """ Makes sure that create_session_user does correct input validation. :param generate_session_token_mock: Mocked so we can skip communicating with the Shotgun server. """ generate_session_token_mock.return_value = "session_token" get_global_root.return_value = os.path.join(self.tank_temp, "session_cache") # No login should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(CustomDefaultManager()).create_session_user("", "session_token") # No password or session token should throw with self.assertRaises(IncompleteCredentials): ShotgunAuthenticator(CustomDefaultManager()).create_session_user("login") # Passing a password should generate a session token session_user = ShotgunAuthenticator(CustomDefaultManager()).create_session_user( "login", password="******", host="https://host.shotgunstudio.com" ) self.assertIsInstance(session_user, user.ShotgunUser) self.assertNotIsInstance(session_user, user.ShotgunWebUser) self.assertNotIsInstance(session_user, user.ShotgunSamlUser) self.assertEqual(generate_session_token_mock.call_count, 1) self.assertEqual(session_user.impl.get_session_token(), "session_token") connection = session_user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token") # Passing invalid session_metadata will result in a regular ShotgunUser session_user = ShotgunAuthenticator(CustomDefaultManager())._create_session_user( "login", password="******", host="https://host.shotgunstudio.com", session_metadata="invalid session_metadata" ) self.assertIsInstance(session_user, user.ShotgunUser) self.assertNotIsInstance(session_user, user.ShotgunWebUser) self.assertNotIsInstance(session_user, user.ShotgunSamlUser) self.assertEqual(generate_session_token_mock.call_count, 2) self.assertEqual(session_user.impl.get_session_token(), "session_token") connection = session_user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token") # Passing valid session_metadata will result in a ShotgunWebUser session_user = ShotgunAuthenticator(CustomDefaultManager())._create_session_user( "login", password="******", host="https://host.shotgunstudio.com", session_metadata=valid_web_session_metadata ) self.assertIsInstance(session_user, user.ShotgunWebUser) self.assertNotIsInstance(session_user, user.ShotgunSamlUser) self.assertEqual(generate_session_token_mock.call_count, 3) self.assertEqual(session_user.impl.get_session_token(), "session_token") connection = session_user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token") # Passing valid session_metadata will result in a ShotgunSamlUser session_user = ShotgunAuthenticator(CustomDefaultManager())._create_session_user( "login", password="******", host="https://host.shotgunstudio.com", session_metadata=valid_sso_session_metadata ) self.assertIsInstance(session_user, user.ShotgunSamlUser) self.assertEqual(generate_session_token_mock.call_count, 4) self.assertEqual(session_user.impl.get_session_token(), "session_token") connection = session_user.create_sg_connection() self.assertEqual(connection.config.session_token, "session_token")
def _authenticate(self): # Need to set authenticated user prior to MetricDispatcher.start below user = ShotgunAuthenticator().create_script_user( "script_user", "script_key", "https://abc.shotgunstudio.com") tank.set_authenticated_user(user)