__title__ = 'ska.utils'
__author__ = 'Artur Barseghyan'
__copyright__ = 'Copyright (c) 2013-2014 Artur Barseghyan'
__license__ = 'GPL 2.0/LGPL 2.1'
__all__ = ('RequestHelper',)
from six import PY3
try:
from six.moves.urllib.parse import urlencode
except ImportError as e:
if PY3:
from urllib.parse import urlencode
else:
from urllib import urlencode
from ska.helpers import (
dict_keys, extract_signed_data as extract_signed_data
)
from ska.exceptions import InvalidData, ImproperlyConfigured
from ska.defaults import (
DEFAULT_URL_SUFFIX, DEFAULT_EXTRA_PARAM, DEFAULT_SIGNATURE_PARAM,
DEFAULT_AUTH_USER_PARAM, DEFAULT_VALID_UNTIL_PARAM,
)
from ska.signatures import Signature
_ = lambda x: x # For future integrations with gettext
# *******************************************************************************************************
# *******************************************************************************************************
# **************************************** Request helper ***********************************************
# *******************************************************************************************************
# *******************************************************************************************************
[docs]class RequestHelper(object):
"""
Request helper for easy put/extract of signature params from URLs.
:param str signature_param:
:param str auth_user_param:
:param str valid_until_param:
:param str extra_param:
"""
def __init__(self, signature_param=DEFAULT_SIGNATURE_PARAM, auth_user_param=DEFAULT_AUTH_USER_PARAM,
valid_until_param=DEFAULT_VALID_UNTIL_PARAM, extra_param=DEFAULT_EXTRA_PARAM,
signature_cls=Signature):
self.signature_param = signature_param
self.auth_user_param = auth_user_param
self.valid_until_param = valid_until_param
self.extra_param = extra_param
self.signature_cls = signature_cls
[docs] def signature_to_url(self, signature, endpoint_url='', suffix=DEFAULT_URL_SUFFIX):
"""
URL encodes the signature params.
:param ska.Signature signature:
:param str endpoint_url:
:param str suffix: Suffix to add after the ``endpoint_url`` and before the appended
signature params.
:return str:
:example:
Required imports.
>>> from ska import Signature, RequestHelper
Generate signature.
>>> signature = Signature.generate_signature(
>>> auth_user = 'user',
>>> secret_key = 'your-secret-key'
>>> )
Create a request helper.
>>> request_helper = RequestHelper(
>>> signature_param = 'signature',
>>> auth_user_param = 'auth_user',
>>> valid_until_param = 'valid_until'
>>> )
Appending signature params to the endpoint URL.
>>> url = request_helper.signature_to_url(
>>> signature = signature,
>>> endpoint_url = 'http://e.com/api/'
>>> )
http://e.com/api/?valid_until=1378045287.0&auth_user=user&signature=YlZpLFsjUKBalL4x5trhkeEgqE8%3D
"""
params = {
self.signature_param: signature.signature,
self.auth_user_param: signature.auth_user,
self.valid_until_param: signature.valid_until,
self.extra_param: dict_keys(signature.extra, return_string=True),
}
# Make some check that params used do not overlap with names reserved (`auth_user`, `signature`, etc).
params.update(signature.extra)
return "{0}{1}{2}".format(endpoint_url, suffix, urlencode(params))
[docs] def signature_to_dict(self, signature):
"""
Puts signature into a dictionary, which can later on be used to send when sending
(POST) requests to the server.
:param ska.Signature signature:
:return dict:
:example:
Required imports.
>>> from ska import Signature, RequestHelper
Generate signature.
>>> signature = Signature.generate_signature(
>>> auth_user = 'user',
>>> secret_key = 'your-secret-key'
>>> )
Create a request helper.
>>> request_helper = RequestHelper(
>>> signature_param = 'signature',
>>> auth_user_param = 'auth_user',
>>> valid_until_param = 'valid_until'
>>> )
Appending signature params to the endpoint URL.
>>> signed_dict = request_helper.signature_to_dict(
>>> signature = signature
>>> )
{
'signature': 'YlZpLFsjUKBalL4x5trhkeEgqE8=',
'auth_user': 'user',
'valid_until': '1378045287.0'
}
"""
d = {
self.signature_param: signature.signature,
self.auth_user_param: signature.auth_user,
self.valid_until_param: signature.valid_until,
self.extra_param: dict_keys(signature.extra, return_string=True),
}
d.update(signature.extra)
return d
[docs] def validate_request_data(self, data, secret_key):
"""
Validates the request data.
:param dict data:
:param str secret_key:
:return ska.SignatureValidationResult:
:example:
If your imaginary ``HttpRequest`` object has ``GET`` property (dict), then you
would validate the request data as follows.
Create a ``RequestHelper`` object with param names expected.
Required imports.
>>> from ska import RequestHelper
Create a request helper.
>>> request_helper = RequestHelper(
>>> signature_param = 'signature',
>>> auth_user_param = 'auth_user',
>>> valid_until_param = 'valid_until'
>>> )
Validate the request data.
>>> validation_result = request_helper.validate_request_data(
>>> data = request.GET,
>>> secret_key = 'your-secret-key'
>>> )
"""
signature = data.get(self.signature_param, '')
auth_user = data.get(self.auth_user_param, '')
valid_until = data.get(self.valid_until_param, '')
extra = extract_signed_data(data=data, extra=data.get(self.extra_param, '').split(','))
validation_result = self.signature_cls.validate_signature(
signature = signature,
auth_user = auth_user,
secret_key = secret_key,
valid_until = valid_until,
return_object = True,
extra = extra
)
return validation_result