Пример #1
0
def add_or_update(request, election=None):
    user = request.admin
    institution = user.institution

    if request.method == "GET":
        election_form = ElectionForm(user,
                                     institution,
                                     instance=election,
                                     lang=request.LANGUAGE_CODE)
    else:
        election_form = ElectionForm(user,
                                     institution,
                                     request.POST,
                                     instance=election)

    if election_form.is_valid():
        creating = election is None
        with transaction.atomic():
            election = election_form.save()
            if not election.admins.filter(pk=user.pk).count():
                election.admins.add(user)
            if election_form.creating:
                election.logger.info("Election created")
                msg = "New election created"
                subject = "New Zeus election"
                election.notify_admins(msg=msg, subject=subject)
            if not election.has_helios_trustee():
                election.generate_trustee()
            if election.polls.count() == 0:
                url = election_reverse(election, 'polls_add')
            else:
                url = election_reverse(election, 'index')
            if election.voting_extended_until:
                subject = "Voting extension"
                msg = "Voting end date extended"
                election.notify_admins(msg=msg, subject=subject)

            election.zeus.compute_election_public()
            election.logger.info("Public key updated")
            hook_url = None
            if creating:
                hook_url = election.get_module().run_hook('post_create')
            else:
                hook_url = election.get_module().run_hook('post_update')
            return HttpResponseRedirect(hook_url or url)

    context = {'election_form': election_form, 'election': election}
    set_menu('election_edit', context)
    tpl = "election_new"
    if election and election.pk:
        tpl = "election_edit"
    return render_template(request, tpl, context)
Пример #2
0
def add_edit(request, election, poll=None):
    if not poll and not election.feature_can_add_poll:
        raise PermissionDenied
    if poll and not poll.feature_can_edit:
        raise PermissionDenied
    if election.linked_polls and 'batch_file' in request.FILES:
        return _add_batch(request, election)
    if poll:
        oldname = poll.name
    if request.method == "POST":
        form = PollForm(request.POST, instance=poll, election=election)
        if form.is_valid():
            new_poll = form.save()
            if form.has_changed():
                new_poll.logger.info("Poll updated %r" % form.changed_data)
            message = _("Poll updated successfully")
            messages.success(request, message)
            newname = new_poll.name
            # log poll edit/creation
            if poll:
                if oldname != newname:
                    poll.logger.info("Renamed from %s to %s", oldname, newname)
            else:
                new_poll.logger.info("Poll created")
            url = election_reverse(election, 'polls_list')
            return redirect(url)
    if request.method == "GET":
        form = PollForm(instance=poll, election=election)
    context = {'election': election, 'poll': poll, 'form': form}
    set_menu('polls', context)
    if poll:
        set_menu('edit_poll', context)
    tpl = "election_poll_add_or_edit"
    return render_template(request, tpl, context)
Пример #3
0
def login(request, election, trustee_email, trustee_secret):
    trustee = get_object_or_404(Trustee,
                                election=election,
                                email=trustee_email)
    if not trustee:
        raise PermissionDenied("Invalid election")

    if trustee_secret == trustee.secret:
        user = auth.ZeusUser(trustee)
        if request.zeususer.is_authenticated() and (
                not request.zeususer.is_trustee
                or request.zeususer._user.pk != trustee.pk):
            messages.error(
                request,
                _("You need to logout from your current account "
                  "to access this view."))
            return HttpResponseRedirect(reverse('error', kwargs={'code': 403}))

        user.authenticate(request)
        election.logger.info("Trustee %r logged in", trustee.email)
        return HttpResponseRedirect(
            reverse('election_trustee_home', args=[election.uuid]))
    else:
        url = election_reverse(election, 'index')
        return HttpResponseRedirect(url)
Пример #4
0
def home(request, election, trustee):
    context = {'election': election, 'trustee': trustee}
    if not trustee.public_key:
        url = election_reverse(election, 'trustee_keygen')
        return HttpResponseRedirect(url)

    set_menu('trustee', context)
    return render_template(request, 'election_trustee_home', context)
Пример #5
0
def endnow(request, election):
    if election.voting_extended_until:
        election.voting_extended_until = datetime.datetime.now()
    else:
        election.voting_ends_at = datetime.datetime.now()
    election.save()
    election.logger.info("Changed election dates to be able to close voting")
    url = election_reverse(election, 'index')
    return HttpResponseRedirect(url)
Пример #6
0
def trustee_delete(request, election, trustee_uuid):
    election.zeus.invalidate_election_public()
    trustee = election.trustees.get(uuid=trustee_uuid)
    trustee.delete()
    election.logger.info("Trustee %r deleted", trustee.email)
    election.zeus.compute_election_public()
    election.logger.info("Public key updated")
    url = election_reverse(election, 'trustees_list')
    return HttpResponseRedirect(url)
Пример #7
0
def _add_batch(request, election):
    batch_file = request.FILES['batch_file']
    try:
        data = yaml.safe_load(batch_file)
    except Exception:
        messages.error(request, _("Invalid batch file contents"))
        url = election_reverse(election, 'polls_list')
        return HttpResponseRedirect(url)

    try:
        _handle_batch(election, data.get('polls'), data.get('vars', {}),
                      data.get('auto_link', False))
    except Exception as e:
        logging.exception(e)
        election.logger.exception(e)
        messages.error(request, str(e))

    url = election_reverse(election, 'polls_list')
    return HttpResponseRedirect(url)
Пример #8
0
def results(request, election, poll):
    if not request.zeususer.is_admin and not poll.feature_public_results:
        raise PermissionDenied('41')

    if not poll.get_module().display_poll_results:
        url = election_reverse(election, 'index')
        return HttpResponseRedirect(url)

    context = {'poll': poll, 'election': election}
    set_menu('results', context)
    return render_template(request, 'election_poll_results', context)
Пример #9
0
def cancel(request, election):

    cancel_msg = request.POST.get('cancel_msg', '')
    cancel_date = datetime.datetime.now()

    election.canceled_at = cancel_date
    election.cancelation_reason = cancel_msg
    election.completed_at = cancel_date

    election.save()
    url = election_reverse(election, 'index')
    return HttpResponseRedirect(url)
Пример #10
0
def freeze(request, election):
    election.logger.info("Starting to freeze")
    tasks.election_validate_create(election.id)

    # hacky delay. Hopefully validate create task will start running
    # before the election view redirect.
    if not settings.CELERY_TASK_ALWAYS_EAGER:
        import time
        time.sleep(getattr(settings, 'ZEUS_ELECTION_FREEZE_DELAY', 4))

    url = election_reverse(election, 'index')
    return HttpResponseRedirect(url)
Пример #11
0
 def post_create(self, election):
     # create the two polls
     poll = election.polls.create(name=str(_("Electors: Group A")),
                                  oauth2_type='',
                                  oauth2_code_url='',
                                  oauth2_client_secret='',
                                  oauth2_client_type='',
                                  oauth2_confirmation_url='',
                                  oauth2_exchange_url='',
                                  oauth2_client_id='',
                                  jwt_public_key='')
     election.polls.create(name=str(_("Electors: Group B")))
     return election_reverse(election, 'polls_list')
Пример #12
0
def close_mixing(request, election):
    election.logger.info("Closing remote mixes")

    election.remote_mixing_finished_at = datetime.datetime.now()
    election.save()

    tasks.election_validate_mixing(election.id)
    # hacky delay. Hopefully validate create task will start running
    # before the election view redirect.
    import time
    time.sleep(getattr(settings, 'ZEUS_ELECTION_FREEZE_DELAY', 4))
    url = election_reverse(election, 'index')
    return HttpResponseRedirect(url)
Пример #13
0
def recompute_results(request, election):
    election.compute_results_started_at = None
    election.compute_results_finished_at = None
    election.compute_results_status = 'waiting'
    election.completed_at = None
    election.save()

    for poll in election.polls.all():
        poll.compute_results_started_at = None
        poll.compute_results_finished_at = None
        poll.compute_results_status = 'waiting'
        poll.save()
        transaction.on_commit(lambda: poll_compute_results.delay(poll.pk))

    url = election_reverse(election, 'index')
    return HttpResponseRedirect(url)
Пример #14
0
    def post_create(self, election):
        # create the two polls
        poll = election.polls.create(
            name=unicode(_("Electors: Group A")),
            oauth2_type=u'',
            oauth2_code_url=u'',
            oauth2_client_secret=u'',
            oauth2_client_type=u'',
            oauth2_confirmation_url=u'',
            oauth2_exchange_url=u'',
            oauth2_client_id=u'',
            jwt_public_key=u''

        )
        election.polls.create(name=unicode(_("Electors: Group B")))
        return election_reverse(election, 'polls_list')
Пример #15
0
def voters_email(request, election, poll=None, voter_uuid=None):
    user = request.admin

    TEMPLATES = [
        ('vote', _('Time to Vote')),
        ('info', _('Additional Info')),
    ]

    default_template = 'vote'

    if not election.any_poll_feature_can_send_voter_mail:
        raise PermissionDenied('34')

    if not election.any_poll_feature_can_send_voter_booth_invitation:
        TEMPLATES.pop(0)
        default_template = 'info'

    polls = [poll]
    if not poll:
        polls = election.polls_by_link_id

    voter = None
    if voter_uuid:
        try:
            if poll:
                voter = get_object_or_404(Voter, uuid=voter_uuid, poll=poll)
            else:
                voter = get_object_or_404(Voter,
                                          uuid=voter_uuid,
                                          election=election)
        except Voter.DoesNotExist:
            raise PermissionDenied('35')
        if not voter:
            url = election_reverse(election, 'index')
            return HttpResponseRedirect(url)

        if voter.excluded_at:
            TEMPLATES.pop(0)
            default_template = 'info'

    if election.voting_extended_until and not election.voting_ended_at:
        if not voter or (voter and not voter.excluded_at):
            TEMPLATES.append(('extension', _('Voting end date extended')))

    if request.method == 'POST':
        template = request.POST.get('template', default_template)
    else:
        template = request.GET.get('template', default_template)

    if template not in [t[0] for t in TEMPLATES]:
        raise Exception("bad template")

    election_url = election.get_absolute_url()

    default_subject = render_to_string('email/%s_subject.txt' % template,
                                       {'custom_subject': "<SUBJECT>"})

    tpl_context = {
        'election': election,
        'election_url': election_url,
        'custom_subject': default_subject,
        'custom_message': '<BODY>',
        'custom_message_sms': '<SMS_BODY>',
        'SECURE_URL_HOST': settings.SECURE_URL_HOST,
        'voter': {
            'vote_hash': '<SMART_TRACKER>',
            'name': '<VOTER_NAME>',
            'voter_name': '<VOTER_NAME>',
            'voter_surname': '<VOTER_SURNAME>',
            'voter_login_id': '<VOTER_LOGIN_ID>',
            'voter_password': '******',
            'login_code': '<VOTER_LOGIN_CODE>',
            'audit_passwords': '1',
            'get_audit_passwords': ['pass1', 'pass2', '...'],
            'get_quick_login_url': '<VOTER_LOGIN_URL>',
            'poll': poll,
            'election': election
        }
    }

    default_body = render_to_string('email/%s_body.txt' % template,
                                    tpl_context)

    default_sms_body = render_to_string('sms/%s_body.txt' % template,
                                        tpl_context)

    q_param = request.GET.get('q', None)

    filtered_voters = election.voters.filter()
    if poll:
        filtered_voters = poll.voters.filter()

    if not q_param:
        filtered_voters = filtered_voters.none()
    else:
        filtered_voters = election.get_module().filter_voters(
            filtered_voters, q_param, request)

        if not filtered_voters.count():
            message = _("No voters were found.")
            messages.error(request, message)
            url = election_reverse(election, 'polls_list')
            return HttpResponseRedirect(url)

    if request.method == "GET":
        email_form = EmailVotersForm(election, template)
        email_form.fields['email_subject'].initial = dict(TEMPLATES)[template]
        if voter:
            email_form.fields['send_to'].widget = \
                email_form.fields['send_to'].hidden_widget()
    else:
        email_form = EmailVotersForm(election, template, request.POST)
        if email_form.is_valid():
            # the client knows to submit only once with a specific voter_id
            voter_constraints_include = None
            voter_constraints_exclude = None
            update_booth_invitation_date = False
            if template == 'vote':
                update_booth_invitation_date = True

            if voter:
                voter_constraints_include = {'uuid': voter.uuid}

            # exclude those who have not voted
            if email_form.cleaned_data['send_to'] == 'voted':
                voter_constraints_exclude = {'vote_hash': None}

            # include only those who have not voted
            if email_form.cleaned_data['send_to'] == 'not-voted':
                voter_constraints_include = {'vote_hash': None}

            for _poll in polls:
                if not _poll.feature_can_send_voter_mail:
                    continue

                if template == 'vote' and not \
                        _poll.feature_can_send_voter_booth_invitation:
                    continue

                subject_template = 'email/%s_subject.txt' % template
                body_template = 'email/%s_body.txt' % template
                body_template_sms = 'sms/%s_body.txt' % template
                contact_method = email_form.cleaned_data['contact_method']

                extra_vars = {
                    'SECURE_URL_HOST': settings.SECURE_URL_HOST,
                    'custom_subject': email_form.cleaned_data['email_subject'],
                    'custom_message': email_form.cleaned_data['email_body'],
                    'custom_message_sms': email_form.cleaned_data['sms_body'],
                    'election_url': election_url,
                }
                task_kwargs = {
                    'contact_id': template,
                    'notify_once': email_form.cleaned_data.get('notify_once'),
                    'subject_template_email': subject_template,
                    'body_template_email': body_template,
                    'body_template_sms': body_template_sms,
                    'contact_methods': contact_method.split(":"),
                    'template_vars': extra_vars,
                    'voter_constraints_include': voter_constraints_include,
                    'voter_constraints_exclude': voter_constraints_exclude,
                    'update_date': True,
                    'update_booth_invitation_date':
                    update_booth_invitation_date,
                    'q_param': q_param,
                }
                log_obj = election
                if poll:
                    log_obj = poll
                if voter:
                    log_obj.logger.info(
                        "Notifying single voter %s, [template: %s, filter: %s]",
                        voter.voter_login_id, template, q_param)
                else:
                    log_obj.logger.info(
                        "Notifying voters, [template: %s, filter: %r]",
                        template, q_param)
                tasks.voters_email.delay(_poll.pk, **task_kwargs)

            filters = get_voters_filters_with_constraints(
                q_param, voter_constraints_include, voter_constraints_exclude)
            send_to = filtered_voters.filter(filters)
            if q_param and not send_to.filter(filters).count():
                msg = "No voters matched your filters. No emails were sent."
                messages.error(request, _(msg))
            else:
                messages.info(request, _("Email sending started"))

            url = election_reverse(election, 'polls_list')
            if poll:
                url = poll_reverse(poll, 'voters')
            if q_param:
                url += '?q=%s' % six.moves.urllib.parse.quote_plus(q_param)
            return HttpResponseRedirect(url)
        else:
            message = _("Something went wrong")
            messages.error(request, message)

    if election.sms_enabled and election.sms_data.left <= 0:
        messages.warning(request, _("No SMS deliveries left."))

    context = {
        'email_form': email_form,
        'election': election,
        'poll': poll,
        'voter_o': voter,
        'default_subject': default_subject,
        'default_body': default_body,
        'default_sms_body': default_sms_body,
        'sms_enabled': election.sms_enabled,
        'template': template,
        'filtered_voters': filtered_voters,
        'templates': TEMPLATES
    }
    set_menu('voters', context)
    if not poll:
        set_menu('polls', context)
    return render_template(request, "voters_email", context)
Пример #16
0
def remove(request, election, poll):
    poll.delete()
    poll.logger.info("Poll deleted")
    return HttpResponseRedirect(election_reverse(election, 'polls_list'))
Пример #17
0
def close(request, election):
    election.close_voting()
    tasks.election_validate_voting(election.pk)
    url = election_reverse(election, 'index')
    return HttpResponseRedirect(url)
Пример #18
0
def trustee_send_url(request, election, trustee_uuid):
    trustee = election.trustees.get(uuid=trustee_uuid)
    trustee.send_url_via_mail()
    url = election_reverse(election, 'trustees_list')
    messages.success(request, _("Trustee login url sent"))
    return HttpResponseRedirect(url)
Пример #19
0
def start_mixing(request, election):
    tasks.start_mixing.delay(election_id=election.id)
    url = election_reverse(election, 'index')
    return HttpResponseRedirect(url)