diff --git a/CHANGES.rst b/CHANGES.rst index 7ed84d7a..7f20e762 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -3,7 +3,16 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `_, and this project adheres to `Semantic Versioning `_. -[0.0.7] - 2022-03-15 +[0.0.9] - 2022-xx-xx +==================== + +Added +***** + +- ``DISABLE_PASSWORD_RESET`` configuration option to disable password recovery. :pr:`46` + + +[0.0.8] - 2022-03-15 ==================== Fixed diff --git a/canaille/__init__.py b/canaille/__init__.py index f5d908a1..878e0911 100644 --- a/canaille/__init__.py +++ b/canaille/__init__.py @@ -179,6 +179,9 @@ def create_app(config=None, validate=True): return { "has_smtp": "SMTP" in app.config, + "has_password_recovery": app.config.get( + "ENABLE_PASSWORD_RECOVERY", True + ), "logo_url": app.config.get("LOGO"), "favicon_url": app.config.get("FAVICON", app.config.get("LOGO")), "website_name": app.config.get("NAME", "Canaille"), diff --git a/canaille/account.py b/canaille/account.py index 4af8d9be..55abde58 100644 --- a/canaille/account.py +++ b/canaille/account.py @@ -526,6 +526,9 @@ def impersonate(user, username): @bp.route("/reset", methods=["GET", "POST"]) @smtp_needed() def forgotten(): + if not current_app.config.get("ENABLE_PASSWORD_RECOVERY", True): + abort(404) + form = ForgottenPasswordForm(request.form) if not request.form: return render_template("forgotten-password.html", form=form) @@ -562,6 +565,9 @@ def forgotten(): @bp.route("/reset//", methods=["GET", "POST"]) def reset(uid, hash): + if not current_app.config.get("ENABLE_PASSWORD_RECOVERY", True): + abort(404) + form = PasswordResetForm(request.form) user = User.get(uid) diff --git a/canaille/conf/config.sample.toml b/canaille/conf/config.sample.toml index 7f88a817..7f057711 100644 --- a/canaille/conf/config.sample.toml +++ b/canaille/conf/config.sample.toml @@ -40,6 +40,10 @@ OIDC_METADATA_FILE = "canaille/conf/openid-configuration.json" # wether the login exists or not. # HIDE_INVALID_LOGINS = false +# If ENABLE_PASSWORD_RECOVERY is false, then users cannot ask for a password +# recovery link by email. This option is true by default. +# ENABLE_PASSWORD_RECOVERY = true + # The validity duration of registration invitations, in seconds. # Defaults to 2 days # INVITATION_EXPIRATION = 172800 diff --git a/canaille/templates/login.html b/canaille/templates/login.html index a1c0f1a5..c0861b03 100644 --- a/canaille/templates/login.html +++ b/canaille/templates/login.html @@ -34,7 +34,7 @@
- {% if has_smtp %} + {% if has_smtp and has_password_recovery %} {{ _("Forgotten password") }} {% endif %} diff --git a/canaille/templates/password.html b/canaille/templates/password.html index 1d4e84a1..838793e1 100644 --- a/canaille/templates/password.html +++ b/canaille/templates/password.html @@ -31,7 +31,7 @@
{{ _("I am not %(username)s", username=username) }} - {% if has_smtp %} + {% if has_smtp and has_password_recovery %} {{ _("Forgotten password") }} {% endif %} diff --git a/demo/conf-docker/canaille.toml b/demo/conf-docker/canaille.toml index a2cd4820..551d77f1 100644 --- a/demo/conf-docker/canaille.toml +++ b/demo/conf-docker/canaille.toml @@ -40,6 +40,10 @@ OIDC_METADATA_FILE = "conf/openid-configuration.json" # wether the login exists or not. # HIDE_INVALID_LOGINS = false +# If ENABLE_PASSWORD_RECOVERY is false, then users cannot ask for a password +# recovery link by email. This option is true by default. +# ENABLE_PASSWORD_RECOVERY = true + # The validity duration of registration invitations, in seconds. # Defaults to 2 days # INVITATION_EXPIRATION = 172800 diff --git a/demo/conf/canaille.toml b/demo/conf/canaille.toml index 65603615..fa3b8746 100644 --- a/demo/conf/canaille.toml +++ b/demo/conf/canaille.toml @@ -40,6 +40,10 @@ OIDC_METADATA_FILE = "conf/openid-configuration.json" # wether the login exists or not. # HIDE_INVALID_LOGINS = false +# If ENABLE_PASSWORD_RECOVERY is false, then users cannot ask for a password +# recovery link by email. This option is true by default. +# ENABLE_PASSWORD_RECOVERY = true + # The validity duration of registration invitations, in seconds. # Defaults to 2 days # INVITATION_EXPIRATION = 172800 diff --git a/doc/configuration.rst b/doc/configuration.rst index 7bad3c14..a4da90e2 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -49,7 +49,11 @@ Canaille is based on Flask, so any `flask configuration