from .models import Role, Permission from django.contrib.auth.models import User from django.db.models.signals import post_save from django.dispatch import receiver from student.models import CourseEnrollment import logging @receiver(post_save, sender=CourseEnrollment) def assign_default_role(sender, instance, **kwargs): if instance.user.is_staff: role = Role.objects.get(course_id=instance.course_id, name="Moderator") else: role = Role.objects.get(course_id=instance.course_id, name="Student") logging.info("assign_default_role: adding %s as %s" % (instance.user, role)) instance.user.roles.add(role) def has_permission(user, permission, course_id=None): # if user.permissions.filter(name=permission).exists(): # return True for role in user.roles.filter(course_id=course_id): if role.has_permission(permission): return True return False CONDITIONS = ['is_open', 'is_author'] def check_condition(user, condition, course_id, data): def check_open(user, condition, course_id, data): return not data['content']['closed'] def check_author(user, condition, course_id, data): return data['content']['user_id'] == str(user.id) handlers = { 'is_open' : check_open, 'is_author' : check_author, } return handlers[condition](user, condition, course_id, data) def check_conditions_permissions(user, permissions, course_id, **kwargs): """ Accepts a list of permissions and proceed if any of the permission is valid. Note that ["can_view", "can_edit"] will proceed if the user has either "can_view" or "can_edit" permission. To use AND operator in between, wrap them in a list. """ def test(user, per, operator="or"): if isinstance(per, basestring): if per in CONDITIONS: return check_condition(user, per, course_id, kwargs) return has_permission(user, per, course_id=course_id) elif isinstance(per, list) and operator in ["and", "or"]: results = [test(user, x, operator="and") for x in per] if operator == "or": return True in results elif operator == "and": return not False in results return test(user, permissions, operator="or") VIEW_PERMISSIONS = { 'update_thread' : ['edit_content', ['update_thread', 'is_open', 'author']], # 'create_comment' : [["create_comment", "is_open"]], 'create_comment' : ["create_comment"], 'delete_thread' : ['delete_thread'], 'update_comment' : ['edit_content', ['update_comment', 'is_open', 'author']], 'endorse_comment' : ['endorse_comment'], 'openclose_thread' : ['openclose_thread'], 'create_sub_comment': [['create_sub_comment', 'is_open']], 'delete_comment' : ['delete_comment'], 'vote_for_comment' : [['vote', 'is_open']], 'undo_vote_for_comment': [['unvote', 'is_open']], 'vote_for_thread' : [['vote', 'is_open']], 'undo_vote_for_thread': [['unvote', 'is_open']], 'follow_thread' : ['follow_thread'], 'follow_commentable': ['follow_commentable'], 'follow_user' : ['follow_user'], 'unfollow_thread' : ['unfollow_thread'], 'unfollow_commentable': ['unfollow_commentable'], 'unfollow_user' : ['unfollow_user'], 'create_thread' : ['create_thread'], } def check_permissions_by_view(user, course_id, content, name): # import pdb; pdb.set_trace() try: p = VIEW_PERMISSIONS[name] except KeyError: logging.warning("Permission for view named %s does not exist in permissions.py" % name) return check_conditions_permissions(user, p, course_id, content=content)