diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 1a2ae78..decd5ff 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -18,7 +18,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: [2.7, 3.5, 3.6, 3.7, 3.8] + python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} diff --git a/README.rst b/README.rst index 0d5a725..b6bff14 100644 --- a/README.rst +++ b/README.rst @@ -199,4 +199,4 @@ The PyBankID solution can be tested with `pytest `_: .. code-block:: bash - py.test tests/ + py.test diff --git a/bankid/__version__.py b/bankid/__version__.py index f4377e0..897cde7 100644 --- a/bankid/__version__.py +++ b/bankid/__version__.py @@ -8,5 +8,5 @@ from __future__ import print_function from __future__ import absolute_import -__version__ = "0.10.4" +__version__ = "0.11.0" version = __version__ # backwards compatibility name diff --git a/bankid/exceptions.py b/bankid/exceptions.py index f8c20ca..2372d56 100644 --- a/bankid/exceptions.py +++ b/bankid/exceptions.py @@ -15,16 +15,6 @@ from __future__ import unicode_literals from __future__ import absolute_import -import six - - -def get_error_class(exc, exception_text): - error_class = _ERROR_CODE_TO_CLASS.get(six.text_type(exc.message)) - if error_class is None: - return BankIDError("{0}: {1}".format(exc, exception_text)) - else: - return error_class(exception_text) - def get_json_error_class(response): data = response.json() @@ -49,7 +39,7 @@ class BankIDWarning(Warning): class InvalidParametersError(BankIDError): """User induced error. - **Code:** ``INVALID_PARAMETERS`` + **Code:** ``invalidParameters`` **Reason:** Invalid parameter. Invalid use of method. @@ -63,7 +53,7 @@ class InvalidParametersError(BankIDError): class AlreadyInProgressError(BankIDError): """Failure to create new order due to one already in progress. - **Code:** ``ALREADY_IN_PROGRESS`` + **Code:** ``alreadyInProgress`` **Reason:** An order for this user is already in progress. The order is aborted. No order is created. @@ -82,7 +72,7 @@ def __init__(self, *args, **kwargs): class InternalError(BankIDError): """Remote server error. - **Code:** ``INTERNAL_ERROR`` + **Code:** ``internalError`` **Reason:** Internal technical error in the BankID system. @@ -100,6 +90,8 @@ def __init__(self, *args, **kwargs): class MaintenanceError(BankIDError): """The service is temporarily out of service. + **Code:** ``maintenance`` + **Action by RP:** RP may try again without informing the user. If this error is returned repeatedly, RP must inform the user. Message RFA5. @@ -111,163 +103,11 @@ def __init__(self, *args, **kwargs): self.rfa = 5 -class RetryError(BankIDError): - """Remote server error, different from InternalError. - - **Code:** ``RETRY`` - - **Reason:** Internal technical error in the BankID system. - - **Action by RP:** RP must not automatically try again. RP must - inform the user that a technical error has - occurred. Message RFA5 should be used. - - """ - - def __init__(self, *args, **kwargs): - super(RetryError, self).__init__(*args, **kwargs) - self.rfa = 5 - - -class AccessDeniedRPError(BankIDError): - """Access permission denied error. - - **Code:** ``ACCESS_DENIED_RP`` - - **Reason:** RP does not have access to the service or - requested operation. - - **Action by RP:** RP must not try the same request again. This is - an internal error within RP's system and must - not be communicated to the user as a BankID-error. - - """ - - -class ClientError(BankIDError): - """Remote technical error. - - **Code:** ``CLIENT_ERR`` - - **Reason:** Internal technical error. It was not possible to - create or verify the transaction. - - **Action by RP:** RP must not automatically try again. RP must - inform the user. Message RFA12. - - """ - - def __init__(self, *args, **kwargs): - super(ClientError, self).__init__(*args, **kwargs) - self.rfa = 12 - - -class ExpiredTransactionError(BankIDError): - """Error due to collecting on an expired order. - - **Code:** ``EXPIRED_TRANSACTION`` - - **Reason:** The order has expired. The BankID security - app/program did not start, the user did not - finalize the signing or the RP called collect - too late. - - **Action by RP:** RP must inform the user. Message RFA8. - - """ - - def __init__(self, *args, **kwargs): - super(ExpiredTransactionError, self).__init__(*args, **kwargs) - self.rfa = 8 - - -class CertificateError(BankIDError): - """Error due to certificate issues. - - **Code:** ``CERTIFICATE_ERR`` - - **Reason:** - This error is returned if: - 1) The user has entered wrong security code - too many times in her mobile device. The - Mobile BankID cannot be used. - 2) The users BankID is revoked. - 3) The users BankID is invalid. - - **Action by RP:** RP must inform the user. Message RFA13. - - """ - - def __init__(self, *args, **kwargs): - super(CertificateError, self).__init__(*args, **kwargs) - self.rfa = 3 - - -class UserCancelError(BankIDError): - """User had issue a cancel on the order. - - **Code:** ``USER_CANCEL`` - - **Reason:** The user decided to cancel the order. - - **Action by RP:** RP must inform the user. Message RFA6. - - """ - - def __init__(self, *args, **kwargs): - super(UserCancelError, self).__init__(*args, **kwargs) - self.rfa = 6 - - -class CancelledError(BankIDError): - """User had issue a cancel on the order. - - **Code:** ``CANCELLED`` - - **Reason:** The order was cancelled. The system - received a new order for the user. - - **Action by RP:** RP must inform the user. Message RFA3. - - """ - - def __init__(self, *args, **kwargs): - super(CancelledError, self).__init__(*args, **kwargs) - self.rfa = 3 - - -class StartFailedError(BankIDError): - """Error handling the order's progression due to RP/user issues. - - **Code:** ``START_FAILED`` - - **Reason:** The user did not provide her ID, or the RP - requires ``autostarttoken`` to be used, but the - client did not start within a certain time limit. - The reason may be: - - 1) RP did not use autoStartToken when starting - BankID security program/app. - 2) The client software was not installed - or other problem with the user’s computer. - - **Action by RP:** - - 1) The RP must use autoStartToken when - starting the client. - 2) The RP must inform the user. Message RFA17. - - """ - - def __init__(self, *args, **kwargs): - super(StartFailedError, self).__init__(*args, **kwargs) - # TODO: Dual cause, in which only one requires RFA. Remove? - self.rfa = 17 - - class UnauthorizedError(BankIDError): """RP does not have access to the service. + **Code:** ``unauthorized`` + **Action by RP:** RP must not try the same request again. This is an internal error within RP's system and must not be ' communicated to the user as a BankID error. @@ -280,6 +120,8 @@ class UnauthorizedError(BankIDError): class NotFoundError(BankIDError): """An erroneously URL path was used. + **Code:** ``notFound`` + **Action by RP:** RP must not try the same request again. This is an internal error within RP's system and must not be ' communicated to the user as a BankID error. @@ -292,6 +134,8 @@ class NotFoundError(BankIDError): class RequestTimeoutError(BankIDError): """It took too long time to transmit the request. + **Code:** ``requestTimeout`` + **Action by RP:** RP must not automatically try again. This error may occur if the processing at RP or the communication is too slow. RP must inform the user. Message RFA5 @@ -303,28 +147,14 @@ def __init__(self, *args, **kwargs): self.rfa = 5 -_ERROR_CODE_TO_CLASS = { - "INVALID_PARAMETERS": InvalidParametersError, - "ALREADY_IN_PROGRESS": AlreadyInProgressError, - "INTERNAL_ERROR": InternalError, - "RETRY": RetryError, - "ACCESS_DENIED_RP": AccessDeniedRPError, - "CLIENT_ERR": ClientError, - "EXPIRED_TRANSACTION": ExpiredTransactionError, - "CERTIFICATE_ERR": CertificateError, - "USER_CANCEL": UserCancelError, - "CANCELLED": CancelledError, - "START_FAILED": StartFailedError, -} - - _JSON_ERROR_CODE_TO_CLASS = { "invalidParameters": InvalidParametersError, "alreadyInProgress": AlreadyInProgressError, "unauthorized": UnauthorizedError, "notFound": NotFoundError, + # 'methodNotAllowed': , # This will not be handled here... "requestTimeout": RequestTimeoutError, # 'unsupportedMediaType': , # This will not be handled here... "internalError": InternalError, - "Maintenance": MaintenanceError, + "maintenance": MaintenanceError, } diff --git a/docs/get_started.rst b/docs/get_started.rst index 89ac66b..c0ba9b4 100644 --- a/docs/get_started.rst +++ b/docs/get_started.rst @@ -38,7 +38,6 @@ Dependencies PyBankID makes use of the following external packages: * `requests>=2.7.0 `_ -* `zeep>=1.3.0 `_ * `six>=1.9.0 `_ diff --git a/docs/soapclient.rst b/docs/soapclient.rst deleted file mode 100644 index 913a715..0000000 --- a/docs/soapclient.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. _soapclient: - -BankID SOAP Client -================== - -The Relying Party client using the ``v4`` SOAP API. - -**This client will be deprecated in February 2020. Prior to this a** -:exc:`PendingDeprecationWarning` **will be issued on using.** - -Usage ------ - -First, create a ``BankIDClient``: - -.. code-block:: python - - >>> from bankid import BankIDClient - >>> client = BankIDClient(certificates=('path/to/certificate.pem', - ... 'path/to/key.pem')) - -Connection to production server is the default in the client. If test -server is desired, send in the ``test_server=True`` keyword in the init -of the client. - -A sign order is then placed by - -.. code-block:: python - - >>> client.sign(user_visible_data="The information to sign.", - ... personal_number="YYYYMMDDXXXX") - {'autoStartToken': '798c1ea1-e67a-4df6-a2f6-164ac223fd52', - 'orderRef': 'a9b791c3-459f-492b-bf61-23027876140b'} - -and an authentication order is initiated by - -.. code-block:: python - - >>> client.authenticate(personal_number="YYYYMMDDXXXX") - {'autoStartToken': '798c1ea1-e67a-4df6-a2f6-164ac223fd52', - 'orderRef': 'a9b791c3-459f-492b-bf61-23027876140b'} - -The status of an order can then be studied by polling -with the ``collect`` method using the received ``orderRef``: - -.. code-block:: python - - >>> client.collect(order_ref="a9b791c3-459f-492b-bf61-23027876140b") - {'progressStatus': 'OUTSTANDING_TRANSACTION'} - >>> client.collect(order_ref="a9b791c3-459f-492b-bf61-23027876140b") - {'progressStatus': 'USER_SIGN'} - >>> client.collect(order_ref="a9b791c3-459f-492b-bf61-23027876140b") - {'ocspResponse': 'MIIHfgoBAKCCB3cw[...]', - 'progressStatus': 'COMPLETE', - 'signature': 'PD94bWwgdmVyc2lvbj0[...]', - 'userInfo': {'givenName': 'Namn', - 'ipAddress': '195.84.248.212', - 'name': 'Namn Namnsson', - 'notAfter': datetime.datetime(2016, 9, 9, 22, 59, 59), - 'notBefore': datetime.datetime(2014, 9, 9, 23, 0), - 'personalNumber': 'YYYYMMDDXXXX', - 'surname': 'Namnsson'}} - -Please note that the ``collect`` method should be used sparingly: in the -`BankID Relying Party Guidelines `_. -it states that *"collect should be called every two seconds and must not be -called more frequent than once per second"*. - -API ---- - -.. automodule:: bankid.client - :members: diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..55b033e --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1 @@ +pytest \ No newline at end of file diff --git a/setup.py b/setup.py index beb4b9a..e6b21da 100644 --- a/setup.py +++ b/setup.py @@ -6,8 +6,8 @@ PyBankID is a client for performing BankID signing. -The Swedish BankID solution for digital signing uses a SOAP -connection solution, and this module aims at providing a simplifying +The Swedish BankID solution for digital signing utilizes a +JSON API, and this module aims at providing a simplifying client for making authentication, signing and collect requests to the BankID servers. diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index b3272d5..04295d5 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -34,7 +34,7 @@ def test_exceptions(exception_class, rfa): (bankid.exceptions.NotFoundError, "notFound"), (bankid.exceptions.RequestTimeoutError, "requestTimeout"), (bankid.exceptions.InternalError, "internalError"), - (bankid.exceptions.MaintenanceError, "Maintenance"), + (bankid.exceptions.MaintenanceError, "maintenance"), (bankid.exceptions.BankIDError, "Unknown error code"), ], )