From 21a6c49aed008059eb3c821fcbc394f253a6ff36 Mon Sep 17 00:00:00 2001 From: Jamie Pezone Date: Wed, 4 Oct 2023 09:26:33 +0100 Subject: [PATCH] Implement re-authentication --- custom_components/ryanair/config_flow.py | 40 +++++++++++------ custom_components/ryanair/const.py | 1 + custom_components/ryanair/coordinator.py | 56 ++++++++++++++---------- custom_components/ryanair/manifest.json | 2 +- 4 files changed, 62 insertions(+), 37 deletions(-) diff --git a/custom_components/ryanair/config_flow.py b/custom_components/ryanair/config_flow.py index ab9108a..f42bcc6 100644 --- a/custom_components/ryanair/config_flow.py +++ b/custom_components/ryanair/config_flow.py @@ -148,15 +148,17 @@ async def async_step_mfa( # if data is not null and contains MFA TOKEN then initiate MFA capture if CUSTOMER_ID in info["data"]: users = load_json_object(CREDENTIALS) - ryanairData = { - CONF_DEVICE_FINGERPRINT: user_input[CONF_DEVICE_FINGERPRINT], - CUSTOMER_ID: info["data"][CUSTOMER_ID], - TOKEN: info["data"][TOKEN], - } - users[user_input[CONF_DEVICE_FINGERPRINT]] = ryanairData + + users[user_input[CONF_DEVICE_FINGERPRINT] + ][CONF_DEVICE_FINGERPRINT] = user_input[CONF_DEVICE_FINGERPRINT] + users[user_input[CONF_DEVICE_FINGERPRINT] + ][CUSTOMER_ID] = info["data"][CUSTOMER_ID] + users[user_input[CONF_DEVICE_FINGERPRINT] + ][TOKEN] = info["data"][TOKEN] + save_json(CREDENTIALS, users) return self.async_create_entry( - title=info["title"], data=ryanairData + title=info["title"], data=users[user_input[CONF_DEVICE_FINGERPRINT]] ) return self.async_show_form( @@ -187,6 +189,14 @@ async def async_step_user( user_input[CONF_DEVICE_FINGERPRINT] = self._fingerprint + users = load_json_object(CREDENTIALS) + ryanairData = { + CONF_EMAIL: user_input[CONF_EMAIL], + CONF_PASSWORD: user_input[CONF_PASSWORD], + CONF_DEVICE_FINGERPRINT: user_input[CONF_DEVICE_FINGERPRINT], + } + users[user_input[CONF_DEVICE_FINGERPRINT]] = ryanairData + save_json(CREDENTIALS, users) try: info = await validate_input(self.hass, user_input) except CannotConnect: @@ -211,15 +221,17 @@ async def async_step_user( ) if CUSTOMER_ID in info["data"]: users = load_json_object(CREDENTIALS) - ryanairData = { - CONF_DEVICE_FINGERPRINT: user_input[CONF_DEVICE_FINGERPRINT], - CUSTOMER_ID: info["data"][CUSTOMER_ID], - TOKEN: info["data"][TOKEN], - } - users[user_input[CONF_DEVICE_FINGERPRINT]] = ryanairData + + users[user_input[CONF_DEVICE_FINGERPRINT] + ][CONF_DEVICE_FINGERPRINT] = user_input[CONF_DEVICE_FINGERPRINT] + users[user_input[CONF_DEVICE_FINGERPRINT] + ][CUSTOMER_ID] = info["data"][CUSTOMER_ID] + users[user_input[CONF_DEVICE_FINGERPRINT] + ][TOKEN] = info["data"][TOKEN] + save_json(CREDENTIALS, users) return self.async_create_entry( - title=info["title"], data=ryanairData + title=info["title"], data=users[user_input[CONF_DEVICE_FINGERPRINT]] ) return self.async_show_form( diff --git a/custom_components/ryanair/const.py b/custom_components/ryanair/const.py index 658fab7..1d355b5 100644 --- a/custom_components/ryanair/const.py +++ b/custom_components/ryanair/const.py @@ -11,6 +11,7 @@ BOARDING_PASS_URL = "https://mntappbp.ryanair.com/v1/boardingpass" BOOKING_DETAILS_URL = "https://nativeapps.ryanair.com/booking/rest/en-IE/query/getbookingbybookingid" EMAIL = "Email" +PASSWORD = "password" RECORD_LOCATOR = "RecordLocator" USER_PROFILE = "usrprof/" ORDERS = "orders/" diff --git a/custom_components/ryanair/coordinator.py b/custom_components/ryanair/coordinator.py index b8901ab..eabc3e6 100644 --- a/custom_components/ryanair/coordinator.py +++ b/custom_components/ryanair/coordinator.py @@ -80,11 +80,21 @@ async def rememberMeToken(self, userData): }, ) rememberMeTokenResponse = await rememberMeTokenResp.json() - print(rememberMeTokenResponse) + users = load_json_object(CREDENTIALS) - users[userData[CONF_DEVICE_FINGERPRINT] - ][X_REMEMBER_ME_TOKEN] = rememberMeTokenResponse[TOKEN] + if rememberMeTokenResponse is not None and ((ACCESS_DENIED in rememberMeTokenResponse and rememberMeTokenResponse[CAUSE] == NOT_AUTHENTICATED) or ( + TYPE in rememberMeTokenResponse and rememberMeTokenResponse[TYPE] == CLIENT_ERROR + )): + authResponse = await authenticateUser(self, userData) + + users[userData[CONF_DEVICE_FINGERPRINT] + ][TOKEN] = authResponse[TOKEN] + users[userData[CONF_DEVICE_FINGERPRINT] + ][CUSTOMER_ID] = authResponse[CUSTOMER_ID] + else: + users[userData[CONF_DEVICE_FINGERPRINT] + ][X_REMEMBER_ME_TOKEN] = rememberMeTokenResponse[TOKEN] save_json(CREDENTIALS, users) @@ -177,6 +187,24 @@ async def getBookingDetails(self, data, bookingInfo): return body +async def authenticateUser(self, userData): + resp = await self.session.request( + method="POST", + url=USER_PROFILE_URL + ACCOUNT_LOGIN, + headers={ + "Content-Type": CONTENT_TYPE_JSON, + CONF_DEVICE_FINGERPRINT: userData[CONF_DEVICE_FINGERPRINT], + }, + json={ + CONF_EMAIL: userData[CONF_EMAIL], + CONF_PASSWORD: userData[CONF_PASSWORD], + CONF_POLICY_AGREED: "true", + }, + ) + body = await resp.json() + return body + + class RyanairBookingDetailsCoordinator(DataUpdateCoordinator): """Booking Details Coordinator""" @@ -488,7 +516,7 @@ async def _async_update_data(self): class RyanairCoordinator(DataUpdateCoordinator): """Data coordinator.""" - def __init__(self, hass: HomeAssistant, session, data) -> None: + def __init__(self, hass: HomeAssistant, session, userData) -> None: """Initialize coordinator.""" super().__init__( @@ -501,9 +529,7 @@ def __init__(self, hass: HomeAssistant, session, data) -> None: ) self.session = session - self.email = data[CONF_EMAIL] - self.password = data[CONF_PASSWORD] - self.fingerprint = data[CONF_DEVICE_FINGERPRINT] + self.userData = userData async def _async_update_data(self): """Fetch data from API endpoint. @@ -512,21 +538,7 @@ async def _async_update_data(self): so entities can quickly look up their data. """ try: - resp = await self.session.request( - method="POST", - url=USER_PROFILE_URL + ACCOUNT_LOGIN, - headers={ - "Content-Type": CONTENT_TYPE_JSON, - CONF_DEVICE_FINGERPRINT: self.fingerprint, - }, - json={ - CONF_EMAIL: self.email, - CONF_PASSWORD: self.password, - CONF_POLICY_AGREED: "true", - }, - ) - body = await resp.json() - + body = await authenticateUser(self, self.userData) except InvalidAuth as err: raise ConfigEntryAuthFailed from err except RyanairError as err: diff --git a/custom_components/ryanair/manifest.json b/custom_components/ryanair/manifest.json index 1f4ef57..f7d2128 100644 --- a/custom_components/ryanair/manifest.json +++ b/custom_components/ryanair/manifest.json @@ -12,6 +12,6 @@ "issue_tracker": "https://github.com/jampez77/Ryanair/issues", "requirements": ["aztec-code-generator==0.11"], "ssdp": [], - "version": "2023.10.0", + "version": "2023.10.1", "zeroconf": [] } \ No newline at end of file