Add new roles and a new permission

This commit is contained in:
Patrick Jentsch 2021-12-03 14:07:03 +01:00
parent 89f518fe38
commit 123537cd16
5 changed files with 56 additions and 10 deletions

View File

@ -39,8 +39,9 @@ def create_app(config_class=Config):
message_queue=app.config.get('NOPAQUE_SOCKETIO_MESSAGE_QUEUE_URI') message_queue=app.config.get('NOPAQUE_SOCKETIO_MESSAGE_QUEUE_URI')
) )
from .utils import HashidConverter from .utils import HashidConverter, permission_context_processor
app.url_map.converters['hashid'] = HashidConverter app.url_map.converters['hashid'] = HashidConverter
app.context_processor(permission_context_processor)
from .events import socketio as socketio_events from .events import socketio as socketio_events
from .events import sqlalchemy as sqlalchemy_events from .events import sqlalchemy as sqlalchemy_events

View File

@ -2,16 +2,47 @@ from flask import abort, current_app
from flask_login import current_user from flask_login import current_user
from functools import wraps from functools import wraps
from threading import Thread from threading import Thread
from .models import Permission
def permission_required(permission):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_user.can(permission):
abort(403)
return f(*args, **kwargs)
return decorated_function
return decorator
def admin_required(f): def admin_required(f):
return permission_required(Permission.ADMINISTRATE)(f)
def socketio_login_required(f):
@wraps(f) @wraps(f)
def wrapped(*args, **kwargs): def decorated_function(*args, **kwargs):
if current_user.is_administrator: if current_user.is_authenticated:
return f(*args, **kwargs) return f(*args, **kwargs)
else: else:
abort(403) return {'code': 401, 'msg': 'Unauthorized'}
return wrapped return decorated_function
def socketio_permission_required(permission):
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_user.can(permission):
return {'code': 403, 'msg': 'Forbidden'}
return f(*args, **kwargs)
return decorated_function
return decorator
def socketio_admin_required(f):
return socketio_permission_required(Permission.ADMINISTRATE)(f)
def background(f): def background(f):

View File

@ -38,8 +38,9 @@ class Permission(enum.IntEnum):
Defines User permissions as integers by the power of 2. User permission Defines User permissions as integers by the power of 2. User permission
can be evaluated using the bitwise operator &. can be evaluated using the bitwise operator &.
''' '''
ADMINISTRATE = 1 ADMINISTRATE = 4
USE_API = 2 CONTRIBUTE = 2
USE_API = 1
class Role(HashidMixin, db.Model): class Role(HashidMixin, db.Model):
@ -93,7 +94,13 @@ class Role(HashidMixin, db.Model):
def insert_roles(): def insert_roles():
roles = { roles = {
'User': [], 'User': [],
'Administrator': [Permission.USE_API, Permission.ADMINISTRATE] 'API user': [Permission.USE_API],
'Contributor': [Permission.CONTRIBUTE],
'Administrator': [
Permission.ADMINISTRATE,
Permission.CONTRIBUTE,
Permission.USE_API
]
} }
default_role_name = 'User' default_role_name = 'User'
for role_name, permissions in roles.items(): for role_name, permissions in roles.items():

View File

@ -22,10 +22,12 @@
<li><a class="subheader">Account</a></li> <li><a class="subheader">Account</a></li>
<li><a href="{{ url_for('settings.index') }}"><i class="material-icons">settings</i>Settings</a></li> <li><a href="{{ url_for('settings.index') }}"><i class="material-icons">settings</i>Settings</a></li>
<li><a href="{{ url_for('auth.logout') }}">Log out</a></li> <li><a href="{{ url_for('auth.logout') }}">Log out</a></li>
{% if current_user.is_administrator() %} {% if current_user.can(Permission.ADMINISTRATE) %}
<li><div class="divider"></div></li> <li><div class="divider"></div></li>
<li><a class="subheader">Administration</a></li> <li><a class="subheader">Specials</a></li>
<li><a href="{{ url_for('admin.index') }}"><i class="material-icons">admin_panel_settings</i>Administration</a></li> <li><a href="{{ url_for('admin.index') }}"><i class="material-icons">admin_panel_settings</i>Administration</a></li>
{% endif %}
{% if current_user.can(Permission.USE_API) %}
<li><a href="{{ url_for('api.doc') }}"><i class="material-icons">api</i>API</a></li> <li><a href="{{ url_for('api.doc') }}"><i class="material-icons">api</i>API</a></li>
{% endif %} {% endif %}
</ul> </ul>

View File

@ -1,5 +1,6 @@
from app import hashids from app import hashids
from werkzeug.routing import BaseConverter from werkzeug.routing import BaseConverter
from .models import Permission
class HashidConverter(BaseConverter): class HashidConverter(BaseConverter):
@ -8,3 +9,7 @@ class HashidConverter(BaseConverter):
def to_url(self, value): def to_url(self, value):
return hashids.encode(value) return hashids.encode(value)
def permission_context_processor():
return {'Permission': Permission}