Browse Source

WIP threads and posts permissions

Rafał Pitoń 10 years ago
parent
commit
86ee757c41
2 changed files with 122 additions and 0 deletions
  1. 1 0
      misago/conf/defaults.py
  2. 121 0
      misago/threads/permissions.py

+ 1 - 0
misago/conf/defaults.py

@@ -165,6 +165,7 @@ MISAGO_ACL_EXTENSIONS = (
     'misago.users.permissions.moderation',
     'misago.users.permissions.delete',
     'misago.forums.permissions',
+    'misago.threads.permissions',
 )
 
 MISAGO_MARKUP_EXTENSIONS = ()

+ 121 - 0
misago/threads/permissions.py

@@ -0,0 +1,121 @@
+from django.core.exceptions import PermissionDenied
+from django.http import Http404
+from django.utils.translation import ugettext_lazy as _
+
+
+from misago.acl import algebra
+from misago.acl.decorators import return_boolean
+from misago.core import forms
+from misago.forums.models import Forum, RoleForumACL, ForumRole
+
+from misago.threads.models import Thread, Post
+
+
+"""
+Admin Permissions Form
+"""
+class PermissionsForm(forms.Form):
+    legend = _("Forum access")
+    can_see = forms.YesNoSwitch(label=_("Can see forum"))
+    can_browse = forms.YesNoSwitch(label=_("Can see forum contents"))
+
+
+def change_permissions_form(role):
+    if isinstance(role, ForumRole):
+        return PermissionsForm
+    else:
+        return None
+
+
+"""
+ACL Builder
+"""
+def build_acl(acl, roles, key_name):
+    new_acl = {
+        'visible_forums': [],
+        'forums': {},
+    }
+    new_acl.update(acl)
+
+    forums_roles = get_forums_roles(roles)
+
+    for forum in Forum.objects.all_forums():
+        build_forum_acl(new_acl, forum, forums_roles, key_name)
+
+    return new_acl
+
+
+def get_forums_roles(roles):
+    queryset = RoleForumACL.objects.filter(role__in=roles)
+    queryset = queryset.select_related('forum_role')
+
+    forums_roles = {}
+    for acl_relation in queryset.iterator():
+        forum_role = acl_relation.forum_role
+        forums_roles.setdefault(acl_relation.forum_id, []).append(forum_role)
+    return forums_roles
+
+
+def build_forum_acl(acl, forum, forums_roles, key_name):
+    if forum.level > 1:
+        if forum.parent_id not in acl['visible_forums']:
+            # dont bother with child forums of invisible parents
+            return
+        elif not acl['forums'][forum.parent_id]['can_browse']:
+            # parent's visible, but its contents aint
+            return
+
+    forum_roles = forums_roles.get(forum.pk, [])
+
+    final_acl = {
+        'can_see': 0,
+        'can_browse': 0,
+    }
+
+    algebra.sum_acls(final_acl, roles=forum_roles, key=key_name,
+        can_see=algebra.greater,
+        can_browse=algebra.greater
+    )
+
+    if final_acl['can_see']:
+        acl['visible_forums'].append(forum.pk)
+        acl['forums'][forum.pk] = final_acl
+
+
+"""
+ACL's for targets
+"""
+def add_acl_to_target(user, target):
+    if isinstance(target, Forum):
+        add_acl_to_forum(user, target)
+    if isinstance(target, Thread):
+        add_acl_to_thread(user, target)
+    if isinstance(target, Post):
+        add_acl_to_post(user, target)
+
+
+def add_acl_to_forum(user, forum):
+    target.acl['can_see'] = can_see_forum(user, target)
+    target.acl['can_browse'] = can_browse_forum(user, target)
+
+
+def add_acl_to_thread(user, thread):
+    pass
+
+
+def add_acl_to_post(user, post):
+    pass
+
+
+"""
+ACL tests
+"""
+def allow_see_forum(user, target):
+    try:
+        forum_id = target.pk
+    except AttributeError:
+        forum_id = int(target)
+
+    if not forum_id in user.acl['visible_forums']:
+        raise Http404()
+can_see_forum = return_boolean(allow_see_forum)