.. -*- Mode: doctest -*-

Doctest for domain/profile.py

The **Users profile management module** was built to make easier to manage
application users. A user profile consists of two objects types: `UserProfile
<http://www.async.com.br/projects/stoq/docs/package/public/stoqlib.domain.profile.UserProfile-class.html>`_ and `ProfileSettings <http://www.async.com.br/projects/stoq/docs/package/public/stoqlib.domain.profile.ProfileSettings-class.html>`_ in a relation of one to n. Each ProfileSettings object represents a permission information about a certain application.
If Stoq applications suit has about twelve application, for each profile we
will have the same number of ProfileSettings instances stored in the database.


Since you create a new profile you can associate it with many existent
users and once the profile is changed, users under it will have also its
permissions changed. The following code explains how to create a new
profile:

First we need to import the modules and initialize a new transaction.

    >>> from stoqlib.database.runtime import new_transaction
    >>> from stoqlib.domain.profile import ProfileSettings, UserProfile
    >>> trans = new_transaction()

Lets just get the number of profiles stored in the database. This will be
useful to check later if our new profile was actually saved.

    >>> prof_number = UserProfile.select(connection=trans).count()
    >>> settings_number = ProfileSettings.select(connection=trans).count()

Here we create a new profile...

    >>> profile = UserProfile(connection=trans, name='assistant')

...and also profile settings for application POS. Note that the default
value for attribute has_permission is False.

    >>> settings = ProfileSettings(connection=trans, app_dir_name='pos',
    ...                            has_permission=True, user_profile=profile)

Check if everything was properly saved into database.

    >>> prof_number = long(prof_number + 1)
    >>> UserProfile.select(connection=trans).count() == prof_number
    True
    >>> settings_number = long(settings_number + 1)
    >>> ProfileSettings.select(connection=trans).count() == settings_number
    True

How about adding permission information for a new application ?
There is an approach to deal with this requirement.

    >>> profile.add_application_reference('warehouse',
    ...                                   has_permission=True)

Is everything properly saved ?

    >>> settings_number = long(settings_number + 1)
    >>> ProfileSettings.select(connection=trans).count() == settings_number
    True

The number of Stoq applications can change in the future and that's why we
have the method update_profile_applications. A simple usage for this method
is:

First import the function from the right path...

    >>> from stoqlib.domain.profile import update_profile_applications

...and them use it !

    >>> new_profile = UserProfile(connection=trans, name='assistant')
    >>> new_profile.profile_settings.count() == 0
    True
    >>> update_profile_applications(trans)

Did it work ? we had before only permission information about POS
application. Now we should have a lot more. Lets check getting first all the
profile settings for our last created profile. Note that Storm
selectBy method is very useful in this case, retrieving all the data of a
certain table matching with one or more columns.


    >>> items = new_profile.profile_settings

There is also a much more easy way to create user profiles without the need
to create manually profile settings or even calling
update_profile_applications functions. See usage for classmethod
create_profile_template:

    >>> profile_name = 'Boss'
    >>> boss_profile = UserProfile.create_profile_template(trans, profile_name,
    ...                                                    has_full_permission=True)

Our profile is for a boss an that's why we have sent
has_full_permission=True argument for this method which defaults to False.

Again, we must check if we have permission information for all the available
applications:

    >>> items = ProfileSettings.selectBy(user_profile=boss_profile,
    ...                                  connection=trans)

Now we have created profiles why not checking  permissions for a certain
application ? We know that bosses must be allowed to access everything so,
does our boss_profile have permission for application 'test_application'?

    >>> boss_profile.add_application_reference('test_application', True)
    >>> boss_profile.check_app_permission('test_application')
    True

    >>> trans.close()
