예제 #1
0
    def authorize(self, request):
        logger.debug(
            "\n\n\n\n\n\t\t\t\t\t********************** AUTHORIZE **************************"
        )
        logger.debug("Received {} - {}".format(request.method, request.path))
        logger.verbose("headers: {}".format(request.headers))

        try:
            received_hash = request.headers.get("Authorization",
                                                "").replace("Bearer ", "")
            if self._validate_confirmation_hash(received_hash):
                sender = {
                    "channel_template_id":
                    request.headers["X-Channeltemplate-Id"],
                    "client_id": request.headers["X-Client-Id"],
                    "owner_id": request.headers["X-Owner-Id"]
                }
                data = {
                    "location": self.implementer.auth_requests(sender=sender)
                }

                return Response(response=json.dumps(data),
                                status=200,
                                mimetype="application/json")
            else:
                logger.debug("Provided invalid confirmation hash! {}".format(
                    self.confirmation_hash))
                return Response(status=403)
        except Exception:
            logger.error("Couldn't complete processing request, {}".format(
                traceback.format_exc(limit=5)))

        return Response(status=403)
예제 #2
0
    def receive_token(self, request):
        logger.debug(
            "\n\n\n\n\n\t\t\t\t\t********************** RECEIVE_TOKEN **************************"
        )
        logger.debug("Received {} - {}".format(request.method, request.path))
        logger.verbose("headers: {}".format(request.headers))
        try:
            received_hash = request.headers.get("Authorization").replace(
                "Bearer ", "")
            if self._validate_confirmation_hash(received_hash):
                if request.is_json:
                    received_data = request.get_json()
                    logger.debug(f'Authorize response data: {received_data}')
                else:
                    return Response(status=422)

                return self.handle_receive_token(
                    received_data, request.headers["X-Client-Id"],
                    request.headers["X-Owner-Id"])

            else:
                logger.debug("Provided invalid confirmation hash!")
                return Response(status=403)
        except Exception:
            logger.error("Couldn't complete processing request, {}".format(
                traceback.format_exc(limit=5)))
예제 #3
0
def validate_quote(quote_id):
    try:
        header = {
            "Authorization": f"Bearer {settings.block['access_token']}",
            "Accept": "application/json",
        }
        if not quote_id:
            logger.warning(f"[validate_quote] Invalid quote_id")
            return False

        url = f"{settings.api_server_full}/applications/{settings.client_id}/quotes/{quote_id}"

        resp = requests.get(url, headers=header)

        if int(resp.status_code) == 200:
            return resp.json()
        else:
            logger.verbose(
                f"[validate_quote] Received response code [{resp.status_code}]"
            )
            raise InvalidRequestException(
                f"Failed to retrieve quote for {quote_id}")

    except (OSError, InvalidRequestException) as e:
        logger.warning(
            f'[validate_quote] Error while making request to platform: {e}')
    except Exception:
        logger.alert(
            f"[validate_quote] Unexpected error: {traceback.format_exc(limit=5)}"
        )
    return False
예제 #4
0
    def create_channel_id(self, device, channel_template, client_id):

        # Creating a new channel for the particular device"s id
        data = {
            "name": device.get("content", "Device"),
            "channeltemplate_id": channel_template,
            "remote_key": device.get('id'),
            "requesting_client_id": client_id
        }

        logger.debug("Initiated POST - {}".format(settings.api_server_full))
        logger.verbose(format_str(data, is_json=True))

        resp = self.session.post("{}/managers/self/channels".format(
            settings.api_server_full),
                                 json=data)

        logger.debug("[create_channel_id] Received response code[{}]".format(
            resp.status_code))

        if resp.status_code == 412 and resp.json().get('code') == 2000:
            raise UnauthorizedException(resp.json().get('text'))

        if resp.status_code != 201:
            logger.debug(format_str(resp.json(), is_json=True))
            raise Exception(
                f"Failed to create channel for channel template {channel_template} "
                f"{traceback.format_exc(limit=5)}")
        return resp.json()["id"]
예제 #5
0
def get_access():
    """
    To send authorization request with 0Auth2.0 to Muzzley platform

    """
    logger.verbose("Trying to authorize with Muzzley...")
    data = {
        "client_id": settings.client_id,
        "client_secret": settings.client_secret,
        "response_type": settings.grant_type,
        "scope": settings.scope,
        "state": "active"
    }
    url = settings.auth_url
    try:
        logger.debug("Initiated POST - {}".format(url))
        resp = requests.post(url, data=data)
        if resp.status_code == 200:
            logger.notice("Manager succesfully Authorized with Muzzley")
            store_info(resp.json())
            start_refresher()
        else:
            error_msg = format_response(resp)
            raise Exception(error_msg)
    except Exception:
        logger.alert("Unexpected error during authorization {}".format(
            traceback.format_exc(limit=5)))
        raise
예제 #6
0
def validate_channel(channel_id):
    try:
        header = {
            "Authorization": f"Bearer {settings.block['access_token']}",
            "Accept": "application/json",
        }
        if not channel_id:
            logger.warning(
                f"[validate_channel] Invalid channel_id: {channel_id}")
            return {}
        url = f"{settings.api_server_full}/channels/{channel_id}"

        resp = requests.get(url, headers=header)

        if int(resp.status_code) == 200:
            return resp.json()
        else:
            logger.verbose(
                f"[validate_channel] Received response code [{resp.status_code}]"
            )
            raise ChannelTemplateNotFound(
                f"Failed to retrieve channel_template_id for {channel_id}")

    except (OSError, ChannelTemplateNotFound) as e:
        logger.warning(
            f'[validate_channel] Error while making request to platform: {e}')
    except Exception:
        logger.alert(
            f"[validate_channel] Unexpected error get_channel_template: {traceback.format_exc(limit=5)}"
        )
    return {}
예제 #7
0
    def get_or_create_channel(self, device, channel_template, client_id):
        try:
            channel_id = self.db.get_channel_id(device["id"])

            # Validate if still exists on Muzzley
            url = "{}/channels/{}".format(settings.api_server_full, channel_id)
            resp = self.session.get(url, data=None)
            logger.verbose("/v3/channels/{} response code {}".format(
                channel_id, resp.status_code))

            if resp.status_code not in (200, 201):
                channel_id = self.create_channel_id(device, channel_template,
                                                    client_id)

                # Ensure persistence of manufacturer's device id (key) to channel id (field) in redis hash
                self.db.set_channel_id(device["id"], channel_id, True)
                logger.verbose(
                    "Channel added to database {}".format(channel_id))

            return channel_id
        except UnauthorizedException as e:
            logger.error(f"{e}")
        except Exception:
            logger.error(
                f'Error get_or_create_channel {traceback.format_exc(limit=5)}')

        return None
예제 #8
0
 def on_publish(self, client, userdata, mid):
     logger.debug(
         "\n\n\n\n\n\t\t\t\t\t******************* ON PUBLISH ****************************"
     )
     logger.verbose(
         "Mqtt - Publish acknowledged by broker, mid({}) userdata={}.".
         format(mid, userdata))
예제 #9
0
    def select_device(self, request):
        logger.debug(
            "\n\n\n\n\n\t\t\t\t\t*******************SELECT_DEVICE****************************"
        )
        logger.debug("Received {} - {}".format(request.method, request.path))
        logger.verbose("headers: {}".format(request.headers))

        try:
            received_hash = request.headers.get("Authorization",
                                                "").replace("Bearer ", "")
            if self._validate_confirmation_hash(received_hash):

                if request.is_json:
                    payload = request.get_json()
                    logger.verbose(format_str(payload, is_json=True))
                    paired_devices = payload["channels"]
                    if not paired_devices:
                        logger.error(
                            "No paired devices found in request: {}".format(
                                payload))
                else:
                    return Response(status=422)

                owner_id = request.headers["X-Owner-Id"]
                client_id = request.headers["X-Client-Id"]
                channel_template = request.headers["X-Channeltemplate-Id"]

                channels, credentials = self.handle_channel_requests(
                    client_id, owner_id, channel_template, paired_devices)

                sender = {
                    "channel_template_id": channel_template,
                    "client_id": client_id,
                    "owner_id": owner_id
                }

                self.implementer.did_pair_devices(
                    sender=sender,
                    credentials=credentials,
                    paired_devices=paired_devices,
                    channels=channels)

                return Response(response=json.dumps(channels),
                                status=200,
                                mimetype="application/json")
            else:
                logger.debug("Provided invalid confirmation hash!")
                return Response(status=403)
        except Exception:
            logger.error("Couldn't complete processing request, {}".format(
                traceback.format_exc(limit=5)))

        return Response(status=403)
예제 #10
0
def store_info(resp):
    """
    Stores the response obtained during authorization with Muzzley in base.Settings.block

    """
    logger.verbose("Caching authorization response info from Muzzley...")
    if 'access_token' and 'refresh_token' and 'expires' and 'code' and 'endpoints' in resp:
        settings.block['access_token'] = resp['access_token']
        settings.block['refresh_token'] = resp['refresh_token']
        settings.block['expires'] = resp['expires']
        settings.block['code'] = resp['code']
        settings.block['http_ep'] = resp['endpoints']['http']
        settings.block['mqtt_ep'] = resp['endpoints']['mqtt']
예제 #11
0
    def update_credentials(self, new_credentials, old_credentials_list):
        """
        Update all credentials in old_credentials_list with new_credentials
        :param new_credentials: dict
        :param old_credentials_list: [{
            'key': ':credential_key',
            'value': :credential_dict
        }, ...]
        """
        old_credentials_list = self.check_credentials_man_id(old_credentials_list, new_credentials)
        error_keys = [cred_['key'] for cred_ in old_credentials_list if cred_['has_error'] is True]
        old_credentials_list = self.filter_credentials(old_credentials_list, new_credentials.get('client_man_id'))
        updated_credentials = []
        logger.info(f'[TokenRefresher] update_credentials: {len(old_credentials_list)} keys to update')
        for cred_ in old_credentials_list:
            key = cred_['key']
            credentials = cred_['value']
            channel_id = key.split('/')[-1]
            owner_id = key.split('/')[1]

            client_app_id = credentials.get('client_id', credentials.get('data', {}).get('client_id', ''))
            client_man_id = credentials.get('client_man_id')
            # replace client_id in new credentials with current client_app_id and client_man_id
            # to keep consistence with different apps
            new_credentials['client_id'] = client_app_id
            new_credentials['client_man_id'] = client_man_id
            try:
                channeltemplate_id = self.channel_relations[channel_id]
            except KeyError:
                channeltemplate_id = self.implementer.get_channel_template(channel_id)

            if channeltemplate_id and \
                    (settings.config_boot.get('on_pair', {}).get('update_all_channeltemplates', True)
                     or channeltemplate_id == self.channel_template):
                logger.debug(f'[update_credentials] new credentials {key}')
                logger.info(f"[update_credentials] client_app_id: {client_app_id}; owner_id: {owner_id}; "
                            f"channel_id: {channel_id}; channeltemplate_id: {channeltemplate_id}")
                self.channel_relations[channel_id] = channeltemplate_id
                stored = self.implementer.store_credentials(owner_id, client_app_id, channeltemplate_id,
                                                            new_credentials)
                if stored:
                    self.db.set_credentials(new_credentials, client_app_id, owner_id, channel_id)
                    updated_credentials.append(key)
                else:
                    logger.verbose(f'[update_credentials] Ignoring key {key}')
                    error_keys.append(key)
            else:
                logger.verbose(f'[update_credentials] Ignoring key {key}')
                error_keys.append(key)

        return list(set(updated_credentials)), list(set(error_keys))
예제 #12
0
    def get_application(self):
        try:
            logger.debug(f"[get_application] Trying to get application data - {settings.webhook_url}")
            resp = requests.get(settings.webhook_url, headers=self.session.headers)
            logger.verbose("[get_application] Received response code[{}]".format(resp.status_code))

            if int(resp.status_code) == 200:
                logger.notice("[get_application] Get application successful!")
                return resp.json()
            else:
                raise Exception('[get_application] Error getting application!')

        except Exception:
            logger.alert("Failed while get application! {}".format(traceback.format_exc(limit=5)))
            raise
예제 #13
0
    def devices_list(self, request):
        logger.debug(
            "\n\n\n\n\n\t\t\t\t\t********************** LIST_DEVICES **************************"
        )
        logger.debug("Received {} - {}".format(request.method, request.path))
        logger.verbose("headers: {}".format(request.headers))

        try:
            received_hash = request.headers.get("Authorization",
                                                "").replace("Bearer ", "")
            if self._validate_confirmation_hash(received_hash):
                credentials = self.db.get_credentials(
                    request.headers["X-Client-Id"],
                    request.headers["X-Owner-Id"])

                if not credentials:
                    logger.error("No credentials found in database")
                    return Response(status=404)

                sender = {
                    "channel_template_id":
                    request.headers["X-Channeltemplate-Id"],
                    "client_id": request.headers["X-Client-Id"],
                    "owner_id": request.headers["X-Owner-Id"]
                }
                data = self.implementer.get_devices(sender=sender,
                                                    credentials=credentials)
                if not data:
                    logger.info("No devices found for this user")

                for element in data:
                    if "content" not in element or ("content" in element and
                                                    not element["content"]):
                        element["content"] = ""

                return Response(response=json.dumps(data),
                                status=200,
                                mimetype="application/json")

            else:
                logger.debug("Provided invalid confirmation hash!")
                return Response(status=403)
        except Exception:
            logger.error("Couldn't complete processing request, {}".format(
                traceback.format_exc(limit=5)))

        return Response(status=403)
예제 #14
0
 def update_all_owners(self, new_credentials, channel_id, ignore_keys=None):
     ignore_keys = ignore_keys or []
     all_owners_credentials = self.db.full_query(f'credential-owners/*/channels/{channel_id}')
     all_owners_credentials = list(filter(lambda x: x['key'] not in ignore_keys, all_owners_credentials))
     all_owners_credentials = self.check_credentials_man_id(all_owners_credentials, new_credentials)
     error_keys = [cred_['key'] for cred_ in all_owners_credentials if cred_.get('has_error', False) is True]
     all_owners_credentials = self.filter_credentials(all_owners_credentials, new_credentials.get('client_man_id'))
     logger.info(f'[update_all_owners] {len(all_owners_credentials)} keys to update for channel {channel_id}')
     updated_cred = []
     if all_owners_credentials:
         updated_, error_ = self.update_credentials(new_credentials, all_owners_credentials)
         updated_cred.extend(updated_)
         updated_cred.extend(ignore_keys)
         updated_cred.extend(error_)
         for owner_credentials in all_owners_credentials:
             owner_id = owner_credentials['key'].split('/')[1]
             logger.verbose(f'[update_all_owners] Trying to update all credentials for the owner: {owner_id}')
             updated_cred.extend(self.update_all_channels(new_credentials, owner_id, updated_cred))
     return list(set(updated_cred)), list(set(error_keys))
예제 #15
0
 def update_all_channels(self, new_credentials, owner_id, ignore_keys=None):
     ignore_keys = ignore_keys or []
     all_channels_credentials = self.db.full_query(f'credential-owners/{owner_id}/channels/*')
     all_channels_credentials = list(filter(lambda x: x['key'] not in ignore_keys, all_channels_credentials))
     logger.info(f'[update_all_channels] {len(all_channels_credentials)} keys to update for owner {owner_id}')
     updated_cred = []
     if all_channels_credentials:
         updated_, error_ = self.update_credentials(new_credentials, all_channels_credentials)
         updated_cred.extend(updated_)
         ignore_keys.extend(updated_)
         ignore_keys.extend(error_)
         for channel_credentials in all_channels_credentials:
             channel_id = channel_credentials['key'].split('/')[-1]
             logger.verbose(f'[update_all_channels]  Trying to update all credentials for the channel: {channel_id}')
             updated_, error_keys = self.update_all_owners(new_credentials, channel_id, ignore_keys)
             updated_cred.extend(updated_)
             ignore_keys.extend(updated_)
             ignore_keys.extend(error_)
     return list(set(updated_cred))
예제 #16
0
    def after(self, response):

        try:

            if 'Location' in response.headers:
                logger.debug('Redirect {} code[{}]'.format(
                    response.headers['Location'], response.status))
            else:
                logger.debug('Responding with status code[{}]'.format(
                    response.status))

            if response.mimetype == 'application/json':
                logger.verbose('\n{}\n'.format(
                    json.dumps(json.loads(response.response[0]),
                               indent=4,
                               sort_keys=True)))

        except:
            logger.error('Post request logging failed!')

        return response
예제 #17
0
    def patch_custom_endpoints(self):
        try:
            custom_endpoints = settings.custom_endpoints
            url = settings.webhook_url
            data = {'quote_actions': {}}

            for endpoint in custom_endpoints:
                data['quote_actions'].update({
                    endpoint['namespace']: f"{settings.schema_pub}://{settings.host_pub}/"
                                           f"{settings.api_version}{endpoint['uri']}"
                })

            if data['quote_actions']:
                logger.debug(f"[patch_custom_endpoints] Initiated PATCH - {url}")
                logger.verbose("\n{}\n".format(json.dumps(data, indent=4, sort_keys=True)))

                resp = requests.patch(url, data=json.dumps(data), headers=self.session.headers)

                logger.verbose("[patch_{}] Received response code[{}]".format(endpoint['namespace'], resp.status_code))
                logger.verbose("\n{}\n".format(json.dumps(resp.json(), indent=4, sort_keys=True)))

                if int(resp.status_code) == 200:
                    logger.notice(f"[patch_custom_endpoints] {endpoint['namespace']} setup successful!")
                else:
                    raise Exception(f"[patch_custom_endpoints] {endpoint['namespace']} setup not successful!")

        except Exception:
            logger.alert("Failed at patch endpoint! {}".format(traceback.format_exc(limit=5)))
            raise
예제 #18
0
    def patch_endpoints(self):
        try:
            full_host = "{}://{}/{}".format(settings.schema_pub,
                                            settings.host_pub,
                                            settings.api_version)
            data = {
                "authorize": "{}/authorize".format(full_host),
                "receive_token": "{}/receive-token".format(full_host),
                "devices_list": "{}/devices-list".format(full_host),
                "select_device": "{}/select-device".format(full_host)
            }

            url = settings.webhook_url

            logger.debug("Initiated PATCH - {} {}".format(
                url, self.session.headers))
            logger.verbose(format_str(data, is_json=True))

            resp = requests.patch(url,
                                  data=json.dumps(data),
                                  headers=self.session.headers)

            logger.verbose(
                "[patch_endpoints] Received response code[{}]".format(
                    resp.status_code))
            logger.verbose(format_str(resp.json(), is_json=True))

            self.set_confirmation_hash()

        except Exception:
            logger.alert("Failed at patch endpoints! {}".format(
                traceback.format_exc(limit=5)))
            raise
예제 #19
0
    def _basic_quote_validation(self, request):
        logger.debug(f"Received {request.method} - {request.path}")
        logger.verbose(f"headers: {request.headers}")
        received_hash = request.headers.get("Authorization", "").replace("Bearer ", "")
        if self._validate_confirmation_hash(received_hash):
            data = request.json
            if not data:
                raise InvalidRequestException("Missing Payload")
            service_id = data.get('service_id')
            quote_id = data.get('quote_id')
            if not (service_id
                    and is_valid_uuid(service_id)
                    and service_id in [_service['id'] for _service in settings.services]):
                raise InvalidRequestException("Invalid Service")
            if not (quote_id
                    and is_valid_uuid(quote_id)
                    and validate_quote(quote_id)):
                raise InvalidRequestException("Invalid Quote")

            return service_id, quote_id
        else:
            logger.debug("[basic_quote_validation] Provided invalid confirmation hash!")
            raise UnauthorizedException("Invalid token!")
예제 #20
0
def renew_token():
    logger.verbose("Trying to refresh Tokens...")
    url = settings.renew_url
    header = {"Content-Type": "application/json"}
    data = {
        "client_id": settings.client_id,
        "refresh_token": settings.block['refresh_token'],
        "grant_type": settings.grant_type
    }
    try:
        logger.debug("Initiated POST - {}".format(url))

        resp = requests.get(url, params=data, headers=header)
        if resp.status_code == 200:
            logger.notice("Manager succesfully performed Token refresh")
            store_info(resp.json())
            start_refresher()
        else:
            error_msg = format_response(resp)
            raise Exception(error_msg)
    except Exception:
        logger.alert("Unexpected error during token renewal: {}".format(
            traceback.format_exc(limit=5)))
        os._exit(1)
예제 #21
0
    def patch_endpoints(self):
        try:
            _data = settings.services

            for _service in _data:

                try:

                    if settings.config_boot.get('patch_services', True) is True:
                        data = {
                            'activation_uri': '{}://{}/{}/services/{}/authorize'.format(settings.schema_pub,
                                                                                        settings.host_pub,
                                                                                        settings.api_version,
                                                                                        _service['id'])
                        }

                        logger.debug("[patch_endpoints] Initiated PATCH - {}".format(_service.get('url')))
                        logger.verbose("\n{}\n".format(json.dumps(data, indent=4, sort_keys=True)))

                        resp = requests.patch('{}/services/{}'.format(settings.api_server_full, _service['id']),
                                              data=json.dumps(data), headers=self.session.headers)

                        logger.verbose("[patch_endpoints] Received response code[{}]".format(resp.status_code))
                        logger.verbose("\n{}\n".format(json.dumps(resp.json(), indent=4, sort_keys=True)))

                        if int(resp.status_code) == 200:
                            logger.notice("[patch_endpoints] Service setup successful!")
                        else:
                            raise Exception('Service setup not successful!')

                except Exception as e:

                    logger.alert("[patch_endpoints] Failed to set service!\n{}".format(e))
                    os._exit(1)

            self.patch_custom_endpoints()
            self.set_confirmation_hash()

        except Exception:
            logger.alert("[patch_endpoints] Failed at patch endpoints! {}".format(traceback.format_exc(limit=5)))
            raise
예제 #22
0
from flask_cors import CORS
from base.thread_pool import ThreadPool
from base.constants import DEFAULT_THREAD_POOL_LIMIT
if settings.config_thread_pool.get('enabled', True):
    thread_pool = ThreadPool(
        settings.config_thread_pool.get('num_threads',
                                        DEFAULT_THREAD_POOL_LIMIT))
    thread_pool.start()
else:
    thread_pool = None

from base import views
from base.common.tcp_base import TCPBase

# Flask App
logger.verbose("Creating Flask Object...")

try:
    if not settings.mqtt:
        app = Flask(__name__, instance_relative_config=True)
        app.config.from_object("flask_config")
        if settings.enable_cors is True:
            CORS(app, supports_credentials=True)
        views = views.Views(app, thread_pool)
        logger.info("[Boot]: Flask object successfully created!")
        if settings.config_tcp.get('enabled', False):
            tcp_ = TCPBase(webhook=views.webhook)
            tcp_.kickoff()
    else:
        app = views.Views()
        logger.info("[Boot]: Mqtt")
예제 #23
0
def handle_credentials(credentials,
                       old_credentials,
                       client_id,
                       owner_id,
                       channel_id,
                       ignore_keys=None):
    from base.solid import implementer
    refresher = TokenRefresherManager(implementer=implementer)
    ignore_keys = ignore_keys or []

    logger.debug(
        "\n\n\n\n\n\t\t\t\t\t*******************HANDLE_CREDENTIALS****************************"
    )
    logger.info(
        f"Client_id {client_id}; Owner_id: {owner_id}; channel_id: {channel_id}"
    )
    if settings.config_refresh.get('enabled') is True:
        if not channel_id:
            logger.warning(
                f"[handle_credentials] channel_id not set: {channel_id}")
            return
        elif 'refresh_token' not in old_credentials:
            logger.error(
                "[handle_credentials] Refresh token not found in old credentials"
            )
            return
        else:
            if not settings.config_boot.get('on_pair', {}).get(
                    'update_all_channeltemplates', True):
                refresher.channel_template = implementer.get_channel_template(
                    channel_id)
                refresher.channel_relations[
                    channel_id] = refresher.channel_template

            updated_cred = []
            updated_cred.extend(ignore_keys)
            refresh_token = old_credentials['refresh_token']
            credentials_list = refresher.get_credentials_by_refresh_token(
                refresh_token) or []
            # remove updated keys from credentials list
            credentials_list = [
                cred_ for cred_ in credentials_list
                if cred_['key'] not in ignore_keys
            ]

            logger.verbose(
                f"[handle_credentials] Starting update by token_refresher for channel: {channel_id}"
            )
            updated_, error_keys = refresher.update_credentials(
                credentials, credentials_list)
            ignore_keys.extend(updated_)
            ignore_keys.extend(error_keys)
            updated_cred.extend(updated_)

            logger.debug(
                f"[handle_credentials] Starting update all owners for channel: {channel_id}"
            )
            updated_, error_keys = refresher.update_all_owners(
                credentials, channel_id, ignore_keys)
            ignore_keys.extend(updated_)
            ignore_keys.extend(error_keys)
            updated_cred.extend(updated_)

            logger.debug("[handle_credentials] Starting update all channels")
            updated_cred.extend(
                refresher.update_all_channels(credentials, owner_id,
                                              ignore_keys))

            logger.debug(
                f"[handle_credentials] Updated keys: {list(set(updated_cred))}"
            )

            del refresher.channel_template
            del refresher.channel_relations
예제 #24
0
    def channels_grant(self, device, client_id, owner_id, channel_template,
                       credentials):

        try:
            channel_template = self.implementer.update_channel_template(
                device['id']) or channel_template
            channel_id = self.get_or_create_channel(device, channel_template,
                                                    client_id)
            if not channel_id:
                logger.warning("[channels_grant] No channel found")
                return False

            # Granting permission to intervenient with id X-Client-Id
            url = "{}/channels/{}/grant-access".format(
                settings.api_server_full, channel_id)

            try:
                data = {
                    "client_id": client_id,
                    "requesting_client_id": client_id,
                    "role": "application",
                    "remote_key": device.get('id')
                }

                logger.debug("Initiated POST - {}".format(url))
                logger.verbose(format_str(data, is_json=True))

                resp_app = self.session.post(url, json=data)
                logger.debug(
                    "[channels_grant] Received response code[{}]".format(
                        resp_app.status_code))

                if resp_app.status_code == 412 and resp_app.json().get(
                        'code') == 2000:
                    raise UnauthorizedException(resp_app.json().get('text'))

                if resp_app.status_code not in (201, 200):
                    logger.debug(format_str(resp_app.json(), is_json=True))
                    return False
            except UnauthorizedException as e:
                logger.error(f"{e}")
                return False
            except Exception:
                logger.error("Failed to grant access to client {} {}".format(
                    client_id, traceback.format_exc(limit=5)))
                return False

            # Granting permission to intervenient with id X-Owner-Id
            try:
                data = {
                    "client_id": owner_id,
                    "requesting_client_id": client_id,
                    "role": "user",
                    "remote_key": device.get('id')
                }

                logger.debug("Initiated POST - {}".format(url))
                logger.verbose(format_str(data, is_json=True))

                resp_user = self.session.post(url, json=data)
                logger.verbose(
                    "[channels_grant] Received response code[{}]".format(
                        resp_user.status_code))

                if resp_app.status_code == 412 and resp_app.json().get(
                        'code') == 2000:
                    raise UnauthorizedException(resp_app.json().get('text'))

                if resp_user.status_code not in (201, 200):
                    logger.debug(format_str(resp_user.json(), is_json=True))
                    return False
            except UnauthorizedException as e:
                logger.error(f"{e}")
                return False
            except Exception:
                logger.error("Failed to grant access to owner {} {}".format(
                    channel_template, traceback.format_exc(limit=5)))
                return False

            return channel_id

        except Exception:
            logger.error('Error while requesting grant: {}'.format(
                traceback.format_exc(limit=5)))

        return None