Browse Source

ACL builder works

Ralfp 12 years ago
parent
commit
6e5fe32d15

+ 34 - 2
misago/acl/builder.py

@@ -1,5 +1,37 @@
 from django.conf import settings
 from django.conf import settings
 from django.utils.importlib import import_module
 from django.utils.importlib import import_module
+from misago.forms import Form
 
 
-def build_form(request, form, target):
-    return form
+def build_form(request, role):
+    form_type = type('ACLForm', (Form,), dict(layout=[]))
+    for provider in settings.PERMISSION_PROVIDERS:
+        app_module = import_module(provider)
+        try:
+            app_module.make_form(request, role, form_type)
+        except AttributeError:
+            pass
+    return form_type
+
+
+class BaseACL(object):
+    def __init__(self):
+        self.acl = {}
+
+
+class ACL(object):
+    def __init__(self, version):
+        self.version = version
+
+
+def build_acl(request, roles):
+    acl = ACL(request.monitor['acl_version'])
+    perms = []
+    for role in roles:
+        perms.append(role.get_permissions())
+    for provider in settings.PERMISSION_PROVIDERS:
+        app_module = import_module(provider)
+        try:
+            app_module.build(acl, perms)
+        except AttributeError:
+            pass
+    return acl

+ 23 - 0
misago/acl/middleware.py

@@ -0,0 +1,23 @@
+from django.core.cache import cache, InvalidCacheBackendError
+from misago.acl.builder import build_acl
+
+class ACLMiddleware(object):
+    def process_request(self, request):
+        if request.user.is_authenticated():
+            acl_key = request.user.make_acl_key()
+        else:
+            acl_key = request.session.get('acl_key')
+            if not acl_key:
+                acl_key = request.user.make_acl_key()
+                request.session['acl_key'] = acl_key
+        
+        try:
+            user_acl = cache.get(acl_key)
+            if user_acl.version != request.monitor['acl_version']:
+                raise InvalidCacheBackendError()
+        except AttributeError, InvalidCacheBackendError:
+            user_acl = build_acl(request, request.user.get_roles())
+            cache.set(acl_key, user_acl, 2592000)
+
+        request.acl = user_acl
+        

+ 22 - 7
misago/admin/acl.py

@@ -1,11 +1,26 @@
-def form(request, role, fields, layout):
-    pass
+from django.utils.translation import ugettext_lazy as _
+from django import forms
+from misago.acl.builder import BaseACL
+from misago.forms import YesNoSwitch
 
 
+def make_form(request, role, form):
+    if role.token != 'admin' and request.user.is_god():
+        form.base_fields['can_use_acp'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
+        form.layout.append((
+                            _("Admin Control Panel"),
+                            (('can_use_acp', {'label': _("Can use Admin Control Panel"), 'help_text': _("Change this permission to yes to grant admin access for users with this role.")}),),
+                            ))
 
 
-def dehydrate(acl, data):
-    pass
 
 
+class AdminACL(BaseACL):
+    def is_admin(self):
+        return self.acl['can_use_acp']
+    
 
 
-def build(data):
-    pass
-
+def build(acl, roles):
+    acl.admin = AdminACL()
+    acl.admin.acl['can_use_acp'] = False
+    
+    for role in roles:
+        if 'can_use_acp' in role and role['can_use_acp'] > acl.admin.acl['can_use_acp']:
+            acl.admin.acl['can_use_acp'] = role['can_use_acp']

+ 1 - 5
misago/roles/forms.py

@@ -11,8 +11,4 @@ class RoleForm(Form):
                 ('name', {'label': _("Role Name"), 'help_text': _("Role Name is used to identify this role in Admin Control Panel.")}),
                 ('name', {'label': _("Role Name"), 'help_text': _("Role Name is used to identify this role in Admin Control Panel.")}),
                 ),
                 ),
               ),
               ),
-             )
-
-
-class PermsForm(Form):
-    layout = []
+             )

+ 0 - 3
misago/roles/middleware.py

@@ -1,3 +0,0 @@
-class ACLMiddleware(object):
-    def process_request(self, request):
-        print 'ACL MIDDLEWARE!!!'

+ 4 - 4
misago/roles/models.py

@@ -5,7 +5,7 @@ try:
     import cPickle as pickle
     import cPickle as pickle
 except ImportError:
 except ImportError:
     import pickle
     import pickle
-    
+
 class Role(models.Model):
 class Role(models.Model):
     """
     """
     Misago User Role model
     Misago User Role model
@@ -24,16 +24,16 @@ class Role(models.Model):
     
     
     def get_permissions(self):
     def get_permissions(self):
         if self.permissions_cache:
         if self.permissions_cache:
-            return permissions_cache
+            return self.permissions_cache
         
         
         try:
         try:
-            self.permissions_cache = base64.decodestring(pickle.loads(self.permissions))
+            self.permissions_cache = pickle.loads(base64.decodestring(self.permissions))
         except Exception:
         except Exception:
             # ValueError, SuspiciousOperation, unpickling exceptions. If any of
             # ValueError, SuspiciousOperation, unpickling exceptions. If any of
             # these happen, just return an empty dictionary (an empty permissions list).
             # these happen, just return an empty dictionary (an empty permissions list).
             self.permissions_cache = {}
             self.permissions_cache = {}
             
             
-        return permissions_cache
+        return self.permissions_cache
     
     
     def set_permissions(self, permissions):
     def set_permissions(self, permissions):
         self.permissions_cache = permissions
         self.permissions_cache = permissions

+ 5 - 5
misago/roles/views.py

@@ -1,10 +1,11 @@
+import copy
 from django.core.urlresolvers import reverse as django_reverse
 from django.core.urlresolvers import reverse as django_reverse
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 from misago.acl.builder import build_form 
 from misago.acl.builder import build_form 
 from misago.admin import site
 from misago.admin import site
 from misago.admin.widgets import *
 from misago.admin.widgets import *
 from misago.utils import slugify
 from misago.utils import slugify
-from misago.roles.forms import RoleForm, PermsForm
+from misago.roles.forms import RoleForm
 from misago.roles.models import Role
 from misago.roles.models import Role
 
 
 def reverse(route, target=None):
 def reverse(route, target=None):
@@ -103,13 +104,12 @@ class ACL(FormWidget):
     id = 'acl'
     id = 'acl'
     name = _("Change Role Permissions")
     name = _("Change Role Permissions")
     fallback = 'admin_roles'
     fallback = 'admin_roles'
-    form = PermsForm
     target_name = 'name'
     target_name = 'name'
     notfound_message = _('Requested Role could not be found.')
     notfound_message = _('Requested Role could not be found.')
     submit_fallback = True
     submit_fallback = True
     
     
     def get_form(self, request, target):
     def get_form(self, request, target):
-        self.form = build_form(request, self.form, target)
+        self.form = build_form(request, target)
         return self.form
         return self.form
     
     
     def get_url(self, request, model):
     def get_url(self, request, model):
@@ -127,12 +127,12 @@ class ACL(FormWidget):
         return initial
         return initial
     
     
     def submit_form(self, request, form, target):
     def submit_form(self, request, form, target):
-        raw_acl = model.get_permissions()
+        raw_acl = target.get_permissions()
         for perm in form.cleaned_data:
         for perm in form.cleaned_data:
             raw_acl[perm] = form.cleaned_data[perm]
             raw_acl[perm] = form.cleaned_data[perm]
         target.set_permissions(raw_acl)
         target.set_permissions(raw_acl)
         target.save(force_update=True)
         target.save(force_update=True)
-        request.model['acl_version'] = int(request.model['acl_version']) + 1
+        request.monitor['acl_version'] = int(request.monitor['acl_version']) + 1
         
         
         return target, Message(_('Role "%(name)s" permissions have been changed.') % {'name': self.original_name}, 'success')
         return target, Message(_('Role "%(name)s" permissions have been changed.') % {'name': self.original_name}, 'success')
 
 

+ 2 - 1
misago/settings_base.py

@@ -83,12 +83,13 @@ MIDDLEWARE_CLASSES = (
     'misago.banning.middleware.BanningMiddleware',
     'misago.banning.middleware.BanningMiddleware',
     'misago.messages.middleware.MessagesMiddleware',
     'misago.messages.middleware.MessagesMiddleware',
     'misago.users.middleware.UserMiddleware',
     'misago.users.middleware.UserMiddleware',
-    'misago.roles.middleware.ACLMiddleware',
+    'misago.acl.middleware.ACLMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.common.CommonMiddleware',
 )
 )
 
 
 # List of application permission providers
 # List of application permission providers
 PERMISSION_PROVIDERS = (
 PERMISSION_PROVIDERS = (
+    'misago.usercp.acl',
     'misago.admin.acl',
     'misago.admin.acl',
 )
 )
 
 

+ 26 - 0
misago/usercp/acl.py

@@ -0,0 +1,26 @@
+from django.utils.translation import ugettext_lazy as _
+from django import forms
+from misago.acl.builder import BaseACL
+from misago.forms import YesNoSwitch
+
+def make_form(request, role, form):
+    form.base_fields['can_use_signature'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
+    form.layout.append((
+                        _("Signature"),
+                        (('can_use_signature', {'label': _("Can have signature")}),),
+                        ))
+
+
+class UserCPACL(BaseACL):
+    def can_use_signature(self):
+        return self.acl['signature']
+
+
+def build(acl, roles):
+    acl.usercp = UserCPACL()
+    acl.usercp.acl['signature'] = False
+    
+    for role in roles:
+        if 'can_use_signature' in role and role['can_use_signature'] > acl.usercp.acl['signature']:
+            acl.usercp.acl['signature'] = role['can_use_signature']
+

+ 24 - 4
misago/users/models.py

@@ -5,13 +5,16 @@ from path import path
 from django.conf import settings
 from django.conf import settings
 from django.contrib.auth.hashers import (
 from django.contrib.auth.hashers import (
     check_password, make_password, is_password_usable, UNUSABLE_PASSWORD)
     check_password, make_password, is_password_usable, UNUSABLE_PASSWORD)
+from django.core.cache import cache, InvalidCacheBackendError
 from django.core.exceptions import ValidationError
 from django.core.exceptions import ValidationError
 from django.core.mail import EmailMultiAlternatives
 from django.core.mail import EmailMultiAlternatives
 from django.db import models
 from django.db import models
 from django.template import RequestContext
 from django.template import RequestContext
 from django.utils import timezone as tz_util
 from django.utils import timezone as tz_util
 from django.utils.translation import ugettext_lazy as _
 from django.utils.translation import ugettext_lazy as _
+from misago.acl.builder import build_acl
 from misago.monitor.monitor import Monitor
 from misago.monitor.monitor import Monitor
+from misago.roles.models import Role
 from misago.settings.settings import Settings as DBSettings
 from misago.settings.settings import Settings as DBSettings
 from misago.users.validators import validate_username, validate_password, validate_email
 from misago.users.validators import validate_username, validate_password, validate_email
 from misago.utils import get_random_string, slugify
 from misago.utils import get_random_string, slugify
@@ -351,6 +354,9 @@ class User(models.Model):
             raw_password = password_reversed
             raw_password = password_reversed
         return check_password(raw_password, self.password, setter)
         return check_password(raw_password, self.password, setter)
     
     
+    def get_roles(self):
+        return self.roles.all()
+        
     def make_acl_key(self):
     def make_acl_key(self):
         roles_ids = []
         roles_ids = []
         for role in self.roles.all():
         for role in self.roles.all():
@@ -358,9 +364,17 @@ class User(models.Model):
         self.acl_key = 'acl_%s' % hashlib.md5('_'.join(roles_ids)).hexdigest()[0:8]
         self.acl_key = 'acl_%s' % hashlib.md5('_'.join(roles_ids)).hexdigest()[0:8]
         return self.acl_key
         return self.acl_key
     
     
-    def get_acl(self):
-        pass
-    
+    def get_acl(self, request):
+        try:
+            acl = cache.get(self.acl_key)
+            if acl.version != request.monitor.acl_version:
+                raise InvalidCacheBackendError()
+        except AttributeError, InvalidCacheBackendError:
+            # build acl cache
+            acl = build_acl(request, self.get_roles())
+            cache.set(self.acl_key, acl, 2592000)
+        return acl
+            
     def get_avatar(self, size='normal'):
     def get_avatar(self, size='normal'):
         # Get uploaded avatar
         # Get uploaded avatar
         if self.avatar_type == 'upload':
         if self.avatar_type == 'upload':
@@ -436,8 +450,14 @@ class Guest(object):
     def is_crawler(self):
     def is_crawler(self):
         return False
         return False
         
         
+    def get_roles(self):
+        return Role.objects.find(token='guest')
+    
+    def make_acl_key(self):
+        return 'acl_%s' % hashlib.md5(Role.objects.get(token='guest').pk).hexdigest()[0:8]
+
         
         
-class Crawler(object): 
+class Crawler(Guest): 
     """
     """
     Misago Crawler dummy
     Misago Crawler dummy
     """
     """