mirror of
https://github.com/spiral-project/ihatemoney.git
synced 2025-05-05 20:51:49 +02:00
Update to a more flexible admin authentication
We do not rely on the ADMIN_PASSWORD being defined or not to ask for admin permissions. Instead we now have a flexible admin auth that can be conditionnaly bypassed
This commit is contained in:
parent
0e374cd5e0
commit
d9ae72f4f3
7 changed files with 65 additions and 33 deletions
|
@ -11,7 +11,11 @@ This document describes changes between each past release.
|
|||
- **BREAKING CHANGE** Use a hashed ``ADMIN_PASSWORD`` instead of a clear text one, ``./budget/manage.py generate_password_hash`` can be used to generate a proper password HASH (#236)
|
||||
- **BREAKING CHANGE** Turn the WSGI file into a python module, renamed from budget/ihatemoney.wsgi to budget/wsgi.py. Please update your Apache configuration!
|
||||
- Changed the recommended gunicorn configuration to use the wsgi module as an entrypoint
|
||||
- **BREAKING CHANGE** The default value of ``ADMIN_PASSWORD`` has changed. If you have a custom settings file which set ``ADMIN_PASSWORD`` to an empty string (""), the application will use the default admin password until you update your settings.
|
||||
|
||||
### Added
|
||||
|
||||
- Add a new setting to allow public project creation (ALLOW_PUBLIC_PROJECT_CREATION)
|
||||
|
||||
### Removed
|
||||
|
||||
|
|
|
@ -11,4 +11,6 @@ MAIL_DEFAULT_SENDER = ("Budget manager", "budget@notmyidea.org")
|
|||
|
||||
ACTIVATE_DEMO_PROJECT = True
|
||||
|
||||
ADMIN_PASSWORD = ""
|
||||
ADMIN_PASSWORD = "pbkdf2:sha256:50000$jc3isZTD$b3be8d04ed5c2c1ac89d5eb777facc94adaee48d473c9620f1e0cb73f3dcfa11"
|
||||
|
||||
ALLOW_PUBLIC_PROJECT_CREATION = True
|
||||
|
|
|
@ -71,6 +71,19 @@ def configure():
|
|||
UserWarning
|
||||
)
|
||||
|
||||
if not app.config['ADMIN_PASSWORD']:
|
||||
app.config['ADMIN_PASSWORD'] = default_settings.ADMIN_PASSWORD
|
||||
# Since 2.0
|
||||
warnings.warn(
|
||||
"The way Ihatemoney handles admin authentication has changed. You seem to be using "
|
||||
+ "an empty ADMIN_PASSWORD which is not supported anymore. Your ADMIN_PASWWORD has been"
|
||||
+ " automatically set to the default password to let you access your admin endpoints."
|
||||
+ " However this password is not secure and must be changed in your settings file. Use"
|
||||
+ " the command './budget/manage.py generate_password_hash' to generate a proper"
|
||||
+ " password hash and copy the output to the value of ADMIN_PASSWORD",
|
||||
UserWarning
|
||||
)
|
||||
|
||||
configure()
|
||||
|
||||
|
||||
|
|
|
@ -28,9 +28,7 @@
|
|||
</form>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-5 col-md-3 offset-sm-1">
|
||||
{% if is_admin_mode_enabled %}
|
||||
<a href="{{ url_for(".create_project") }}">...{{ _("or create a new one") }}</a>
|
||||
{% else %}
|
||||
{% if is_public_project_creation_allowed %}
|
||||
<form id="creation-form" class="form-horizontal" action="{{ url_for(".create_project") }}" method="post">
|
||||
<fieldset class="form-group">
|
||||
<legend>...{{ _("or create a new one") }}</legend>
|
||||
|
@ -40,6 +38,8 @@
|
|||
<button class="btn" type="submit">{{ _("let's get started") }}</button>
|
||||
</div>
|
||||
</form>
|
||||
{% else %}
|
||||
<a href="{{ url_for(".create_project") }}">...{{ _("or create a new one") }}</a>
|
||||
{% endif %}
|
||||
</main>
|
||||
</div>
|
||||
|
|
|
@ -378,6 +378,8 @@ class BudgetTestCase(TestCase):
|
|||
|
||||
def test_admin_authentication(self):
|
||||
run.app.config['ADMIN_PASSWORD'] = generate_password_hash("pass")
|
||||
# Disable public project creation so we have an admin endpoint to test
|
||||
run.app.config['ALLOW_PUBLIC_PROJECT_CREATION'] = False
|
||||
|
||||
# test the redirection to the authentication page when trying to access admin endpoints
|
||||
resp = self.app.get("/create")
|
||||
|
|
|
@ -34,17 +34,26 @@ main = Blueprint("main", __name__)
|
|||
mail = Mail()
|
||||
|
||||
|
||||
def requires_admin(f):
|
||||
def requires_admin(bypass=None):
|
||||
"""Require admin permissions for @requires_admin decorated endpoints.
|
||||
Has no effect if ADMIN_PASSWORD is empty (default value)
|
||||
The bypass variable is optionnal and used to conditionnaly bypass the admin authentication
|
||||
It expects a tuple containing the name of an application setting and its expected value
|
||||
e.g. if you use @require_admin(bypass=("ALLOW_PUBLIC_PROJECT_CREATION", True))
|
||||
Admin authentication will be bypassed when ALLOW_PUBLIC_PROJECT_CREATION is set to True
|
||||
"""
|
||||
@wraps(f)
|
||||
def admin_auth(*args, **kws):
|
||||
is_admin = session.get('is_admin')
|
||||
if is_admin or not current_app.config['ADMIN_PASSWORD']:
|
||||
return f(*args, **kws)
|
||||
raise Redirect303(url_for('.admin', goto=request.path))
|
||||
return admin_auth
|
||||
def check_admin(f):
|
||||
@wraps(f)
|
||||
def admin_auth(*args, **kws):
|
||||
is_admin_auth_bypassed = False
|
||||
if bypass is not None and current_app.config.get(bypass[0]) == bypass[1]:
|
||||
is_admin_auth_bypassed = True
|
||||
is_admin = session.get('is_admin')
|
||||
if is_admin or is_admin_auth_bypassed:
|
||||
return f(*args, **kws)
|
||||
raise Redirect303(url_for('.admin', goto=request.path))
|
||||
return admin_auth
|
||||
return check_admin
|
||||
|
||||
|
||||
@main.url_defaults
|
||||
|
@ -157,18 +166,17 @@ def authenticate(project_id=None):
|
|||
def home():
|
||||
project_form = ProjectForm()
|
||||
auth_form = AuthenticationForm()
|
||||
# If ADMIN_PASSWORD is empty we consider that admin mode is disabled
|
||||
is_admin_mode_enabled = bool(current_app.config['ADMIN_PASSWORD'])
|
||||
is_public_project_creation_allowed = current_app.config['ALLOW_PUBLIC_PROJECT_CREATION']
|
||||
is_demo_project_activated = current_app.config['ACTIVATE_DEMO_PROJECT']
|
||||
|
||||
return render_template("home.html", project_form=project_form,
|
||||
is_demo_project_activated=is_demo_project_activated,
|
||||
is_admin_mode_enabled=is_admin_mode_enabled,
|
||||
is_public_project_creation_allowed=is_public_project_creation_allowed,
|
||||
auth_form=auth_form, session=session)
|
||||
|
||||
|
||||
@main.route("/create", methods=["GET", "POST"])
|
||||
@requires_admin
|
||||
@requires_admin(bypass=("ALLOW_PUBLIC_PROJECT_CREATION", True))
|
||||
def create_project():
|
||||
form = ProjectForm()
|
||||
if request.method == "GET" and 'project_id' in request.values:
|
||||
|
|
|
@ -72,23 +72,26 @@ ihatemoney relies on a configuration file. If you run the application for the
|
|||
first time, you will need to take a few moments to configure the application
|
||||
properly.
|
||||
|
||||
+----------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| Setting name | Default | What does it do? |
|
||||
+============================+===========================+========================================================================================+
|
||||
| SQLALCHEMY_DATABASE_URI | ``sqlite:///budget.db`` | Specifies the type of backend to use and its location. More information |
|
||||
| | | on the format used can be found on `the SQLAlchemy documentation`. |
|
||||
+----------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| SECRET_KEY | ``tralala`` | The secret key used to encrypt the cookies. **This needs to be changed**. |
|
||||
+----------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| MAIL_DEFAULT_SENDER | ``("Budget manager", | A python tuple describing the name and email adress to use when sending |
|
||||
| | "budget@notmyidea.org")`` | emails. |
|
||||
+----------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| ACTIVATE_DEMO_PROJECT | ``True`` | If set to `True`, a demo project will be available on the frontpage. |
|
||||
+----------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| | ``""`` | If not empty, the specified password must be entered to create new projects. |
|
||||
| ADMIN_PASSWORD | | To generate the proper password HASH, use ``./budget/manage.py generate_password_hash``|
|
||||
| | | and copy its output into the value of *ADMIN_PASSWORD*. |
|
||||
+----------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
+------------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| Setting name | Default | What does it do? |
|
||||
+==============================+===========================+========================================================================================+
|
||||
| SQLALCHEMY_DATABASE_URI | ``sqlite:///budget.db`` | Specifies the type of backend to use and its location. More information |
|
||||
| | | on the format used can be found on `the SQLAlchemy documentation`. |
|
||||
+------------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| SECRET_KEY | ``tralala`` | The secret key used to encrypt the cookies. **This needs to be changed**. |
|
||||
+------------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| MAIL_DEFAULT_SENDER | ``("Budget manager", | A python tuple describing the name and email adress to use when sending |
|
||||
| | "budget@notmyidea.org")`` | emails. |
|
||||
+------------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| ACTIVATE_DEMO_PROJECT | ``True`` | If set to `True`, a demo project will be available on the frontpage. |
|
||||
+------------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| | | Hashed password to access protected endpoints. The default password is ``adminpass``. |
|
||||
| ADMIN_PASSWORD | ``"pbkdf2:sha256:50.."`` | **This needs to be changed**. |
|
||||
| | | To generate the proper password HASH, use ``./budget/manage.py generate_password_hash``|
|
||||
| | | and copy its output into the value of *ADMIN_PASSWORD*. |
|
||||
+------------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
| ALLOW_PUBLIC_PROJECT_CREATION| ``True`` | If set to `True`, everyone can create a project without entering the admin password |
|
||||
+------------------------------+---------------------------+----------------------------------------------------------------------------------------+
|
||||
|
||||
.. _`the SQLAlechemy documentation`: http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls
|
||||
|
||||
|
|
Loading…
Reference in a new issue