aboutsummaryrefslogtreecommitdiff
path: root/budget/web.py
diff options
context:
space:
mode:
author0livd <0livd@users.noreply.github.com>2017-05-18 10:48:09 +0100
committerAlexis Metaireau <alexis@notmyidea.org>2017-05-18 11:48:09 +0200
commitea8eda35a7bd831964c38b38cc9a5b19bcb44d6a (patch)
tree5a5efbe2523a1f8f84aec65c298a9b4fd6a9421e /budget/web.py
parent091553be566d97816ed898207b56d2694eb2efdd (diff)
downloadihatemoney-mirror-ea8eda35a7bd831964c38b38cc9a5b19bcb44d6a.zip
ihatemoney-mirror-ea8eda35a7bd831964c38b38cc9a5b19bcb44d6a.tar.gz
ihatemoney-mirror-ea8eda35a7bd831964c38b38cc9a5b19bcb44d6a.tar.bz2
Public project creation and admin permissions (#210)
* Add a @requires_admin decorator It can be used to protect specific endpoints with ADMIN_PASSWORD (a password that is stored unencrypted in the settings) The decorator has no effect if ADMIN_PASSWORD is an empty string (default value) * Require admin permissions to access create project endpoint When ADMIN_PASSWORD is not empty, project creation form on the home page will be replaced by a link to the create project endpoint so one is able to enter the admin password before filling the form
Diffstat (limited to 'budget/web.py')
-rw-r--r--budget/web.py39
1 files changed, 37 insertions, 2 deletions
diff --git a/budget/web.py b/budget/web.py
index efb427c..3bfa73a 100644
--- a/budget/web.py
+++ b/budget/web.py
@@ -16,11 +16,12 @@ from flask_babel import get_locale, gettext as _
from smtplib import SMTPRecipientsRefused
import werkzeug
from sqlalchemy import orm
+from functools import wraps
# local modules
from models import db, Project, Person, Bill
-from forms import AuthenticationForm, EditProjectForm, InviteForm, \
- MemberForm, PasswordReminder, ProjectForm, get_billform_for, \
+from forms import AdminAuthenticationForm, AuthenticationForm, EditProjectForm, \
+ InviteForm, MemberForm, PasswordReminder, ProjectForm, get_billform_for, \
ExportForm
from utils import Redirect303, list_of_dicts2json, list_of_dicts2csv
@@ -28,6 +29,19 @@ main = Blueprint("main", __name__)
mail = Mail()
+def requires_admin(f):
+ """Require admin permissions for @requires_admin decorated endpoints.
+ Has no effect if ADMIN_PASSWORD is empty (default value)
+ """
+ @wraps(f)
+ def admin_auth(*args, **kws):
+ admin_password = session.get('admin_password', '')
+ if not admin_password == current_app.config['ADMIN_PASSWORD']:
+ raise Redirect303(url_for('.admin', goto=request.path))
+ return f(*args, **kws)
+ return admin_auth
+
+
@main.url_defaults
def add_project_id(endpoint, values):
"""Add the project id to the url calls if it is expected.
@@ -66,6 +80,23 @@ def pull_project(endpoint, values):
url_for(".authenticate", project_id=project_id))
+@main.route("/admin", methods=["GET", "POST"])
+def admin():
+ """Admin authentication"""
+ form = AdminAuthenticationForm()
+ goto = request.args.get('goto', url_for('.home'))
+ if request.method == "POST":
+ if form.validate():
+ if form.admin_password.data == current_app.config['ADMIN_PASSWORD']:
+ session['admin_password'] = form.admin_password.data
+ session.update()
+ return redirect(goto)
+ else:
+ msg = _("This admin password is not the right one")
+ form.errors['admin_password'] = [msg]
+ return render_template("authenticate.html", form=form, admin_auth=True)
+
+
@main.route("/authenticate", methods=["GET", "POST"])
def authenticate(project_id=None):
"""Authentication form"""
@@ -121,14 +152,18 @@ 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_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,
auth_form=auth_form, session=session)
@main.route("/create", methods=["GET", "POST"])
+@requires_admin
def create_project():
form = ProjectForm()
if request.method == "GET" and 'project_id' in request.values: