=============
TODOS/Roadmap
=============

TODOS
=====
Base on MoSCoW principle. Must haves and should haves are planned to be worked
on.

* Features/issues marked with plus (+) are implemented/solved.
* Features/issues marked with minus (-) are yet to be implemented.

Must haves
----------
+ Class based views validation decorator.
+ Extend the Django app with authentication backend for logging into Django with
  tokens generated by `ska`.
+ For auth backend, add models for tracking of the used tokens. Add management
  commands for purging the tracking data.
+ Demo (quick installer) for Django app.
+ Populate foo model data in demo app.
+ Make it easy to add additional data (such as user data, for auth backend) to
  the URL. Sign additional data (affect the signature hash) when providing
  extra params. In that case, provider (see later on) would be just one of
  those; NOTE, that it shall be a reserved "term").
+ In Django app, allow multiple secret keys (add param provider, which would
  contain a UID of the provider and would be as well embed into the signature).
  Based on the UID, locally an appropriate provider would be picked. The
  default secret_key would stay intact.
+ Allow to define a custom callback per provider.
+ Log errors of authentication backend.
+ In the validation result, in addition to `reason` and `result` properties,
  add `error_codes` property, which is basically a list of codes. Define the
  codes in some separate module or in `constants`, so that it's possible to
  determine (if desired) which case are we dealing with.
+ Make it possible to use other algorithms, than HMAC. Implement an abstract
  Signature class. Leave the HMAC SHA-1 as a default, but make it possible to
  provide a custom one or even a self defined hash algorithm.
+ Update the documentation and add code comments reflecting the hash algorithm
  changes.
+ Add tests for various hash algorithms.
+ Add tests for Django auth backend.
- Make a django template tag module for signing urls. The concept of signing
  should be based on providing an existing RequestHelper for handling the
  URL signing or making a RequestHelper in the template context and reusing it
  for signing URLs.
- Make it possible to encrypt the URL values (so that they are not exposed
  plain-text, but rather use some encryption method, which is possible to
  decrypt.
- Better documentation for `ska.contrib.django.ska` module.
- Make sure (perform a check), that given request variables do not overlap with
  reserved words: auth_user, valid_until, signature, extra.
- Find and implement the best way of making `ska` timezone aware. Likely,
  reserve another keyword for it and pass in ``extra`` argument on the sender
  side. On the recipient side, if present - use when validating.
- Add `provider`, `first_name`, `last_name`, `email` to the Django `constants`
  module.

Should haves
------------
- Update the tests (mkdirs) so that database creation for Django ska app works
  smoothly.

Could haves
-----------
- Additional security measures (like browser info embed into signature). If
  browser changed, it becomes invalid.
- Add browser info to the token (auth backend).

Would haves
-----------
- Plone app for logging into Plone with tokens generated by `ska` (
  in-development).

Mind bucket
===========
Appending additional data
-------------------------
We provide a dictionary with data, that should be embed into the URL to the
sign_url function. Imagine, that some request requires more data to be
sent (like username or email), which we would want to use in the end.

Thus, we really provide an extra dictionary with data, that should be sent
embed into the URL.

In order to validate the request on the endpoint (because, the original URL
could contain some more data), we need to generate a list of additional fields,
added by the package. We know already about the `auth_user`, `signature` and
`valid_until`, but additional data, that was embed into the signature, should
be listed in the `extra` request param in the following way: names of params
should be comma separated. In order to avoid faking the data, the hash should
be made of entire data in the following way:

- Additional data dict, would be sorted by keys.
- We would iterate through the dictionary and make a string of it.
- Then we would append the string to the ``get_base`` method and it would be
  hashed.

.. code-block:: python

    sign_url(
        auth_user='user',
        secret_key='your-secret_key',
        url='http://e.com/api/',
        extra={
            'email': 'doe@example.com',
            'last_name': 'Doe',
            'first_name': 'Joe',
        }
    )

And finally, instead of this:

http://e.com/api/?valid_until=1378.0&auth_user=user&signature=YlZ

We would get this:

http://e.com/api/?valid_until=1378.0&auth_user=user&signature=YlZ&first_name=John&last_name=Doe&
email=doe@example.com&age=64&gender=male&extra=email,first_name,last_name

When validating a request, we would read the contents of the ``extra`` param,
and assembled the original data, that was used to generate the signature.

The rest of data (age, gender), which was not a part of the signed data, is
not interesting. We would read the ``extra`` param (if exists), assembled a
dictionary, create base of it and go on matching the hash in the very same
way we did before.

When validating the request, we would do as follows.

.. code-block:: python

    validation_result = validate_signed_request_data(
        request.REQUEST,
        secret_key='your-secret_key'
    )