annotate forums/permissions.py @ 1201:fe10aea76cbd tip

Add 2023 MP3 compilation links
author Brian Neal <bgneal@gmail.com>
date Sun, 24 Mar 2024 14:50:23 -0500
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