Mercurial > public > sg101
diff gpp/forums/permissions.py @ 459:9d3bd7304050
Fixing #221. Also combined all permissions checks into a new module, permissions.py. This allows us to cache user, category, and forum groups information since it rarely changes.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sat, 02 Jul 2011 23:35:45 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gpp/forums/permissions.py Sat Jul 02 23:35:45 2011 +0000 @@ -0,0 +1,114 @@ +""" +This module does permissions checking for the forums application. + +""" +from django.core.cache import cache + +# How long (in secs) to cache group information for various entities: +CATEGORY_TIMEOUT = 4 * 60 * 60 +FORUM_TIMEOUT = 4 * 60 * 60 +USER_TIMEOUT = 15 * 60 + + +def can_access(category, user): + """ + This function returns True if the given user can access the forum category + and False otherwise. + + """ + if user.is_superuser: + return True + + # If this category has no groups assigned to it, return True. Else, return + # True if the user belongs to a group that has been assigned to this + # category, and False otherwise. + + # Get the groups assigned to this category. + cat_groups = get_category_groups(category) + + if len(cat_groups) == 0: + return True # No groups => public category + + user_groups = get_user_groups(user) + return bool(user_groups & cat_groups) + + +def can_moderate(forum, user): + """ + Returns True if the user can moderate the forum. + + """ + # Get the simple cases out of the way first: + if not user.is_authenticated(): + return False + elif user.is_superuser: + return True + + # If we get here, we have to see if there is an intersection between the + # user's groups and the forum's moderator groups. + + forum_groups = get_forum_groups(forum) + user_groups = get_user_groups(user) + + return bool(user_groups & forum_groups) + + +def can_post(topic, user): + """ + Returns True if the user can post in the topic and False otherwise. + + """ + if not user.is_authenticated(): + return False + if user.is_superuser or can_moderate(topic.forum, user): + return True + + return not topic.locked and can_access(topic.forum.category, user) + + +def get_user_groups(user): + """ + Returns a set of group ID's that the user belongs to. + + """ + user_groups_key = '%s_groups' % user.username + return _get_groups(user_groups_key, user.groups.all(), USER_TIMEOUT) + + +def get_forum_groups(forum): + """ + Returns a set of group ID's of the forum's moderator groups. + + """ + forum_groups_key = 'forum_%d_mods' % forum.id + return _get_groups(forum_groups_key, forum.moderators.all(), FORUM_TIMEOUT) + + +def get_category_groups(category): + """ + Returns a set of group ID's of the groups that can access this forum + category. + + """ + cat_groups_key = 'cat_%d_groups' % category.id + return _get_groups(cat_groups_key, category.groups.all(), CATEGORY_TIMEOUT) + + +def _get_groups(key, qs, timeout): + """ + This internal function contains the code common to the get_xxx_groups() + functions. Returns a set of group ID's from the cache. If the set is not + found in the cache, the set is generated from the queryset qs and cached + with the given timeout. + + key - the cache key for the set of group ID's + qs - the query set of groups to query if the set is not in the cache + timeout - the cache timeout to use + + """ + groups = cache.get(key) + if groups is None: + groups = set([g.id for g in qs]) + cache.set(key, groups, timeout) + + return groups