Browse Source

Refactored ACP's Permissions section

Ralfp 12 years ago
parent
commit
3ea7448559

+ 0 - 0
misago/core/admin/forumroles/__init__.py


+ 20 - 0
misago/core/admin/forumroles/forms.py

@@ -0,0 +1,20 @@
+from django.utils.translation import ugettext_lazy as _
+from django import forms
+from misago.forms import Form
+from misago.validators import validate_sluggable
+
+class ForumRoleForm(Form):
+    name = forms.CharField(max_length=255, validators=[validate_sluggable(
+                                                                         _("Role name must be sluggable."),
+                                                                         _("Role name is too long.")
+                                                                         )])
+
+    def finalize_form(self):
+        self.layout = (
+                       (
+                        _("Basic Role Options"),
+                        (
+                         ('name', {'label': _("Role Name"), 'help_text': _("Role Name is used to identify this role in Admin Control Panel.")}),
+                         ),
+                        ),
+                       )

+ 144 - 0
misago/core/admin/forumroles/views.py

@@ -0,0 +1,144 @@
+import copy
+from django.core.urlresolvers import reverse as django_reverse
+from django.utils.translation import ugettext as _
+from misago.acl.builder import build_forum_form
+from misago.admin import site
+from misago.core.admin.widgets import *
+from misago.forms import Form, YesNoSwitch
+from misago.models import ForumRole
+from misago.utils.strings import slugify
+from misago.core.admin.forumroles.forms import ForumRoleForm
+
+def reverse(route, target=None):
+    if target:
+        return django_reverse(route, kwargs={'target': target.pk, 'slug': slugify(target.name)})
+    return django_reverse(route)
+
+
+"""
+Views
+"""
+class List(ListWidget):
+    admin = site.get_action('roles_forums')
+    id = 'list'
+    columns = (
+               ('role', _("Role")),
+               )
+    nothing_checked_message = _('You have to check at least one role.')
+    actions = (
+               ('delete', _("Delete selected forum roles"), _("Are you sure you want to delete selected roles?")),
+               )
+
+    def sort_items(self, page_items, sorting_method):
+        return page_items.order_by('name')
+
+    def get_item_actions(self, item):
+        return (
+                self.action('adjust', _("Role Permissions"), reverse('admin_roles_forums_acl', item)),
+                self.action('pencil', _("Edit Role"), reverse('admin_roles_forums_edit', item)),
+                self.action('remove', _("Delete Role"), reverse('admin_roles_forums_delete', item), post=True, prompt=_("Are you sure you want to delete this role?")),
+                )
+
+    def action_delete(self, items, checked):
+        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
+        Role.objects.filter(id__in=checked).delete()
+        return Message(_('Selected forum roles have been deleted successfully.'), 'success'), reverse('admin_roles_forums')
+
+
+class New(FormWidget):
+    admin = site.get_action('roles_forums')
+    id = 'new'
+    fallback = 'admin_roles_forums'
+    form = ForumRoleForm
+    submit_button = _("Save Role")
+
+    def get_new_url(self, model):
+        return reverse('admin_roles_forums_new')
+
+    def get_edit_url(self, model):
+        return reverse('admin_roles_forums_edit', model)
+
+    def submit_form(self, form, target):
+        new_role = ForumRole(
+                      name=form.cleaned_data['name'],
+                     )
+        new_role.save(force_insert=True)
+        return new_role, Message(_('New Forum Role has been created.'), 'success')
+
+
+class Edit(FormWidget):
+    admin = site.get_action('roles_forums')
+    id = 'edit'
+    name = _("Edit Forum Role")
+    fallback = 'admin_roles_forums'
+    form = ForumRoleForm
+    target_name = 'name'
+    notfound_message = _('Requested Forum Role could not be found.')
+    submit_fallback = True
+
+    def get_url(self, model):
+        return reverse('admin_roles_forums_edit', model)
+
+    def get_edit_url(self, model):
+        return self.get_url(model)
+
+    def get_initial_data(self, model):
+        return {
+                'name': model.name,
+                }
+
+    def submit_form(self, form, target):
+        target.name = form.cleaned_data['name']
+        target.save(force_update=True)
+        return target, Message(_('Changes in forum role "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
+
+
+class ACL(FormWidget):
+    admin = site.get_action('roles_forums')
+    id = 'acl'
+    name = _("Change Forum Role Permissions")
+    fallback = 'admin_roles_forums'
+    target_name = 'name'
+    notfound_message = _('Requested Forum Role could not be found.')
+    submit_fallback = True
+    template = 'acl_form'
+
+    def get_form(self, target):
+        self.form = build_forum_form(self.request, target)
+        return self.form
+
+    def get_url(self, model):
+        return reverse('admin_roles_forums_acl', model)
+
+    def get_edit_url(self, model):
+        return self.get_url(model)
+
+    def get_initial_data(self, model):
+        raw_acl = model.permissions
+        initial = {}
+        for field in self.form.base_fields:
+            if field in raw_acl:
+                initial[field] = raw_acl[field]
+        return initial
+
+    def submit_form(self, form, target):
+        raw_acl = target.permissions
+        for perm in form.cleaned_data:
+            raw_acl[perm] = form.cleaned_data[perm]
+        target.permissions = raw_acl
+        target.save(force_update=True)
+        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
+
+        return target, Message(_('Forum Role "%(name)s" permissions have been changed.') % {'name': self.original_name}, 'success')
+
+
+class Delete(ButtonWidget):
+    admin = site.get_action('roles_forums')
+    id = 'delete'
+    fallback = 'admin_roles_forums'
+    notfound_message = _('Requested Forum Role could not be found.')
+
+    def action(self, target):
+        target.delete()
+        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
+        return Message(_('Forum Role "%(name)s" has been deleted.') % {'name': _(target.name)}, 'success'), False

+ 0 - 0
misago/core/admin/roles/__init__.py


+ 26 - 0
misago/core/admin/roles/forms.py

@@ -0,0 +1,26 @@
+from django.utils.translation import ugettext_lazy as _
+from django import forms
+from misago.forms import Form, YesNoSwitch
+from misago.validators import validate_sluggable
+
+class RoleForm(Form):
+    name = forms.CharField(max_length=255,validators=[validate_sluggable(
+                                                                         _("Role name must be sluggable."),
+                                                                         _("Role name is too long.")
+                                                                         )])
+    protected = forms.BooleanField(widget=YesNoSwitch,required=False)
+    
+    def finalize_form(self):
+        self.layout = [
+                       [
+                        _("Basic Role Options"),
+                        [
+                         ('name', {'label': _("Role Name"), 'help_text': _("Role Name is used to identify this role in Admin Control Panel.")}),
+                         ('protected', {'label': _("Protect this Role"), 'help_text': _("Only system administrators can edit or assign protected roles.")}),
+                         ],
+                        ],
+                       ]
+        
+        if not self.request.user.is_god():
+            del self.fields['protected']
+            del self.layout[0][1][1]

+ 260 - 0
misago/core/admin/roles/views.py

@@ -0,0 +1,260 @@
+import copy
+from django.core.urlresolvers import reverse as django_reverse
+from django.shortcuts import redirect
+from django.utils.translation import ugettext as _
+from misago.acl.builder import build_form 
+from misago.admin import site
+from misago.core.admin.widgets import *
+from misago.forms import Form, YesNoSwitch
+from misago.models import Forum, ForumRole, Role
+from misago.utils.strings import slugify
+from misago.core.admin.roles.forms import RoleForm
+
+def reverse(route, target=None):
+    if target:
+        return django_reverse(route, kwargs={'target': target.pk, 'slug': slugify(target.name)})
+    return django_reverse(route)
+
+
+"""
+Views
+"""
+class List(ListWidget):
+    admin = site.get_action('roles')
+    id = 'list'
+    columns=(
+             ('role', _("Role")),
+             )
+    nothing_checked_message = _('You have to check at least one role.')
+    actions=(
+             ('delete', _("Delete selected roles"), _("Are you sure you want to delete selected roles?")),
+             )
+    
+    def sort_items(self, page_items, sorting_method):
+        return page_items.order_by('name')
+    
+    def get_item_actions(self, item):
+        return (
+                self.action('list', _("Forums Permissions"), reverse('admin_roles_masks', item)),
+                self.action('adjust', _("Role Permissions"), reverse('admin_roles_acl', item)),
+                self.action('pencil', _("Edit Role"), reverse('admin_roles_edit', item)),
+                self.action('remove', _("Delete Role"), reverse('admin_roles_delete', item), post=True, prompt=_("Are you sure you want to delete this role?")),
+                )
+
+    def action_delete(self, items, checked):
+        for item in items:
+            if unicode(item.pk) in checked:
+                if item.token:
+                    return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
+                if item.protected and not self.request.user.is_god():
+                    return Message(_('You cannot delete protected roles.'), 'error'), reverse('admin_roles')
+                if item.user_set.count() > 0:
+                    return Message(_('You cannot delete roles that are assigned to users.'), 'error'), reverse('admin_roles')
+        
+        Role.objects.filter(id__in=checked).delete()
+        return Message(_('Selected roles have been deleted successfully.'), 'success'), reverse('admin_roles')
+
+
+class New(FormWidget):
+    admin = site.get_action('roles')
+    id = 'new'
+    fallback = 'admin_roles' 
+    form = RoleForm
+    submit_button = _("Save Role")
+        
+    def get_new_url(self, model):
+        return reverse('admin_roles_new')
+    
+    def get_edit_url(self, model):
+        return reverse('admin_roles_edit', model)
+    
+    def submit_form(self, form, target):
+        new_role = Role(
+                      name = form.cleaned_data['name'],
+                     )
+        new_role.save(force_insert=True)
+        return new_role, Message(_('New Role has been created.'), 'success')    
+    
+   
+class Edit(FormWidget):
+    admin = site.get_action('roles')
+    id = 'edit'
+    name = _("Edit Role")
+    fallback = 'admin_roles'
+    form = RoleForm
+    target_name = 'name'
+    translate_target_name = True
+    notfound_message = _('Requested Role could not be found.')
+    submit_fallback = True
+    
+    def get_url(self, model):
+        return reverse('admin_roles_edit', model)
+    
+    def get_edit_url(self, model):
+        return self.get_url(model)
+    
+    def get_initial_data(self, model):
+        if self.request.user.is_god():
+            return {'name': model.name, 'protected': model.protected}
+        return {'name': model.name}
+    
+    def get_and_validate_target(self, target):
+        result = super(Edit, self).get_and_validate_target(target)
+        if result and result.protected and not self.request.user.is_god():
+            self.request.messages.set_flash(Message(_('Role "%(name)s" is protected, you cannot edit it.') % {'name': _(result.name)}), 'error', self.admin.id)
+            return None
+        return result
+    
+    def submit_form(self, form, target):
+        target.name = form.cleaned_data['name']
+        if self.request.user.is_god():
+            target.protected = form.cleaned_data['protected']
+        target.save(force_update=True)
+        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
+        return target, Message(_('Changes in role "%(name)s" have been saved.') % {'name': self.original_name}, 'success')
+
+
+class Forums(ListWidget):
+    admin = site.get_action('roles')
+    id = 'forums'
+    hide_actions = True
+    name = _('Role Forums Permissions')
+    table_form_button = _('Change Permissions')
+    empty_message = _('No forums are currently defined.')
+    template = 'forums'
+    
+    def get_url(self):
+        return reverse('admin_roles_masks', self.role) 
+    
+    def get_items(self):
+        return Forum.objects.get(token='root').get_descendants()
+    
+    def sort_items(self, page_items, sorting_method):
+        final_items = []
+        for forum in Forum.objects.filter(token__in=['annoucements', 'reports', 'private']).order_by('token'):
+            if forum.token == 'annoucements':
+                forum.name = _("Global Annoucements")
+            if forum.token == 'reports':
+                forum.name = _("Reports")
+            if forum.token == 'private':
+                forum.name = _("Private Discussions")
+            final_items.append(forum)
+        for forum in page_items.order_by('lft').all():
+            final_items.append(forum)
+        return final_items
+
+    def add_template_variables(self, variables):
+        variables['target'] = _(self.role.name)
+        return variables
+    
+    def get_table_form(self, page_items):
+        perms = {}
+        try:
+            forums = self.role.permissions['forums']
+            for fid in forums:
+               perms[str(fid)] = str(forums[fid])
+        except KeyError:
+            pass
+        
+        perms_form = {}
+        roles_select = [("0", _("No Access"))]
+        for role in self.roles:
+            roles_select.append((str(role.pk), _(role.name)))
+
+        for item in page_items:
+            perms_form['forum_' + str(item.pk)] = forms.ChoiceField(choices=roles_select,initial=(perms[str(item.pk)] if str(item.pk) in perms else "0"))
+        
+        # Turn dict into object
+        return type('ChangeForumRolesForm', (Form,), perms_form)
+    
+    def table_action(self, page_items, cleaned_data):
+        perms = {}
+        for item in page_items:
+            if cleaned_data['forum_' + str(item.pk)] != "0":
+                perms[item.pk] = long(cleaned_data['forum_' + str(item.pk)])
+        role_perms = self.role.permissions
+        role_perms['forums'] = perms
+        self.role.permissions = role_perms
+        self.role.save(force_update=True)
+        return Message(_('Forum permissions have been saved.'), 'success'), self.get_url()
+        
+    def __call__(self, request, slug, target):
+        self.request = request
+        try:
+            self.role = Role.objects.get(id=target)
+            if self.role and self.role.protected and not request.user.is_god():
+                request.messages.set_flash(Message(_('Role "%(name)s" is protected, you cannot edit it.') % {'name': _(self.role.name)}), 'error', self.admin.id)
+                return redirect(reverse('admin_roles'))
+        except Role.DoesNotExist:
+            request.messages.set_flash(Message(_('Requested Role could not be found.')), 'error', self.admin.id)
+            return redirect(reverse('admin_roles'))
+        self.roles = ForumRole.objects.order_by('name').all()
+        if not self.roles:
+            request.messages.set_flash(Message(_('No forum roles are currently set.')), 'error', self.admin.id)
+            return redirect(reverse('admin_roles'))
+        return super(Forums, self).__call__(request)
+
+
+class ACL(FormWidget):
+    admin = site.get_action('roles')
+    id = 'acl'
+    name = _("Change Role Permissions")
+    fallback = 'admin_roles'
+    target_name = 'name'
+    translate_target_name = True
+    notfound_message = _('Requested Role could not be found.')
+    submit_fallback = True
+    template = 'acl_form'
+    
+    def get_form(self, target):
+        self.form = build_form(self.request, target)
+        return self.form
+    
+    def get_url(self, model):
+        return reverse('admin_roles_acl', model)
+    
+    def get_edit_url(self, model):
+        return self.get_url(model)
+    
+    def get_initial_data(self, model):
+        raw_acl = model.permissions
+        initial = {}
+        for field in self.form.base_fields:
+            if field in raw_acl:
+                initial[field] = raw_acl[field]
+        return initial
+    
+    def get_and_validate_target(self, target):
+        result = super(ACL, self).get_and_validate_target(target)
+        if result and result.protected and not self.request.user.is_god():
+            self.request.messages.set_flash(Message(_('Role "%(name)s" is protected, you cannot edit it.') % {'name': _(result.name)}), 'error', self.admin.id)
+            return None
+        return result
+    
+    def submit_form(self, form, target):
+        raw_acl = target.permissions
+        for perm in form.cleaned_data:
+            raw_acl[perm] = form.cleaned_data[perm]
+        target.permissions = raw_acl
+        target.save(force_update=True)
+        self.request.monitor['acl_version'] = int(self.request.monitor['acl_version']) + 1
+        
+        return target, Message(_('Role "%(name)s" permissions have been changed.') % {'name': self.original_name}, 'success')
+
+
+class Delete(ButtonWidget):
+    admin = site.get_action('roles')
+    id = 'delete'
+    fallback = 'admin_roles'
+    notfound_message = _('Requested Role could not be found.')
+    
+    def action(self, target):
+        if target.token:
+            return Message(_('You cannot delete system roles.'), 'error'), reverse('admin_roles')
+        if target.protected and not self.request.user.is_god():
+            return Message(_('This role is protected.'), 'error'), reverse('admin_roles')
+        if target.user_set.count() > 0:
+            return Message(_('This role is assigned to one or more users.'), 'error'), reverse('admin_roles')
+
+        target.delete()
+        return Message(_('Role "%(name)s" has been deleted.') % {'name': _(target.name)}, 'success'), False

+ 5 - 5
misago/core/admin/sections/__init__.py

@@ -8,6 +8,11 @@ ADMIN_SECTIONS = (
                  icon='signal',
                  ),
     AdminSection(
+                 id='perms',
+                 name=_("Permissions"),
+                 icon='adjust',
+                 ),
+    AdminSection(
                  id='system',
                  name=_("System"),
                  icon='cog',
@@ -25,9 +30,4 @@ ADMIN_SECTIONS = (
                  name=_("Forums"),
                  icon='comment',
                  ),
-    AdminSection(
-                 id='perms',
-                 name=_("Permissions"),
-                 icon='adjust',
-                 ),
 """

+ 2 - 3
misago/core/admin/sections/perms.py

@@ -3,7 +3,6 @@ from django.utils.translation import ugettext_lazy as _
 from misago.admin import AdminAction
 from misago.models import ForumRole, Role
 
-
 ADMIN_ACTIONS = (
    AdminAction(
                section='perms',
@@ -27,7 +26,7 @@ ADMIN_ACTIONS = (
                          },
                         ],
                route='admin_roles',
-               urlpatterns=patterns('misago.roles.views',
+               urlpatterns=patterns('misago.core.admin.roles.views',
                         url(r'^$', 'List', name='admin_roles'),
                         url(r'^new/$', 'New', name='admin_roles_new'),
                         url(r'^forums/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'Forums', name='admin_roles_masks'),
@@ -58,7 +57,7 @@ ADMIN_ACTIONS = (
                          },
                         ],
                route='admin_roles_forums',
-               urlpatterns=patterns('misago.forumroles.views',
+               urlpatterns=patterns('misago.core.admin.forumroles.views',
                         url(r'^$', 'List', name='admin_roles_forums'),
                         url(r'^new/$', 'New', name='admin_roles_forums_new'),
                         url(r'^acl/(?P<slug>([a-z0-9]|-)+)-(?P<target>\d+)/$', 'ACL', name='admin_roles_forums_acl'),