From 3d2ba33917b5b72a5eaf57a3843ee9c8033d15c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Wed, 16 Oct 2013 01:31:03 +0200 Subject: Check user's authorisation when loading entries by ID. --- app/utils.py | 30 +++++++++++++++++++++++++++++- app/views/__init__.py | 4 ++-- app/views/consts.py | 10 ++++++++-- app/views/expenses.py | 5 ++++- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/app/utils.py b/app/utils.py index 3a08535..e6a7c95 100644 --- a/app/utils.py +++ b/app/utils.py @@ -1,7 +1,9 @@ from functools import wraps -from flask import request, render_template, url_for +from flask import flash, request, render_template, url_for from flask import redirect as _redirect +from .login import current_user + def _gen_tpl(endpoint): return endpoint.replace('.', '/') + '.jinja' @@ -33,3 +35,29 @@ def redirect (target, **kwargs): return _redirect(url) else: return _redirect(url, code) + +def assert_authorisation(constructor, param): + def decorator(f): + @wraps(f) + def decorated_function(*args, **kwargs): + p = kwargs.get(param, None) + + if p is None: + raise TypeError("Keyword %s expected but not received." % param) + + obj = constructor(p) + if obj is None: + flash(u"Eintrag existiert nicht!", u'error') + return redirect('index') + + if not hasattr(obj, 'user_id'): + return f(*args, **kwargs) + + # explicitly use user_id to avoid having to load the user object + if obj.user_id != current_user.id: + flash(u"Nicht erlaubte Operation!", u'error') + return redirect('index') + else: + return f(*args, **kwargs) + return decorated_function + return decorator diff --git a/app/views/__init__.py b/app/views/__init__.py index c9d9e8f..8737d07 100644 --- a/app/views/__init__.py +++ b/app/views/__init__.py @@ -7,14 +7,14 @@ from .. import app, db # Some general imports # from ..login import current_user, login_required -from ..utils import templated, redirect +from ..utils import templated, redirect, assert_authorisation from ..flask_extend import Blueprint from flask import flash __all__ = [ 'db', 'app', 'current_user', 'login_required', - 'templated', 'redirect', + 'assert_authorisation', 'templated', 'redirect', 'Blueprint', 'flash', 'request', 'url_for' ] diff --git a/app/views/consts.py b/app/views/consts.py index 20b3db1..0dcec57 100644 --- a/app/views/consts.py +++ b/app/views/consts.py @@ -1,12 +1,15 @@ from . import Blueprint, db, \ current_user, login_required, \ - templated, redirect, request + assert_authorisation, templated, redirect, request from ..model import Category, ConstExpense from ..forms import ConstForm, today import datetime from sqlalchemy import sql +from functools import partial + +assert_authorisation = partial(assert_authorisation, ConstExpense.get) mod = Blueprint('consts', __name__) @@ -53,18 +56,20 @@ def list (): @mod.route('/') @login_required +@assert_authorisation('id') @templated() def show(id): return { 'exp': ConstExpense.get(id) } @mod.route('/edit/', methods=('GET', 'POST')) @login_required +@assert_authorisation('id') @templated() def edit(id): exp = ConstExpense.get(id) form = const_form(exp) - if request.method == 'POST': + if form.is_submitted(): if 'deleteB' in request.form: db.session.delete(exp) db.session.commit() @@ -79,6 +84,7 @@ def edit(id): @mod.route('/add/from/') @login_required +@assert_authorisation('other') @templated('.add') def add_from(other): exp = ConstExpense() # needed to initialize 'CE.next' diff --git a/app/views/expenses.py b/app/views/expenses.py index f5181e9..f36cbb4 100644 --- a/app/views/expenses.py +++ b/app/views/expenses.py @@ -1,13 +1,15 @@ from . import Blueprint, db, \ current_user, login_required, \ - templated, redirect, request + assert_authorisation, templated, redirect, request from ..model import Category, SingleExpense, CatExpense, MonthExpense from ..forms import ExpenseForm import datetime, decimal from sqlalchemy import sql, func +from functools import partial +assert_authorisation = partial(assert_authorisation, SingleExpense.get) mod = Blueprint('expenses', __name__) def expense_form(obj=None): @@ -82,6 +84,7 @@ def show(): @mod.route('/edit/', methods=('GET', 'POST')) @login_required +@assert_authorisation('id') @templated() def edit(id): exp = SingleExpense.get(id) -- cgit v1.2.3