Skip to content

Commit

Permalink
Version 0.2.0
Browse files Browse the repository at this point in the history
Closes #4

Python 3 adaptations
Changed test_server keyword default value to False.
Added two tests
Refactored exception raising
Updated test certificate URL
Updated README
Updated classification troves
Added overage to Travis building
Changed to suds-jurko from old suds.
Py3 added to Travis tests.
Added six to help with Py3 conversion.
Minor PEP8 mods.
  • Loading branch information
hbldh committed Oct 1, 2015
1 parent 8a83fe4 commit fbe1b64
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 45 deletions.
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ language: python
sudo: false
python:
- 2.7
- 3.3
- 3.4
branches:
only:
- master
- develop
install:
- "pip install -r requirements.txt"
script: nosetests tests --logging-level=INFO
script: nosetests tests --with-coverage --cover-package=bankid

9 changes: 1 addition & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,7 @@ The PyBankID solution can be tested with ``nosetests``:

.. code-block:: bash
nosetests tests/ --logging-level=INFO
The logging level option is needed due to an issue with the `suds
<https://fedorahosted.org/suds/>`_ module, where a debug level line
breaks the tests.

Only one test is run against the actual BankID test server, to see that the client
can connect and that all urls are up to date.
nosetests tests/
Documentation
-------------
Expand Down
23 changes: 13 additions & 10 deletions bankid/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
# release. 'dev' as a _version_extra string means this is a development
# version.
_version_major = 0
_version_minor = 1
_version_patch = 4
#_version_extra = 'dev4'
#_version_extra = 'b1'
_version_minor = 2
_version_patch = 0
# _version_extra = 'dev4'
# _version_extra = 'alpha0'
_version_extra = '' # Uncomment this for full releases

# Construct full version string from these.
Expand All @@ -28,8 +28,8 @@

description = "BankID client for Python"

long_description = \
"""PyBankID is a client for performing BankID signing.
long_description = """
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
Expand All @@ -43,8 +43,9 @@

license = 'MIT'

authors = {'hbldh': ('Henrik Blidh', 'henrik.blidh@nedomkull.com'),
}
authors = {
'hbldh': ('Henrik Blidh', 'henrik.blidh@nedomkull.com'),
}
author = 'Henrik Blidh'
author_email = 'henrik.blidh@nedomkull.com'
url = 'https://github.com/hbldh/pybankid/'
Expand All @@ -54,11 +55,13 @@
keywords = ['BankID', 'SOAP']
classifiers = [
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'License :: OSI Approved :: MIT License',
'Operating System :: POSIX :: Linux',
'Operating System :: Microsoft :: Windows',
'Operating System :: MacOS :: MacOS X',
'Development Status :: 3 - Alpha',
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Topic :: Utilities'
]
]
15 changes: 8 additions & 7 deletions bankid/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from __future__ import absolute_import

import warnings
import StringIO
import six
import base64
import datetime

Expand All @@ -37,7 +37,7 @@

class BankIDClient(object):

def __init__(self, certificates, test_server=True):
def __init__(self, certificates, test_server=False):
self.certs = certificates

if test_server:
Expand Down Expand Up @@ -76,7 +76,7 @@ def authenticate(self, personal_number, **kwargs):
out = self.client.service.Authenticate(
personalNumber=personal_number, **kwargs)
except WebFault as e:
raise get_error_class(e)("Could not complete Authenticate order.")
raise get_error_class(e, "Could not complete Authenticate order.")

return self._dictify(out)

Expand All @@ -102,7 +102,7 @@ def sign(self, user_visible_data, personal_number=None, **kwargs):
userVisibleData=base64.b64encode(user_visible_data),
personalNumber=personal_number, **kwargs)
except WebFault as e:
raise get_error_class(e)("Could not complete Sign order.")
raise get_error_class(e, "Could not complete Sign order.")

return self._dictify(out)

Expand All @@ -121,7 +121,7 @@ def collect(self, order_ref):
try:
out = self.client.service.Collect(orderRef=order_ref)
except WebFault as e:
raise get_error_class(e)("Could not complete Collect call.")
raise get_error_class(e, "Could not complete Collect call.")

return self._dictify(out)

Expand Down Expand Up @@ -153,7 +153,7 @@ def _dictify(self, doc):
try:
for k in doc:
if isinstance(doc[k], Text):
out[k] = unicode(doc[k])
out[k] = doc[k].decode('utf8')
elif isinstance(doc[k], datetime.datetime):
out[k] = doc[k]
else:
Expand All @@ -163,6 +163,7 @@ def _dictify(self, doc):

return out


class RequestsTransport(HttpAuthenticated):
"""A Requests-based transport for suds, enabling the use of https and
certificates when communicating with the SOAP service.
Expand All @@ -184,7 +185,7 @@ def open(self, request):
resp = self.requests_session.get(request.url,
data=request.message,
headers=request.headers)
result = StringIO.StringIO(resp.content.decode('utf-8'))
result = six.BytesIO(six.b(resp.content.decode('utf-8')))
return result

def send(self, request):
Expand Down
14 changes: 7 additions & 7 deletions bankid/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
.. module:: exceptions
:platform: Unix, Windows
:synopsis:
:synopsis:
.. moduleauthor:: hbldh <henrik.blidh@nedomkull.com>
Expand All @@ -19,15 +19,15 @@
from __future__ import unicode_literals
from __future__ import absolute_import

import re
import six


def get_error_class(exc):
s = re.search("Server raised fault: '([\w_]+)'", unicode(exc))
if s:
return _ERROR_CODE_TO_CLASS[s.groups()[0]]
def get_error_class(exc, exception_text):
error_class = _ERROR_CODE_TO_CLASS.get(six.text_type(exc.fault.faultstring))
if error_class is None:
return BankIDError("{0}: {1}".format(exc, exception_text))
else:
raise exc
return error_class(exception_text)


class BankIDError(Exception):
Expand Down
7 changes: 4 additions & 3 deletions bankid/testcert.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import requests

_TEST_CERT_PASSWORD = 'qwerty123'
_TEST_CERT_URL = "https://www.bankid.com/assets/bankid/rp/fptestcert1.P12"
_TEST_CERT_URL = "https://www.bankid.com/assets/bankid/rp/FPTestcert2_20150818_102329.pfx"


def create_test_server_cert_and_key(destination_path):
Expand Down Expand Up @@ -63,10 +63,10 @@ def create_test_server_cert_and_key(destination_path):
def split_test_cert_and_key():
"""Fetch the P12 certificate from BankID servers, split it into
a certificate part and a key part and return the two components as text data.
:returns: Tuple of certificate and key string data.
:rtype: tuple
"""
# Paths to temporary files.
cert_tmp_path = os.path.join(tempfile.gettempdir(), os.path.basename(_TEST_CERT_URL))
Expand Down Expand Up @@ -114,6 +114,7 @@ def split_test_cert_and_key():

return certificate, key


def main():
paths = create_test_server_cert_and_key(os.path.expanduser('~'))
print('Saved certificate as {0}'.format(paths[0]))
Expand Down
3 changes: 2 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
requests>=2.7.0
suds==0.4
suds-jurko>=0.6
six>=1.9.0
32 changes: 24 additions & 8 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
.. module:: test_client
:platform: Unix, Windows
:synopsis:
:synopsis:
.. moduleauthor:: hbldh <henrik.blidh@nedomkull.com>
Expand All @@ -24,8 +24,11 @@
import tempfile
import uuid

from nose.tools import raises

import bankid.client
import bankid.testcert
import bankid.exceptions


def get_random_personal_number():
Expand All @@ -37,7 +40,7 @@ def _luhn_digit(id_):
Code adapted from [Faker]
(https://github.com/joke2k/faker/blob/master/faker/providers/ssn/sv_SE/__init__.py)
:param id_: The partial number to calcualte checksum of.
:param id_: The partial number to calculate checksum of.
:type id_: str
:return: Integer digit in [0, 9].
:rtype: int
Expand All @@ -62,21 +65,22 @@ def digits_of(n):
pn = "{0:04d}{1:02d}{2:02d}{3:03d}".format(year, month, day, suffix)
return pn + str(_luhn_digit(pn[2:]))


class TestClientOnTestServer(object):
"""Test Suite testing once against the actual BankID test server to
test that connection can be made with BankIDClient.
"""

def __init__(self):
self.cert_file = None
self.certificate_file = None
self.key_file = None

def setUp(self):
def setup(self):
certificate, key = bankid.testcert.create_test_server_cert_and_key(tempfile.gettempdir())
self.certificate_file = certificate
self.key_file = key

def tearDown(self):
def teardown(self):
try:
os.remove(self.certificate_file)
os.remove(self.key_file)
Expand All @@ -85,11 +89,23 @@ def tearDown(self):

def test_authentication_and_collect(self):
"""Authenticate call and then collect with the returned orderRef UUID."""

c = bankid.client.BankIDClient(certificates=(self.certificate_file, self.key_file), test_server=True)
out = c.authenticate(get_random_personal_number())
assert isinstance(out, dict)
# UUID.__init__ performs the UUID compliance assertion.
order_ref = uuid.UUID(out.get('orderRef'), version=4)
collect_status = c.collect(order_ref)
assert collect_status.get('progressStatus') in ('OUTSTANDING_TRANSACTION', 'NO_CLIENT')
collect_status = c.collect(out.get('orderRef'))
assert collect_status.get('progressStatus') in ('OUTSTANDING_TRANSACTION', 'NO_CLIENT')

@raises(bankid.exceptions.InvalidParametersError)
def test_invalid_orderref_raises_error(self):
c = bankid.client.BankIDClient(certificates=(self.certificate_file, self.key_file), test_server=True)
collect_status = c.collect('invalid-uuid')

@raises(bankid.exceptions.AlreadyInProgressError)
def test_already_in_progress_raises_error(self):
c = bankid.client.BankIDClient(certificates=(self.certificate_file, self.key_file), test_server=True)
pn = get_random_personal_number()
out = c.authenticate(pn)
out2 = c.authenticate(pn)

0 comments on commit fbe1b64

Please sign in to comment.