annotate forums/permissions.py @ 887:9a15f7c27526

Actually save model object upon change. This commit was tested on the comments model. Additional logging added. Added check for Markdown image references. Added TODOs after observing behavior on comments.
author Brian Neal <bgneal@gmail.com>
date Tue, 03 Feb 2015 21:09:44 -0600
parents ee87ea74d46b
children
rev   line source
bgneal@459 1 """
bgneal@459 2 This module does permissions checking for the forums application.
bgneal@459 3
bgneal@459 4 """
bgneal@459 5 from django.core.cache import cache
bgneal@459 6
bgneal@459 7 # How long (in secs) to cache group information for various entities:
bgneal@459 8 CATEGORY_TIMEOUT = 4 * 60 * 60
bgneal@459 9 FORUM_TIMEOUT = 4 * 60 * 60
bgneal@459 10 USER_TIMEOUT = 15 * 60
bgneal@459 11
bgneal@459 12
bgneal@459 13 def can_access(category, user):
bgneal@459 14 """
bgneal@459 15 This function returns True if the given user can access the forum category
bgneal@459 16 and False otherwise.
bgneal@459 17
bgneal@459 18 """
bgneal@459 19 if user.is_superuser:
bgneal@459 20 return True
bgneal@459 21
bgneal@459 22 # If this category has no groups assigned to it, return True. Else, return
bgneal@459 23 # True if the user belongs to a group that has been assigned to this
bgneal@459 24 # category, and False otherwise.
bgneal@459 25
bgneal@459 26 # Get the groups assigned to this category.
bgneal@459 27 cat_groups = get_category_groups(category)
bgneal@459 28
bgneal@459 29 if len(cat_groups) == 0:
bgneal@459 30 return True # No groups => public category
bgneal@459 31
bgneal@459 32 user_groups = get_user_groups(user)
bgneal@459 33 return bool(user_groups & cat_groups)
bgneal@459 34
bgneal@459 35
bgneal@459 36 def can_moderate(forum, user):
bgneal@459 37 """
bgneal@459 38 Returns True if the user can moderate the forum.
bgneal@459 39
bgneal@459 40 """
bgneal@459 41 # Get the simple cases out of the way first:
bgneal@459 42 if not user.is_authenticated():
bgneal@459 43 return False
bgneal@459 44 elif user.is_superuser:
bgneal@459 45 return True
bgneal@459 46
bgneal@459 47 # If we get here, we have to see if there is an intersection between the
bgneal@459 48 # user's groups and the forum's moderator groups.
bgneal@459 49
bgneal@459 50 forum_groups = get_forum_groups(forum)
bgneal@459 51 user_groups = get_user_groups(user)
bgneal@459 52
bgneal@459 53 return bool(user_groups & forum_groups)
bgneal@459 54
bgneal@459 55
bgneal@459 56 def can_post(topic, user):
bgneal@459 57 """
bgneal@459 58 Returns True if the user can post in the topic and False otherwise.
bgneal@459 59
bgneal@459 60 """
bgneal@459 61 if not user.is_authenticated():
bgneal@459 62 return False
bgneal@459 63 if user.is_superuser or can_moderate(topic.forum, user):
bgneal@459 64 return True
bgneal@459 65
bgneal@459 66 return not topic.locked and can_access(topic.forum.category, user)
bgneal@459 67
bgneal@459 68
bgneal@459 69 def get_user_groups(user):
bgneal@459 70 """
bgneal@459 71 Returns a set of group ID's that the user belongs to.
bgneal@459 72
bgneal@459 73 """
bgneal@459 74 user_groups_key = '%s_groups' % user.username
bgneal@459 75 return _get_groups(user_groups_key, user.groups.all(), USER_TIMEOUT)
bgneal@459 76
bgneal@459 77
bgneal@459 78 def get_forum_groups(forum):
bgneal@459 79 """
bgneal@459 80 Returns a set of group ID's of the forum's moderator groups.
bgneal@459 81
bgneal@459 82 """
bgneal@459 83 forum_groups_key = 'forum_%d_mods' % forum.id
bgneal@459 84 return _get_groups(forum_groups_key, forum.moderators.all(), FORUM_TIMEOUT)
bgneal@459 85
bgneal@459 86
bgneal@459 87 def get_category_groups(category):
bgneal@459 88 """
bgneal@459 89 Returns a set of group ID's of the groups that can access this forum
bgneal@459 90 category.
bgneal@459 91
bgneal@459 92 """
bgneal@459 93 cat_groups_key = 'cat_%d_groups' % category.id
bgneal@459 94 return _get_groups(cat_groups_key, category.groups.all(), CATEGORY_TIMEOUT)
bgneal@459 95
bgneal@459 96
bgneal@459 97 def _get_groups(key, qs, timeout):
bgneal@459 98 """
bgneal@459 99 This internal function contains the code common to the get_xxx_groups()
bgneal@459 100 functions. Returns a set of group ID's from the cache. If the set is not
bgneal@459 101 found in the cache, the set is generated from the queryset qs and cached
bgneal@459 102 with the given timeout.
bgneal@459 103
bgneal@459 104 key - the cache key for the set of group ID's
bgneal@459 105 qs - the query set of groups to query if the set is not in the cache
bgneal@459 106 timeout - the cache timeout to use
bgneal@459 107
bgneal@459 108 """
bgneal@459 109 groups = cache.get(key)
bgneal@459 110 if groups is None:
bgneal@459 111 groups = set([g.id for g in qs])
bgneal@459 112 cache.set(key, groups, timeout)
bgneal@459 113
bgneal@459 114 return groups