123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- from django import forms
- from django.db import models
- from django.db.models import Q
- from django.utils.translation import ugettext_lazy as _
- from misago.acl.builder import BaseACL
- from misago.acl.utils import ACLError403, ACLError404
- from misago.forms import YesNoSwitch
- def make_forum_form(request, role, form):
- form.base_fields['can_read_threads'] = forms.ChoiceField(choices=(
- ('0', _("No")),
- ('1', _("Yes, owned")),
- ('2', _("Yes, all")),
- ))
- form.base_fields['can_start_threads'] = forms.ChoiceField(choices=(
- ('0', _("No")),
- ('1', _("Yes, with moderation")),
- ('2', _("Yes")),
- ))
- form.base_fields['can_edit_own_threads'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_soft_delete_own_threads'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_write_posts'] = forms.ChoiceField(choices=(
- ('0', _("No")),
- ('1', _("Yes, with moderation")),
- ('2', _("Yes")),
- ))
- form.base_fields['can_edit_own_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_soft_delete_own_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_upvote_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_downvote_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_see_posts_scores'] = forms.ChoiceField(choices=(
- ('0', _("No")),
- ('1', _("Yes, final score")),
- ('2', _("Yes, both up and down-votes")),
- ))
- form.base_fields['can_see_votes'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_make_polls'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_vote_in_polls'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_see_poll_votes'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_see_attachments'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_upload_attachments'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_download_attachments'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['attachment_size'] = forms.IntegerField(min_value=0,initial=100)
- form.base_fields['attachment_limit'] = forms.IntegerField(min_value=0,initial=3)
- form.base_fields['can_approve'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_edit_labels'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_see_changelog'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_pin_threads'] = forms.ChoiceField(choices=(
- ('0', _("No")),
- ('1', _("Yes, to stickies")),
- ('2', _("Yes, to annoucements")),
- ))
- form.base_fields['can_edit_threads_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_move_threads_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_close_threads'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_protect_posts'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
- form.base_fields['can_delete_threads'] = forms.ChoiceField(choices=(
- ('0', _("No")),
- ('1', _("Yes, soft-delete")),
- ('2', _("Yes, hard-delete")),
- ))
- form.base_fields['can_delete_posts'] = forms.ChoiceField(choices=(
- ('0', _("No")),
- ('1', _("Yes, soft-delete")),
- ('2', _("Yes, hard-delete")),
- ))
- form.base_fields['can_delete_polls'] = forms.ChoiceField(choices=(
- ('0', _("No")),
- ('1', _("Yes, soft-delete")),
- ('2', _("Yes, hard-delete")),
- ))
- form.base_fields['can_delete_attachments'] = forms.BooleanField(widget=YesNoSwitch,initial=False,required=False)
-
- form.layout.append((
- _("Threads"),
- (
- ('can_read_threads', {'label': _("Can read threads")}),
- ('can_start_threads', {'label': _("Can start new threads")}),
- ('can_edit_own_threads', {'label': _("Can edit own threads")}),
- ('can_soft_delete_own_threads', {'label': _("Can soft-delete own threads")}),
- ),
- ),)
- form.layout.append((
- _("Posts"),
- (
- ('can_write_posts', {'label': _("Can write posts")}),
- ('can_edit_own_posts', {'label': _("Can edit own posts")}),
- ('can_soft_delete_own_posts', {'label': _("Can soft-delete own posts")}),
- ),
- ),)
- form.layout.append((
- _("Karma"),
- (
- ('can_upvote_posts', {'label': _("Can upvote posts")}),
- ('can_downvote_posts', {'label': _("Can downvote posts")}),
- ('can_see_posts_scores', {'label': _("Can see post score")}),
- ('can_see_votes', {'label': _("Can see who voted on post")}),
- ),
- ),)
- form.layout.append((
- _("Polls"),
- (
- ('can_make_polls', {'label': _("Can make polls")}),
- ('can_vote_in_polls', {'label': _("Can vote in polls")}),
- ('can_see_poll_votes', {'label': _("Can see who voted in poll")}),
- ),
- ),)
- form.layout.append((
- _("Attachments"),
- (
- ('can_see_attachments', {'label': _("Can see attachments")}),
- ('can_upload_attachments', {'label': _("Can upload attachments")}),
- ('can_download_attachments', {'label': _("Can download attachments")}),
- ('attachment_size', {'label': _("Max size of single attachment (in Kb)"), 'help_text': _("Enter zero for no limit.")}),
- ('attachment_limit', {'label': _("Max number of attachments per post"), 'help_text': _("Enter zero for no limit.")}),
- ),
- ),)
- form.layout.append((
- _("Moderation"),
- (
- ('can_approve', {'label': _("Can accept threads and posts")}),
- ('can_edit_labels', {'label': _("Can edit thread labels")}),
- ('can_see_changelog', {'label': _("Can see edits history")}),
- ('can_make_annoucements', {'label': _("Can make annoucements")}),
- ('can_pin_threads', {'label': _("Can change threads weight")}),
- ('can_edit_threads_posts', {'label': _("Can edit threads and posts")}),
- ('can_move_threads_posts', {'label': _("Can move, merge and split threads and posts")}),
- ('can_close_threads', {'label': _("Can close threads")}),
- ('can_protect_posts', {'label': _("Can protect posts"), 'help_text': _("Protected posts cannot be changed by their owners.")}),
- ('can_delete_threads', {'label': _("Can delete threads")}),
- ('can_delete_posts', {'label': _("Can delete posts")}),
- ('can_delete_polls', {'label': _("Can delete polls")}),
- ('can_delete_attachments', {'label': _("Can delete attachments")}),
- ),
- ),)
- class ThreadsACL(BaseACL):
- def get_role(self, forum):
- try:
- try:
- return self.acl[forum.pk]
- except AttributeError:
- return self.acl[forum]
- except KeyError:
- return {}
-
- def allow_thread_view(self, user, thread):
- try:
- forum_role = self.acl[thread.forum_id]
- if forum_role['can_read_threads'] == 0:
- raise ACLError403(_("You don't have permission to read threads in this forum."))
- if forum_role['can_read_threads'] == 1 and thread.weight < 2 and thread.start_poster_id != user.id:
- raise ACLError404()
- if thread.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == thread.start_poster)):
- raise ACLError404()
- if thread.deleted and not forum_role['can_delete_threads']:
- raise ACLError404()
- except KeyError:
- raise ACLError403(_("You don't have permission to read threads in this forum."))
-
- def allow_post_view(self, user, thread, post):
- forum_role = self.acl[thread.forum_id]
- if post.moderated and not (forum_role['can_approve'] or (user.is_authenticated() and user == post.user)):
- raise ACLError404()
- if post.deleted and not (forum_role['can_delete_posts'] or (user.is_authenticated() and user == post.user)):
- raise ACLError404()
-
- def get_readable_forums(self, acl):
- readable = []
- for forum in self.acl:
- if acl.forums.can_browse(forum) and self.acl[forum]['can_read_threads']:
- readable.append(forum)
- return readable
-
- def filter_threads(self, request, forum, queryset):
- try:
- forum_role = self.acl[forum.pk]
- if not forum_role['can_approve']:
- if request.user.is_authenticated():
- queryset = queryset.filter(Q(moderated=0) | Q(start_poster=request.user))
- else:
- queryset = queryset.filter(moderated=0)
- if forum_role['can_read_threads'] == 1:
- queryset = queryset.filter(Q(weight=2) | Q(start_poster_id=request.user.id))
- if not forum_role['can_delete_threads']:
- queryset = queryset.filter(deleted=False)
- except KeyError:
- return False
- return queryset
-
- def filter_posts(self, request, thread, queryset):
- try:
- forum_role = self.acl[thread.forum.pk]
- if not forum_role['can_approve']:
- if request.user.is_authenticated():
- queryset = queryset.filter(Q(moderated=0) | Q(user=request.user))
- else:
- queryset = queryset.filter(moderated=0)
- except KeyError:
- return False
- return queryset
-
- def can_start_threads(self, forum):
- try:
- forum_role = self.acl[forum.pk]
- if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
- return False
- if forum.closed and forum_role['can_close_threads'] == 0:
- return False
- return True
- except KeyError:
- return False
-
- def allow_new_threads(self, forum):
- try:
- forum_role = self.acl[forum.pk]
- if forum_role['can_read_threads'] == 0 or forum_role['can_start_threads'] == 0:
- raise ACLError403(_("You don't have permission to start new threads in this forum."))
- if forum.closed and forum_role['can_close_threads'] == 0:
- raise ACLError403(_("This forum is closed, you can't start new threads in it."))
- except KeyError:
- raise ACLError403(_("You don't have permission to start new threads in this forum."))
-
- def can_edit_thread(self, user, forum, thread, post):
- try:
- forum_role = self.acl[thread.forum_id]
- if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
- return False
- if forum_role['can_edit_threads_posts']:
- return True
- if forum_role['can_edit_own_threads'] and not post.protected and post.user_id == user.pk:
- return True
- return False
- except KeyError:
- return False
-
- def allow_thread_edit(self, user, forum, thread, post):
- try:
- forum_role = self.acl[thread.forum_id]
- self.allow_deleted_post_view(forum)
- if not forum_role['can_close_threads']:
- if forum.closed:
- raise ACLError403(_("You can't edit threads in closed forums."))
- if thread.closed:
- raise ACLError403(_("You can't edit closed threads."))
- if not forum_role['can_edit_threads_posts']:
- if post.user_id != user.pk:
- raise ACLError403(_("You can't edit other members threads."))
- if not forum_role['can_edit_own_threads']:
- raise ACLError403(_("You can't edit your threads."))
- if post.protected:
- raise ACLError403(_("This thread is protected, you cannot edit it."))
- except KeyError:
- raise ACLError403(_("You don't have permission to edit threads in this forum."))
- def can_reply(self, forum, thread):
- try:
- forum_role = self.acl[forum.pk]
- if forum_role['can_write_posts'] == 0:
- return False
- if (forum.closed or thread.closed) and forum_role['can_close_threads'] == 0:
- return False
- return True
- except KeyError:
- return False
- def allow_reply(self, forum, thread):
- try:
- forum_role = self.acl[thread.forum.pk]
- if forum_role['can_write_posts'] == 0:
- raise ACLError403(_("You don't have permission to write replies in this forum."))
- if forum_role['can_close_threads'] == 0:
- if forum.closed:
- raise ACLError403(_("You can't write replies in closed forums."))
- if thread.closed:
- raise ACLError403(_("You can't write replies in closed threads."))
- except KeyError:
- raise ACLError403(_("You don't have permission to write replies in this forum."))
-
- def can_edit_reply(self, user, forum, thread, post):
- try:
- forum_role = self.acl[thread.forum_id]
- if forum_role['can_close_threads'] == 0 and (forum.closed or thread.closed):
- return False
- if forum_role['can_edit_threads_posts']:
- return True
- if forum_role['can_edit_own_posts'] and not post.protected and post.user_id == user.pk:
- return True
- return False
- except KeyError:
- return False
-
- def allow_reply_edit(self, user, forum, thread, post):
- try:
- forum_role = self.acl[thread.forum_id]
- self.allow_deleted_post_view(forum)
- if not forum_role['can_close_threads']:
- if forum.closed:
- raise ACLError403(_("You can't edit replies in closed forums."))
- if thread.closed:
- raise ACLError403(_("You can't edit replies in closed threads."))
- if not forum_role['can_edit_threads_posts']:
- if post.user_id != user.pk:
- raise ACLError403(_("You can't edit other members replies."))
- if not forum_role['can_edit_own_posts']:
- raise ACLError403(_("You can't edit your replies."))
- if post.protected:
- raise ACLError403(_("This reply is protected, you cannot edit it."))
- except KeyError:
- raise ACLError403(_("You don't have permission to edit replies in this forum."))
-
- def can_see_changelog(self, user, forum, post):
- try:
- forum_role = self.acl[forum.pk]
- return forum_role['can_see_changelog'] or user.pk == post.user_id
- except KeyError:
- return False
-
- def allow_changelog_view(self, user, forum, post):
- try:
- forum_role = self.acl[forum.pk]
- self.allow_deleted_post_view(forum)
- if not (forum_role['can_see_changelog'] or user.pk == post.user_id):
- raise ACLError403(_("You don't have permission to see history of changes made to this post."))
- except KeyError:
- raise ACLError403(_("You don't have permission to see history of changes made to this post."))
-
- def can_make_revert(self, forum, thread):
- try:
- forum_role = self.acl[forum.pk]
- if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
- return False
- return forum_role['can_edit_threads_posts']
- except KeyError:
- return False
-
- def allow_revert(self, forum, thread):
- try:
- forum_role = self.acl[forum.pk]
- if not forum_role['can_close_threads']:
- if forum.closed:
- raise ACLError403(_("You can't make reverts in closed forums."))
- if thread.closed:
- raise ACLError403(_("You can't make reverts in closed threads."))
- if not forum_role['can_edit_threads_posts']:
- raise ACLError403(_("You don't have permission to make reverts in this forum."))
- except KeyError:
- raise ACLError403(_("You don't have permission to make reverts in this forum."))
-
- def can_mod_threads(self, forum):
- try:
- forum_role = self.acl[forum.pk]
- return (
- forum_role['can_approve']
- or forum_role['can_pin_threads']
- or forum_role['can_move_threads_posts']
- or forum_role['can_close_threads']
- or forum_role['can_delete_threads']
- )
- except KeyError:
- return False
-
- def can_mod_posts(self, thread):
- try:
- forum_role = self.acl[thread.forum.pk]
- return (
- forum_role['can_edit_threads_posts']
- or forum_role['can_move_threads_posts']
- or forum_role['can_close_threads']
- or forum_role['can_delete_threads']
- or forum_role['can_delete_posts']
- )
- except KeyError:
- return False
-
- def can_approve(self, forum):
- try:
- forum_role = self.acl[forum.pk]
- return forum_role['can_approve']
- except KeyError:
- return False
-
- def can_protect(self, forum):
- try:
- forum_role = self.acl[forum.pk]
- return forum_role['can_protect_posts']
- except KeyError:
- return False
- def can_delete_thread(self, user, forum, thread, post):
- try:
- forum_role = self.acl[forum.pk]
- if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
- return False
- if post.protected and not forum_role['can_protect_posts']:
- return False
- if forum_role['can_delete_threads']:
- return forum_role['can_delete_threads']
- if thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads']:
- return 1
- return False
- except KeyError:
- return False
-
- def allow_delete_thread(self, user, forum, thread, post, delete=False):
- try:
- forum_role = self.acl[forum.pk]
- if not forum_role['can_close_threads']:
- if forum.closed:
- raise ACLError403(_("You don't have permission to delete threads in closed forum."))
- if thread.closed:
- raise ACLError403(_("This thread is closed, you cannot delete it."))
- if post.protected and not forum_role['can_protect_posts']:
- raise ACLError403(_("This post is protected, you cannot delete it."))
- if delete and forum_role['can_delete_threads'] < 2:
- raise ACLError403(_("You cannot hard delete this thread."))
- if not (forum_role['can_delete_threads'] or (thread.start_poster_id == user.pk and forum_role['can_soft_delete_own_threads'])):
- raise ACLError403(_("You don't have permission to delete this thread."))
- if thread.deleted and not delete:
- raise ACLError403(_("This thread is already deleted."))
- except KeyError:
- raise ACLError403(_("You don't have permission to delete this thread."))
- def can_delete_post(self, user, forum, thread, post):
- try:
- forum_role = self.acl[forum.pk]
- if not forum_role['can_close_threads'] and (forum.closed or thread.closed):
- return False
- if post.protected and not forum_role['can_protect_posts']:
- return False
- if forum_role['can_delete_posts']:
- return forum_role['can_delete_posts']
- if post.user_id == user.pk and not post.protected and forum_role['can_soft_delete_own_posts']:
- return 1
- return False
- except KeyError:
- return False
- def allow_delete_post(self, user, forum, thread, post, delete=False):
- try:
- forum_role = self.acl[forum.pk]
- if not forum_role['can_close_threads']:
- if forum.closed:
- raise ACLError403(_("You don't have permission to delete posts in closed forum."))
- if thread.closed:
- raise ACLError403(_("This thread is closed, you cannot delete its posts."))
- if post.protected and not forum_role['can_protect_posts']:
- raise ACLError403(_("This post is protected, you cannot delete it."))
- if delete and forum_role['can_delete_posts'] < 2:
- raise ACLError403(_("You cannot hard delete this post."))
- if not (forum_role['can_delete_posts'] or (post.user_id == user.pk and forum_role['can_soft_delete_own_posts'])):
- raise ACLError403(_("You don't have permission to delete this post."))
- if post.deleted and not delete:
- raise ACLError403(_("This post is already deleted."))
- except KeyError:
- raise ACLError403(_("You don't have permission to delete this post."))
-
- def can_see_deleted_threads(self, forum):
- try:
- forum_role = self.acl[forum.pk]
- return forum_role['can_delete_threads']
- except KeyError:
- raise false
-
- def can_see_deleted_posts(self, forum):
- try:
- forum_role = self.acl[forum.pk]
- return forum_role['can_delete_posts']
- except KeyError:
- raise false
-
- def allow_deleted_post_view(self, forum):
- try:
- forum_role = self.acl[forum.pk]
- if not forum_role['can_delete_posts']:
- raise ACLError404()
- except KeyError:
- raise ACLError404()
- def build_forums(acl, perms, forums, forum_roles):
- acl.threads = ThreadsACL()
- for forum in forums:
- forum_role = {
- 'can_read_threads': 0,
- 'can_start_threads': 0,
- 'can_edit_own_threads': False,
- 'can_soft_delete_own_threads': False,
- 'can_write_posts': 0,
- 'can_edit_own_posts': False,
- 'can_soft_delete_own_posts': False,
- 'can_upvote_posts': False,
- 'can_downvote_posts': False,
- 'can_see_posts_scores': 0,
- 'can_see_votes': False,
- 'can_make_polls': False,
- 'can_vote_in_polls': False,
- 'can_see_poll_votes': False,
- 'can_see_attachments': False,
- 'can_upload_attachments': False,
- 'can_download_attachments': False,
- 'attachment_size': 100,
- 'attachment_limit': 3,
- 'can_approve': False,
- 'can_edit_labels': False,
- 'can_see_changelog': False,
- 'can_make_annoucements': False,
- 'can_pin_threads': 0,
- 'can_edit_threads_posts': False,
- 'can_move_threads_posts': False,
- 'can_close_threads': False,
- 'can_protect_posts': False,
- 'can_delete_threads': 0,
- 'can_delete_posts': 0,
- 'can_delete_polls': 0,
- 'can_delete_attachments': False,
- }
- for perm in perms:
- try:
- role = forum_roles[perm['forums'][forum.pk]]
- for p in forum_role:
- try:
- if p in ['attachment_size', 'attachment_limit'] and role[p] == 0:
- forum_role[p] = 0
- elif int(role[p]) > forum_role[p]:
- forum_role[p] = int(role[p])
- except KeyError:
- pass
- except KeyError:
- pass
- acl.threads.acl[forum.pk] = forum_role
-
|