Contributing
************

Contributions are welcome.  If you would like add features or fix
bugs, please review the information below.

One source of history or ideas are the bug reports. There you can find
ideas for requested features, or the remains of rejected ideas.

If you have a 'big idea' - please file an issue first so it can be
discussed prior to you spending a lot of time developing. New features
need to be generally useful - if your feature has limited
applicability, consider making a small change that ENABLES your
feature, rather than trying to get the entire feature into Flask-
Security.


Checklist
=========

   * All new code and bug fixes need unit tests

   * If you change/add to the external API be sure to update
     docs/openapi.yaml

   * Additions to configuration variables and/or messages must be
     documented

   * Make sure any new public API methods have good docstrings, are
     picked up by the api.rst document, and are exposed in __init__.py
     if appropriate.

   * Add appropriate info to CHANGES.rst


Getting the code
================

The code is hosted on a GitHub repo at https://github.com/Flask-
Middleware/flask-security.  To get a working environment, follow these
steps:

   1. (Optional, but recommended) Create a Python 3.6 (or greater)
      virtualenv to work in, and activate it.

   2. Fork the repo Flask-Security
         (look for the "Fork" button).

   3. Clone your fork locally:

         $ git clone https://github.com/<your-username>/flask-security

   4. Create a branch for local development:

         $ git checkout -b name-of-your-bugfix-or-feature

   5. Change directory to flask_security:

         $ cd flask_security

   6. Install the requirements:

         $ pip install -r requirements/dev.txt

   7. Install pre-commit hooks:

         $ pre-commit install

   8. Develop the Feature/Bug Fix and edit

   9. Write Tests for your code in:

         tests/

   10. When done, verify unit tests, syntax etc. all pass:

          $ pytest tests
          $ pre-commit run --all-files
          $ python setup.py build_sphinx compile_catalog

   11. Use tox:

          $ tox  # run everything CI does
          $ tox -e py38-low  # make sure works with older dependencies
          $ tox -e style  # run pre-commit/style checks

   12. When the tests are successful, commit your changes and push
       your branch to GitHub:

          $ git add .
          $ git commit -m "Your detailed description of your changes."
          $ git push origin name-of-your-bugfix-or-feature

   13. Submit a pull request through the GitHub website.

   14. Be sure that the CI tests and coverage checks pass.


Updating the Swagger API document
=================================

When making changes to the external API, you need to update the
openapi.yaml formal specification. To do this - install the swagger
editor locally:

   $ npm -g install swagger-editor-dist http-server

Then in a browser navigate to:

   file:///usr/local/lib/node_modules/swagger-editor-dist/index.html#

Edit - it is a WYSIWYG editor and will show you errors. Once you save
(as yaml) you need to look at what it will render as:

   $ python setup.py build_sphinx
   $ http-server -p 8081

Then in your browser navigate to:

   http://localhost:8081/docs/_build/html/index.html
   or
   http://localhost:8081/docs/_build/html/_static/openapi_view.html

Please note that changing "openapi.yaml" won't re-trigger a docs build
- so you might have to manually delete "docs/_build".


Updating Translations
=====================

If you change any translatable strings (such as new messages, modified
forms, etc.) you need to re-generate the translations:

   $ python setup.py extract_messages
   $ python setup.py update_catalog
   $ python setup.py compile_catalog


Testing
=======

Unit tests are critical since Flask-Security is a piece of middleware.
They also help other contributors understand any subtleties in the
code and edge conditions that need to be handled.


Datastore
---------

By default the unit tests use an in-memory sqlite DB to test
datastores (except for MongoDatastore which uses mongomock). While
this is sufficient for most changes, changes to the datastore layer
require testing against a real DB (the CI tests test against
postgres). It is easy to run the unit tests against a real DB
instance. First of course install the DB locally then:

   # For postgres
   pytest --realdburl postgresql://<user>@localhost/
   # For mysql
   pytest --realdburl "mysql+pymysql://root:<password>@localhost/"


Views
-----

Much of Flask-Security is concerned with form-based views. These can
be difficult to test especially translations etc. In the tests
directory is a stand-alone Flask application "view_scaffold.py" that
can be run and you can point your browser to it and walk through the
various views.
