Skip to content

Instantly share code, notes, and snippets.

@sprytnyk
Created November 20, 2017 15:46
Show Gist options
  • Save sprytnyk/bc10ccff4b595925c23dd5013ef8d323 to your computer and use it in GitHub Desktop.
Save sprytnyk/bc10ccff4b595925c23dd5013ef8d323 to your computer and use it in GitHub Desktop.
Simple Flask MongoDB roles, permissions and decorator for views
import datetime
from functools import wraps
from werkzeug.security import (
generate_password_hash,
check_password_hash
)
from flask import abort
from flask_login import UserMixin, current_user
from core import db
class User(db.Document, UserMixin):
meta = {
'collection': 'users'
}
username = db.StringField()
email = db.EmailField()
password = db.StringField()
roles = db.ListField()
created_at = db.DateTimeField(default=datetime.datetime.now())
def get_id(self):
return str(self.pk)
def set_password(self, password):
self.password = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password, password)
@staticmethod
def validate_login(password_hash, password):
return check_password_hash(password_hash, password)
class Permission(db.Document):
meta = {
'collection': 'permissions'
}
role = db.ReferenceField('Role')
action = db.StringField()
class Role(db.Document):
meta = {
'collection': 'roles'
}
name = db.StringField()
permissions = db.ListField()
def has_permission(self, role, action):
return any(
[
role == perm.role.name and action == perm.action
for perm in self.permissions
]
)
def permission_required(permissions):
"""
Check if a user has permission to a resource.
:param permissions: List of permissions consistent with tuples. E.g.
[('user', 'read'), ('admin', 'create')]
:return: a function or raise 403
"""
def wrapper(func):
@wraps(func)
def wrapped(*args, **kwargs):
roles = Permission.objects.distinct('role')
if hasattr(current_user, 'roles'):
if set(current_user.roles) & set(roles):
for role, action in permissions:
for user_role in current_user.roles:
if user_role.has_permission(role, action):
return func(*args, **kwargs)
abort(403)
return wrapped
return wrapper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment