Merge pull request #1802 from normanjaeckel/Blocked
Removed possibility to block candidates. Fixes #1708.
This commit is contained in:
commit
1f72ef4099
@ -15,6 +15,7 @@ Agenda:
|
||||
- Removed mptt.
|
||||
Assignments:
|
||||
- Renamed app from assignment to assignments.
|
||||
- Removed possibility to block candidates.
|
||||
- Massive refactoring and cleanup of the app.
|
||||
Motions:
|
||||
- Renamed app from motion to motions.
|
||||
|
23
openslides/assignments/migrations/0005_auto_20160109_1624.py
Normal file
23
openslides/assignments/migrations/0005_auto_20160109_1624.py
Normal file
@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assignments', '0004_auto_20160109_1329'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='assignmentrelateduser',
|
||||
name='status',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='assignmentrelateduser',
|
||||
name='elected',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
@ -24,15 +24,6 @@ class AssignmentRelatedUser(RESTModelMixin, models.Model):
|
||||
"""
|
||||
Many to Many table between an assignment and user.
|
||||
"""
|
||||
STATUS_CANDIDATE = 1
|
||||
STATUS_ELECTED = 2
|
||||
STATUS_BLOCKED = 3
|
||||
STATUSES = (
|
||||
(STATUS_CANDIDATE, ugettext_lazy('candidate')),
|
||||
(STATUS_ELECTED, ugettext_lazy('elected')),
|
||||
(STATUS_BLOCKED, ugettext_lazy('blocked')),
|
||||
)
|
||||
|
||||
assignment = models.ForeignKey(
|
||||
'Assignment',
|
||||
on_delete=models.CASCADE,
|
||||
@ -40,9 +31,7 @@ class AssignmentRelatedUser(RESTModelMixin, models.Model):
|
||||
user = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.CASCADE)
|
||||
status = models.IntegerField(
|
||||
choices=STATUSES,
|
||||
default=STATUS_CANDIDATE)
|
||||
elected = models.BooleanField(default=False)
|
||||
|
||||
class Meta:
|
||||
default_permissions = ()
|
||||
@ -106,9 +95,9 @@ class Assignment(RESTModelMixin, models.Model):
|
||||
settings.AUTH_USER_MODEL,
|
||||
through='AssignmentRelatedUser')
|
||||
"""
|
||||
Users that are candidates, elected or blocked as candidate.
|
||||
Users that are candidates or elected.
|
||||
|
||||
See AssignmentRelatedUser for more infos.
|
||||
See AssignmentRelatedUser for more information.
|
||||
"""
|
||||
|
||||
tags = models.ManyToManyField(Tag, blank=True)
|
||||
@ -145,7 +134,7 @@ class Assignment(RESTModelMixin, models.Model):
|
||||
Queryset that represents the candidates for the assignment.
|
||||
"""
|
||||
return self.related_users.filter(
|
||||
assignmentrelateduser__status=AssignmentRelatedUser.STATUS_CANDIDATE)
|
||||
assignmentrelateduser__elected=False)
|
||||
|
||||
@property
|
||||
def elected(self):
|
||||
@ -153,15 +142,7 @@ class Assignment(RESTModelMixin, models.Model):
|
||||
Queryset that represents all elected users for the assignment.
|
||||
"""
|
||||
return self.related_users.filter(
|
||||
assignmentrelateduser__status=AssignmentRelatedUser.STATUS_ELECTED)
|
||||
|
||||
@property
|
||||
def blocked(self):
|
||||
"""
|
||||
Queryset that represents all blocked users for the assignment.
|
||||
"""
|
||||
return self.related_users.filter(
|
||||
assignmentrelateduser__status=AssignmentRelatedUser.STATUS_BLOCKED)
|
||||
assignmentrelateduser__elected=True)
|
||||
|
||||
def is_candidate(self, user):
|
||||
"""
|
||||
@ -179,21 +160,13 @@ class Assignment(RESTModelMixin, models.Model):
|
||||
"""
|
||||
return self.elected.filter(pk=user.pk).exists()
|
||||
|
||||
def is_blocked(self, user):
|
||||
"""
|
||||
Returns True if the user is blocked for candidature.
|
||||
|
||||
Costs one database query.
|
||||
"""
|
||||
return self.blocked.filter(pk=user.pk).exists()
|
||||
|
||||
def set_candidate(self, user):
|
||||
"""
|
||||
Adds the user as candidate.
|
||||
"""
|
||||
related_user, __ = self.assignment_related_users.update_or_create(
|
||||
user=user,
|
||||
defaults={'status': AssignmentRelatedUser.STATUS_CANDIDATE})
|
||||
defaults={'elected': False})
|
||||
|
||||
def set_elected(self, user):
|
||||
"""
|
||||
@ -201,15 +174,7 @@ class Assignment(RESTModelMixin, models.Model):
|
||||
"""
|
||||
related_user, __ = self.assignment_related_users.update_or_create(
|
||||
user=user,
|
||||
defaults={'status': AssignmentRelatedUser.STATUS_ELECTED})
|
||||
|
||||
def set_blocked(self, user):
|
||||
"""
|
||||
Block user from this assignment, so he can not get an candidate.
|
||||
"""
|
||||
related_user, __ = self.assignment_related_users.update_or_create(
|
||||
user=user,
|
||||
defaults={'status': AssignmentRelatedUser.STATUS_BLOCKED})
|
||||
defaults={'elected': True})
|
||||
|
||||
def delete_related_user(self, user):
|
||||
"""
|
||||
|
@ -29,7 +29,7 @@ class AssignmentRelatedUserSerializer(ModelSerializer):
|
||||
fields = (
|
||||
'id',
|
||||
'user',
|
||||
'status',
|
||||
'elected',
|
||||
'assignment') # js-data needs the assignment-id in the nested object to define relations.
|
||||
|
||||
|
||||
|
@ -107,7 +107,7 @@ class AssignmentViewSet(ModelViewSet):
|
||||
return _('You were nominated successfully.')
|
||||
|
||||
def withdraw_self(self, request, assignment):
|
||||
# Withdraw candidature and set self blocked.
|
||||
# Withdraw candidature.
|
||||
if assignment.phase == assignment.PHASE_FINISHED:
|
||||
raise ValidationError({'detail': _('You can not withdraw your candidature to this election because it is finished.')})
|
||||
if assignment.phase == assignment.PHASE_VOTING and not request.user.has_perm('assignments.can_manage'):
|
||||
@ -115,16 +115,14 @@ class AssignmentViewSet(ModelViewSet):
|
||||
self.permission_denied(request)
|
||||
if not assignment.is_candidate(request.user):
|
||||
raise ValidationError({'detail': _('You are not a candidate of this election.')})
|
||||
assignment.set_blocked(request.user)
|
||||
return _(
|
||||
'You have withdrawn your candidature successfully. '
|
||||
'You can not be nominated by other participants anymore.')
|
||||
assignment.delete_related_user(request.user)
|
||||
return _('You have withdrawn your candidature successfully.')
|
||||
|
||||
def get_user_from_request_data(self, request):
|
||||
"""
|
||||
Helper method to get a specific user from request data (not the
|
||||
request.user) so that the views self.candidature_other or
|
||||
self.mark_elected can play with him.
|
||||
self.mark_elected can play with it.
|
||||
"""
|
||||
if not isinstance(request.data, dict):
|
||||
detail = _('Invalid data. Expected dictionary, got %s.') % type(request.data)
|
||||
@ -165,8 +163,6 @@ class AssignmentViewSet(ModelViewSet):
|
||||
# To nominate another user during voting you have to be a manager.
|
||||
self.permission_denied(request)
|
||||
if not request.user.has_perm('assignments.can_manage'):
|
||||
if assignment.is_blocked(user):
|
||||
raise ValidationError({'detail': _('User %s does not want to be a candidate. Only a manager can do this.') % user})
|
||||
if assignment.is_elected(user):
|
||||
raise ValidationError({'detail': _('User %s is already elected.') % user})
|
||||
if assignment.is_candidate(user):
|
||||
@ -181,10 +177,10 @@ class AssignmentViewSet(ModelViewSet):
|
||||
if assignment.phase == assignment.PHASE_FINISHED:
|
||||
detail = _('You can not delete someones candidature to this election because it is finished.')
|
||||
raise ValidationError({'detail': detail})
|
||||
if not assignment.is_candidate(user) and not assignment.is_blocked(user):
|
||||
if not assignment.is_candidate(user):
|
||||
raise ValidationError({'detail': _('User %s has no status in this election.') % user})
|
||||
assignment.delete_related_user(user)
|
||||
return _('Candidate %s was withdrawn/unblocked successfully.') % user
|
||||
return _('Candidate %s was withdrawn successfully.') % user
|
||||
|
||||
@detail_route(methods=['post', 'delete'])
|
||||
def mark_elected(self, request, pk=None):
|
||||
|
@ -65,7 +65,6 @@ class CanidatureSelf(TestCase):
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFalse(Assignment.objects.get(pk=self.assignment.pk).candidates.filter(username='admin').exists())
|
||||
self.assertTrue(Assignment.objects.get(pk=self.assignment.pk).blocked.filter(username='admin').exists())
|
||||
|
||||
def test_withdraw_self_twice(self):
|
||||
response = self.client.delete(reverse('assignment-candidature-self', args=[self.assignment.pk]))
|
||||
@ -90,7 +89,6 @@ class CanidatureSelf(TestCase):
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertFalse(Assignment.objects.get(pk=self.assignment.pk).candidates.exists())
|
||||
self.assertTrue(Assignment.objects.get(pk=self.assignment.pk).blocked.filter(username='admin').exists())
|
||||
|
||||
def test_withdraw_self_during_voting_non_admin(self):
|
||||
self.assignment.set_candidate(get_user_model().objects.get(username='admin'))
|
||||
|
Loading…
Reference in New Issue
Block a user