diff --git a/blinkpy/blinkpy.py b/blinkpy/blinkpy.py index 18dc25f..b9d98c0 100644 --- a/blinkpy/blinkpy.py +++ b/blinkpy/blinkpy.py @@ -29,7 +29,7 @@ from blinkpy.helpers.util import ( create_session, merge_dicts, get_time, BlinkURLHandler, BlinkAuthenticationException) from blinkpy.helpers.constants import ( - BLINK_URL, LOGIN_URL, LOGIN_BACKUP_URL) + BLINK_URL, LOGIN_URL, OLD_LOGIN_URL, LOGIN_BACKUP_URL) from blinkpy.helpers.constants import __version__ REFRESH_RATE = 30 @@ -119,33 +119,12 @@ class Blink(): if not isinstance(self._password, str): raise BlinkAuthenticationException(ERROR.PASSWORD) - login_url = LOGIN_URL - response = api.request_login(self, - login_url, - self._username, - self._password, - is_retry=is_retry) - try: - if response.status_code != 200: - _LOGGER.debug("Received response code %s during login.", - response.status_code) - login_url = LOGIN_BACKUP_URL - response = api.request_login(self, - login_url, - self._username, - self._password, - is_retry=is_retry) - response = response.json() - (self.region_id, self.region), = response['region'].items() - except AttributeError: - _LOGGER.error("Login API endpoint failed with response %s", - response, - exc_info=True) + login_urls = [LOGIN_URL, OLD_LOGIN_URL, LOGIN_BACKUP_URL] + + response = self.login_request(login_urls, is_retry=is_retry) + + if not response: return False - except KeyError: - _LOGGER.warning("Could not extract region info.") - self.region_id = 'piri' - self.region = 'UNKNOWN' self._host = "{}.{}".format(self.region_id, BLINK_URL) self._token = response['authtoken']['authtoken'] @@ -154,10 +133,44 @@ class Blink(): self._auth_header = {'Host': self._host, 'TOKEN_AUTH': self._token} self.urls = BlinkURLHandler(self.region_id) - self._login_url = login_url return self._auth_header + def login_request(self, login_urls, is_retry=False): + """Make a login request.""" + try: + login_url = login_urls.pop(0) + except IndexError: + _LOGGER.error("Could not login to blink servers.") + return False + + _LOGGER.info("Attempting login with %s", login_url) + + response = api.request_login(self, + login_url, + self._username, + self._password, + is_retry=is_retry) + try: + if response.status_code != 200: + response = self.login_request(login_urls) + response = response.json() + (self.region_id, self.region), = response['region'].items() + + except AttributeError: + _LOGGER.error("Login API endpoint failed with response %s", + response, + exc_info=True) + return False + + except KeyError: + _LOGGER.warning("Could not extract region info.") + self.region_id = 'piri' + self.region = 'UNKNOWN' + + self._login_url = login_url + return response + def get_ids(self): """Set the network ID and Account ID.""" response = api.request_networks(self) diff --git a/blinkpy/helpers/constants.py b/blinkpy/helpers/constants.py index 1b59f97..b9f3b40 100644 --- a/blinkpy/helpers/constants.py +++ b/blinkpy/helpers/constants.py @@ -47,7 +47,8 @@ URLS BLINK_URL = 'immedia-semi.com' DEFAULT_URL = "{}.{}".format('prod', BLINK_URL) BASE_URL = "https://{}".format(DEFAULT_URL) -LOGIN_URL = "{}/login".format(BASE_URL) +LOGIN_URL = "{}/api/v2/login".format(BASE_URL) +OLD_LOGIN_URL = "{}/login".format(BASE_URL) LOGIN_BACKUP_URL = "https://{}.{}/login".format('rest.piri', BLINK_URL) ''' diff --git a/tests/test_blink_functions.py b/tests/test_blink_functions.py index d5d10ab..3607a73 100644 --- a/tests/test_blink_functions.py +++ b/tests/test_blink_functions.py @@ -2,7 +2,6 @@ import unittest from unittest import mock import logging -from requests import Request from blinkpy import blinkpy from blinkpy.sync_module import BlinkSyncModule @@ -56,24 +55,32 @@ class TestBlinkFunctions(unittest.TestCase): """Clean up after test.""" self.blink = None - @mock.patch('blinkpy.blinkpy.api.http_req') + @mock.patch('blinkpy.blinkpy.api.request_login') def test_backup_url(self, req, mock_sess): """Test backup login method.""" - fake_req = Request('POST', 'http://wrong.url').prepare() json_resp = { 'authtoken': {'authtoken': 'foobar123'}, 'networks': {'1234': {'name': 'foobar', 'onboarded': True}} } + bad_req = mresp.MockResponse({}, 404) new_req = mresp.MockResponse(json_resp, 200) req.side_effect = [ - mresp.mocked_session_send(fake_req), + bad_req, + bad_req, new_req ] - self.blink.get_auth_token() - self.assertEqual(self.blink.region_id, 'piri') - self.assertEqual(self.blink.region, 'UNKNOWN') + self.blink.login_request(['test1', 'test2', 'test3']) # pylint: disable=protected-access - self.assertEqual(self.blink._token, 'foobar123') + self.assertEqual(self.blink._login_url, 'test3') + + req.side_effect = [ + bad_req, + new_req, + bad_req + ] + self.blink.login_request(['test1', 'test2', 'test3']) + # pylint: disable=protected-access + self.assertEqual(self.blink._login_url, 'test2') def test_merge_cameras(self, mock_sess): """Test merge camera functionality."""