Example #1
0
def generateSign(request, secret):
    if type(request) != dict or type(secret) != str:
        raise Exception("type error")
    ret = ""
    stmp = sorted(request.items(), key=lambda d: d[0])
    for i in stmp:
        ret += i[0] + "=" + str(i[1]) + "&"
    print(ret[:-1])
    return hashlib.md5((ret[:-1] + secret).encode('utf-8')).hexdigest()
Example #2
0
def build_xoauth_string(url, consumer, token=None):
    """Build an XOAUTH string for use in SMTP/IMPA authentication."""
    request = Request.from_consumer_and_token(consumer, token, "GET", url)

    signing_method = SignatureMethod_HMAC_SHA1()
    request.sign_request(signing_method, consumer, token)

    params = []
    for k, v in sorted(request.items()):
        if v is not None:
            params.append('%s="%s"' % (k, escape(v)))

    return "%s %s %s" % ("GET", url, ','.join(params))
Example #3
0
def build_xoauth_string(url, consumer, token=None):
    """Build an XOAUTH string for use in SMTP/IMPA authentication."""
    request = Request.from_consumer_and_token(consumer, token,
        "GET", url)

    signing_method = SignatureMethod_HMAC_SHA1()
    request.sign_request(signing_method, consumer, token)

    params = []
    for k, v in sorted(request.items()):
        if v is not None:
            params.append('%s="%s"' % (k, escape(v)))

    return "%s %s %s" % ("GET", url, ','.join(params))
Example #4
0
    def do_client_registration(self, request, client_id, ignore=None):
        if ignore is None:
            ignore = []

        _cinfo = self.cdb[client_id].copy()
        logger.debug("_cinfo: %s" % _cinfo)

        for key, val in list(request.items()):
            if key not in ignore:
                _cinfo[key] = val

        if "redirect_uris" in request:
            ruri = []
            for uri in request["redirect_uris"]:
                if urllib.parse.urlparse(uri).fragment:
                    err = ClientRegistrationErrorResponse(
                        error="invalid_configuration_parameter",
                        error_description="redirect_uri contains fragment")
                    return Response(err.to_json(),
                                    content="application/json",
                                    status="400 Bad Request")
                base, query = urllib.parse.splitquery(uri)
                if query:
                    ruri.append((base, urllib.parse.parse_qs(query)))
                else:
                    ruri.append((base, query))
            _cinfo["redirect_uris"] = ruri

        if "sector_identifier_uri" in request:
            si_url = request["sector_identifier_uri"]
            try:
                res = self.server.http_request(si_url)
            except ConnectionError as err:
                logger.error("%s" % err)
                return self._error_response(
                    "invalid_configuration_parameter",
                    descr="Couldn't open sector_identifier_uri")

            if not res:
                return self._error_response(
                    "invalid_configuration_parameter",
                    descr="Couldn't open sector_identifier_uri")

            logger.debug("sector_identifier_uri => %s" % res.text)

            try:
                si_redirects = json.loads(res.text)
            except ValueError:
                return self._error_response(
                    "invalid_configuration_parameter",
                    descr="Error deserializing sector_identifier_uri content")

            if "redirect_uris" in request:
                logger.debug("redirect_uris: %s" % request["redirect_uris"])
                for uri in request["redirect_uris"]:
                    try:
                        assert uri in si_redirects
                    except AssertionError:
                        return self._error_response(
                            "invalid_configuration_parameter",
                            descr="redirect_uri missing from sector_identifiers"
                        )

            _cinfo["si_redirects"] = si_redirects
            _cinfo["sector_id"] = si_url
        elif "redirect_uris" in request:
            if len(request["redirect_uris"]) > 1:
                # check that the hostnames are the same
                host = ""
                for url in request["redirect_uris"]:
                    part = urllib.parse.urlparse(url)
                    _host = part.netloc.split(":")[0]
                    if not host:
                        host = _host
                    else:
                        try:
                            assert host == _host
                        except AssertionError:
                            return self._error_response(
                                "invalid_configuration_parameter",
                                descr=
                                "'sector_identifier_uri' must be registered")

        for item in ["policy_url", "logo_url"]:
            if item in request:
                if self._verify_url(request[item], _cinfo["redirect_uris"]):
                    _cinfo[item] = request[item]
                else:
                    return self._error_response(
                        "invalid_configuration_parameter",
                        descr="%s pointed to illegal URL" % item)

        try:
            self.keyjar.load_keys(request, client_id)
            try:
                logger.debug("keys for %s: [%s]" % (
                    client_id,
                    ",".join(["%s" % x for x in self.keyjar[client_id]])))
            except KeyError:
                pass
        except Exception as err:
            logger.error("Failed to load client keys: %s" % request.to_dict())
            err = ClientRegistrationErrorResponse(
                error="invalid_configuration_parameter",
                error_description="%s" % err)
            return Response(err.to_json(), content="application/json",
                            status="400 Bad Request")

        return _cinfo
Example #5
0
    def do_client_registration(self, request, client_id, ignore=None):
        if ignore is None:
            ignore = []

        _cinfo = self.cdb[client_id].copy()
        logger.debug("_cinfo: %s" % _cinfo)

        for key, val in list(request.items()):
            if key not in ignore:
                _cinfo[key] = val

        if "redirect_uris" in request:
            ruri = []
            for uri in request["redirect_uris"]:
                if urllib.parse.urlparse(uri).fragment:
                    err = ClientRegistrationErrorResponse(
                        error="invalid_configuration_parameter",
                        error_description="redirect_uri contains fragment")
                    return Response(err.to_json(),
                                    content="application/json",
                                    status="400 Bad Request")
                base, query = urllib.parse.splitquery(uri)
                if query:
                    ruri.append((base, urllib.parse.parse_qs(query)))
                else:
                    ruri.append((base, query))
            _cinfo["redirect_uris"] = ruri

        if "sector_identifier_uri" in request:
            si_url = request["sector_identifier_uri"]
            try:
                res = self.server.http_request(si_url)
            except ConnectionError as err:
                logger.error("%s" % err)
                return self._error_response(
                    "invalid_configuration_parameter",
                    descr="Couldn't open sector_identifier_uri")

            if not res:
                return self._error_response(
                    "invalid_configuration_parameter",
                    descr="Couldn't open sector_identifier_uri")

            logger.debug("sector_identifier_uri => %s" % res.text)

            try:
                si_redirects = json.loads(res.text)
            except ValueError:
                return self._error_response(
                    "invalid_configuration_parameter",
                    descr="Error deserializing sector_identifier_uri content")

            if "redirect_uris" in request:
                logger.debug("redirect_uris: %s" % request["redirect_uris"])
                for uri in request["redirect_uris"]:
                    try:
                        assert uri in si_redirects
                    except AssertionError:
                        return self._error_response(
                            "invalid_configuration_parameter",
                            descr="redirect_uri missing from sector_identifiers"
                        )

            _cinfo["si_redirects"] = si_redirects
            _cinfo["sector_id"] = si_url
        elif "redirect_uris" in request:
            if len(request["redirect_uris"]) > 1:
                # check that the hostnames are the same
                host = ""
                for url in request["redirect_uris"]:
                    part = urllib.parse.urlparse(url)
                    _host = part.netloc.split(":")[0]
                    if not host:
                        host = _host
                    else:
                        try:
                            assert host == _host
                        except AssertionError:
                            return self._error_response(
                                "invalid_configuration_parameter",
                                descr=
                                "'sector_identifier_uri' must be registered")

        for item in ["policy_url", "logo_url"]:
            if item in request:
                if self._verify_url(request[item], _cinfo["redirect_uris"]):
                    _cinfo[item] = request[item]
                else:
                    return self._error_response(
                        "invalid_configuration_parameter",
                        descr="%s pointed to illegal URL" % item)

        try:
            self.keyjar.load_keys(request, client_id)
            try:
                logger.debug("keys for %s: [%s]" % (client_id, ",".join(
                    ["%s" % x for x in self.keyjar[client_id]])))
            except KeyError:
                pass
        except Exception as err:
            logger.error("Failed to load client keys: %s" % request.to_dict())
            err = ClientRegistrationErrorResponse(
                error="invalid_configuration_parameter",
                error_description="%s" % err)
            return Response(err.to_json(),
                            content="application/json",
                            status="400 Bad Request")

        return _cinfo
    def _request(self, request, auth_required=True):
        """
    Make an HTTP(S) request to an API endpoint based on what's specified in the
    request object passed

    ## Input

    Required request keys:
      api
        Either REST or SOAP

      call
        Name of the SOAP method or relative path of the REST URL

    Optional keys:
      query
        Contents of the query string passed as a dict

      data
        Data to post. For SOAP API calls this will be the SOAP envelope. For
        REST API calls this will be a dict converted to JSON automatically
        by this method

      use_cookie_auth
        Whether or not to use an HTTP Cookie in lieu of a querystring for authorization

    ## Output

    Returns a dict:
      status
        Number HTTP status code returned by the response, if any

      raw
        The raw contents of the response, if any

      data
        A python dict representing the data contained in the response, if any
    """
        for required_key in ['api', 'call']:
            if not request.has_key(required_key) and request[required_key]:
                self.log(
                    "All requests are required to have a key [{}] with a value"
                    .format(required_key),
                    level='critical')
                return None

        url = None
        if request['api'] == self.API_TYPE_REST:
            url = "{}/{}".format(self._rest_api_endpoint,
                                 request['call'].lstrip('/'))
        else:
            url = self._soap_api_endpoint

        self.log("Making a request to {}".format(url), level='debug')

        # add the authentication parameters
        if auth_required:
            if request['api'] == self.API_TYPE_REST:
                if not request['use_cookie_auth']:  # sID is a query string
                    if not request['query']: request['query'] = {}
                    request['query']['sID'] = self._sessions[
                        self.API_TYPE_REST]
            elif request['api'] == self.API_TYPE_SOAP:
                # sID is part of the data
                if not request['data']: request['data'] = {}
                request['data']['sID'] = self._sessions[self.API_TYPE_SOAP]

        # remove any blank request keys
        for k, v in request.items():
            if not v: request[k] = None

        # prep the query string
        if request.has_key('query') and request['query']:
            # get with query string
            qs = {}
            for k, v in request['query'].items():  # strip out null entries
                if v: qs[k] = v

            url += '?%s' % urllib.urlencode(qs)
            self.log("Added query string. Full URL is now {}".format(url),
                     level='debug')

        self.log("URL to request is: {}".format(url))

        # Prep the SSL context
        ssl_context = ssl.create_default_context()
        if self.ignore_ssl_validation:
            ssl_context.check_hostname = False
            ssl_context.verify_mode = ssl.CERT_NONE
            self.log(
                "SSL certificate validation has been disabled for this call",
                level='warning')

        # Prep the URL opener
        url_opener = urllib.request.build_opener(
            urllib.request.HTTPSHandler(context=ssl_context))

        # Prep the request
        request_type = 'GET'
        headers = {
            'Accept':
            'application/json,text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*',
            'Content-Type': 'application/json',
        }

        # authentication calls don't accept the Accept header
        if request['call'].startswith('authentication'):
            del (headers['Accept'])

        # some rest calls use a cookie to pass the sID
        if request['api'] == self.API_TYPE_REST and request['use_cookie_auth']:
            headers['Cookie'] = 'sID="{}"'.format(
                self._sessions[self.API_TYPE_REST])

        if request['api'] == self.API_TYPE_REST and request['call'] in [
                'apiVersion', 'status/manager/ping'
        ]:
            headers = {
                'Accept':
                'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*',
                'Content-Type': 'text/plain',
            }

        if request['api'] == self.API_TYPE_SOAP:
            # always a POST
            headers = {
                'SOAPAction': '',
                'content-type': 'application/soap+xml'
            }
            data = self._prep_data_for_soap(request['call'], request['data'])
            url_request = urllib.request.Request(url,
                                                 data=data,
                                                 headers=headers)
            request_type = 'POST'
            self.log("Making a SOAP request with headers {}".format(headers),
                     level='debug')
            self.log("   and data {}".format(data), level='debug')
        elif request['call'] == 'authentication/logout':
            url_request = urllib.request.Request(url, headers=headers)
            setattr(
                url_request, 'get_method',
                lambda: 'DELETE')  # make this request use the DELETE HTTP verb
            request_type = 'DELETE'
            self.log(
                "Making a REST DELETE request with headers {}".format(headers),
                level='debug')
        elif request.has_key('data') and request['data']:
            # POST
            url_request = urllib.request.Request(url,
                                                 data=json.dumps(
                                                     request['data']),
                                                 headers=headers)
            request_type = 'POST'
            self.log(
                "Making a REST POST request with headers {}".format(headers),
                level='debug')
            self.log("    and data {}".format(request['data']), level='debug')
        else:
            # GET
            url_request = urllib.request.Request(url, headers=headers)
            self.log(
                "Making a REST GET request with headers {}".format(headers),
                level='debug')

        # Make the request
        response = None
        try:
            response = url_opener.open(url_request)
        except Exception as url_err:
            self.log("Failed to make {} {} call [{}]".format(
                request['api'].upper(), request_type,
                request['call'].lstrip('/')),
                     err=url_err)

        # Convert the request from JSON
        result = {
            'status': response.getcode() if response else None,
            'raw': response.read() if response else None,
            'headers': dict(response.headers) if response else dict(),
            'data': None
        }
        bytes_of_data = len(result['raw']) if result['raw'] else 0
        self.log("Call returned HTTP status {} and {} bytes of data".format(
            result['status'], bytes_of_data),
                 level='debug')

        if response:
            if request['api'] == self.API_TYPE_SOAP:
                # XML response
                try:
                    if result['raw']:
                        full_data = xmltodict.parse(result['raw'])
                        if full_data.has_key('soapenv:Envelope') and full_data[
                                'soapenv:Envelope'].has_key('soapenv:Body'):
                            result['data'] = full_data['soapenv:Envelope'][
                                'soapenv:Body']
                            if result['data'].has_key('{}Response'.format(
                                    request['call'])):
                                if result['data']['{}Response'.format(
                                        request['call'])].has_key(
                                            '{}Return'.format(
                                                request['call'])):
                                    result['data'] = result['data'][
                                        '{}Response'.format(request['call'])][
                                            '{}Return'.format(request['call'])]
                                else:
                                    result['data'] = result['data'][
                                        '{}Response'.format(request['call'])]
                        else:
                            result['data'] = full_data
                except Exception as xmltodict_err:
                    self.log("Could not convert response from call {}".format(
                        request['call']),
                             err=xmltodict_err)
            else:
                # JSON response
                try:
                    if result['raw'] and result['status'] != 204:
                        result['type'] = result['headers']['content-type']
                        result['data'] = json.loads(
                            result['raw']
                        ) if 'json' in result['type'] else None
                except Exception as json_err:
                    # report the exception as 'info' because it's not fatal and the data is
                    # still captured in result['raw']
                    self.log(
                        "Could not convert response from call {} to JSON. Threw exception:\n\t{}"
                        .format(request['call'], json_err),
                        level='info')

        return result
Example #7
0
 def _get_all(self) -> Dict[int, Any]:
     request = self._get("/" + self.name)
     return {
         int(k): self.node(k, self.url, **v)
         for k, v in request.items()
     }  # unstring the keys
Example #8
0
    def calculate(self,
                  latitude,
                  longitude,
                  altitude=None,
                  depth=None,
                  radius=None,
                  year=None,
                  date=None,
                  username=None,
                  password=None):
        """
        Calculate magnetic field using the API.

        Input:
        -- latitude -- The latitude where magnetic values are requested.
        -- longitude -- The longitude where magnetic values are requested.
        -- altitude -- The height above mean sea level where magnetic values are requested.
        -- depth -- The depth below mean sea level.
        -- radius -- The radial distance from the centre of the earth.
        -- year -- The year for which magnetic field values are requested.
        -- date -- The date when magnetic field values are requested.
        -- username -- Username for HTTP auth for protected models.
        -- password -- Password for HTTP auth for protected models.
        For more details see <http://geomag.bgs.ac.uk/web_service/GMModels/help/parameters>.

        Output:
        -- model -- Used model.
        -- model_revision -- Used model revision, including sub revision.
        -- date -- Used date.
        -- coordinates -- Used coordinates.
        -- -- latitude -- Used latitude.
        -- -- longitude -- Used longitude.
        -- -- altitude / depth / geocentric-radius -- Used height.
        -- field-value -- Field value.
        -- -- declination -- Declination.
        -- -- inclination -- Inclination.
        -- -- total-intensity -- Total intensity.
        -- -- north-intensity -- North intensity.
        -- -- east-intensity -- East intensity.
        -- -- vertical-intensity -- Vertical intensity.
        -- -- horizontal-intensity -- Horizontal intensity.
        -- secular-variation -- Secular variation.
        -- -- declination -- Declination.
        -- -- inclination -- Inclination.
        -- -- total-intensity -- Total intensity.
        -- -- north-intensity -- North intensity.
        -- -- east-intensity -- East intensity.
        -- -- vertical-intensity -- Vertical intensity.
        -- -- horizontal-intensity -- Horizontal intensity.
        Output is returned as dictionary. Some output properties will have `units`
        and `value` sub properties. Output format will depend on used input,
        specially for height and date.
        """

        request = {
            'latitude': latitude,
            'longitude': longitude,
            'altitude': altitude,
            'depth': depth,
            'radius': radius,
            'year': year,
            'date': date,
            'format': 'json',
        }

        parameters = urllib.parse.urlencode(
            {k: v
             for k, v in request.items() if v is not None})

        for base_url in self.custom_url, self.main_url:
            if base_url:
                try:
                    url = base_url \
                    + '/' + self.model \
                    + '/' + self.revision \
                    + ('v' + self.sub_revision if self.sub_revision else '') \
                    + '?' + parameters

                    request = urllib.request.Request(url)

                    if username and password:
                        auth = base64.b64encode(b'%s:%s' %
                                                (username, password))
                        request.add_header("Authorization", "Basic %s" % auth)

                    response = urllib.request.urlopen(url).read()
                    result = json.loads(response.decode('utf-8'))

                    break

                except (URLError, ValueError) as err:
                    error = err

        try:
            return result['geomagnetic-field-model-result']

        except (NameError, KeyError):
            # pylint: disable=E1101
            # pylint: disable=R1720

            if isinstance(error, HTTPError):
                if error.code == 400:
                    raise RequestError(
                        error.read().decode('utf-8').strip('\n'))
                else:
                    raise ApiError(str(error))

            elif isinstance(error, URLError):
                raise ApiError(str(error))

            elif isinstance(error, ValueError):
                raise RequestError(str(error))

            raise ValueError(
                'Can\'t get result because of wrong request or API error')