fixing unit tests fixing merge error fixing xqueue submission issue with unicode url (trial 0.1) fixing fotmats as commented upon removing yaml file language selection Unicode changes to support QRF removed unnecessary pass in modulestore/init.py fixing merge error fixing fotmats as commented upon removing yaml file language selection fixing pep8 violations - fixing pylint violations pylint violation fixing line spaces and formats ignore pylint E1101 remove empty line fixing pylint violations pep8 violations bulk mail unicode/decode fix migration error fix pep8 just to push again more unicode/decode Final changes to comments and error messages.
115 lines
4.1 KiB
Python
115 lines
4.1 KiB
Python
"""
|
|
Module for checking permissions with the comment_client backend
|
|
"""
|
|
|
|
import logging
|
|
from django.core import cache
|
|
|
|
|
|
CACHE = cache.get_cache('default')
|
|
CACHE_LIFESPAN = 60
|
|
|
|
|
|
def cached_has_permission(user, permission, course_id=None):
|
|
"""
|
|
Call has_permission if it's not cached. A change in a user's role or
|
|
a role's permissions will only become effective after CACHE_LIFESPAN seconds.
|
|
"""
|
|
key = u"permission_{user_id:d}_{course_id}_{permission}".format(
|
|
user_id=user.id, course_id=course_id, permission=permission)
|
|
val = CACHE.get(key, None)
|
|
if val not in [True, False]:
|
|
val = has_permission(user, permission, course_id=course_id)
|
|
CACHE.set(key, val, CACHE_LIFESPAN)
|
|
return val
|
|
|
|
|
|
def has_permission(user, permission, course_id=None):
|
|
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):
|
|
try:
|
|
return data and not data['content']['closed']
|
|
except KeyError:
|
|
return False
|
|
|
|
def check_author(user, condition, course_id, data):
|
|
try:
|
|
return data and data['content']['user_id'] == str(user.id)
|
|
except KeyError:
|
|
return False
|
|
|
|
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 cached_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', 'is_author']],
|
|
'create_comment': [["create_comment", "is_open"]],
|
|
'delete_thread': ['delete_thread', ['update_thread', 'is_author']],
|
|
'update_comment': ['edit_content', ['update_comment', 'is_open', 'is_author']],
|
|
'endorse_comment': ['endorse_comment'],
|
|
'openclose_thread': ['openclose_thread'],
|
|
'create_sub_comment': [['create_sub_comment', 'is_open']],
|
|
'delete_comment': ['delete_comment', ['update_comment', 'is_open', 'is_author']],
|
|
'vote_for_comment': [['vote', 'is_open']],
|
|
'undo_vote_for_comment': [['unvote', 'is_open']],
|
|
'vote_for_thread': [['vote', 'is_open']],
|
|
'flag_abuse_for_thread': [['vote', 'is_open']],
|
|
'un_flag_abuse_for_thread': [['vote', 'is_open']],
|
|
'flag_abuse_for_comment': [['vote', 'is_open']],
|
|
'un_flag_abuse_for_comment': [['vote', 'is_open']],
|
|
'undo_vote_for_thread': [['unvote', 'is_open']],
|
|
'pin_thread': ['create_comment'],
|
|
'un_pin_thread': ['create_comment'],
|
|
'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):
|
|
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)
|