"""Interface to the ows-users microservice.""" from ddtrace import tracer from flask import g from oto import response as oto_response from owsrequest.constants import headers as owsrequest_headers from analytics.constants import access as access_constants from analytics.constants import service as service_constants from analytics.services import request # we should allow administrators to use the mobile app if Mobile # is enabled on account level feature control PERMITTED_ROLES = [access_constants.ROLE_ADMINISTRATOR, access_constants.ROLE_ANALYTICS] @tracer.wrap(name="user_has_access") def user_has_access(account_id, account_type, user_id): """Check if user has an access to the mobile app. Args: account_id (str): Vendor unique identifier account_type (str): Vendor or subaccount user_id (str): Orchard-User-Id, e.g. alw:48071 Return bool: True if user has an access to mobile or Administrator feature, False otherwise """ headers = { owsrequest_headers.GRASS_ACCOUNT_TYPE: account_type, owsrequest_headers.GRASS_ACCOUNT_ID: account_id, owsrequest_headers.ORCHARD_USER_ID: user_id, } ows_users_response = _check_users_roles_endpoint(headers) if ows_users_response.status_code != 200: _log_failure(ows_users_response) ows_users_response = _check_session_endpoint(headers) result = _correct_roles_in_response(ows_users_response) return oto_response.Response(message=result) @tracer.wrap(name="get_linked_accounts") def get_linked_accounts(user_id): """Get a users linked accounts. Args: user_id (str): Orchard-User-Id, e.g. alw:48071 Return list: Of linked accounts """ ows_users_response = request.get( service_constants.OWS_USERS, service_constants.OWS_USERS_LINKED_ACCOUNTS_RESOURCE.format( user_id=str(user_id).lstrip("alw:") ), ) if ows_users_response.status_code != 200: raise Exception( "ows_users response error for resource {resource}: " "status code - {status_code}, reason - {reason}, Correlation-Id - " "{correlation_id}".format( resource=service_constants.OWS_USERS_LINKED_ACCOUNTS_RESOURCE, status_code=ows_users_response.status_code, reason=ows_users_response.reason, correlation_id=ows_users_response.headers.get("correlation-id"), ) ) return ows_users_response.json() def _check_users_roles_endpoint(headers): """Return response from OWS_USERS_ROLES_RESOURCE.""" ows_users_response = request.get( service_constants.OWS_USERS, service_constants.OWS_USERS_ROLES_RESOURCE, headers=headers, ) return ows_users_response def _log_failure(ows_users_response): """Log error.""" g.log.info( "Roles access failed with status code {status_code}".format( status_code=ows_users_response.status_code ) ) def _check_session_endpoint(headers): """Return response from OWS_USERS_METADATA_RESOURCE.""" ows_metadata_response = request.get( service_constants.OWS_USERS, service_constants.OWS_USERS_METADATA_RESOURCE, headers=headers, ) if ows_metadata_response.status_code != 200: raise Exception( "ows_users response error for resource {resource}: " "status code - {status_code}, reason - {reason}, Correlation-Id - " "{correlation_id}".format( resource=service_constants.OWS_USERS_METADATA_RESOURCE, status_code=ows_metadata_response.status_code, reason=ows_metadata_response.reason, correlation_id=ows_metadata_response.headers.get("correlation-id"), ) ) return ows_metadata_response def _correct_roles_in_response(response): """Return True if user has access and False if not.""" result = False response_body = response.json() if "vend_contact_roles" in response_body: roles = [item["role"]["role"] for item in response_body["vend_contact_roles"]] elif "role_names" in response_body: roles = response_body["role_names"] result = any([True for r in roles if r in PERMITTED_ROLES]) return result