# Development

This is a short guide to help you get started with Postorius development.

## Development Workflow

The source code is hosted on GitLab, which means that we are using Git for version control.

Changes are not made directly in the project’s master branch, but in feature-related personal branches, which get reviewed and then merged into the master branch. There is a contribution guide here, that mentions the basics about contributing to any mailman project.

An ideal workflow would be like this:

1. File a bug to suggest a new feature or report a bug (or just pick one of the existing bugs).

2. Create a new branch with your code changes.

3. Make a “merge request” to get your code reviewed and merged.

## First Contributions / Coverage Reports

If you don’t know how you can contribute, writing tests is a good way to get you started.

You can start by exploring the existing test coverage and finding code that’s not covered ie. not tested.

## Installing and running the tests

After checkout you can run the tests using `tox`:

    $ tox

By default this will test against a couple of different environments. If you want to only run the tests in a specific environment or a single module, you can specify this using the `-e` option and/or a double dash:

    # List all currently configured envs:
    $ tox -l
    py35-django111
    py35-django20
    py35-djangolatest
    py36-django111
    py36-django20
    py36-djangolatest
    py37-django111
    py37-django20
    py37-djangolatest
    pep8

    # Test Django 2.1 on Python3.7 only:
    $ tox -e py37-django21

    # Run only tests in ``test_address_activation``:
    $ tox -- postorius.tests.test_address_activation

    # You get the idea...
    $ tox -e py37-django21 -- postorius.tests.test_address_activation

All test modules reside in the `postorius/src/postorius/tests` directory. Please have a look at the existing examples.

## Calling Mailman’s REST API

A lot of Postorius’ code involves calls to Mailman’s REST API (through the `mailmanclient` library). Postorius’ test uses pytest along with pytest-django to run tests.

Postorius uses pytest fixtures to setup Mailman Core’s REST API and is defined at `postorius.tests.mailman_api_tests.conftest.mailman_rest_layer`. It is set to `autouse=True` so, all the tests inside the module `mailman_api_tests` automatically use it.

`mailman_rest_layer` starts up `incoming` runner and `rest` runner using `mailman.testing.helpersTestableMaster`. It also removes all the data after every `TestCase` class.

## View Authorization

Three of Django’s default User roles are relevant for Postorius:

- Superuser: Can do everything.

- AnonymousUser: Can view list index and info pages.

- Authenticated users: Can view list index and info pages. Can (un)subscribe from lists.

Apart from these default roles, there are two others relevant in Postorius:

- List owners: Can change list settings, moderate messages and delete their lists.

- List moderators: Can moderate messages.

There are a number of decorators to protect views from unauthorized users.

- `@user_passes_test(lambda u: u.is_superuser)` (redirects to login form)

- `@login_required` (redirects to login form)

- `@list_owner_required` (returns 403 if logged-in user isn’t the list’s owner)

- `@list_moderator_required` (returns 403 if logged-in user isn’t the list’s moderator)

## Accessing the Mailman API

Postorius uses mailmanclient to connect to Mailman’s REST API. In order to directly use the client, `cd` to the `example_project` folder and execute `python manage.py mmclient`. This will open a python shell (IPython, if that’s available) and provide you with a client object connected to your local Mailman API server (it uses the credentials from your settings.py).

A quick example:

    $ python manage.py mmclient

    >>> client
    <Client (user:pwd) http://localhost:8001/3.1/>

    >>> print(client.system['mailman_version'])
    GNU Mailman 3.0.0b2+ (Here Again)

    >>> mailman_dev = client.get_list('mailman-developers@python.org')
    >>> print(mailman_dev.settings)
    {u'description': u'Mailman development',
     u'default_nonmember_action': u'hold', ...}

For detailed information how to use mailmanclient, check out its documentation.