permissions.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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 return_boolean
  6. from misago.core import forms
  7. from misago.forums.models import Forum, RoleForumACL, ForumRole
  8. from misago.threads.models import Thread, Post
  9. """
  10. Admin Permissions Form
  11. """
  12. class PermissionsForm(forms.Form):
  13. legend = _("Forum access")
  14. can_see = forms.YesNoSwitch(label=_("Can see forum"))
  15. can_browse = forms.YesNoSwitch(label=_("Can see forum contents"))
  16. def change_permissions_form(role):
  17. if isinstance(role, ForumRole):
  18. return PermissionsForm
  19. else:
  20. return None
  21. """
  22. ACL Builder
  23. """
  24. def build_acl(acl, roles, key_name):
  25. new_acl = {
  26. 'visible_forums': [],
  27. 'forums': {},
  28. }
  29. new_acl.update(acl)
  30. forums_roles = get_forums_roles(roles)
  31. for forum in Forum.objects.all_forums():
  32. build_forum_acl(new_acl, forum, forums_roles, key_name)
  33. return new_acl
  34. def get_forums_roles(roles):
  35. queryset = RoleForumACL.objects.filter(role__in=roles)
  36. queryset = queryset.select_related('forum_role')
  37. forums_roles = {}
  38. for acl_relation in queryset.iterator():
  39. forum_role = acl_relation.forum_role
  40. forums_roles.setdefault(acl_relation.forum_id, []).append(forum_role)
  41. return forums_roles
  42. def build_forum_acl(acl, forum, forums_roles, key_name):
  43. if forum.level > 1:
  44. if forum.parent_id not in acl['visible_forums']:
  45. # dont bother with child forums of invisible parents
  46. return
  47. elif not acl['forums'][forum.parent_id]['can_browse']:
  48. # parent's visible, but its contents aint
  49. return
  50. forum_roles = forums_roles.get(forum.pk, [])
  51. final_acl = {
  52. 'can_see': 0,
  53. 'can_browse': 0,
  54. }
  55. algebra.sum_acls(final_acl, roles=forum_roles, key=key_name,
  56. can_see=algebra.greater,
  57. can_browse=algebra.greater
  58. )
  59. if final_acl['can_see']:
  60. acl['visible_forums'].append(forum.pk)
  61. acl['forums'][forum.pk] = final_acl
  62. """
  63. ACL's for targets
  64. """
  65. def add_acl_to_target(user, target):
  66. if isinstance(target, Forum):
  67. add_acl_to_forum(user, target)
  68. if isinstance(target, Thread):
  69. add_acl_to_thread(user, target)
  70. if isinstance(target, Post):
  71. add_acl_to_post(user, target)
  72. def add_acl_to_forum(user, forum):
  73. target.acl['can_see'] = can_see_forum(user, target)
  74. target.acl['can_browse'] = can_browse_forum(user, target)
  75. def add_acl_to_thread(user, thread):
  76. pass
  77. def add_acl_to_post(user, post):
  78. pass
  79. """
  80. ACL tests
  81. """
  82. def allow_see_forum(user, target):
  83. try:
  84. forum_id = target.pk
  85. except AttributeError:
  86. forum_id = int(target)
  87. if not forum_id in user.acl['visible_forums']:
  88. raise Http404()
  89. can_see_forum = return_boolean(allow_see_forum)