123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- from django import forms
- from django.core.exceptions import PermissionDenied
- from django.utils import timezone
- from django.utils.translation import gettext_lazy as _
- from django.utils.translation import ngettext
- from misago.acl import algebra
- from misago.acl.decorators import return_boolean
- from misago.acl.models import Role
- from misago.admin.forms import YesNoSwitch
- from misago.threads.models import Poll, Thread
- __all__ = [
- 'allow_start_poll',
- 'can_start_poll',
- 'allow_edit_poll',
- 'can_edit_poll',
- 'allow_delete_poll',
- 'can_delete_poll',
- 'allow_vote_poll',
- 'can_vote_poll',
- 'allow_see_poll_votes',
- 'can_see_poll_votes',
- ]
- class RolePermissionsForm(forms.Form):
- legend = _("Polls")
- can_start_polls = forms.TypedChoiceField(
- label=_("Can start polls"),
- coerce=int,
- initial=0,
- choices=[
- (0, _("No")),
- (1, _("Own threads")),
- (2, _("All threads")),
- ],
- )
- can_edit_polls = forms.TypedChoiceField(
- label=_("Can edit polls"),
- coerce=int,
- initial=0,
- choices=[
- (0, _("No")),
- (1, _("Own polls")),
- (2, _("All polls")),
- ],
- )
- can_delete_polls = forms.TypedChoiceField(
- label=_("Can delete polls"),
- coerce=int,
- initial=0,
- choices=[
- (0, _("No")),
- (1, _("Own polls")),
- (2, _("All polls")),
- ],
- )
- poll_edit_time = forms.IntegerField(
- label=_("Time limit for own polls edits, in minutes"),
- help_text=_("Enter 0 to don't limit time for editing own polls."),
- initial=0,
- min_value=0,
- )
- can_always_see_poll_voters = YesNoSwitch(
- label=_("Can always see polls voters"),
- help_text=_("Allows users to see who voted in poll even if poll votes are secret."),
- )
- def change_permissions_form(role):
- if isinstance(role, Role) and role.special_role != 'anonymous':
- return RolePermissionsForm
- else:
- return None
- def build_acl(acl, roles, key_name):
- acl.update({
- 'can_start_polls': 0,
- 'can_edit_polls': 0,
- 'can_delete_polls': 0,
- 'poll_edit_time': 0,
- 'can_always_see_poll_voters': 0,
- })
- return algebra.sum_acls(
- acl,
- roles=roles,
- key=key_name,
- can_start_polls=algebra.greater,
- can_edit_polls=algebra.greater,
- can_delete_polls=algebra.greater,
- poll_edit_time=algebra.greater_or_zero,
- can_always_see_poll_voters=algebra.greater
- )
- def add_acl_to_poll(user, poll):
- poll.acl.update({
- 'can_vote': can_vote_poll(user, poll),
- 'can_edit': can_edit_poll(user, poll),
- 'can_delete': can_delete_poll(user, poll),
- 'can_see_votes': can_see_poll_votes(user, poll),
- })
- def add_acl_to_thread(user, thread):
- thread.acl.update({
- 'can_start_poll': can_start_poll(user, thread),
- })
- def register_with(registry):
- registry.acl_annotator(Poll, add_acl_to_poll)
- registry.acl_annotator(Thread, add_acl_to_thread)
- def allow_start_poll(user, target):
- if user.is_anonymous:
- raise PermissionDenied(_("You have to sign in to start polls."))
- category_acl = user.acl_cache['categories'].get(
- target.category_id, {
- 'can_close_threads': False,
- }
- )
- if not user.acl_cache.get('can_start_polls'):
- raise PermissionDenied(_("You can't start polls."))
- if user.acl_cache.get('can_start_polls') < 2 and user.pk != target.starter_id:
- raise PermissionDenied(_("You can't start polls in other users threads."))
- if not category_acl.get('can_close_threads'):
- if target.category.is_closed:
- raise PermissionDenied(_("This category is closed. You can't start polls in it."))
- if target.is_closed:
- raise PermissionDenied(_("This thread is closed. You can't start polls in it."))
- can_start_poll = return_boolean(allow_start_poll)
- def allow_edit_poll(user, target):
- if user.is_anonymous:
- raise PermissionDenied(_("You have to sign in to edit polls."))
- category_acl = user.acl_cache['categories'].get(
- target.category_id, {
- 'can_close_threads': False,
- }
- )
- if not user.acl_cache.get('can_edit_polls'):
- raise PermissionDenied(_("You can't edit polls."))
- if user.acl_cache.get('can_edit_polls') < 2:
- if user.pk != target.poster_id:
- raise PermissionDenied(_("You can't edit other users polls in this category."))
- if not has_time_to_edit_poll(user, target):
- message = ngettext(
- "You can't edit polls that are older than %(minutes)s minute.",
- "You can't edit polls that are older than %(minutes)s minutes.",
- user.acl_cache['poll_edit_time']
- )
- raise PermissionDenied(message % {'minutes': user.acl_cache['poll_edit_time']})
- if target.is_over:
- raise PermissionDenied(_("This poll is over. You can't edit it."))
- if not category_acl.get('can_close_threads'):
- if target.category.is_closed:
- raise PermissionDenied(_("This category is closed. You can't edit polls in it."))
- if target.thread.is_closed:
- raise PermissionDenied(_("This thread is closed. You can't edit polls in it."))
- can_edit_poll = return_boolean(allow_edit_poll)
- def allow_delete_poll(user, target):
- if user.is_anonymous:
- raise PermissionDenied(_("You have to sign in to delete polls."))
- category_acl = user.acl_cache['categories'].get(
- target.category_id, {
- 'can_close_threads': False,
- }
- )
- if not user.acl_cache.get('can_delete_polls'):
- raise PermissionDenied(_("You can't delete polls."))
- if user.acl_cache.get('can_delete_polls') < 2:
- if user.pk != target.poster_id:
- raise PermissionDenied(_("You can't delete other users polls in this category."))
- if not has_time_to_edit_poll(user, target):
- message = ngettext(
- "You can't delete polls that are older than %(minutes)s minute.",
- "You can't delete polls that are older than %(minutes)s minutes.",
- user.acl_cache['poll_edit_time']
- )
- raise PermissionDenied(message % {'minutes': user.acl_cache['poll_edit_time']})
- if target.is_over:
- raise PermissionDenied(_("This poll is over. You can't delete it."))
- if not category_acl.get('can_close_threads'):
- if target.category.is_closed:
- raise PermissionDenied(_("This category is closed. You can't delete polls in it."))
- if target.thread.is_closed:
- raise PermissionDenied(_("This thread is closed. You can't delete polls in it."))
- can_delete_poll = return_boolean(allow_delete_poll)
- def allow_vote_poll(user, target):
- if user.is_anonymous:
- raise PermissionDenied(_("You have to sign in to vote in polls."))
- if target.has_selected_choices and not target.allow_revotes:
- raise PermissionDenied(_("You have already voted in this poll."))
- if target.is_over:
- raise PermissionDenied(_("This poll is over. You can't vote in it."))
- category_acl = user.acl_cache['categories'].get(
- target.category_id, {
- 'can_close_threads': False,
- }
- )
- if not category_acl.get('can_close_threads'):
- if target.category.is_closed:
- raise PermissionDenied(_("This category is closed. You can't vote in it."))
- if target.thread.is_closed:
- raise PermissionDenied(_("This thread is closed. You can't vote in it."))
- can_vote_poll = return_boolean(allow_vote_poll)
- def allow_see_poll_votes(user, target):
- if not target.is_public and not user.acl_cache['can_always_see_poll_voters']:
- raise PermissionDenied(_("You dont have permission to this poll's voters."))
- can_see_poll_votes = return_boolean(allow_see_poll_votes)
- def has_time_to_edit_poll(user, target):
- edit_time = user.acl_cache['poll_edit_time']
- if edit_time:
- diff = timezone.now() - target.posted_on
- diff_minutes = int(diff.total_seconds() / 60)
- return diff_minutes < edit_time
- else:
- return True
|