Commit 1b690611 by benjaoming

Permissions in settings tab can be applied recursively and owner can be changed.

parent 85c58dc5
Not implemented - will be ASAP Not implemented - will be ASAP
============================== ==============================
* Permission system in settings tab **Almost done** (option to apply changes recursively and to change owner if user has a grant permission)
* Notification system **Almost done** (email notifications) * Notification system **Almost done** (email notifications)
* Image plugin **In progress**
* Circuit Editor plugin * Circuit Editor plugin
* Custom storage engine for attachments * Custom storage engine for attachments
* Implement notifications, revision log messages and user messages thoroughly * Implement notifications, revision log messages and user messages thoroughly
...@@ -19,8 +17,10 @@ Not implemented - will be ASAP ...@@ -19,8 +17,10 @@ Not implemented - will be ASAP
* Embeddable article template tag * Embeddable article template tag
* Expand prepopulated database * Expand prepopulated database
* "Fix Wiki URL bug in the footnotes plugin for python-markdown" ? * "Fix Wiki URL bug in the footnotes plugin for python-markdown" ?
* Permission system in settings tab **Done**
* Special view for deleted articles w/ restore button **Done** * Special view for deleted articles w/ restore button **Done**
* Article deletion **Done** * Article deletion **Done**
* Image plugin **Done**
* Attachment plugin **Done** * Attachment plugin **Done**
* Simple user account handling: login/register etc. **Done** * Simple user account handling: login/register etc. **Done**
* South migrations **Done** * South migrations **Done**
......
...@@ -13,6 +13,7 @@ from wiki.editors import getEditor ...@@ -13,6 +13,7 @@ from wiki.editors import getEditor
from wiki.core.diff import simple_merge from wiki.core.diff import simple_merge
from django.forms.widgets import HiddenInput from django.forms.widgets import HiddenInput
from wiki.core.plugins.base import PluginSettingsFormMixin from wiki.core.plugins.base import PluginSettingsFormMixin
from django.contrib.auth.models import User
class CreateRootForm(forms.Form): class CreateRootForm(forms.Form):
...@@ -231,12 +232,17 @@ class PermissionsForm(PluginSettingsFormMixin, forms.ModelForm): ...@@ -231,12 +232,17 @@ class PermissionsForm(PluginSettingsFormMixin, forms.ModelForm):
settings_order = 5 settings_order = 5
settings_write_access = False settings_write_access = False
owner_username = forms.CharField(required=False, label=_(u'Owner'),
help_text=_(u'Enter the username of the owner.'))
group = forms.ModelChoiceField(models.Group.objects.all(), widget=SelectWidgetBootstrap(), group = forms.ModelChoiceField(models.Group.objects.all(), widget=SelectWidgetBootstrap(),
empty_label=_(u'(none)'), required=False) empty_label=_(u'(none)'), required=False)
recursive = forms.BooleanField(label=_(u'Inherit permissions'), help_text=_(u'Check here to apply the above permissions recursively to articles under this one.'),
required=False)
def get_usermessage(self): def get_usermessage(self):
if self.changed_data: if self.changed_data:
return _('Your permission settings were updated.') return _('Permission settings for the article were updated.')
else: else:
return _('Your permission settings were unchanged, so nothing saved.') return _('Your permission settings were unchanged, so nothing saved.')
...@@ -245,12 +251,54 @@ class PermissionsForm(PluginSettingsFormMixin, forms.ModelForm): ...@@ -245,12 +251,54 @@ class PermissionsForm(PluginSettingsFormMixin, forms.ModelForm):
self.user = user self.user = user
kwargs['instance'] = article kwargs['instance'] = article
super(PermissionsForm, self).__init__(*args, **kwargs) super(PermissionsForm, self).__init__(*args, **kwargs)
if user.has_perm("wiki.admin"): self.can_change_groups = True
self.can_assign = False
if user.has_perm("wiki.assign"):
self.can_assign = True
self.fields['group'].queryset = models.Group.objects.all() self.fields['group'].queryset = models.Group.objects.all()
else: else:
self.fields['group'].queryset = models.Group.objects.filter(user=user) self.fields['owner_username'].widget = forms.HiddenInput()
self.fields['recursive'].widget = forms.HiddenInput()
groups = models.Group.objects.filter(user=user)
self.fields['group'].queryset = groups
# Sanity: If somehow the article belongs to a group that the
# owner is not a member of, don't let the owner make any decisions
# for group permissions.
if article.group and not user in article.group.user_set.all():
self.can_change_groups = False
self.fields['group'].widget = forms.HiddenInput()
self.fields['group_read'].widget = forms.HiddenInput()
self.fields['group_write'].widget = forms.HiddenInput()
self.fields['owner_username'].initial = article.owner.username if article.owner else ""
def clean_owner_username(self):
if self.can_assign:
username = self.cleaned_data['owner_username']
if username:
try:
user = User.objects.get(username=username)
except models.User.DoesNotExist:
raise forms.ValidationError(_(u'No user with that username'))
else:
user = None
else:
user = self.article.owner
return user
def save(self, commit=True):
article = super(PermissionsForm, self).save(commit=False)
article.owner = self.cleaned_data['owner_username']
if not self.can_change_groups:
article.group = self.article.group
article.group_read = self.article.group_read
article.group_write = self.article.group_write
if self.can_assign and self.cleaned_data['recursive']:
article.set_permissions_recursive()
article.save()
class Meta: class Meta:
model = models.Article model = models.Article
fields = ('group', 'group_read', 'group_write', 'other_read', 'other_write') fields = ('owner_username', 'group', 'group_read', 'group_write', 'other_read', 'other_write',
'recursive')
...@@ -69,11 +69,11 @@ class Article(models.Model): ...@@ -69,11 +69,11 @@ class Article(models.Model):
return True return True
return False return False
def decendant_objects(self): def descendant_objects(self):
"""NB! This generator is expensive, so use it with care!!""" """NB! This generator is expensive, so use it with care!!"""
for obj in self.articleforobject_set.filter(is_mptt=True): for obj in self.articleforobject_set.filter(is_mptt=True):
for decendant in obj.content_object.get_decendants(): for descendant in obj.content_object.get_descendants():
yield decendant yield descendant
def get_children(self, max_num=None, **kwargs): def get_children(self, max_num=None, **kwargs):
"""NB! This generator is expensive, so use it with care!!""" """NB! This generator is expensive, so use it with care!!"""
...@@ -84,25 +84,28 @@ class Article(models.Model): ...@@ -84,25 +84,28 @@ class Article(models.Model):
if max_num and cnt > max_num: return if max_num and cnt > max_num: return
yield child yield child
# All recursive permission methods will use decendant_objects to access # All recursive permission methods will use descendant_objects to access
# generic relations and check if they are using MPTT and have INHERIT_PERMISSIONS=True # generic relations and check if they are using MPTT and have INHERIT_PERMISSIONS=True
def set_permissions_recursive(self): def set_permissions_recursive(self):
for decendant in self.decendant_objects(): for descendant in self.descendant_objects():
if decendant.INHERIT_PERMISSIONS: if descendant.INHERIT_PERMISSIONS:
decendant.group_read = self.group_read descendant.group_read = self.group_read
decendant.group_write = self.group_write descendant.group_write = self.group_write
decendant.other_read = self.other_read descendant.other_read = self.other_read
decendant.other_write = self.other_write descendant.other_write = self.other_write
descendant.save()
def set_group_recursive(self): def set_group_recursive(self):
for decendant in self.decendant_objects(): for descendant in self.descendant_objects():
if decendant.INHERIT_PERMISSIONS: if descendant.INHERIT_PERMISSIONS:
decendant.group = self.group descendant.group = self.group
descendant.save()
def set_owner_recursive(self): def set_owner_recursive(self):
for decendant in self.decendant_objects(): for descendant in self.descendant_objects():
if decendant.INHERIT_PERMISSIONS: if descendant.INHERIT_PERMISSIONS:
decendant.owner = self.owner descendant.owner = self.owner
descendant.save()
def add_revision(self, new_revision, save=True): def add_revision(self, new_revision, save=True):
""" """
......
...@@ -35,7 +35,8 @@ class ImagePreprocessor(markdown.preprocessors.Preprocessor): ...@@ -35,7 +35,8 @@ class ImagePreprocessor(markdown.preprocessors.Preprocessor):
alignment = m.group('align').strip() alignment = m.group('align').strip()
try: try:
image = models.Image.objects.get(article=self.markdown.article, image = models.Image.objects.get(article=self.markdown.article,
id=image_id) id=image_id,
current_revision__deleted=False)
except models.Image.DoesNotExist: except models.Image.DoesNotExist:
pass pass
line = line.replace(m.group(1), "") line = line.replace(m.group(1), "")
......
{% load thumbnail %} {% load thumbnail i18n %}
{% comment %} {% comment %}
This template is used for the markdown extension that renders images and captions This template is used for the markdown extension that renders images and captions
{% endcomment %} {% endcomment %}
...@@ -9,10 +9,14 @@ ...@@ -9,10 +9,14 @@
<a href="{{ revision.image.url }}"> <a href="{{ revision.image.url }}">
<img src="{{ thumb.url }}" alt="{{ revision.get_filename }}" /> <img src="{{ thumb.url }}" alt="{{ revision.get_filename }}" />
</a> </a>
{% empty %}
<div class="caption"> <div class="caption">
{{ caption|safe }} <em>{% trans "Image not found" %}</em>
</div> </div>
{% endthumbnail %} {% endthumbnail %}
<div class="caption">
{{ caption|safe }}
</div>
</div> </div>
</div> </div>
{% endwith %} {% endwith %}
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
{% if not preview %} {% if not preview %}
{% if article.current_revision %} {% if article.current_revision %}
{% cache 1 article article.current_revision.id %} {% cache 6000 article article.current_revision.id %}
{{ article.render }} {{ article.render }}
{% endcache %} {% endcache %}
{% endif %} {% endif %}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment