Browse Source

Ajout d'un décorateur @priv_required

master
Dark-Storm 8 months ago
parent
commit
cd533a4ea3
Signed by: Dark-Storm <l.gatin@neuf.fr> GPG Key ID: F61F10FA138E797C
7 changed files with 83 additions and 2 deletions
  1. 4
    0
      app/models/privs.py
  2. 1
    1
      app/models/users.py
  3. 2
    1
      app/routes/account.py
  4. 2
    0
      app/routes/search.py
  5. 30
    0
      app/routes/users.py
  6. 41
    0
      app/utils/priv_required.py
  7. 3
    0
      config.py

+ 4
- 0
app/models/privs.py View File

@@ -27,6 +27,10 @@ class SpecialPrivilege(db.Model):
def __repr__(self):
return f'<Privilege "{self.priv}" of member #{mid}>'

# TODO: clean this. filter does not work ootb
def filter(*args, **kwargs):
return False

# Group: User group, corresponds to a community role and a set of privileges
class Group(db.Model):
__tablename__ = 'group'

+ 1
- 1
app/models/users.py View File

@@ -127,7 +127,7 @@ class Member(User, db.Model):

def priv(self, priv):
"""Check whether the member has the specified privilege."""
if SpecialPrivilege.filter(uif=self.id, priv=priv):
if SpecialPrivilege.filter(uid=self.id, priv=priv):
return True
return False
# return db.session.query(User, Group, GroupPrivilege).filter(

+ 2
- 1
app/routes/account.py View File

@@ -31,6 +31,7 @@ def account():
return render('account.html', form=form)

@app.route('/account/delete', methods=['GET', 'POST'])
@login_required
def delete_account():
del_form = DeleteAccountForm()
if request.method == "POST":
@@ -42,7 +43,7 @@ def delete_account():
return redirect(url_for('index'))
else:
flash('Erreur lors de la suppression du compte', 'error')
del_form.delete.data = False # Force to check the case to delete the account
del_form.delete.data = False # Force to tick to delete the account
return render('delete_account.html', del_form=del_form)



+ 2
- 0
app/routes/search.py View File

@@ -2,6 +2,8 @@ from app import app
from app.forms.search import AdvancedSearchForm
from app.utils.render import render

from app.utils.priv_required import priv_required

@app.route('/search')
def search():
form = AdvancedSearchForm()

+ 30
- 0
app/routes/users.py View File

@@ -0,0 +1,30 @@
from flask import redirect, url_for, request, flash
from flask_login import login_required, current_user, logout_user
from app import app, db
from app.forms.account import UpdateAccountForm, RegistrationForm, DeleteAccountForm
from app.models.users import Member
from app.utils.render import render

@app.route('/users/<username>')
def user():
form = UpdateAccountForm()
if request.method == "POST":
if form.validate_on_submit():
if form.avatar.data:
f = form.avatar.data
f.save("./app/static/"+current_user.avatar)
current_user.update(
email = form.email.data or None,
password = form.password.data or None,
birthday = form.birthday.data,
signature = form.signature.data,
biography = form.biography.data,
newsletter = form.newsletter.data
)
db.session.merge(current_user)
db.session.commit()
flash('Modifications effectuées', 'ok')
else:
flash('Erreur lors de la modification', 'error')

return render('account.html', form=form)

+ 41
- 0
app/utils/priv_required.py View File

@@ -0,0 +1,41 @@
from functools import wraps
from flask import redirect, url_for, request, flash
from flask_login import current_user
from flask_login.config import EXEMPT_METHODS
from app import app
from config import V5Config

def priv_required(*perms):
"""
If you decorate a view with this, it will ensure that the current user is
authenticated and has required permissions before calling the actual view.
(If they are not, it calls the :attr:`LoginManager.unauthorized` callback.)
For example::

@app.route('/admin')
@priv_required('access-admin-board')
def admin_board():
pass

It can be convenient to globally turn off authentication when unit testing.
To enable this, if the application configuration variable `LOGIN_DISABLED`
is set to `True`, this decorator will be ignored.
"""
def decorated_view(func):
@wraps(func)
def wrapped(*args, **kwargs):
if request.method in EXEMPT_METHODS:
return func(*args, **kwargs)
elif app.config.get('LOGIN_DISABLED'):
#if app.config.get('LOGIN_DISABLED'):
return func(*args, **kwargs)
elif not current_user.is_authenticated:
return app.login_manager.unauthorized()
else:
for p in perms:
if not current_user.priv(p):
flash(V5Config.UNAUTHORIZED_MSG, 'error')
return redirect(url_for('index'))
return func(*args, **kwargs)
return wrapped
return decorated_view

+ 3
- 0
config.py View File

@@ -12,3 +12,6 @@ class V5Config(object):
PRIVS_MAXLEN = 64
# Forbidden user names
FORBIDDEN_USERNAMES = [ "admin", "root", "webmaster", "contact" ]
# Unauthorized message (@priv_required)
UNAUTHORIZED_MSG = "Vous n'avez pas l'autorisation d'effectuer cette action !"


Loading…
Cancel
Save