Example #1
0
    def test_enrollment_fails(self, mock_refresh, mock_edx_enr):  # pylint: disable=unused-argument
        """
        Test error when backend raises an exception
        """
        error = HTTPError()
        error.response = MagicMock()
        error.response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR
        mock_edx_enr.side_effect = error
        resp = self.client.post(self.url, {'course_id': self.course_id}, format='json')
        assert resp.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
        # the response has a structure like {"error": "<message>"}
        assert isinstance(resp.data, dict)
        assert 'error' in resp.data
        assert mock_edx_enr.call_count == 1
        # assert just the second argument, since the first is `self`
        assert mock_edx_enr.call_args[0][1] == self.course_id

        # if instead edX returns a 400 error, an exception is raised by
        # the view and the user gets a different error message
        error.response.status_code = status.HTTP_400_BAD_REQUEST
        mock_edx_enr.side_effect = error
        resp = self.client.post(self.url, {'course_id': self.course_id}, format='json')
        assert resp.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
        assert isinstance(resp.data, list)
        assert len(resp.data) == 1
        assert PossiblyImproperlyConfigured.__name__ in resp.data[0]

        # if the error from the call to edX is is not HTTPError, the user gets a normal json error
        mock_edx_enr.side_effect = ValueError()
        resp = self.client.post(self.url, {'course_id': self.course_id}, format='json')
        assert resp.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
        # the response has a structure like {"error": "<message>"}
        assert isinstance(resp.data, dict)
        assert 'error' in resp.data
Example #2
0
    def _send(self, **kwargs):

        params = {
            'login': kwargs['login'],
            'psw': kwargs['password'],
            'phones': kwargs['tel'],
            'mes': kwargs['text'],
            'fmt': 3,
        }
        try:
            resp = requests.get(
                url=self.gate_url_template + '?' + urllib.parse.urlencode(params)
            )  # raises exception in case of some conection/pool failure
            if re.search('^[45]', str(resp.status_code)):
                raise HTTPError(resp.status_code)  # raises exception in case of 4xx or 5xx HTTP response
            json = resp.json()
            if 'error' in json:
                e = HTTPError(  # raises exception if 200 OK but there is a problem in business logic
                    '%s:\n%s' % (
                        self.error_descr.get(json['error_code']),
                        json.get('error')
                    )
                )
                e.sms_id = json.get('id')  # supply the message id if any
                raise e
            else:
                return json['id']
        except HTTPError as e:
            raise
Example #3
0
    def _http_resource(self, method, resource, params=None, data=None, legacy=False, order_by=None, limit=None, valrange=None, sort=None):
        """Makes an HTTP request."""

        if not is_collection(resource):
            resource = [resource]

        url = self._url_for(*resource)

        headers = self._get_headers_for_request(method, url, legacy=legacy, order_by=order_by, limit=limit, valrange=valrange, sort=sort)

        r = self._session.request(method, url, params=params, data=data, headers=headers)

        if 'ratelimit-remaining' in r.headers:
            self._ratelimit_remaining = r.headers['ratelimit-remaining']

        if 'Request-Id' in r.headers:
            self._last_request_id = r.headers['Request-Id']

        #if 'Accept-Ranges' in r.headers:
            #print "Accept-Ranges = {0}".format(r.headers['Accept-Ranges'])

        if r.status_code == 422:
            http_error = HTTPError('%s - %s Client Error: %s' %
                                   (self._last_request_id, r.status_code, r.content.decode("utf-8")))
            http_error.response = r
            raise http_error

        if r.status_code == 429:
            #Rate limit reached
            raise RateLimitExceeded("You have exceeded your rate limit \n{0}".format(r.content.decode("utf-8")))

        if (not str(r.status_code).startswith('2')) and (not r.status_code in [304]):
            pass
        r.raise_for_status()
        return r
Example #4
0
    def _http_alpha_resource(self, method, resource, params=None, data=None, legacy=False, order_by=None, limit=None, valrange=None, sort=None):
        """Makes an HTTP request."""

        if not is_collection(resource):
            resource = [resource]

        url = self._url_for_alpha(*resource)
        print(url)
        headers = self._get_headers_for_alpha_request(method, url, legacy=legacy, order_by=order_by, limit=limit, valrange=valrange, sort=sort)
        print(headers)
        request = Request(url, data, headers, method=method)

        r = urlopen(request)

        if 'ratelimit-remaining' in r.headers:
            self._ratelimit_remaining = r.headers['ratelimit-remaining']

        if 'Request-Id' in r.headers:
            self._last_request_id = r.headers['Request-Id']

        if r.status == 422:
            http_error = HTTPError('%s - %s Client Error: %s' %
                                   (self._last_request_id, r.status, r.content.decode("utf-8")))
            http_error.response = r
            raise http_error

        if r.status == 429:
            raise RateLimitExceeded("You have exceeded your rate limit \n{0}".format(r.content.decode("utf-8")))

        if (not str(r.status).startswith('2')) and (not r.status in [304]):
            pass
        return r
Example #5
0
 def get_call(url, params=None):
     if params['access_token'] == '222':
         return self.mock_resp
     else:
         error = HTTPError()
         error.response = MagicMock()
         error.response.status_code = 401
         raise error
 def patched_client(self, path, status=401, reason="Unauthorized"):
     error = HTTPError()
     error.response = mock.MagicMock()
     error.response.status_code = status
     error.response.reason = reason
     error.response.text = ('{"status": "invalid-credentials", '
                            '"errors": [{"location": "body", '
                            '"name": "", '
                            '"description": "Unauthorized"}]}')
     patch = mock.patch(path, side_effect=error)
     try:
         yield patch.start()
     finally:
         patch.stop()
Example #7
0
    def _http_resource(self, method, resource, params=None, data=None):
        """Makes an HTTP request."""

        if not is_collection(resource):
            resource = [resource]

        url = self._url_for(*resource)
        r = self._session.request(method, url, params=params, data=data)

        if r.status_code == 422:
            http_error = HTTPError('%s Client Error: %s' % (r.status_code, r.content))
            http_error.response = r
            raise http_error
        
        r.raise_for_status()

        return r
Example #8
0
    def _http_resource(self, method, resource, params=None, data=None):
        """Makes an HTTP request."""

        if not is_collection(resource):
            resource = [resource]

        # This is needed because we only send application/json
        data = json_encode(data)

        url = self._url_for(*resource)
        r = self._session.request(method, url, params=params, data=data)

        if r.status_code == 422:
            http_error = HTTPError("%s Client Error: %s" % (r.status_code, r.content))
            http_error.response = r
            raise http_error

        r.raise_for_status()
        return r
    def test_http_exception_redirection(self):
        """
        Test ExceptionMiddleware is correctly redirected to login page
        when PSA raises HttpError exception.
        """

        request = RequestFactory().get("dummy_url")
        next_url = get_next_url_for_login_page(request)
        login_url = '/login?next=' + next_url
        request.META['HTTP_REFERER'] = 'http://example.com:8000/login'
        exception = HTTPError()
        exception.response = HttpResponse(status=502)

        # Add error message for error in auth pipeline
        MessageMiddleware().process_request(request)
        response = ExceptionMiddleware().process_exception(
            request, exception
        )
        target_url = response.url

        self.assertEqual(response.status_code, 302)
        self.assertTrue(target_url.endswith(login_url))
Example #10
0
 def _create_request_error(self, code):
     error = HTTPError()
     error.response = MagicMock()
     error.response.status_code = code
     keyrock_backend_v1.requests.get.side_effect = error
Example #11
0
def mock_404(monkeypatch):
    mock_error = HTTPError()
    monkeypatch.setattr(mock_error, 'response', MagicMock(status_code=404))
    yield mock_error
Example #12
0
"""Tests for certbot_dns_cloudxns.dns_cloudxns."""

import os
import unittest

import mock
from requests.exceptions import HTTPError, RequestException

from certbot.plugins import dns_test_common
from certbot.plugins import dns_test_common_lexicon
from certbot.tests import util as test_util

DOMAIN_NOT_FOUND = Exception('No domain found')
GENERIC_ERROR = RequestException
LOGIN_ERROR = HTTPError('400 Client Error: ...')

API_KEY = 'foo'
SECRET = 'bar'


class AuthenticatorTest(test_util.TempDirTestCase,
                        dns_test_common_lexicon.BaseLexiconAuthenticatorTest):
    def setUp(self):
        super(AuthenticatorTest, self).setUp()

        from certbot_dns_cloudxns.dns_cloudxns import Authenticator

        path = os.path.join(self.tempdir, 'file.ini')
        dns_test_common.write(
            {
                "cloudxns_api_key": API_KEY,
class BaseLexiconClientTest:
    DOMAIN_NOT_FOUND = Exception('No domain found')
    GENERIC_ERROR = RequestException
    LOGIN_ERROR = HTTPError('400 Client Error: ...')
    UNKNOWN_LOGIN_ERROR = HTTPError('500 Surprise! Error: ...')

    record_prefix = "_acme-challenge"
    record_name = record_prefix + "." + DOMAIN
    record_content = "bar"

    def test_add_txt_record(self: _LexiconAwareTestCase) -> None:
        self.client.add_txt_record(DOMAIN, self.record_name,
                                   self.record_content)

        self.provider_mock.create_record.assert_called_with(
            rtype='TXT', name=self.record_name, content=self.record_content)

    def test_add_txt_record_try_twice_to_find_domain(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.authenticate.side_effect = [
            self.DOMAIN_NOT_FOUND, ''
        ]

        self.client.add_txt_record(DOMAIN, self.record_name,
                                   self.record_content)

        self.provider_mock.create_record.assert_called_with(
            rtype='TXT', name=self.record_name, content=self.record_content)

    def test_add_txt_record_fail_to_find_domain(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.authenticate.side_effect = [
            self.DOMAIN_NOT_FOUND,
            self.DOMAIN_NOT_FOUND,
            self.DOMAIN_NOT_FOUND,
        ]

        self.assertRaises(errors.PluginError, self.client.add_txt_record,
                          DOMAIN, self.record_name, self.record_content)

    def test_add_txt_record_fail_to_authenticate(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.authenticate.side_effect = self.LOGIN_ERROR

        self.assertRaises(errors.PluginError, self.client.add_txt_record,
                          DOMAIN, self.record_name, self.record_content)

    def test_add_txt_record_fail_to_authenticate_with_unknown_error(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.authenticate.side_effect = self.UNKNOWN_LOGIN_ERROR

        self.assertRaises(errors.PluginError, self.client.add_txt_record,
                          DOMAIN, self.record_name, self.record_content)

    def test_add_txt_record_error_finding_domain(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.authenticate.side_effect = self.GENERIC_ERROR

        self.assertRaises(errors.PluginError, self.client.add_txt_record,
                          DOMAIN, self.record_name, self.record_content)

    def test_add_txt_record_error_adding_record(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.create_record.side_effect = self.GENERIC_ERROR

        self.assertRaises(errors.PluginError, self.client.add_txt_record,
                          DOMAIN, self.record_name, self.record_content)

    def test_del_txt_record(self: _LexiconAwareTestCase) -> None:
        self.client.del_txt_record(DOMAIN, self.record_name,
                                   self.record_content)

        self.provider_mock.delete_record.assert_called_with(
            rtype='TXT', name=self.record_name, content=self.record_content)

    def test_del_txt_record_fail_to_find_domain(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.authenticate.side_effect = [
            self.DOMAIN_NOT_FOUND,
            self.DOMAIN_NOT_FOUND,
            self.DOMAIN_NOT_FOUND,
        ]

        self.client.del_txt_record(DOMAIN, self.record_name,
                                   self.record_content)

    def test_del_txt_record_fail_to_authenticate(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.authenticate.side_effect = self.LOGIN_ERROR

        self.client.del_txt_record(DOMAIN, self.record_name,
                                   self.record_content)

    def test_del_txt_record_fail_to_authenticate_with_unknown_error(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.authenticate.side_effect = self.UNKNOWN_LOGIN_ERROR

        self.client.del_txt_record(DOMAIN, self.record_name,
                                   self.record_content)

    def test_del_txt_record_error_finding_domain(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.authenticate.side_effect = self.GENERIC_ERROR

        self.client.del_txt_record(DOMAIN, self.record_name,
                                   self.record_content)

    def test_del_txt_record_error_deleting_record(
            self: _LexiconAwareTestCase) -> None:
        self.provider_mock.delete_record.side_effect = self.GENERIC_ERROR

        self.client.del_txt_record(DOMAIN, self.record_name,
                                   self.record_content)
    def test_build_exists(self):
        """
        Test the build_exists function
        """
        with patch("veracode.api.get_app_id", return_value="1337"):
            upload_api = UploadAPI(app_name=test_constants.VALID_UPLOAD_API["app_name"])

        with patch.object(
            UploadAPI,
            "http_get",
            return_value=test_constants.VALID_UPLOAD_API_GETBUILDLIST_MISSING_BUILDID_IN_RESPONSE_XML[
                "Element"
            ],
        ):
            # Succeed when no existing build IDs are present
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertTrue(submit_artifacts.build_exists(upload_api=upload_api))

            # Raise a RuntimeError when element_contains_error returns True
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=True
            ):
                self.assertRaises(
                    RuntimeError,
                    submit_artifacts.build_exists,
                    upload_api=upload_api,
                )

        ## Create Sandbox Scan and have existing build ID
        upload_api.sandbox_id = "12345"
        with patch.object(
            UploadAPI,
            "http_get",
            return_value=test_constants.VALID_UPLOAD_API_GETBUILDLIST_BUILDID_IN_RESPONSE_XML[
                "Element"
            ],
        ):
            # Fail when build already exists
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                self.assertFalse(submit_artifacts.build_exists(upload_api=upload_api))

        # Raise RuntimeError when HTTPError occurs
        with patch("veracode.api.VeracodeXMLAPI.http_get") as mock_http:
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                mock_http.side_effect = HTTPError()
                self.assertRaises(
                    RuntimeError,
                    submit_artifacts.build_exists,
                    upload_api=upload_api,
                )

        # Raise RuntimeError when HTTPError occurs
        with patch("veracode.api.VeracodeXMLAPI.http_get") as mock_http:
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                mock_http.side_effect = HTTPError()
                self.assertRaises(
                    RuntimeError,
                    submit_artifacts.build_exists,
                    upload_api=upload_api,
                )
    def test_upload_large_file(self, mock_element_contains_error):
        """
        Test the upload_large_file function
        """
        mock_element_contains_error.return_value = False
        # Succeed when calling the upload_large_file function and the api call
        # gets a valid response
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VALID_UPLOAD_API_UPLOADLARGEFILE_RESPONSE_XML[
                "bytes"
            ],
        ):
            # Policy scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(
                    app_name=test_constants.VALID_UPLOAD_API["app_name"]
                )
                valid_artifact = test_constants.VALID_FILE["Path"]

            with patch(
                "veracode.submit_artifacts.open",
                new=mock_open(read_data=test_constants.VALID_FILE["bytes"]),
            ):
                self.assertTrue(
                    submit_artifacts.upload_large_file(
                        upload_api=upload_api, artifact=valid_artifact
                    )
                )

            # Sandbox scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(
                    app_name=test_constants.VALID_UPLOAD_API["app_name"]
                )
                upload_api.sandbox_id = "12345"
                valid_artifact = test_constants.VALID_FILE["Path"]

            with patch(
                "veracode.submit_artifacts.open",
                new=mock_open(read_data=test_constants.VALID_FILE["bytes"]),
            ):
                self.assertTrue(
                    submit_artifacts.upload_large_file(
                        upload_api=upload_api, artifact=valid_artifact
                    )
                )

        # Fail when calling the upload_large_file function and the api call
        # raises a HTTPError
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VALID_UPLOAD_API_UPLOADLARGEFILE_RESPONSE_XML[
                "bytes"
            ],
            side_effect=HTTPError(),
        ):
            # Policy scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(
                    app_name=test_constants.VALID_UPLOAD_API["app_name"]
                )
                valid_artifact = test_constants.VALID_FILE["Path"]

            with patch(
                "veracode.submit_artifacts.open",
                new=mock_open(read_data=test_constants.VALID_FILE["bytes"]),
            ):
                self.assertRaises(
                    HTTPError,
                    submit_artifacts.upload_large_file,
                    upload_api=upload_api,
                    artifact=valid_artifact,
                )

            # Sandbox scan
            with patch("veracode.api.get_app_id", return_value="1337"):
                upload_api = UploadAPI(
                    app_name=test_constants.VALID_UPLOAD_API["app_name"]
                )
                upload_api.sandbox_id = "12345"
                valid_artifact = test_constants.VALID_FILE["Path"]

            with patch(
                "veracode.submit_artifacts.open",
                new=mock_open(read_data=test_constants.VALID_FILE["bytes"]),
            ):
                self.assertRaises(
                    HTTPError,
                    submit_artifacts.upload_large_file,
                    upload_api=upload_api,
                    artifact=valid_artifact,
                )
Example #16
0
 def raise_for_status(self):
     if self.status_code >= 400:
         raise HTTPError()
Example #17
0
 def test_make_normandy_call_with_HTTP_error(self):
     self.mock_normandy_requests_get.side_effect = HTTPError()
     with self.assertRaises(NonsuccessfulNormandyCall) as e:
         make_normandy_call("/url/")
         self.assertEqual(e.message, "Error calling Normandy API")
Example #18
0
 def fail():
     raise HTTPError("Big, big error")
Example #19
0
 def _make_httperror(self, url, status_code, reason):
     response = Response()
     response.reason = reason
     response.status_code = status_code
     response.url = url
     return HTTPError(request=Request('POST', url), response=response)
Example #20
0
 def internal_server_error():
     raise HTTPError(response=Mock(status_code=503))
Example #21
0
 def raise_http_error(*args, **kwargs):  # pylint: disable=unused-argument
     """Mock function to raise an exception"""
     error = HTTPError()
     error.response = MagicMock()
     error.response.status_code = status_code
     raise error
 def fake_method(**kwargs):
     e = HTTPError('Fake 404')
     e.response = Response()
     setattr(e.response, 'status_code', 404)
     raise e
Example #23
0
 def err_resp():
     resp = lambda: None  # noqa
     resp.status_code = 400
     resp.json = lambda: {}  # noqa
     raise HTTPError(response=resp)
Example #24
0
 def test_status_checks_no_json(self, mock_raise, mock_get):
     mock_raise.side_effect = HTTPError('An HTTP error occurred.')
     mock_get.return_value = requests.Response()
     with self.assertRaises(HTTPError) as e:
         self.mtu.session.get('http://example.com')
     self.assertTrue('An HTTP error occurred' in str(e.exception))
Example #25
0
 def raise_for_status(self):
     if self.status != 200:
         raise HTTPError('Not 200 Client Error')
Example #26
0
 def raise_for_status(self):
     raise HTTPError()
Example #27
0
 def p(self):
     raise HTTPError("foo")
Example #28
0
def raise_detailed_error(request_object):
    try:
        request_object.raise_for_status()
    except HTTPError as e:
        # raise detailed error message
        raise HTTPError(e, request_object.text)
Example #29
0
    def get_activity_logs(self, st, et=None, filter=None):
        """
        Get's the activity log for the specified date or date range. If et is None, it will get all logs (from midnight
        to 11:59:59 UTC) for the date specified by st. If et is set, it will retrieve logs from st-et. Note that the
        Power BI Activity Service currently supports only retrieving one day of logs at a time.

        "filter" is a string parameter that's sent to the service to filter the types of events returned. For example,
        "Activity eq 'viewreport' and UserId eq '*****@*****.**'" gets report views for john(contoso.com).
        Right now the service only supports the operators ['eq', 'and'].

        NOTE: It appears that only data from December 15th, 2019 and on can be retrieved by the API as of the writing
        of this code. This isn't an official limitation I've found in the documentation, but seems to be the case.

        NOTE: This API allows at most 200 Requests per hour.

        For a good overview of the service, see https://powerbi.microsoft.com/en-us/blog/the-power-bi-activity-log-makes-it-easy-to-download-activity-data-for-custom-usage-reporting/

        :param st: The date to retrieve usage for (python datetime).
        :param et: The date to retrieve usage for (python datetime).
        :param filter: A string that defines a filter for retrieving the information. See the Power BI REST API
                       Documentation for details.
        :return:
        """
        # TODO: It would be nice if the available parameters for the "filter" function were defined somewhere in code.

        if et is None:
            dt_str = st.strftime("%Y-%m-%d")
            st_dt_str = f"{dt_str}T00:00:00"
            et_dt_str = f"{dt_str}T23:59:59"
        else:
            st_dt_str = st.strftime("%Y-%m-%dT:%H%M%S")
            et_dt_str = et.strftime("%Y-%m-%dT:%H%M%S")

        # https://api.powerbi.com/v1.0/myorg/admin/activityevents?startDateTime='{st_dt_str}'&endDateTime='{et_dt_str}'

        # form the url
        filter_snippet = f"startDateTime='{st_dt_str}'&endDateTime='{et_dt_str}'"
        url = f'{self.base_url}/{self.group_part}/{self.activities_events_snippet}?{filter_snippet}'

        if filter is not None:
            url += f"$filter={filter}"

        # form the headers
        headers = self.client.auth_header

        # get the response
        response = requests.get(url, headers=headers)

        # 200 is the only successful code, raise an exception on any other response code
        if response.status_code != 200:
            raise HTTPError(response, f'Get Datasets request returned http error: {response.json()}')

        response_obj = response.json()

        event_entities = response_obj["activityEventEntities"]
        continuation_uri = response_obj["continuationUri"]
        continuation_token = response_obj["continuationToken"]

        activity_events = event_entities

        # Even if nothing is returned, it takes around 24 tries until no continuation token is returned.
        # (This is how Microsoft says the API is to be used.)
        # It seems to send the first set of actual data around 12-15 calls in. This doesn't seem to change even if you
        # slow down the API calls (in total number of calls required or when the first set of actual data is returned).

        cont_count = 1
        while continuation_token is not None:

            response = requests.get(continuation_uri, headers=headers)
            response_obj = response.json()

            event_entities = response_obj["activityEventEntities"]
            continuation_uri = response_obj["continuationUri"]
            continuation_token = response_obj["continuationToken"]

            activity_events.extend(event_entities)
            # print(f"{cont_count}: {len(event_entities)}")
            cont_count += 1

        # print(f"Took {cont_count} tries to exhaust continuation token for {len(activity_events)} events.")

        # Convert Datetime Strings to Python datetimes
        _date_fmt_str = '%Y-%m-%dT%H:%M:%S'
        for event in activity_events:
            event["CreationTime"] = datetime.datetime.strptime(event["CreationTime"], _date_fmt_str)
            # Change the Timezone to UTC
            event["CreationTime"] = event["CreationTime"].replace(tzinfo=datetime.timezone.utc)

        return activity_events
Example #30
0
 def test_get_storage_session_raises_session_init_error_when_tmp_auth_raises_http_error(
         self, mock_tmp_auth):
     mock_tmp_auth.get_storage_url.side_effect = Py42HTTPError(HTTPError())
     storage_session_manager = ConnectionManager()
     with pytest.raises(Py42StorageSessionInitializationError):
         storage_session_manager.get_storage_connection(mock_tmp_auth)
    def test_begin_prescan(self):
        """
        Test the begin_prescan function
        """
        # Succeed when calling the begin_prescan function and the api call gets
        # a valid response
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VALID_UPLOAD_API_BEGINPRESCAN_RESPONSE_XML[
                "Element"
            ],
        ):
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertTrue(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

                    # Sandbox scan
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertTrue(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

            # Fail when the begin_prescan function gets a response containing an
            # error in the response body
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=True
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertFalse(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

                    # Sandbox scan
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertFalse(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

        # Fail when calling the begin_prescan function and the api call gets a
        # mocked side effect of HTTPError
        with patch.object(UploadAPI, "http_post", side_effect=HTTPError()):
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan
                    upload_api = UploadAPI(app_name="31337")
                    self.assertFalse(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )

                    # Sandbox scan
                    upload_api = UploadAPI(app_name="31337")
                    upload_api.sandbox_id = "12345"
                    self.assertFalse(
                        submit_artifacts.begin_prescan(upload_api=upload_api)
                    )
 def parse_response(response):
     if response.status == http.client.NO_CONTENT:
         return None
     if not response.status == http.client.OK:
         raise HTTPError(response=response)
     return helpers.AVSMultipartDecoder(response).directives
    def test_create_build(self):
        """
        Test the create_build function
        """
        # Test the create_build function when the api call gets a valid response
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VALID_UPLOAD_API_CREATEBUILD_RESPONSE_XML[
                "Element"
            ],
        ):
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan, no error in response body
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertTrue(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

                    # Sandbox scan, no error in response body
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertTrue(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

            # Fail when the create_build function gets a response containing an
            # error in the response body
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=True
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan, response body contains error
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertFalse(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

                    # Sandbox scan, response body contains error
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertFalse(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

        # Fail when calling the create_build function and the api call gets a
        # mocked error message response and a mocked side effect of HTTPError
        with patch.object(
            UploadAPI,
            "http_post",
            return_value=test_constants.VERACODE_ERROR_RESPONSE_XML["Element"],
            side_effect=HTTPError(),
        ):
            with patch(
                "veracode.submit_artifacts.element_contains_error", return_value=False
            ):
                with patch("veracode.api.get_app_id", return_value="1337"):
                    # Policy scan, no error in response body
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    self.assertFalse(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )

                    # Sandbox scan, no error in response body
                    upload_api = UploadAPI(
                        app_name=test_constants.VALID_UPLOAD_API["app_name"]
                    )
                    upload_api.sandbox_id = "12345"
                    self.assertFalse(
                        submit_artifacts.create_build(upload_api=upload_api)
                    )
Example #34
0
    def _query(self, source, image_filename=None):
        ''' Returns datastream of a url generated from its context '''

        chunk_size = 1024
        for i in range(1, 10):
            try:
                timeout = 300 * i

                domain = self.domain

                # Build uri path for thread or catalog
                static_source = ["image"]
                if source == "board":
                    path = "/" + self.board + "/thread/" + self.threadno

                    # only fetch last 50 replies on update and if jsondata contains field tail_size
                    if self.lasttime and self.tail_size and not self.notail:
                        self.is_tail = True
                        path += "-tail"

                    path += ".json"

                elif source == "catalog":
                    path = "/" + self.board + "/catalog.json"

                elif source == "image":
                    domain = "i.4cdn.org"

                    path = "/" + self.board + "/" + image_filename
                else:
                    return None

# 				if self.config.get("site.ssl"):
# 					uri = "https://" + domain + path
# 				else:
# 					uri = "http://" + domain + path

                uri = "https://" + domain + path  # TODO user setting for http/https

                self.dlog.msg("ContentFetcher: In _query for " + uri, 4)

                headers = {'Accept-encoding': 'gzip'}

                socket.setdefaulttimeout(timeout)  # TODO user setting

                if (source not in static_source and self.lasttime != ""):
                    headers.update({'If-Modified-Since': self.lasttime})

                # Fetch data and store into content
                content = ""
                request = requests.get(uri, headers=headers, stream=True)

                # Get content length for percentage progress
                try:
                    content_length = int(request.headers['Content-length'])
                    self.dlog.msg(
                        "ContentFetcher: Headers: " + str(request.headers), 5)
                except KeyError or ValueError:
                    content_length = False

                request.raise_for_status()
                for data in request.iter_content(chunk_size=chunk_size):

                    socket.setdefaulttimeout(timeout)
                    content += data

                    # Show thread download progress in the location of the statusbar
                    if self.stdscr and self.sb:
                        try:
                            # Save position
                            #saved_y, saved_x = self.stdscr.getyx()

                            #screensize_y, screensize_x = self.stdscr.getmaxyx();
                            statusText = " " + source.upper() + "-GET: " + str(
                                len(content) / 1024) + "K"

                            # show the progress bar/total size for uncompressed images,
                            # TODO need to work with request.raw to get the correct size for gzip'd content
                            if content_length and source == 'image':
                                statusText += "/" + str(
                                    content_length / 1024) + "K" + "(" + str(
                                        len(content) * 100 /
                                        (content_length)) + "%)"

                            self.sb.setStatus(statusText)
                            #self.stdscr.addstr(screensize_y-2, screensize_x-3-len(statusText), statusText, curses.color_pair(1))  # @UndefinedVariable
                            # Restore prior position
                            #self.stdscr.move(saved_y, saved_x)
                            #self.stdscr.refresh()
                        except Exception as err:
                            self.dlog.warn(err,
                                           logLevel=3,
                                           msg=">>>in ContentFetcher.query()")
                            continue

                    #self.dlog.msg("ContentFetcher: Data transmission from >>>/" + self.board + "/" + self.threadno + "/ (" + str((len(content)+len(data))/1024) + "K)", 3)

                # Raise redirection status codes mainly to catch 304 Not Modified
                if 300 <= request.status_code < 400:
                    http_error_msg = u'%s' % (request.status_code)
                    http_error = HTTPError(http_error_msg, response=request)
                    raise (http_error)

                request.raise_for_status()

                if source not in static_source:
                    #self.lasttime = datastream.headers.get('Last-Modified')
                    self.lasttime = request.headers.get('Last-Modified')

#				# TODO: remove, requests seems to automatically deflate
# 				try:
# 					if request.headers.get('Content-Encoding') == 'gzip':
# 						content = gzip.GzipFile(fileobj=StringIO(content)).read()
# 				except:
# 					pass

# blank
                if self.sb:
                    self.sb.setStatus(" " + source.upper() + "-GET: " +
                                      str(content_length / 1024) + "K (100%)")

                return content

            except SSLError as e:
                self.dlog.msg(str(e) + " New timeout: " + str(timeout))
                continue
            except HTTPError:
                raise
            except Exception as e:
                self.dlog.excpt(e,
                                msg=">>>in ContentFetcher.get()",
                                cn=self.__class__.__name__)
                raise
            break
Example #35
0
 def expect_request(self, url, data, throws=None):
     response = self.mocker.mock()
     self.expect(self.requests.post(url, data=data)).result(response)
     self.expect(response.raise_for_status())
     if throws:
         self.mocker.throw(HTTPError('http error %s' % throws))
 def test_exception_raised_when_making_calls(self):
     with patch('pycrunchbase.pycrunchbase.requests') as mock_request:
         mock_request.get = Mock(side_effect=HTTPError())
         cb = CrunchBase('123')
         with self.assertRaises(HTTPError):
             cb.organizations('organization')
Example #37
0
    def _internal_request(self, request_obj, url, method, **kwargs):
        """ Internal handling of requests. Handles Exceptions.

        :param request_obj: a requests session.
        :param str url: url to send request to
        :param str method: type of request (get/put/post/patch/delete)
        :param kwargs: extra params to send to the request api
        :return: Response of the request
        :rtype: requests.Response
        """
        method = method.lower()
        if method not in self._allowed_methods:
            raise ValueError('Method must be one of the allowed ones')
        if method == 'get':
            kwargs.setdefault('allow_redirects', True)
        elif method in ['post', 'put', 'patch']:
            if 'headers' not in kwargs:
                kwargs['headers'] = {}
            if kwargs.get('headers') is not None and kwargs['headers'].get(
                    'Content-type') is None:
                kwargs['headers']['Content-type'] = 'application/json'
            if 'data' in kwargs and kwargs['data'] is not None and kwargs[
                    'headers'].get('Content-type') == 'application/json':
                kwargs['data'] = json.dumps(kwargs['data'])  # convert to json

        if self.timeout is not None:
            kwargs['timeout'] = self.timeout

        request_done = False
        token_refreshed = False

        while not request_done:
            self._check_delay()  # sleeps if needed
            try:
                log.info('Requesting ({}) URL: {}'.format(method.upper(), url))
                log.info('Request parameters: {}'.format(kwargs))
                # auto_retry will occur inside this function call if enabled
                response = request_obj.request(method, url, **kwargs)
                response.raise_for_status()  # raise 4XX and 5XX error codes.
                log.info('Received response ({}) from URL {}'.format(
                    response.status_code, response.url))
                request_done = True
                return response
            except TokenExpiredError as e:
                # Token has expired, try to refresh the token and try again on the next loop
                if self.token_backend.token.is_long_lived is False and self.auth_flow_type == 'authorization':
                    raise e
                if token_refreshed:
                    # Refresh token done but still TokenExpiredError raise
                    raise RuntimeError('Token Refresh Operation not working')
                log.info('Oauth Token is expired, fetching a new token')
                if self.refresh_token() is False:
                    raise RuntimeError('Token Refresh Operation not working')
                log.info('New oauth token fetched')
                token_refreshed = True
            except (ConnectionError, ProxyError, SSLError, Timeout) as e:
                # We couldn't connect to the target url, raise error
                log.debug('Connection Error calling: {}.{}'
                          ''.format(url, ('Using proxy: {}'.format(self.proxy)
                                          if self.proxy else '')))
                raise e  # re-raise exception
            except HTTPError as e:
                # Server response with 4XX or 5XX error status codes

                # try to extract the error message:
                try:
                    error = response.json()
                    error_message = error.get('error', {}).get('message', '')
                except ValueError:
                    error_message = ''

                status_code = int(e.response.status_code / 100)
                if status_code == 4:
                    # Client Error
                    # Logged as error. Could be a library error or Api changes
                    log.error('Client Error: {} | Error Message: {}'.format(
                        str(e), error_message))
                else:
                    # Server Error
                    log.debug('Server Error: {}'.format(str(e)))
                if self.raise_http_errors:
                    if error_message:
                        raise HTTPError('{} | Error Message: {}'.format(
                            e.args[0], error_message),
                                        response=response) from None
                    else:
                        raise e
                else:
                    return e.response
            except RequestException as e:
                # catch any other exception raised by requests
                log.debug('Request Exception: {}'.format(str(e)))
                raise e
Example #38
0
class NewCreditsViewTestCase(MTPBaseTestCase):

    @property
    def url(self):
        return reverse('new-credits')

    def test_new_credits_display(self):
        with responses.RequestsMock() as rsps:
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            self.login()
            response = self.client.get(self.url, follow=True)
            self.assertContains(response, '52.00')
            self.assertContains(response, '45.00')

    @override_settings(ENVIRONMENT='prod')  # because non-prod environments don't send to .local
    @mock.patch(
        'cashbook.tasks.nomis.create_transaction',

        # return {'id' == '<prisoner-number>-1'}
        side_effect=lambda **kwargs: {'id': f'{kwargs["prisoner_number"]}-1'},
    )
    def test_new_credits_submit(self, mock_create_transaction):
        with responses.RequestsMock() as rsps:
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # create batch
            rsps.add(
                rsps.POST,
                api_url('/credits/batches/'),
                status=201,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            # REDIRECT after success
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get complete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=credited&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # delete completed batch
            rsps.add(
                rsps.DELETE,
                api_url('/credits/batches/%s/' % PROCESSING_BATCH['id']),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.post(
                self.url,
                data={'credits': [1, 2], 'submit_new': 'submit'},
                follow=True
            )
            self.assertEqual(response.status_code, 200)
            expected_calls = [
                [{'id': 1, 'credited': True, 'nomis_transaction_id': 'A1234BC-1'}],
                [{'id': 2, 'credited': True, 'nomis_transaction_id': 'A1234GG-1'}]
            ]
            self.assertTrue(
                json.loads(rsps.calls[3].request.body.decode('utf-8')) in expected_calls and
                json.loads(rsps.calls[4].request.body.decode('utf-8')) in expected_calls
            )

            request_nomis_session_used = mock_create_transaction.call_args_list[0][1]['session']
            mock_create_transaction.assert_has_calls(
                [
                    mock.call(
                        amount=5200,
                        description='Sent by Fred Smith',
                        prison_id='BXI',
                        prisoner_number='A1234BC',
                        record_id='1',
                        retries=1,
                        session=request_nomis_session_used,
                        transaction_type='MTDS',
                    ),
                    mock.call(
                        amount=4500,
                        description='Sent by Fred Jones',
                        prison_id='BXI',
                        prisoner_number='A1234GG',
                        record_id='2',
                        retries=1,
                        session=request_nomis_session_used,
                        transaction_type='MTDS',
                    ),
                ],
                any_order=True,
            )
            self.assertContains(response, '2 credits sent to NOMIS')
            self.assertEqual(len(mail.outbox), 2)
            self.assertTrue(
                '£52.00' in mail.outbox[0].body and '£45.00' in mail.outbox[1].body or
                '£52.00' in mail.outbox[1].body and '£45.00' in mail.outbox[0].body
            )
            self.assertTrue(
                'BAAB65F6' in mail.outbox[0].body or
                'BAAB65F6' in mail.outbox[1].body
            )

    @override_settings(
        ENVIRONMENT='prod',  # because non-prod environments don't send to .local
        PRISONER_CAPPING_ENABLED=True,
        PRISONER_CAPPING_THRESHOLD_IN_POUNDS=100,
    )
    @mock.patch('cashbook.tasks.logger')
    @mock.patch('cashbook.tasks.nomis')
    def test_balance_check_after_credit(self, mock_nomis, mock_logger):
        balances = {
            # credit 1 – £52 – within cap
            'A1234BC': {'cash': 800, 'spends': 0, 'savings': 4000},
            # credit 2 – £45 – exceeds cap
            'A1234GG': {'cash': 1000, 'spends': 200, 'savings': 5500},
        }

        def create_transaction(**kwargs):
            prisoner_number = kwargs['prisoner_number']
            amount = kwargs['amount']
            balances[prisoner_number]['cash'] += amount
            return {'id': f'{prisoner_number}-1'}

        def get_account_balances(prison, prisoner_number):
            self.assertEqual(prison, 'BXI', msg='Unexpected test data')
            return balances[prisoner_number]

        mock_nomis.create_transaction = create_transaction
        mock_nomis.get_account_balances = get_account_balances

        with responses.RequestsMock() as rsps:
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # create batch
            rsps.add(
                rsps.POST,
                api_url('/credits/batches/'),
                status=201,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            # REDIRECT after success
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get complete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=credited&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # delete completed batch
            rsps.add(
                rsps.DELETE,
                api_url('/credits/batches/%s/' % PROCESSING_BATCH['id']),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.post(
                self.url,
                data={'credits': [1, 2], 'submit_new': 'submit'},
                follow=True
            )

        self.assertEqual(response.status_code, 200)
        self.assertContains(response, '2 credits sent to NOMIS')
        logger_error_messages = [call[0][0] for call in mock_logger.error.call_args_list]
        self.assertEqual(len(logger_error_messages), 1)
        self.assertEqual(logger_error_messages[0], 'NOMIS account balance for A1234GG exceeds cap')

    @override_settings(ENVIRONMENT='prod')  # because non-prod environments don't send to .local
    @mock.patch(
        'cashbook.tasks.nomis.create_transaction',
        side_effect=[
            HTTPError(response=mock.Mock(status_code=409)),
            {'id': 'A1234GG-1'},
        ],
    )
    def test_new_credits_submit_with_conflict(self, _):
        with responses.RequestsMock() as rsps:
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # create batch
            rsps.add(
                rsps.POST,
                api_url('/credits/batches/'),
                status=201,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            # REDIRECT after success
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get complete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=credited&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # delete completed batch
            rsps.add(
                rsps.DELETE,
                api_url('/credits/batches/%s/' % PROCESSING_BATCH['id']),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )

            self.login()
            with silence_logger(name='mtp', level=logging.ERROR):
                response = self.client.post(
                    self.url,
                    data={'credits': [1, 2], 'submit_new': 'submit'},
                    follow=True
                )
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, '2 credits sent to NOMIS')
            self.assertEqual(len(mail.outbox), 2)

    @override_settings(ENVIRONMENT='prod')  # because non-prod environments don't send to .local
    @mock.patch(
        'cashbook.tasks.nomis.create_transaction',
        side_effect=[
            HTTPError(response=mock.Mock(status_code=400)),
            {'id': 'A1234GG-1'},
        ],
    )
    @mock.patch(
        'cashbook.tasks.nomis.get_location',
        return_value={
            'nomis_id': 'LEI',
            'name': 'LEEDS (HMP)',
        },
    )
    def test_new_credits_submit_with_uncreditable(self, *_):
        with responses.RequestsMock() as rsps:
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # create batch
            rsps.add(
                rsps.POST,
                api_url('/credits/batches/'),
                status=201,
            )
            # credit credits to NOMIS and API
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/setmanual/'),
                status=204,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            # REDIRECT after success
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get complete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=credited&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # delete completed batch
            rsps.add(
                rsps.DELETE,
                api_url('/credits/batches/%s/' % PROCESSING_BATCH['id']),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(CREDIT_1),
                status=200,
                match_querystring=True,
            )

            self.login()
            with silence_logger(name='mtp', level=logging.CRITICAL):
                response = self.client.post(
                    self.url,
                    data={'credits': [1, 2], 'submit_new': 'submit'},
                    follow=True
                )
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, '1 credit sent to NOMIS')
            self.assertContains(response, '1 credit needs your manual input in NOMIS')
            self.assertEqual(len(mail.outbox), 1)

    @override_settings(ENVIRONMENT='prod')  # because non-prod environments don't send to .local
    @mock.patch(
        'cashbook.views.nomis.get_location',
        return_value={
            'nomis_id': 'LEI',
            'name': 'LEEDS (HMP)',
        },
    )
    def test_manual_credits_submit(self, _):
        with responses.RequestsMock() as rsps:
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # credit credit to API
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            # REDIRECT after success
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(CREDIT_2),
                status=200,
                match_querystring=True,
            )

            self.login()
            response = self.client.post(
                self.url,
                data={'submit_manual_1': ''},
                follow=True
            )
            self.assertEqual(
                json.loads(rsps.calls[2].request.body.decode('utf-8')),
                [{'id': 1, 'credited': True}]
            )
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, '1 credit manually input by you into NOMIS')
Example #39
0
    def request(self,
                method,
                url,
                params=None,
                data=None,
                headers=None,
                cookies=None,
                files=None,
                auth=None,
                timeout=None,
                allow_redirects=True,
                proxies=None,
                hooks=None,
                stream=None,
                verify=None,
                cert=None,
                **kwargs):
        """Constructs a :class:`Request <Request>`, prepares it and sends it.
        Returns :class:`Response <Response>` object.

        :param method: method for the new :class:`Request` object.
        :param url: URL for the new :class:`Request` object.
        :param params: (optional) Dictionary or bytes to be sent in the query
            string for the :class:`Request`.
        :param data: (optional) Dictionary or bytes to send in the body of the
            :class:`Request`.
        :param headers: (optional) Dictionary of HTTP Headers to send with the
            :class:`Request`.
        :param cookies: (optional) Dict or CookieJar object to send with the
            :class:`Request`.
        :param files: (optional) Dictionary of 'filename': file-like-objects
            for multipart encoding upload.
        :param auth: (optional) Auth tuple or callable to enable
            Basic/Digest/Custom HTTP Auth.
        :param timeout: (optional) Float describing the timeout of the
            request.
        :param allow_redirects: (optional) Boolean. Set to True by default.
        :param proxies: (optional) Dictionary mapping protocol to the URL of
            the proxy.
        :param stream: (optional) whether to immediately download the response
            content. Defaults to ``False``.
        :param verify: (optional) if ``True``, the SSL cert will be verified.
            A CA_BUNDLE path can also be provided.
        :param cert: (optional) if String, path to ssl client cert file (.pem).
            If Tuple, ('cert', 'key') pair.
        """
        #===============================================================================================================
        # add by mz
        error_type = kwargs.get("error_type")
        if error_type:
            from requests.exceptions import InvalidURL, URLRequired, ConnectTimeout, ConnectionError, SSLError, ReadTimeout
            from requests.exceptions import InvalidSchema, MissingSchema, ChunkedEncodingError, ContentDecodingError
            from requests.exceptions import RequestException, HTTPError, ProxyError, Timeout, RetryError, StreamConsumedError

            get_error = {
                "InvalidURL": InvalidURL(),
                "URLRequired": URLRequired(),
                "ConnectTimeout": ConnectTimeout(),
                "ConnectionError": ConnectionError(),
                "SSLError": SSLError(),
                "ReadTimeout": ReadTimeout(),
                "InvalidSchema": InvalidSchema(),
                "MissingSchema": MissingSchema(),
                "ChunkedEncodingError": ChunkedEncodingError(),
                "ContentDecodingError": ContentDecodingError(),
                "StreamConsumedError": StreamConsumedError(),
                "TooManyRedirects": TooManyRedirects(),
                "RequestException": RequestException(),
                "HTTPError": HTTPError(),
                "ProxyError": ProxyError(),
                "Timeout": Timeout(),
                "RetryError": RetryError
            }

            error_ = get_error[error_type]
            raise error_
        #===============================================================================================================

        method = builtin_str(method)

        # Create the Request.
        req = Request(
            method=method.upper(),
            url=url,
            headers=headers,
            files=files,
            data=data or {},
            params=params or {},
            auth=auth,
            cookies=cookies,
            hooks=hooks,
        )
        prep = self.prepare_request(req)

        proxies = proxies or {}

        # Gather clues from the surrounding environment.
        if self.trust_env:
            # Set environment's proxies.
            env_proxies = get_environ_proxies(url) or {}
            for (k, v) in env_proxies.items():
                proxies.setdefault(k, v)

            # Look for configuration.
            if not verify and verify is not False:
                verify = os.environ.get('REQUESTS_CA_BUNDLE')

            # Curl compatibility.
            if not verify and verify is not False:
                verify = os.environ.get('CURL_CA_BUNDLE')

        # Merge all the kwargs.
        proxies = merge_setting(proxies, self.proxies)
        stream = merge_setting(stream, self.stream)
        verify = merge_setting(verify, self.verify)
        cert = merge_setting(cert, self.cert)

        # Send the request.
        send_kwargs = {
            'stream': stream,
            'timeout': timeout,
            'verify': verify,
            'cert': cert,
            'proxies': proxies,
            'allow_redirects': allow_redirects,
        }
        resp = self.send(prep, **send_kwargs)

        return resp
Example #40
0
    def push_object(self, fileO, dry=True, publish=True, fire_path=None):
        """
        Function to push (upload) a file.file.File object
        to FIRE. This function currently uses 'curl'.
        As the standard 'requests' module throws memory errors
        when trying to upload large files

        Parameters
        ----------
        fileO : File object
                Object to be uploaded.
        dry : bool, default=True
              If True then it will not try
              to push the File object to FIRE.
        publish : bool, default=True
                 If True then the pushed object will
                 be published on upload.
        fire_path : str, optional
                    Virtual path in FIRE to be used for
                    pushing this File.

        Returns
        -------
        fire_obj : fire.object.fObject
                  fObject with metadata on the stored FIRE object.

        Raises
        ------
        HTTPError
        """
        api_logger.info(f"Pushing File with path: {fileO.name}")

        if is_tool("curl") is False:
            raise Exception("The 'curl' program was not found in this system. Can't continue!...")

        url = f"curl {CONFIG.get('fire', 'root_endpoint')}/{CONFIG.get('fire', 'version')}/objects" \
              f" -u {self.user}:{self.pwd}"

        fire_obj = None
        if dry is False:
            # FIRE api requires atomic operations, so the POST request must be atomic
            # and also multiple atomic PUSH requests for providing fire path and publishing
            url = url+f" -F file=@{fileO.name} -H 'x-fire-md5: {fileO.md5}' -H 'x-fire-size: {fileO.size}' "
            p = Popen(url, stdout=PIPE, stderr=PIPE, shell=True)
            stdout, stderr = p.communicate()
            res = stdout.decode("utf-8")
            fire_obj = None
            api_logger.debug(f"API response:{res}")
            api_logger.debug(f"API response (STDOUT):{stdout}")
            api_logger.debug(f"API response (STDERR):{stderr}")
            # FIRE api is down
            if res == "Service Unavailable":
                raise HTTPError("FIRE Service Unavailable")
            d = json.loads(stdout)
            if "statusCode" in d.keys():
                err = f"{d['statusMessage']}\n{d['detail']}"
                raise HTTPError(err)
            else:
                fire_obj = self.__parse_json_response(d)
                api_logger.info(f"File object pushed with fireOid: {fire_obj.fireOid}")

            if fire_path is not None:
                api_logger.info(f"Virtual FIRE path provided")
                fire_obj = self.update_object(attr_name='firePath', value=fire_path,
                                              fireOid=fire_obj.fireOid, dry=False)
                assert fire_obj is not None, "Error adding a FIRE path to the object"
            if publish is True:
                api_logger.info(f"Pushed object will be published")
                fire_obj = self.update_object(attr_name='publish', value=True,
                                              fireOid=fire_obj.fireOid, dry=False)
                assert fire_obj is not None, "Error adding a publishing the object"

            return fire_obj
        elif dry is True:
            api_logger.info(f"Did not push File with path (dry=True): {fileO.name}")
            api_logger.info(f"Endpoint for pushing is: {url}")
            api_logger.info(f"Use --dry False to effectively push it")
Example #41
0
 def raise_for_status(self):
     if self.status_code != 200:
         raise HTTPError(None)
Example #42
0
 def not_found():
     raise HTTPError(response=Mock(status_code=404))