bgneal@459: """ bgneal@459: This module does permissions checking for the forums application. bgneal@459: bgneal@459: """ bgneal@459: from django.core.cache import cache bgneal@459: bgneal@459: # How long (in secs) to cache group information for various entities: bgneal@459: CATEGORY_TIMEOUT = 4 * 60 * 60 bgneal@459: FORUM_TIMEOUT = 4 * 60 * 60 bgneal@459: USER_TIMEOUT = 15 * 60 bgneal@459: bgneal@459: bgneal@459: def can_access(category, user): bgneal@459: """ bgneal@459: This function returns True if the given user can access the forum category bgneal@459: and False otherwise. bgneal@459: bgneal@459: """ bgneal@459: if user.is_superuser: bgneal@459: return True bgneal@459: bgneal@459: # If this category has no groups assigned to it, return True. Else, return bgneal@459: # True if the user belongs to a group that has been assigned to this bgneal@459: # category, and False otherwise. bgneal@459: bgneal@459: # Get the groups assigned to this category. bgneal@459: cat_groups = get_category_groups(category) bgneal@459: bgneal@459: if len(cat_groups) == 0: bgneal@459: return True # No groups => public category bgneal@459: bgneal@459: user_groups = get_user_groups(user) bgneal@459: return bool(user_groups & cat_groups) bgneal@459: bgneal@459: bgneal@459: def can_moderate(forum, user): bgneal@459: """ bgneal@459: Returns True if the user can moderate the forum. bgneal@459: bgneal@459: """ bgneal@459: # Get the simple cases out of the way first: bgneal@459: if not user.is_authenticated(): bgneal@459: return False bgneal@459: elif user.is_superuser: bgneal@459: return True bgneal@459: bgneal@459: # If we get here, we have to see if there is an intersection between the bgneal@459: # user's groups and the forum's moderator groups. bgneal@459: bgneal@459: forum_groups = get_forum_groups(forum) bgneal@459: user_groups = get_user_groups(user) bgneal@459: bgneal@459: return bool(user_groups & forum_groups) bgneal@459: bgneal@459: bgneal@459: def can_post(topic, user): bgneal@459: """ bgneal@459: Returns True if the user can post in the topic and False otherwise. bgneal@459: bgneal@459: """ bgneal@459: if not user.is_authenticated(): bgneal@459: return False bgneal@459: if user.is_superuser or can_moderate(topic.forum, user): bgneal@459: return True bgneal@459: bgneal@459: return not topic.locked and can_access(topic.forum.category, user) bgneal@459: bgneal@459: bgneal@459: def get_user_groups(user): bgneal@459: """ bgneal@459: Returns a set of group ID's that the user belongs to. bgneal@459: bgneal@459: """ bgneal@459: user_groups_key = '%s_groups' % user.username bgneal@459: return _get_groups(user_groups_key, user.groups.all(), USER_TIMEOUT) bgneal@459: bgneal@459: bgneal@459: def get_forum_groups(forum): bgneal@459: """ bgneal@459: Returns a set of group ID's of the forum's moderator groups. bgneal@459: bgneal@459: """ bgneal@459: forum_groups_key = 'forum_%d_mods' % forum.id bgneal@459: return _get_groups(forum_groups_key, forum.moderators.all(), FORUM_TIMEOUT) bgneal@459: bgneal@459: bgneal@459: def get_category_groups(category): bgneal@459: """ bgneal@459: Returns a set of group ID's of the groups that can access this forum bgneal@459: category. bgneal@459: bgneal@459: """ bgneal@459: cat_groups_key = 'cat_%d_groups' % category.id bgneal@459: return _get_groups(cat_groups_key, category.groups.all(), CATEGORY_TIMEOUT) bgneal@459: bgneal@459: bgneal@459: def _get_groups(key, qs, timeout): bgneal@459: """ bgneal@459: This internal function contains the code common to the get_xxx_groups() bgneal@459: functions. Returns a set of group ID's from the cache. If the set is not bgneal@459: found in the cache, the set is generated from the queryset qs and cached bgneal@459: with the given timeout. bgneal@459: bgneal@459: key - the cache key for the set of group ID's bgneal@459: qs - the query set of groups to query if the set is not in the cache bgneal@459: timeout - the cache timeout to use bgneal@459: bgneal@459: """ bgneal@459: groups = cache.get(key) bgneal@459: if groups is None: bgneal@459: groups = set([g.id for g in qs]) bgneal@459: cache.set(key, groups, timeout) bgneal@459: bgneal@459: return groups