permissions.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. from django.core.exceptions import PermissionDenied
  2. from django.http import Http404
  3. from django.utils.translation import ugettext_lazy as _
  4. from misago.acl import algebra
  5. from misago.acl.decorators import require_target_type, return_boolean
  6. from misago.core import forms
  7. from misago.forums.models import Forum, RoleForumACL, ForumRole
  8. """
  9. Admin Permissions Form
  10. """
  11. class PermissionsForm(forms.Form):
  12. legend = _("Forum access")
  13. can_see = forms.YesNoSwitch(label=_("Can see forum"))
  14. can_browse = forms.YesNoSwitch(label=_("Can see forum contents"))
  15. def change_permissions_form(role):
  16. if isinstance(role, ForumRole):
  17. return PermissionsForm
  18. else:
  19. return None
  20. """
  21. ACL Builder
  22. """
  23. def build_acl(acl, roles, key_name):
  24. new_acl = {
  25. 'visible_forums': [],
  26. 'forums': {},
  27. }
  28. new_acl.update(acl)
  29. forums_roles = get_forums_roles(roles)
  30. for forum in Forum.objects.all_forums():
  31. build_forum_acl(new_acl, forum, forums_roles, key_name)
  32. return new_acl
  33. def get_forums_roles(roles):
  34. queryset = RoleForumACL.objects.filter(role__in=roles)
  35. queryset = queryset.select_related('forum_role')
  36. forums_roles = {}
  37. for acl_relation in queryset.iterator():
  38. forum_role = acl_relation.forum_role
  39. forums_roles.setdefault(acl_relation.forum_id, []).append(forum_role)
  40. return forums_roles
  41. def build_forum_acl(acl, forum, forums_roles, key_name):
  42. if forum.level > 1:
  43. if forum.parent_id not in acl['visible_forums']:
  44. # dont bother with child forums of invisible parents
  45. return
  46. elif not acl['forums'][forum.parent_id]['can_browse']:
  47. # parent's visible, but its contents aint
  48. return
  49. forum_roles = forums_roles.get(forum.pk, [])
  50. final_acl = {
  51. 'can_see': 0,
  52. 'can_browse': 0,
  53. }
  54. algebra.sum_acls(final_acl, roles=forum_roles, key=key_name,
  55. can_see=algebra.greater,
  56. can_browse=algebra.greater
  57. )
  58. if final_acl['can_see']:
  59. acl['visible_forums'].append(forum.pk)
  60. acl['forums'][forum.pk] = final_acl
  61. """
  62. ACL's for targets
  63. """
  64. @require_target_type(Forum)
  65. def add_acl_to_target(user, target):
  66. target.acl['can_see'] = can_see_forum(user, target)
  67. target.acl['can_browse'] = can_browse_forum(user, target)
  68. """
  69. ACL tests
  70. """
  71. def allow_see_forum(user, target):
  72. try:
  73. forum_id = target.pk
  74. except AttributeError:
  75. forum_id = int(target)
  76. if not forum_id in user.acl['visible_forums']:
  77. raise Http404()
  78. can_see_forum = return_boolean(allow_see_forum)
  79. def allow_browse_forum(user, target):
  80. target_acl = user.acl['forums'].get(target.id, {'can_browse': False})
  81. if not target_acl['can_browse']:
  82. message = _('You don\'t have permission '
  83. 'to browse "%(forum)s" contents.')
  84. raise PermissionDenied(message % {'forum': target.name})
  85. can_browse_forum = return_boolean(allow_browse_forum)