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