2011-07-31 10:46:29 +02:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
openslides.participant.views
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
|
|
|
Views for the participant app.
|
|
|
|
|
2012-04-25 22:29:19 +02:00
|
|
|
:copyright: 2011, 2012 by OpenSlides team, see AUTHORS.
|
2011-07-31 10:46:29 +02:00
|
|
|
:license: GNU GPL, see LICENSE for more details.
|
|
|
|
"""
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
# for python 2.5 support
|
2011-11-29 11:02:31 +01:00
|
|
|
from __future__ import with_statement
|
|
|
|
|
2011-07-31 10:46:29 +02:00
|
|
|
import csv
|
2011-09-10 00:16:57 +02:00
|
|
|
from urllib import urlencode
|
2012-04-13 11:35:53 +02:00
|
|
|
|
2011-09-12 08:32:05 +02:00
|
|
|
try:
|
|
|
|
from urlparse import parse_qs
|
2012-04-13 11:35:53 +02:00
|
|
|
except ImportError: # python <= 2.5 grab it from cgi
|
2011-09-12 08:32:05 +02:00
|
|
|
from cgi import parse_qs
|
2011-09-10 00:16:57 +02:00
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
from reportlab.lib import colors
|
|
|
|
from reportlab.lib.units import cm
|
|
|
|
from reportlab.platypus import (SimpleDocTemplate, PageBreak, Paragraph,
|
|
|
|
LongTable, Spacer, Table, TableStyle)
|
|
|
|
|
|
|
|
from django.db import transaction
|
2011-07-31 10:46:29 +02:00
|
|
|
from django.contrib import messages
|
2012-07-07 15:26:00 +02:00
|
|
|
from django.contrib.auth.decorators import login_required
|
|
|
|
from django.contrib.auth.models import User, Group
|
2011-07-31 10:46:29 +02:00
|
|
|
from django.core.urlresolvers import reverse
|
2012-07-07 15:26:00 +02:00
|
|
|
from django.shortcuts import redirect
|
2012-07-10 12:11:07 +02:00
|
|
|
from django.utils.translation import ugettext as _, ungettext
|
2012-04-20 23:23:50 +02:00
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
from openslides.utils import csv_ext
|
|
|
|
from openslides.utils.pdf import stylesheet
|
|
|
|
from openslides.utils.template import Tab
|
|
|
|
from openslides.utils.utils import (template, permission_required,
|
|
|
|
gen_confirm_form, ajax_request, decodedict, encodedict,
|
|
|
|
delete_default_permissions)
|
|
|
|
from openslides.utils.views import FormView, PDFView
|
2011-09-03 19:42:43 +02:00
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
from openslides.config.models import config
|
2012-04-20 23:23:50 +02:00
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
from openslides.participant.models import Profile
|
|
|
|
from openslides.participant.api import gen_username, gen_password
|
|
|
|
from openslides.participant.forms import (UserNewForm, UserEditForm,
|
2012-07-08 09:01:01 +02:00
|
|
|
ProfileForm, UsersettingsForm, UserImportForm, GroupForm,
|
2012-07-07 15:26:00 +02:00
|
|
|
AdminPasswordChangeForm, ConfigForm)
|
2011-07-31 10:46:29 +02:00
|
|
|
|
|
|
|
|
2011-09-04 12:21:58 +02:00
|
|
|
@permission_required('participant.can_see_participant')
|
2011-07-31 10:46:29 +02:00
|
|
|
@template('participant/overview.html')
|
|
|
|
def get_overview(request):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Show all users.
|
|
|
|
"""
|
2011-07-31 10:46:29 +02:00
|
|
|
try:
|
2012-07-07 15:26:00 +02:00
|
|
|
sortfilter = encodedict(parse_qs(
|
|
|
|
request.COOKIES['participant_sortfilter']))
|
2011-07-31 10:46:29 +02:00
|
|
|
except KeyError:
|
2011-09-10 00:16:57 +02:00
|
|
|
sortfilter = {}
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
for value in [u'gender', u'group', u'type', u'committee', u'status',
|
|
|
|
u'sort', u'reverse']:
|
2011-09-10 00:16:57 +02:00
|
|
|
if value in request.REQUEST:
|
|
|
|
if request.REQUEST[value] == '---':
|
|
|
|
try:
|
|
|
|
del sortfilter[value]
|
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
sortfilter[value] = [request.REQUEST[value]]
|
|
|
|
|
|
|
|
query = User.objects
|
|
|
|
if 'gender' in sortfilter:
|
|
|
|
query = query.filter(profile__gender__iexact=sortfilter['gender'][0])
|
|
|
|
if 'group' in sortfilter:
|
|
|
|
query = query.filter(profile__group__iexact=sortfilter['group'][0])
|
|
|
|
if 'type' in sortfilter:
|
|
|
|
query = query.filter(profile__type__iexact=sortfilter['type'][0])
|
|
|
|
if 'committee' in sortfilter:
|
2012-07-07 15:26:00 +02:00
|
|
|
query = query. \
|
|
|
|
filter(profile__committee__iexact=sortfilter['committee'][0])
|
2012-04-02 08:31:26 +02:00
|
|
|
if 'status' in sortfilter:
|
|
|
|
query = query.filter(is_active=sortfilter['status'][0])
|
2011-09-10 00:16:57 +02:00
|
|
|
if 'sort' in sortfilter:
|
2012-04-02 08:36:22 +02:00
|
|
|
if sortfilter['sort'][0] in ['first_name', 'last_name', 'last_login']:
|
2011-09-10 00:16:57 +02:00
|
|
|
query = query.order_by(sortfilter['sort'][0])
|
2012-04-02 08:36:22 +02:00
|
|
|
elif sortfilter['sort'][0] in ['group', 'type', 'committee', 'comment']:
|
2011-09-10 00:16:57 +02:00
|
|
|
query = query.order_by('profile__%s' % sortfilter['sort'][0])
|
2011-10-05 21:35:20 +02:00
|
|
|
else:
|
|
|
|
query = query.order_by('first_name')
|
2011-09-10 00:16:57 +02:00
|
|
|
if 'reverse' in sortfilter:
|
2011-07-31 10:46:29 +02:00
|
|
|
query = query.reverse()
|
2011-09-03 17:17:29 +02:00
|
|
|
|
2012-04-02 08:37:34 +02:00
|
|
|
# list of filtered users (with profile)
|
2011-07-31 10:46:29 +02:00
|
|
|
userlist = query.all()
|
|
|
|
users = []
|
|
|
|
for user in userlist:
|
|
|
|
try:
|
|
|
|
user.get_profile()
|
|
|
|
users.append(user)
|
|
|
|
except Profile.DoesNotExist:
|
|
|
|
pass
|
2012-04-02 08:37:34 +02:00
|
|
|
# list of all existing users (with profile)
|
|
|
|
allusers = []
|
|
|
|
for user in User.objects.all():
|
|
|
|
try:
|
|
|
|
user.get_profile()
|
|
|
|
allusers.append(user)
|
|
|
|
except Profile.DoesNotExist:
|
|
|
|
pass
|
|
|
|
# quotient of selected users and all users
|
|
|
|
if len(allusers) > 0:
|
|
|
|
percent = float(len(users)) * 100 / float(len(allusers))
|
|
|
|
else:
|
|
|
|
percent = 0
|
|
|
|
# list of all existing groups
|
2012-07-07 15:26:00 +02:00
|
|
|
groups = [p['group'] for p in Profile.objects.values('group') \
|
|
|
|
.exclude(group='').distinct()]
|
2012-04-02 08:37:34 +02:00
|
|
|
# list of all existing committees
|
2012-07-07 15:26:00 +02:00
|
|
|
committees = [p['committee'] for p in Profile.objects.values('committee') \
|
|
|
|
.exclude(committee='').distinct()]
|
2011-07-31 10:46:29 +02:00
|
|
|
return {
|
|
|
|
'users': users,
|
2012-04-02 08:37:34 +02:00
|
|
|
'allusers': allusers,
|
|
|
|
'percent': round(percent, 1),
|
2011-07-31 10:46:29 +02:00
|
|
|
'groups': groups,
|
|
|
|
'committees': committees,
|
2012-07-07 15:26:00 +02:00
|
|
|
'cookie': ['participant_sortfilter', urlencode(decodedict(sortfilter),
|
|
|
|
doseq=True)],
|
2011-09-10 00:16:57 +02:00
|
|
|
'sortfilter': sortfilter,
|
2011-07-31 10:46:29 +02:00
|
|
|
}
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
|
2011-09-04 12:21:58 +02:00
|
|
|
@permission_required('participant.can_manage_participant')
|
2011-07-31 10:46:29 +02:00
|
|
|
@template('participant/edit.html')
|
|
|
|
def edit(request, user_id=None):
|
|
|
|
"""
|
2011-11-24 19:42:32 +01:00
|
|
|
View to create and edit users with profile.
|
2011-07-31 10:46:29 +02:00
|
|
|
"""
|
|
|
|
if user_id is not None:
|
|
|
|
user = User.objects.get(id=user_id)
|
|
|
|
else:
|
|
|
|
user = None
|
|
|
|
|
|
|
|
if request.method == 'POST':
|
2011-09-04 09:57:23 +02:00
|
|
|
if user_id is None:
|
|
|
|
userform = UserNewForm(request.POST, prefix="user")
|
2011-07-31 10:46:29 +02:00
|
|
|
profileform = ProfileForm(request.POST, prefix="profile")
|
2011-09-04 09:57:23 +02:00
|
|
|
else:
|
|
|
|
userform = UserEditForm(request.POST, instance=user, prefix="user")
|
2012-07-07 15:26:00 +02:00
|
|
|
profileform = ProfileForm(request.POST, instance=user.profile,
|
|
|
|
prefix="profile")
|
2011-09-03 17:17:29 +02:00
|
|
|
|
2011-11-24 19:42:32 +01:00
|
|
|
if userform.is_valid() and profileform.is_valid():
|
2011-07-31 10:46:29 +02:00
|
|
|
user = userform.save()
|
2011-09-04 09:57:23 +02:00
|
|
|
if user_id is None:
|
|
|
|
user.username = gen_username(user.first_name, user.last_name)
|
|
|
|
user.save()
|
2011-07-31 10:46:29 +02:00
|
|
|
profile = profileform.save(commit=False)
|
|
|
|
profile.user = user
|
2011-11-17 18:14:41 +01:00
|
|
|
if user_id is None:
|
2012-05-19 10:33:59 +02:00
|
|
|
if not profile.firstpassword:
|
|
|
|
profile.firstpassword = gen_password()
|
2011-11-17 18:14:41 +01:00
|
|
|
profile.user.set_password(profile.firstpassword)
|
2012-05-19 10:33:59 +02:00
|
|
|
profile.user.save()
|
2011-07-31 10:46:29 +02:00
|
|
|
profile.save()
|
|
|
|
if user_id is None:
|
2012-07-07 15:26:00 +02:00
|
|
|
messages.success(request,
|
|
|
|
_('New participant was successfully created.'))
|
2011-07-31 10:46:29 +02:00
|
|
|
else:
|
2012-07-07 15:26:00 +02:00
|
|
|
messages.success(request,
|
|
|
|
_('Participant was successfully modified.'))
|
2011-09-03 19:25:05 +02:00
|
|
|
if not 'apply' in request.POST:
|
|
|
|
return redirect(reverse('user_overview'))
|
|
|
|
if user_id is None:
|
|
|
|
return redirect(reverse('user_edit', args=[user.id]))
|
|
|
|
else:
|
|
|
|
messages.error(request, _('Please check the form for errors.'))
|
2011-07-31 10:46:29 +02:00
|
|
|
else:
|
2011-09-04 09:57:23 +02:00
|
|
|
if user_id is None:
|
|
|
|
userform = UserNewForm(prefix="user")
|
2011-07-31 10:46:29 +02:00
|
|
|
profileform = ProfileForm(prefix="profile")
|
2011-09-04 09:57:23 +02:00
|
|
|
else:
|
|
|
|
userform = UserEditForm(instance=user, prefix="user")
|
|
|
|
profileform = ProfileForm(instance=user.profile, prefix="profile")
|
|
|
|
|
2011-07-31 10:46:29 +02:00
|
|
|
return {
|
|
|
|
'userform': userform,
|
|
|
|
'profileform': profileform,
|
|
|
|
'edituser': user,
|
|
|
|
}
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
|
2011-09-04 12:21:58 +02:00
|
|
|
@permission_required('participant.can_manage_participant')
|
2011-07-31 10:46:29 +02:00
|
|
|
@template('confirm.html')
|
|
|
|
def user_delete(request, user_id):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Delete an user.
|
|
|
|
"""
|
2011-07-31 10:46:29 +02:00
|
|
|
user = User.objects.get(pk=user_id)
|
|
|
|
if request.method == 'POST':
|
|
|
|
user.delete()
|
2012-07-07 15:26:00 +02:00
|
|
|
messages.success(request,
|
|
|
|
_('Participant <b>%s</b> was successfully deleted.') % user)
|
2011-07-31 10:46:29 +02:00
|
|
|
else:
|
2012-07-07 15:26:00 +02:00
|
|
|
gen_confirm_form(request,
|
|
|
|
_('Do you really want to delete <b>%s</b>?') % user,
|
|
|
|
reverse('user_delete', args=[user_id]))
|
2011-07-31 10:46:29 +02:00
|
|
|
return redirect(reverse('user_overview'))
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
|
2011-09-04 12:21:58 +02:00
|
|
|
@permission_required('participant.can_manage_participant')
|
2011-07-31 10:46:29 +02:00
|
|
|
@template('confirm.html')
|
2012-05-19 19:22:20 +02:00
|
|
|
def user_set_status(request, user_id):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Set the status of an user.
|
|
|
|
"""
|
2012-04-02 08:35:10 +02:00
|
|
|
try:
|
|
|
|
user = User.objects.get(pk=user_id)
|
2012-05-19 19:22:20 +02:00
|
|
|
if user.is_active:
|
|
|
|
user.is_active = False
|
|
|
|
else:
|
|
|
|
user.is_active = True
|
2011-07-31 10:46:29 +02:00
|
|
|
user.save()
|
2012-04-02 08:35:10 +02:00
|
|
|
except User.DoesNotExist:
|
2012-07-07 15:26:00 +02:00
|
|
|
messages.error(request,
|
|
|
|
_('Participant ID %d does not exist.') % int(user_id))
|
2012-05-19 19:22:20 +02:00
|
|
|
return redirect(reverse('user_overview'))
|
2012-04-02 08:35:10 +02:00
|
|
|
|
|
|
|
if request.is_ajax():
|
2012-05-19 19:22:20 +02:00
|
|
|
return ajax_request({'active': user.is_active})
|
|
|
|
# set success messages for page reload only (= not ajax request)
|
|
|
|
if user.is_active:
|
|
|
|
messages.success(request, _('<b>%s</b> is now <b>present</b>.') % user)
|
|
|
|
else:
|
|
|
|
messages.success(request, _('<b>%s</b> is now <b>absent</b>.') % user)
|
2011-07-31 10:46:29 +02:00
|
|
|
return redirect(reverse('user_overview'))
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
|
2011-09-04 12:21:58 +02:00
|
|
|
@permission_required('participant.can_manage_participant')
|
2011-07-31 10:46:29 +02:00
|
|
|
@template('participant/group_overview.html')
|
|
|
|
def get_group_overview(request):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Show all groups.
|
|
|
|
"""
|
2012-02-15 12:04:11 +01:00
|
|
|
if config['system_enable_anonymous']:
|
2011-11-14 16:37:12 +01:00
|
|
|
groups = Group.objects.all()
|
|
|
|
else:
|
|
|
|
groups = Group.objects.exclude(name='Anonymous')
|
2011-07-31 10:46:29 +02:00
|
|
|
return {
|
|
|
|
'groups': groups,
|
|
|
|
}
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
|
2011-09-04 12:21:58 +02:00
|
|
|
@permission_required('participant.can_manage_participant')
|
2011-07-31 10:46:29 +02:00
|
|
|
@template('participant/group_edit.html')
|
|
|
|
def group_edit(request, group_id=None):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Edit a group.
|
|
|
|
"""
|
2011-07-31 10:46:29 +02:00
|
|
|
if group_id is not None:
|
|
|
|
try:
|
|
|
|
group = Group.objects.get(id=group_id)
|
|
|
|
except Group.DoesNotExist:
|
2011-09-05 19:53:40 +02:00
|
|
|
raise NameError("There is no group %d" % group_id)
|
2011-07-31 10:46:29 +02:00
|
|
|
else:
|
|
|
|
group = None
|
2012-04-18 16:57:33 +02:00
|
|
|
delete_default_permissions()
|
2011-07-31 10:46:29 +02:00
|
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
form = GroupForm(request.POST, instance=group)
|
|
|
|
if form.is_valid():
|
2011-11-14 16:37:12 +01:00
|
|
|
group_name = form.cleaned_data['name'].lower()
|
|
|
|
|
|
|
|
try:
|
|
|
|
anonymous_group = Group.objects.get(name='Anonymous')
|
|
|
|
except Group.DoesNotExist:
|
|
|
|
anonymous_group = None
|
|
|
|
|
|
|
|
# special handling for anonymous auth
|
|
|
|
if group is None and group_name.strip().lower() == 'anonymous':
|
|
|
|
# don't allow to create this group
|
2012-07-07 15:26:00 +02:00
|
|
|
messages.error(request,
|
|
|
|
_('Group name "%s" is reserved for internal use.')
|
|
|
|
% group_name)
|
2011-11-14 16:37:12 +01:00
|
|
|
return {
|
|
|
|
'form' : form,
|
|
|
|
'group': group
|
|
|
|
}
|
|
|
|
|
2011-09-03 19:25:05 +02:00
|
|
|
group = form.save()
|
2011-11-14 16:37:12 +01:00
|
|
|
if anonymous_group is not None and \
|
|
|
|
anonymous_group.id == group.id:
|
2012-07-07 15:26:00 +02:00
|
|
|
# prevent name changes -
|
|
|
|
# XXX: I'm sure this could be done as *one* group.save()
|
2011-11-14 16:37:12 +01:00
|
|
|
group.name = 'Anonymous'
|
|
|
|
group.save()
|
|
|
|
|
2011-07-31 10:46:29 +02:00
|
|
|
if group_id is None:
|
2012-07-07 15:26:00 +02:00
|
|
|
messages.success(request,
|
|
|
|
_('New group was successfully created.'))
|
2011-07-31 10:46:29 +02:00
|
|
|
else:
|
|
|
|
messages.success(request, _('Group was successfully modified.'))
|
2011-09-03 19:25:05 +02:00
|
|
|
if not 'apply' in request.POST:
|
|
|
|
return redirect(reverse('user_group_overview'))
|
|
|
|
if group_id is None:
|
|
|
|
return redirect(reverse('user_group_edit', args=[group.id]))
|
2011-07-31 10:46:29 +02:00
|
|
|
else:
|
|
|
|
messages.error(request, _('Please check the form for errors.'))
|
|
|
|
else:
|
|
|
|
form = GroupForm(instance=group)
|
|
|
|
return {
|
|
|
|
'form': form,
|
|
|
|
'group': group,
|
|
|
|
}
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
|
2011-09-04 12:21:58 +02:00
|
|
|
@permission_required('participant.can_manage_participant')
|
2011-07-31 10:46:29 +02:00
|
|
|
def group_delete(request, group_id):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Delete a group.
|
|
|
|
"""
|
2011-07-31 10:46:29 +02:00
|
|
|
group = Group.objects.get(pk=group_id)
|
|
|
|
if request.method == 'POST':
|
|
|
|
group.delete()
|
2012-07-07 15:26:00 +02:00
|
|
|
messages.success(request,
|
|
|
|
_('Group <b>%s</b> was successfully deleted.') % group)
|
2011-07-31 10:46:29 +02:00
|
|
|
else:
|
2012-07-07 15:26:00 +02:00
|
|
|
gen_confirm_form(request,
|
|
|
|
_('Do you really want to delete <b>%s</b>?') % group,
|
|
|
|
reverse('user_group_delete', args=[group_id]))
|
2011-07-31 10:46:29 +02:00
|
|
|
return redirect(reverse('user_group_overview'))
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
|
2011-07-31 10:46:29 +02:00
|
|
|
@login_required
|
|
|
|
@template('participant/settings.html')
|
|
|
|
def user_settings(request):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Edit own user account.
|
|
|
|
"""
|
2011-07-31 10:46:29 +02:00
|
|
|
if request.method == 'POST':
|
2012-07-01 16:56:01 +02:00
|
|
|
form_user = UsersettingsForm(request.POST,instance=request.user)
|
|
|
|
if form_user.is_valid():
|
2011-07-31 10:46:29 +02:00
|
|
|
form_user.save()
|
|
|
|
messages.success(request, _('User settings successfully saved.'))
|
|
|
|
else:
|
|
|
|
messages.error(request, _('Please check the form for errors.'))
|
|
|
|
else:
|
2012-07-01 16:56:01 +02:00
|
|
|
form_user = UsersettingsForm(instance=request.user)
|
2011-07-31 10:46:29 +02:00
|
|
|
|
|
|
|
return {
|
|
|
|
'form_user': form_user,
|
|
|
|
'edituser': request.user,
|
|
|
|
}
|
|
|
|
|
2012-07-07 15:26:00 +02:00
|
|
|
|
2011-09-04 12:21:58 +02:00
|
|
|
@permission_required('participant.can_manage_participant')
|
2011-07-31 10:46:29 +02:00
|
|
|
@template('participant/import.html')
|
|
|
|
def user_import(request):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Import Users via csv.
|
|
|
|
"""
|
|
|
|
from openslides.application.models import Application
|
2011-07-31 10:46:29 +02:00
|
|
|
try:
|
|
|
|
request.user.profile
|
2011-09-09 10:55:33 +02:00
|
|
|
messages.error(request, _('The import function is available for the superuser (without user profile) only.'))
|
|
|
|
return redirect(reverse('user_overview'))
|
2011-07-31 10:46:29 +02:00
|
|
|
except Profile.DoesNotExist:
|
|
|
|
pass
|
2011-11-14 16:37:12 +01:00
|
|
|
except AttributeError:
|
|
|
|
# AnonymousUser
|
|
|
|
pass
|
2011-07-31 10:46:29 +02:00
|
|
|
|
|
|
|
if request.method == 'POST':
|
|
|
|
form = UserImportForm(request.POST, request.FILES)
|
|
|
|
if form.is_valid():
|
2011-11-22 18:49:36 +01:00
|
|
|
try:
|
2012-04-13 22:33:47 +02:00
|
|
|
# check for valid encoding (will raise UnicodeDecodeError if not)
|
|
|
|
request.FILES['csvfile'].read().decode('utf-8')
|
|
|
|
request.FILES['csvfile'].seek(0)
|
|
|
|
|
2011-11-22 18:49:36 +01:00
|
|
|
with transaction.commit_on_success():
|
2012-04-13 11:35:53 +02:00
|
|
|
|
2012-04-12 19:11:07 +02:00
|
|
|
old_users = {}
|
|
|
|
applications_mapped = 0
|
|
|
|
applications_review = 0
|
|
|
|
applications_removed = 0
|
|
|
|
|
|
|
|
try:
|
|
|
|
janitor = User.objects.get(username='__system__.janitor')
|
|
|
|
except User.DoesNotExist:
|
|
|
|
janitor = User()
|
|
|
|
janitor.first_name = ''
|
|
|
|
janitor.last_name = ''
|
|
|
|
janitor.username = '__system__.janitor'
|
|
|
|
janitor.save()
|
|
|
|
|
|
|
|
applications = Application.objects.all()
|
|
|
|
for application in applications:
|
|
|
|
if form.cleaned_data['application_handling'] == 'DISCARD':
|
|
|
|
# need to do this explicit since some applications may belong
|
|
|
|
# to __system__.janitor which is a permanent user
|
|
|
|
application.delete(force=True)
|
|
|
|
applications_removed += 1
|
|
|
|
else:
|
|
|
|
# collect all applications and map them to their submitters
|
|
|
|
submitter = application.submitter
|
|
|
|
skey = '%s_%s' % (submitter.first_name, submitter.last_name)
|
|
|
|
|
|
|
|
if not skey in old_users:
|
|
|
|
old_users[skey] = []
|
|
|
|
old_users[skey].append(application.id)
|
|
|
|
|
|
|
|
application.submitter = janitor
|
|
|
|
application.save()
|
|
|
|
|
|
|
|
if application.supporter.all():
|
|
|
|
application.writelog(_('Supporters removed after user import.'), user=request.user)
|
|
|
|
|
2011-11-22 18:49:36 +01:00
|
|
|
profiles = Profile.objects.all()
|
|
|
|
for profile in profiles:
|
|
|
|
profile.user.delete()
|
|
|
|
profile.delete()
|
|
|
|
i = -1
|
|
|
|
dialect = csv.Sniffer().sniff(request.FILES['csvfile'].readline())
|
2012-07-07 15:26:00 +02:00
|
|
|
dialect = csv_ext.patchup(dialect)
|
2011-11-22 18:49:36 +01:00
|
|
|
request.FILES['csvfile'].seek(0)
|
2012-04-13 22:33:47 +02:00
|
|
|
|
2012-04-13 22:02:14 +02:00
|
|
|
for (lno, line) in enumerate(csv.reader(request.FILES['csvfile'], dialect=dialect)):
|
2011-11-22 18:49:36 +01:00
|
|
|
i += 1
|
|
|
|
if i > 0:
|
2012-04-13 22:02:14 +02:00
|
|
|
try:
|
|
|
|
(first_name, last_name, gender, group, type, committee, comment) = line[:7]
|
|
|
|
except ValueError:
|
|
|
|
messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
|
|
|
|
i -= 1
|
|
|
|
continue
|
2011-11-22 18:49:36 +01:00
|
|
|
user = User()
|
|
|
|
user.last_name = last_name
|
|
|
|
user.first_name = first_name
|
|
|
|
user.username = gen_username(first_name, last_name)
|
|
|
|
#user.email = email
|
|
|
|
user.save()
|
|
|
|
profile = Profile()
|
|
|
|
profile.user = user
|
|
|
|
profile.gender = gender
|
|
|
|
profile.group = group
|
|
|
|
profile.type = type
|
|
|
|
profile.committee = committee
|
2012-04-02 08:36:22 +02:00
|
|
|
profile.comment = comment
|
2011-11-22 18:49:36 +01:00
|
|
|
profile.firstpassword = gen_password()
|
|
|
|
profile.user.set_password(profile.firstpassword)
|
|
|
|
profile.save()
|
|
|
|
|
|
|
|
if type == 'delegate':
|
2012-05-17 22:03:48 +02:00
|
|
|
delegate = Group.objects.get(name='Delegierter')
|
2011-11-22 18:49:36 +01:00
|
|
|
user.groups.add(delegate)
|
|
|
|
else:
|
|
|
|
observer = Group.objects.get(name='Beobachter')
|
|
|
|
user.groups.add(observer)
|
|
|
|
|
2012-04-12 19:11:07 +02:00
|
|
|
if form.cleaned_data['application_handling'] == 'REASSIGN':
|
|
|
|
# live remap
|
|
|
|
skey = '%s_%s' % (user.first_name, user.last_name)
|
|
|
|
if skey in old_users:
|
|
|
|
for appid in old_users[skey]:
|
|
|
|
try:
|
|
|
|
application = Application.objects.get(id=appid)
|
|
|
|
application.submitter = user
|
|
|
|
application.save()
|
|
|
|
application.writelog(_('Reassigned to "%s" after (re)importing users.') % ("%s %s" % (user.first_name, user.last_name)), user=request.user)
|
|
|
|
applications_mapped += 1
|
|
|
|
except Application.DoesNotExist:
|
|
|
|
messages.error(request, _('Could not reassing application %d - object not found!') % appid)
|
|
|
|
del old_users[skey]
|
|
|
|
|
|
|
|
if old_users:
|
|
|
|
# mark all applications without a valid user as 'needs review'
|
|
|
|
# this will account for *all* applications if application_mode == 'INREVIEW'
|
|
|
|
for skey in old_users:
|
|
|
|
for appid in old_users[skey]:
|
|
|
|
try:
|
|
|
|
application = Application.objects.get(id=appid)
|
|
|
|
if application.status != 'rev':
|
|
|
|
application.set_status(user=request.user, status='rev', force=True)
|
|
|
|
applications_review += 1
|
|
|
|
except Application.DoesNotExist:
|
|
|
|
messages.error(request, _('Could not reassing application %d - object not found!') % appid)
|
|
|
|
|
|
|
|
if applications_review:
|
|
|
|
messages.warning(request, ungettext('%d application could not be reassigned and needs a review!',
|
|
|
|
'%d applications could not be reassigned and need a review!', applications_review) % applications_review)
|
|
|
|
if applications_mapped:
|
|
|
|
messages.success(request, ungettext('%d application was successfully reassigned.',
|
|
|
|
'%d applications were successfully reassigned.', applications_mapped) % applications_mapped)
|
|
|
|
if applications_removed:
|
|
|
|
messages.warning(request, ungettext('%d application was discarded.',
|
|
|
|
'%d applications were discarded.', applications_removed) % applications_removed)
|
|
|
|
|
2012-04-13 22:02:14 +02:00
|
|
|
if i > 0:
|
|
|
|
messages.success(request, _('%d new participants were successfully imported.') % i)
|
2012-04-02 08:36:22 +02:00
|
|
|
return redirect(reverse('user_overview'))
|
2011-11-22 18:49:36 +01:00
|
|
|
except csv.Error:
|
|
|
|
message.error(request, _('Import aborted because of severe errors in the input file.'))
|
2012-04-13 22:33:47 +02:00
|
|
|
except UnicodeDecodeError:
|
|
|
|
messages.error(request, _('Import file has wrong character encoding, only UTF-8 is supported!'))
|
2011-07-31 10:46:29 +02:00
|
|
|
else:
|
|
|
|
messages.error(request, _('Please check the form for errors.'))
|
|
|
|
else:
|
|
|
|
messages.warning(request, _("Attention: All existing participants will be removed if you import new participants."))
|
2012-04-12 19:11:07 +02:00
|
|
|
if Application.objects.all():
|
|
|
|
messages.warning(request, _("Attention: Supporters from all existing applications will be removed."))
|
|
|
|
messages.warning(request, _("Attention: Applications which can't be mapped to new users will be set to 'Needs Review'."))
|
2011-07-31 10:46:29 +02:00
|
|
|
form = UserImportForm()
|
|
|
|
return {
|
|
|
|
'form': form,
|
2011-09-03 17:17:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-09-04 12:21:58 +02:00
|
|
|
@permission_required('participant.can_manage_participant')
|
2011-09-03 17:17:29 +02:00
|
|
|
def reset_password(request, user_id):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Reset the Password.
|
|
|
|
"""
|
2011-09-03 17:17:29 +02:00
|
|
|
user = User.objects.get(pk=user_id)
|
|
|
|
if request.method == 'POST':
|
|
|
|
user.profile.reset_password()
|
2012-07-07 15:26:00 +02:00
|
|
|
messages.success(request,
|
|
|
|
_('The Password for <b>%s</b> was successfully reset.') % user)
|
2011-09-03 17:17:29 +02:00
|
|
|
else:
|
2012-07-07 15:26:00 +02:00
|
|
|
gen_confirm_form(request,
|
|
|
|
_('Do you really want to reset the password for <b>%s</b>?') % user,
|
|
|
|
reverse('user_reset_password', args=[user_id]))
|
2011-09-03 17:17:29 +02:00
|
|
|
return redirect(reverse('user_edit', args=[user_id]))
|
2012-03-18 17:11:58 +01:00
|
|
|
|
|
|
|
|
|
|
|
def register_tab(request):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Register the participant tab.
|
|
|
|
"""
|
|
|
|
selected = request.path.startswith('/participant/')
|
2012-03-18 17:11:58 +01:00
|
|
|
return Tab(
|
|
|
|
title=_('Participants'),
|
|
|
|
url=reverse('user_overview'),
|
2012-07-07 15:26:00 +02:00
|
|
|
permission=request.user.has_perm('participant.can_see_participant')
|
|
|
|
or request.user.has_perm('participant.can_manage_participant'),
|
2012-03-18 17:11:58 +01:00
|
|
|
selected=selected,
|
|
|
|
)
|
2012-04-15 12:39:28 +02:00
|
|
|
|
|
|
|
|
2012-04-20 23:23:50 +02:00
|
|
|
class ParticipantsListPDF(PDFView):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Generate the userliste as PDF.
|
|
|
|
"""
|
2012-04-20 23:23:50 +02:00
|
|
|
permission_required = 'participant.can_see_participant'
|
|
|
|
filename = _("Participant-list")
|
|
|
|
document_title = _('List of Participants')
|
|
|
|
|
|
|
|
def append_to_pdf(self, story):
|
2012-07-07 15:26:00 +02:00
|
|
|
data= [['#', _('Last Name'), _('First Name'), _('Group'), _('Type'),
|
|
|
|
_('Committee')]]
|
2012-04-20 23:23:50 +02:00
|
|
|
sort = 'last_name'
|
|
|
|
counter = 0
|
|
|
|
for user in User.objects.all().order_by(sort):
|
|
|
|
try:
|
|
|
|
counter += 1
|
|
|
|
user.get_profile()
|
|
|
|
data.append([counter,
|
2012-07-07 15:26:00 +02:00
|
|
|
Paragraph(user.last_name, stylesheet['Tablecell']),
|
|
|
|
Paragraph(user.first_name, stylesheet['Tablecell']),
|
|
|
|
Paragraph(user.profile.group, stylesheet['Tablecell']),
|
|
|
|
Paragraph(user.profile.get_type_display(),
|
|
|
|
stylesheet['Tablecell']),
|
|
|
|
Paragraph(user.profile.committee, stylesheet['Tablecell']),
|
|
|
|
])
|
2012-04-20 23:23:50 +02:00
|
|
|
except Profile.DoesNotExist:
|
|
|
|
counter -= 1
|
|
|
|
pass
|
2012-07-07 15:26:00 +02:00
|
|
|
t = LongTable(data,
|
|
|
|
style=[
|
|
|
|
('VALIGN',(0,0),(-1,-1), 'TOP'),
|
|
|
|
('LINEABOVE',(0,0),(-1,0),2,colors.black),
|
|
|
|
('LINEABOVE',(0,1),(-1,1),1,colors.black),
|
|
|
|
('LINEBELOW',(0,-1),(-1,-1),2,colors.black),
|
|
|
|
('ROWBACKGROUNDS', (0, 1), (-1, -1),
|
|
|
|
(colors.white, (.9, .9, .9))),
|
|
|
|
])
|
2012-04-20 23:23:50 +02:00
|
|
|
t._argW[0]=0.75*cm
|
|
|
|
story.append(t)
|
|
|
|
|
|
|
|
|
|
|
|
class ParticipantsPasswordsPDF(PDFView):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Generate the Welcomepaper for the users.
|
|
|
|
"""
|
2012-04-20 23:23:50 +02:00
|
|
|
permission_required = 'participant.can_manage_participant'
|
|
|
|
filename = _("Participant-passwords")
|
|
|
|
top_space = 0
|
2012-04-27 22:47:41 +02:00
|
|
|
|
2012-04-29 18:58:51 +02:00
|
|
|
def get_template(self, buffer):
|
2012-07-07 15:26:00 +02:00
|
|
|
return SimpleDocTemplate(buffer, topMargin=-6, bottomMargin=-6,
|
|
|
|
leftMargin=0, rightMargin=0, showBoundary=False)
|
2012-04-29 18:58:51 +02:00
|
|
|
|
|
|
|
def build_document(self, pdf_document, story):
|
|
|
|
pdf_document.build(story)
|
|
|
|
|
2012-04-20 23:23:50 +02:00
|
|
|
def append_to_pdf(self, story):
|
|
|
|
data= []
|
|
|
|
participant_pdf_system_url = config["participant_pdf_system_url"]
|
|
|
|
participant_pdf_welcometext = config["participant_pdf_welcometext"]
|
|
|
|
for user in User.objects.all().order_by('last_name'):
|
|
|
|
try:
|
|
|
|
user.get_profile()
|
|
|
|
cell = []
|
|
|
|
cell.append(Spacer(0,0.8*cm))
|
2012-07-07 15:26:00 +02:00
|
|
|
cell.append(Paragraph(_("Account for OpenSlides"),
|
|
|
|
stylesheet['Ballot_title']))
|
|
|
|
cell.append(Paragraph(_("for %s") % (user.profile),
|
|
|
|
stylesheet['Ballot_subtitle']))
|
2012-04-20 23:23:50 +02:00
|
|
|
cell.append(Spacer(0,0.5*cm))
|
2012-07-07 15:26:00 +02:00
|
|
|
cell.append(Paragraph(_("User: %s") % (user.username),
|
|
|
|
stylesheet['Monotype']))
|
|
|
|
cell.append(Paragraph(_("Password: %s")
|
|
|
|
% (user.profile.firstpassword), stylesheet['Monotype']))
|
2012-04-20 23:23:50 +02:00
|
|
|
cell.append(Spacer(0,0.5*cm))
|
2012-07-07 15:26:00 +02:00
|
|
|
cell.append(Paragraph(_("URL: %s")
|
|
|
|
% (participant_pdf_system_url),
|
|
|
|
stylesheet['Ballot_option']))
|
2012-06-06 13:51:54 +02:00
|
|
|
cell.append(Spacer(0,0.5*cm))
|
2012-04-20 23:23:50 +02:00
|
|
|
cell2 = []
|
|
|
|
cell2.append(Spacer(0,0.8*cm))
|
|
|
|
if participant_pdf_welcometext is not None:
|
2012-07-07 15:26:00 +02:00
|
|
|
cell2.append(Paragraph(
|
|
|
|
participant_pdf_welcometext.replace('\r\n','<br/>'),
|
|
|
|
stylesheet['Ballot_subtitle']))
|
2012-04-27 22:47:41 +02:00
|
|
|
|
2012-04-20 23:23:50 +02:00
|
|
|
data.append([cell,cell2])
|
|
|
|
except Profile.DoesNotExist:
|
|
|
|
pass
|
2012-04-27 22:47:41 +02:00
|
|
|
|
2012-04-20 23:23:50 +02:00
|
|
|
t=Table(data, 10.5*cm, 7.42*cm)
|
2012-07-07 15:26:00 +02:00
|
|
|
t.setStyle(TableStyle([
|
|
|
|
('LINEBELOW', (0,0), (-1,0), 0.25, colors.grey),
|
|
|
|
('LINEBELOW', (0,1), (-1,1), 0.25, colors.grey),
|
|
|
|
('LINEBELOW', (0,1), (-1,-1), 0.25, colors.grey),
|
|
|
|
('VALIGN', (0,0), (-1,-1), 'TOP'),
|
|
|
|
]))
|
2012-04-20 23:23:50 +02:00
|
|
|
story.append(t)
|
|
|
|
|
|
|
|
|
2012-04-15 12:39:28 +02:00
|
|
|
class Config(FormView):
|
2012-07-07 15:26:00 +02:00
|
|
|
"""
|
|
|
|
Config page for the participant app.
|
|
|
|
"""
|
2012-04-15 12:39:28 +02:00
|
|
|
permission_required = 'config.can_manage_config'
|
|
|
|
form_class = ConfigForm
|
|
|
|
template_name = 'participant/config.html'
|
|
|
|
|
|
|
|
def get_initial(self):
|
|
|
|
return {
|
|
|
|
'participant_pdf_system_url': config['participant_pdf_system_url'],
|
2012-07-07 15:26:00 +02:00
|
|
|
'participant_pdf_welcometext': config['participant_pdf_welcometext']
|
2012-04-15 12:39:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
def form_valid(self, form):
|
2012-07-07 15:26:00 +02:00
|
|
|
config['participant_pdf_system_url'] = \
|
|
|
|
form.cleaned_data['participant_pdf_system_url']
|
|
|
|
config['participant_pdf_welcometext'] = \
|
|
|
|
form.cleaned_data['participant_pdf_welcometext']
|
|
|
|
messages.success(self.request,
|
|
|
|
_('Participants settings successfully saved.'))
|
2012-04-18 16:57:33 +02:00
|
|
|
return super(Config, self).form_valid(form)
|