Browse Source

Moving on with ACL implementation

Rafał Pitoń 11 years ago
parent
commit
f6f82ce082

+ 47 - 0
misago/acl/providers.py

@@ -35,7 +35,54 @@ class PermissionProviders(object):
 providers = PermissionProviders()
 providers = PermissionProviders()
 
 
 
 
+"""
+Module functions for ACLS
+
+Workflow for ACLs in Misago is simple:
+
+First, you get user ACL. You can introspect it directory to find out user
+permissions, or if you have objects, you can use this acl to make those objects
+aware of their ACLs. This gives objects themselves special "acl" attribute with
+properties defined by ACL providers within their "add_acl_to_target"
+"""
+def get_user_acl(user):
+    """
+    Get hydrated ACL for User
+    """
+    pass
+
+
+def _add_acl_to_target(acl, target):
+    """
+    Add valid ACL to single target
+    """
+    for provider, module in providers.list():
+        module.add_acl_to_target(acl, target)
+
+
+def add_acl(acl, target):
+    """
+    Add valid ACL to target (iterable of objects or single object)
+    """
+    targets = []
+
+    try:
+        for item in target:
+            targets.append(item)
+    except TypeError:
+        targets.append(target)
+
+    for target in targets:
+        _add_acl_to_target(acl, target)
+
+
+"""
+Admin utils
+"""
 def get_change_permissions_forms(role, data=None):
 def get_change_permissions_forms(role, data=None):
+    """
+    Utility function for building forms in admin
+    """
     role_permissions = role.permissions
     role_permissions = role.permissions
 
 
     forms = []
     forms = []

+ 1 - 0
misago/conf/defaults.py

@@ -107,6 +107,7 @@ MIDDLEWARE_CLASSES = (
     'django.middleware.common.CommonMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'misago.users.middleware.UserMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
     'misago.core.middleware.threadstore.ThreadStoreMiddleware',
     'misago.core.middleware.threadstore.ThreadStoreMiddleware',

+ 0 - 3
misago/templates/misago/admin/users/edit.html

@@ -35,10 +35,7 @@ class="form-horizontal"
     {% endif %}
     {% endif %}
 
 
     {{ form.title|as_crispy_field }}
     {{ form.title|as_crispy_field }}
-
-    {% if 'roles' in form.fields %}
     {{ form.roles|as_crispy_field }}
     {{ form.roles|as_crispy_field }}
-    {% endif %}
 
 
     {% if 'staff_level' in form.fields %}
     {% if 'staff_level' in form.fields %}
     {{ form.staff_level|as_crispy_field }}
     {{ form.staff_level|as_crispy_field }}

+ 0 - 3
misago/templates/misago/admin/users/new.html

@@ -35,10 +35,7 @@ class="form-horizontal"
     {% endif %}
     {% endif %}
 
 
     {{ form.title|as_crispy_field }}
     {{ form.title|as_crispy_field }}
-
-    {% if 'roles' in form.fields %}
     {{ form.roles|as_crispy_field }}
     {{ form.roles|as_crispy_field }}
-    {% endif %}
 
 
     {% if 'staff_level' in form.fields %}
     {% if 'staff_level' in form.fields %}
     {{ form.staff_level|as_crispy_field }}
     {{ form.staff_level|as_crispy_field }}

+ 7 - 0
misago/users/middleware.py

@@ -0,0 +1,7 @@
+from misago.users.models import AnonymousUser
+
+
+class UserMiddleware(object):
+    def process_request(self, request):
+        if request.user.is_anonymous():
+            request.user = AnonymousUser()

+ 46 - 1
misago/users/models/usermodel.py

@@ -1,8 +1,11 @@
 from django.contrib.auth.models import (AbstractBaseUser, PermissionsMixin,
 from django.contrib.auth.models import (AbstractBaseUser, PermissionsMixin,
-                                        UserManager as BaseUserManager)
+                                        UserManager as BaseUserManager,
+                                        AnonymousUser as DjangoAnonymousUser)
 from django.db import models
 from django.db import models
 from django.utils import timezone
 from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
+from misago.acl import get_user_acl
+from misago.acl.models import Role
 from misago.admin import site
 from misago.admin import site
 from misago.core.utils import slugify
 from misago.core.utils import slugify
 from misago.users.models import Rank
 from misago.users.models import Rank
@@ -94,6 +97,14 @@ class User(AbstractBaseUser, PermissionsMixin):
         app_label = 'users'
         app_label = 'users'
 
 
     @property
     @property
+    def acl(self):
+        try:
+            return self._acl_cache
+        except AttributeError:
+            self._acl_cache = get_user_acl(self)
+            return self._acl_cache
+
+    @property
     def staff_level(self):
     def staff_level(self):
         if self.is_superuser:
         if self.is_superuser:
             return 2
             return 2
@@ -134,10 +145,44 @@ class User(AbstractBaseUser, PermissionsMixin):
         self.email = UserManager.normalize_email(new_email)
         self.email = UserManager.normalize_email(new_email)
         self.email_hash = hash_email(new_email)
         self.email_hash = hash_email(new_email)
 
 
+    def get_roles(self):
+        roles_pks = []
+        roles_dict = {}
+
+        for role in self.role_set.all():
+            roles_pks.append(role.pk)
+            roles_dict[role.pk] = role
+
+        if self.rank:
+            for role in self.rank.role_set.all():
+                if role.pk not in roles_pks:
+                    roles_pks.append(role.pk)
+                    roles_dict[role.pk] = role
+
+        return [roles_dict[r] for r in roles_pks]
+
     def update_acl_token(self):
     def update_acl_token(self):
         pass
         pass
 
 
 
 
+class AnonymousUser(DjangoAnonymousUser):
+    acl_key = 'anonymous'
+
+    @property
+    def acl(self):
+        try:
+            return self._acl_cache
+        except AttributeError:
+            self._acl_cache = get_user_acl(self)
+            return self._acl_cache
+
+    def get_roles(self):
+        try:
+            return [Role.objects.get(special_role="anonymous")]
+        except Role.DoesNotExist:
+            raise RuntimeError("Anonymous user role not found.")
+
+
 """register model in misago admin"""
 """register model in misago admin"""
 site.add_node(
 site.add_node(
     parent='misago:admin',
     parent='misago:admin',