def send_call_message(device, unique_key, phonenumber, caller_id, attempt): """ Function to send the call push notification. Args: device (Device): A Device object. unique_key (string): String with the unique_key. phonenumber (string): Phonenumber that is calling. caller_id (string): ID of the caller. attempt (int): The amount of attempts made. """ data = { 'unique_key': unique_key, 'phonenumber': phonenumber, 'caller_id': caller_id, 'attempt': attempt, } if device.app.platform == APNS_PLATFORM: send_apns_message(device, device.app, TYPE_CALL, data) elif device.app.platform == GCM_PLATFORM: send_gcm_message(device, device.app, TYPE_CALL, data) elif device.app.platform == ANDROID_PLATFORM: send_fcm_message(device, device.app, TYPE_CALL, data) else: log_middleware_information( '{0} | Trying to sent \'call\' notification to unknown platform:{1} device:{2}', OrderedDict([ ('unique_key', unique_key), ('platform', device.app.platform), ('token', device.token), ]), logging.WARNING, device=device, )
def post(self, request): """ Handle the post request of this view. Args: request (Request): Containing the post data. Returns: json: Status key with OK value. """ serialized_data = self._serialize_request(request) unique_key = serialized_data['unique_key'] message_start_time = serialized_data['message_start_time'] available = serialized_data['available'] cache_key = 'call_{0}'.format(unique_key) redis_cache = RedisClusterCache() # Check if key exists to avoid endpoint probing spam. if not redis_cache.exists(cache_key): return Response('', status=HTTP_404_NOT_FOUND) # Wait loop for asterisk sets the device platform as placeholder # for the available flag. platform = redis_cache.get(cache_key) redis_cache.set(cache_key, available) roundtrip = time.time() - float(message_start_time) log_middleware_information( '{0} | Device responded. Message start-time: {1} sec, round trip-time: {2} sec', OrderedDict([ ('unique_key', unique_key), ('starttime', datetime.datetime.fromtimestamp(message_start_time)), ('roundtrip', roundtrip), ]), logging.INFO, ) # Threaded task to log information to the database. log_to_db(platform, roundtrip, available) # If device responded too late return 404 request (call) not found. if (roundtrip > (settings.APP_PUSH_ROUNDTRIP_WAIT / 1000)): return Response('', status=HTTP_404_NOT_FOUND) return Response('', status=HTTP_202_ACCEPTED)
def _serialize_data(self, data, serializer_class=None): """ Function to serialize data with the serializer given in the serializer_class attribute. Also validates the data and responds with a HTTP_400_BAD_REQUEST when validation failed. Due to being an open api we do not want to give away the required fields and their requirements. Args: data(dict): Dictonary with that data that need to be serialized. serializer_class(Serializer): Class to use for serialization. Returns: dict: Dictionary with the validated data. Raises: NotImplementedError: When serializer_class attribute is not set. ParseError: When validation fails but because it's an open API we do not want to give away what failed. ParseError returns a HTTP_400_BAD_REQUEST. """ if serializer_class is None: if self.serializer_class is None: raise NotImplementedError( 'serializer_class Attribute should be set') else: self.serializer_class = serializer_class serializer = self.serializer_class(data=data) if not serializer.is_valid(raise_exception=False): # Log errors. log_middleware_information( 'BAD REQUEST! Serialization failed with following errors:\n\n{0}\n\nData:\n\n{1}', OrderedDict([ ('serializer_errors', serializer.errors), ('data', data), ]), logging.INFO, ) # This raises a bad request response. raise ParseError(detail=None) return serializer.validated_data
def _check_status_code(self, status_code): """ Function for checking the status code. Args: status_code(int): That status code of a response. """ if status_code == 200: return elif status_code == 401: raise AuthenticationFailed(detail=None) elif status_code == 403: raise PermissionDenied(detail=None) else: # Temporarily unavailable. log_middleware_information( 'Unsupported VG response code {0}', OrderedDict([ ('status_code', status_code), ]), logging.WARNING, ) raise UnavailableException(detail=None)
def post(self, request): """ Function to log the reason for a device. """ serialized_data = self._serialize_request(request) reason = serialized_data['reason'] unique_key = serialized_data['unique_key'] sip_user_id = serialized_data['sip_user_id'] try: # Check if there is a registered device for given sip_user_id. device = get_object_or_404(Device, sip_user_id=sip_user_id) except Http404: log_middleware_information( '{0} | Failed to find a device for SIP_user_ID : {1}', OrderedDict([ ('unique_key', unique_key), (LOG_SIP_USER_ID, sip_user_id), ]), logging.WARNING, ) raise log_middleware_information( '{0} | {1} Device not available because: {2} on {3}', OrderedDict([ ('unique_key', unique_key), ('platform', device.app.platform.upper()), ('reason', reason), ('timestamp', datetime.datetime.fromtimestamp( time.time()).strftime('%H:%M:%S.%f')), ]), logging.INFO, device=device, ) return Response(status=HTTP_200_OK)
def send_text_message(device, app, message): """ Function to send a push notification with a message. Args: device (Device): A Device object. message (string): The message that needs to be send to the device. """ if app.platform == APNS_PLATFORM: send_apns_message(device, app, TYPE_MESSAGE, {'message': message}) elif app.platform == GCM_PLATFORM: send_gcm_message(device, app, TYPE_MESSAGE, {'message': message}) elif app.platform == ANDROID_PLATFORM: send_fcm_message(device, app, TYPE_MESSAGE, {'message': message}) else: log_middleware_information( 'Trying to sent \'message\' notification to unknown platform:{0} device:{1}', OrderedDict([ ('platform', device.app.platform), ('token', device.token), ]), logging.WARNING, device=device, )
def get_apns2_connection(app, device, unique_key): """ Get the active APNSv2 connection. This returns a reference to the global connection object, and initializes it if the connection was not yet made. Args: app (App): App requesting the connection. device (Device): Device requesting the connection. unique_key (str): Unique key used for logging. Returns: APNsClient. """ global apns2_connection_pool if app.app_id not in apns2_connection_pool: full_cert_path = os.path.join(settings.CERT_DIR, app.push_key) apns2_connection = APNsClient(full_cert_path, use_sandbox=settings.APNS_IS_SANDBOX) log_middleware_information( '{0} | Opened new connection to APNSv2 for app_id: {1}', OrderedDict([ ('token', unique_key), ('app_id', app.app_id), ]), logging.INFO, device=device, ) apns2_connection_pool.update({app.app_id: apns2_connection}) else: # Test the existing connection, will throw an exception if this fails. apns2_connection = apns2_connection_pool[app.app_id] apns2_connection.connect() return apns2_connection
def delete(self, request, platform): """ Function for deleting a Device. """ serialized_data = self._serialize_request( request, serializer_class=DeleteDeviceSerializer) token = serialized_data['token'] sip_user_id = serialized_data['sip_user_id'] app_id = serialized_data['app'] try: device = get_object_or_404( Device, sip_user_id=sip_user_id, token=token, app__app_id=app_id, app__platform=platform, ) device.delete() except Http404: log_middleware_information( 'Could not unregister device {0} for SIP_USER_ID {1}', OrderedDict([ ('token', token), (LOG_SIP_USER_ID, sip_user_id), ]), logging.WARNING, ) raise except Exception: log_middleware_information( 'EXCEPTION WHILE UNREGISTERING DEVICE {0} FOR SIP_USER_ID : {1}', OrderedDict([ ('token', token), (LOG_SIP_USER_ID, sip_user_id), ]), logging.CRITICAL, ) raise log_middleware_information( 'Unregistered device {0} for SIP_USER_ID {1}', OrderedDict([ ('token', token), (LOG_SIP_USER_ID, sip_user_id), ]), logging.INFO, device=device, ) return Response('', status=HTTP_200_OK)
def send_gcm_message(device, app, message_type, data=None): """ Send a Google Cloud Messaging message. """ token_list = [device.token] unique_key = device.token key = '%d-cycle.key' % int(time()) if message_type == TYPE_CALL: unique_key = data['unique_key'] message = get_call_push_payload( unique_key, data['phonenumber'], data['caller_id'], data['attempt'], ) elif message_type == TYPE_MESSAGE: message = get_message_push_payload(data['message']) else: log_middleware_information( '{0} | Trying to sent message of unknown type: {1}', OrderedDict([ ('unique_key', unique_key), ('message_type', message_type), ]), logging.WARNING, device=device, ) gcm = GCM(app.push_key) try: start_time = time() response = gcm.json_request( registration_ids=token_list, data=message, collapse_key=key, priority='high', ) success = response.get('success') canonical = response.get('canonical') errors = response.get('errors') if success: for reg_id, msg_id in success.items(): log_middleware_information( '{0} | GCM \'{1}\' message sent at time:{2} to {3}', OrderedDict([ ('unique_key', unique_key), ('message_type', message_type), ('sent_time', datetime.datetime.fromtimestamp(start_time).strftime( '%H:%M:%S.%f')), ('registration_id', reg_id), ]), logging.INFO, device=device, ) if canonical: for reg_id, new_reg_id in canonical.items(): log_middleware_information( '{0} | Should replace device token {1} with {2} in database', OrderedDict([ ('unique_key', unique_key), ('registration_id', reg_id), ('new_registration_id', new_reg_id), ]), logging.WARNING, device=device, ) if errors: for err_code, reg_id in errors.items(): log_middleware_information( '{0} | Should remove {1} because {2}', OrderedDict([ ('unique_key', unique_key), ('registration_id', reg_id), ('error_code', err_code), ]), logging.WARNING, device=device, ) except GCMAuthenticationException: # Stop and fix your settings. log_middleware_information( '{0} | Our Google API key was rejected!!!', OrderedDict([ ('unique_key', unique_key), ]), logging.ERROR, device=device, ) except ValueError: # Probably your extra options, such as time_to_live, # are invalid. Read error message for more info. log_middleware_information( '{0} | Invalid message/option or invalid GCM response', OrderedDict([ ('unique_key', unique_key), ]), logging.ERROR, device=device, ) except Exception: log_middleware_information( '{0} | Error sending GCM message', OrderedDict([ ('unique_key', unique_key), ]), logging.CRITICAL, device=device, )
def send_fcm_message(device, app, message_type, data=None): """ Function for sending a push message using firebase. """ registration_id = device.token unique_key = device.token if message_type == TYPE_CALL: unique_key = data['unique_key'] message = get_call_push_payload( unique_key, data['phonenumber'], data['caller_id'], data['attempt'], ) elif message_type == TYPE_MESSAGE: message = get_message_push_payload(data['message']) else: log_middleware_information( '{0} | Trying to sent message of unknown type: {1}', OrderedDict([ ('unique_key', unique_key), ('message_type', message_type), ]), logging.WARNING, device=device, ) push_service = FCMNotification(api_key=app.push_key) try: start_time = time() result = push_service.notify_single_device( registration_id=registration_id, data_message=message) except AuthenticationError: log_middleware_information( '{0} | Our Google API key was rejected!!!', OrderedDict([ ('unique_key', unique_key), ]), logging.ERROR, device=device, ) except InternalPackageError: log_middleware_information( '{0} | Bad api request made by package.', OrderedDict([ ('unique_key', unique_key), ]), logging.ERROR, device=device, ) except FCMServerError: log_middleware_information( '{0} | FCM Server error.', OrderedDict([ ('unique_key', unique_key), ]), logging.ERROR, device=device, ) else: if result.get('success'): log_middleware_information( '{0} | FCM \'{1}\' message sent at time:{2} to {3}', OrderedDict([ ('unique_key', unique_key), ('message_type', message_type), ('sent_time', datetime.datetime.fromtimestamp( start_time).strftime('%H:%M:%S.%f')), ('registration_id', registration_id), ]), logging.INFO, device=device, ) if result.get('failure'): log_middleware_information( '{0} | Should remove {1} because {2}', OrderedDict([ ('unique_key', unique_key), ('registration_id', registration_id), ('results', result['results']), ]), logging.WARNING, device=device, ) if (len(result['results']) > 0 and 'error' in result['results'][0] and result['results'][0]['error'] == 'NotRegistered'): log_middleware_information( '{0} | Removed {1}', OrderedDict([ ('unique_key', unique_key), ('device', device), ]), logging.INFO, ) # Remove the unique key from the cache so we can sent # NAK to asterisk. redis_cache = RedisClusterCache() if redis_cache.exists(unique_key): redis_cache.set(unique_key, "Removed") device.delete() if result.get('canonical_ids'): log_middleware_information( '{0} | Should replace device token {1}', OrderedDict([ ('unique_key', unique_key), ('registration_id', registration_id), ]), logging.WARNING, device=device, )
def send_apns_message(device, app, message_type, data=None): """ Send an Apple Push Notification message via the new v2 API. """ unique_key = device.token if message_type == TYPE_CALL: unique_key = data['unique_key'] message = Payload(custom=get_call_push_payload( unique_key, data['phonenumber'], data['caller_id'], data['attempt'], )) elif message_type == TYPE_MESSAGE: message = Payload(custom=get_message_push_payload(data['message'])) else: log_middleware_information( '{0} | TRYING TO SENT MESSAGE OF UNKNOWN TYPE: {1}', OrderedDict([ ('unique_key', unique_key), ('message_type', message_type), ]), logging.WARNING, device=device, ) # Unknown message type: ignore this message. return # Get the APNSv2 connection. There is one global connection. client = get_apns2_connection(app, device, unique_key) try: log_middleware_information( '{0} | Sending APNSv2 \'{1}\' message at time:{2} to {3}', OrderedDict([ ('unique_key', unique_key), ('message_type', message_type), ('message_time', datetime.datetime.fromtimestamp( time()).strftime('%H:%M:%S.%f')), ('token', device.token), ]), logging.INFO, device=device, ) start_time = time() try: client.send_notification(device.token, message) finally: elapsed_time = time() - start_time log_middleware_information( '{0} | Sending message to APNSv2 took {1:.2f}s', OrderedDict([ ('unique_key', unique_key), ('conn_time', elapsed_time), ]), logging.INFO, device=device, ) except (DeviceTokenNotForTopic, BadDeviceToken, Unregistered) as ex: # According to APNs protocol the token reported here # is garbage (invalid or empty), stop using and remove it. log_middleware_information( '{0} | Sending APNSv2 message failed for device: {1}, reason: {2}', OrderedDict([ ('unique_key', unique_key), ('token', device.token), ('error_msg', type(ex).__name__), ]), logging.WARNING, device=device, ) except APNsException as ex: # Failures not related to devices. log_middleware_information( '{0} | Error sending APNSv2 message. \'{1}\'', OrderedDict([ ('unique_key', unique_key), ('error_msg', type(ex).__name__), ]), logging.WARNING, device=device, ) except Exception: log_middleware_information( '{0} | Error sending APNSv2 message', OrderedDict(unique_key=unique_key, ), logging.CRITICAL, device=device, )
def post(self, request, platform): """ Function to create or update a Device. """ serialized_data = self._serialize_request(request) token = serialized_data['token'] sip_user_id = serialized_data['sip_user_id'] app_id = serialized_data['app'] remote_logging_id = serialized_data.get('remote_logging_id') app = get_object_or_404(App, app_id=app_id, platform=platform) device, created = Device.objects.update_or_create( sip_user_id=sip_user_id, defaults={ 'app_id': app.id, 'token': token, 'remote_logging_id': remote_logging_id, }) # Track status. status = 'OK' # Update token. if device.token != token: if not created: task_notify_old_token(device, device.app) status += ' updated and send notify to old token' else: status += ' and updated token' device.token = token # Update remote_logging_id. if device.remote_logging_id != remote_logging_id: device.remote_logging_id = remote_logging_id status += ', updated the remote_logging_id' # Update fields. device.name = serialized_data.get('name', None) device.os_version = serialized_data.get('os_version', None) device.client_version = serialized_data.get('client_version', None) device.last_seen = timezone.now() device.sandbox = serialized_data['sandbox'] device.app = app device.save() status_code = HTTP_200_OK if created: status_code = HTTP_201_CREATED log_middleware_information( '{0} {1} device:{2} registered for SIP_USER_ID: {3}. Status: {4}.', OrderedDict([ ('app_id', app_id), ('platform', device.app.platform.upper()), ('device_token', device.token), (LOG_SIP_USER_ID, sip_user_id), ('status', status), ]), logging.INFO, device=device, ) return Response('', status=status_code)
def post(self, request): """ Handle post requests on this view. Args: request (Request): Containing the post data. Returns: string: With status=ACK or status=NAK based on succes or failure. Raises: Http404: When an app_id is provided that does not exist. """ redis_cache = RedisClusterCache() serialized_data = self._serialize_request(request) sip_user_id = serialized_data['sip_user_id'] caller_id = serialized_data['caller_id'] phonenumber = serialized_data['phonenumber'] call_id = serialized_data['call_id'] if not call_id: # Generate unique_key for reference on incoming call answer. unique_key = random.getrandbits(128) unique_key = '%032x' % unique_key else: unique_key = call_id try: # Check if there is a registered device for given sip_user_id. device = get_object_or_404(Device, sip_user_id=sip_user_id) except Http404: log_middleware_information( '{0} | Failed to find a device for SIP_user_ID : {1} sending NAK', OrderedDict([ ('unique_key', unique_key), (LOG_SIP_USER_ID, sip_user_id), ]), logging.WARNING, ) # Push data to Redis for when a sip user id couldn't be found. redis_cache.client.rpush( VIALER_MIDDLEWARE_INCOMING_CALL_FAILED_TOTAL_KEY, { OS_KEY: 'Middleware', ACTION_KEY: 'Received', FAILED_REASON_KEY: 'failed no sip_user_id', }) # Log to the metrics file. metrics_data = { OS_KEY: 'Middleware', ACTION_KEY: 'Received', FAILED_REASON_KEY: 'failed no sip_user_id', 'unique_key': unique_key, } log_data_to_metrics_log(metrics_data, sip_user_id) except Exception: log_middleware_information( '{0} | EXCEPTION WHILE FINDING DEVICE FOR SIP_USER_ID : {1}', OrderedDict([ ('unique_key', unique_key), (LOG_SIP_USER_ID, sip_user_id), ]), logging.CRITICAL, ) else: log_middleware_information( '{0} | Incoming call for SIP:{1} FROM:\'{2}/{3}\'', OrderedDict([ ('unique_key', unique_key), (LOG_SIP_USER_ID, sip_user_id), (LOG_CALL_FROM, phonenumber), (LOG_CALLER_ID, caller_id), ]), logging.INFO, device=device, ) # Push data to Redis for when a incoming call is received. redis_cache.client.rpush( VIALER_MIDDLEWARE_INCOMING_CALL_SUCCESS_TOTAL_KEY, { OS_KEY: 'Middleware', ACTION_KEY: 'Received', }) # Log to the metrics file. metrics_data = { OS_KEY: 'Middleware', ACTION_KEY: 'Received', 'unique_key': unique_key, } log_data_to_metrics_log(metrics_data, sip_user_id) attempt = 1 # Send push message to wake up app. task_incoming_call_notify( device, unique_key, phonenumber, caller_id, attempt, ) # Time related settings. wait_interval = settings.APP_PUSH_ROUNDTRIP_WAIT / 1000 wait_until = time.time() + wait_interval resend_interval = settings.APP_PUSH_RESEND_INTERVAL / 1000 next_resend_time = time.time() + resend_interval # Determine max possible attempts. Avoid sending a push # close to the end of the loop. max_attemps = int(wait_interval / resend_interval) - 1 cache_key = 'call_{0}'.format(unique_key) # Create cache entry with device platform as placeholder for the # available flag. Done for logging purposes. redis_cache.set(cache_key, device.app.platform) log_middleware_information( '{0} | {1} Starting \'wait for it\' loop until {2} ({3}msec)', OrderedDict([ ('unique_key', unique_key), ('platform', device.app.platform.upper()), ('wait_until', datetime.datetime.fromtimestamp( wait_until).strftime('%H:%M:%S.%f')), ('roundtrip', settings.APP_PUSH_ROUNDTRIP_WAIT), ]), logging.INFO, device=device, ) # We have to wait till the app responds and sets the cache value. while time.time() < wait_until: available = redis_cache.get(cache_key) # Get on an empty key returns None so we need to check for # True and False. if available == 'True': log_middleware_information( '{0} | {1} Device checked in on time, sending ACK on {2}', OrderedDict([ ('unique_key', unique_key), ('platform', device.app.platform.upper()), ('ack_time', datetime.datetime.fromtimestamp( time.time()).strftime('%H:%M:%S.%f')), ]), logging.INFO, device=device, ) # Push data to Redis for when a device successful # responded to the middleware. redis_cache.client.rpush( VIALER_MIDDLEWARE_PUSH_NOTIFICATION_SUCCESS_TOTAL_KEY, { OS_KEY: device.app.platform, DIRECTION_KEY: VIALER_MIDDLEWARE_INCOMING_VALUE, }) # Log to the metrics file. metrics_data = { OS_KEY: device.app.platform, CALL_SETUP_SUCCESSFUL_KEY: 'true', } log_data_to_metrics_log(metrics_data, sip_user_id) # Success status for asterisk. return Response('status=ACK') elif available == 'False': log_middleware_information( '{0} | {1} Device not available, sending NAK on {2}', OrderedDict([ ('unique_key', unique_key), ('platform', device.app.platform.upper()), ('nak_time', datetime.datetime.fromtimestamp( time.time()).strftime('%H:%M:%S.%f')), ]), logging.INFO, device=device, ) # Push data to Redis for when a device responded as not # available to the middleware. redis_cache.client.rpush( VIALER_MIDDLEWARE_PUSH_NOTIFICATION_FAILED_TOTAL_KEY, { OS_KEY: device.app.platform, DIRECTION_KEY: VIALER_MIDDLEWARE_INCOMING_VALUE, FAILED_REASON_KEY: 'Device not available', }) # Log to the metrics file. metrics_data = { OS_KEY: device.app.platform, CALL_SETUP_SUCCESSFUL_KEY: 'false', FAILED_REASON_KEY: 'Device not available', } log_data_to_metrics_log(metrics_data, sip_user_id) # App is not available. return Response('status=NAK') elif available == 'Removed': log_middleware_information( '{0} | {1} Device has no valid push token, sending NAK on {2}', OrderedDict([ ('unique_key', unique_key), ('platform', device.app.platform.upper()), ('nak_time', datetime.datetime.fromtimestamp( time.time()).strftime('%H:%M:%S.%f')), ]), logging.INFO, device=device, ) return Response('status=NAK') else: # Try to resend the push message every X seconds or # after exceeding the max_attempts. if time.time( ) > next_resend_time and attempt < max_attemps: attempt += 1 next_resend_time = time.time() + resend_interval task_incoming_call_notify( device, unique_key, phonenumber, caller_id, attempt, ) time.sleep(.01) # wait 10 ms log_middleware_information( '{0} | {1} Device did NOT check in on time, sending NAK on {2}', OrderedDict([ ('unique_key', unique_key), ('platform', device.app.platform.upper()), ('nak_time', datetime.datetime.fromtimestamp( time.time()).strftime('%H:%M:%S.%f')), ]), logging.INFO, device=device, ) # Push data to Redis for when a device has not responded to the middleware. redis_cache.client.rpush( VIALER_MIDDLEWARE_PUSH_NOTIFICATION_FAILED_TOTAL_KEY, { OS_KEY: device.app.platform, DIRECTION_KEY: VIALER_MIDDLEWARE_INCOMING_VALUE, FAILED_REASON_KEY: 'Unable to get response from phone', }) # Log to the metrics file. metrics_data = { OS_KEY: device.app.platform, CALL_SETUP_SUCCESSFUL_KEY: 'false', FAILED_REASON_KEY: 'Device did not respond in time', } log_data_to_metrics_log(metrics_data, sip_user_id) # Failed status for asterisk. return Response('status=NAK')
def authenticate(self, request): """ Function for authentication against VoIPGRID api. """ if settings.TESTING: return (AnonymousUser, None) # Get auth headers. auth = get_authorization_header(request) if not auth: # Raises 'Authentication credentials were not provided'. raise NotAuthenticated(detail=None) # Serialize data to check for sip_user_id. serializer = SipUserIdSerializer(data=request.data) if not serializer.is_valid(raise_exception=False): log_middleware_information( 'BAD REQUEST! Authentication failed due to invalid sip_user_id in data:\n\n{0}', OrderedDict([ ('data', request.data), ]), logging.INFO, ) # This raises a bad request response. raise ParseError(detail=None) # Get sip_user_id. sip_user_id = serializer.validated_data['sip_user_id'] # Created new headers with old auth data. headers = {'Authorization': auth} # Get user profile. response = requests.get(settings.VG_API_USER_URL, headers=headers) # Check status code. self._check_status_code(response.status_code) # Parse to json. json_response = response.json() # Get app account reference on systemuser. app_account_url = json_response['app_account'] if not app_account_url: # Has no app account and thus no access to api. log_middleware_information( 'No app account for systemuser {0} - {1}', OrderedDict([ ('id', json_response['id']), (LOG_EMAIL, json_response['email']), ]), logging.INFO, device=Device.objects.get(sip_user_id=sip_user_id), ) raise PermissionDenied(detail=None) # Get url for app account. app_account_api_url = settings.VG_API_BASE_URL + app_account_url # Get app account. response = requests.get(app_account_api_url, headers=headers) # Check status code. self._check_status_code(response.status_code) # Get account id. account_id = response.json()['account_id'] # Compare account id to sip user id the request is meant for. if str(sip_user_id) != str(account_id): # Raise permissions denied. raise PermissionDenied(detail=None) # All good. return (AnonymousUser, None)