Example #1
0
 def setUp(self):
     self.admin = User(username='******')
     self.admin.save()
     self.anonym = User(username='******')
     self.anonym.save()
     self.app1 = Motion(submitter=self.admin)
     self.app1.save()
Example #2
0
    def test_set_identifier_allready_set(self):
        """
        If the motion already has a identifier, the method does nothing.
        """
        motion = Motion(identifier='My test identifier')

        motion.set_identifier()

        self.assertEqual(motion.identifier, 'My test identifier')
Example #3
0
    def test_set_identifier_manually(self):
        """
        If the config is set to manually, the method does nothing.
        """
        config['motion_identifier'] = 'manually'
        motion = Motion()

        motion.set_identifier()

        # If the identifier should be set manually, the method does nothing
        self.assertIsNone(motion.identifier)
Example #4
0
    def test_set_identifier_amendment(self):
        """
        If the motion is an amendment, the identifier is the identifier from the
        parent + a suffix.
        """
        config['motion_amendments_enabled'] = True
        self.motion.identifier = 'Parent identifier'
        self.motion.save()
        motion = Motion(parent=self.motion)

        motion.set_identifier()

        self.assertEqual(motion.identifier, 'Parent identifier A 1')
Example #5
0
    def test_version_data(self):
        motion = Motion()
        self.assertEqual(motion.title, '')
        with self.assertRaises(AttributeError):
            self._title

        motion.title = 'title'
        self.assertEqual(motion._title, 'title')

        motion.text = 'text'
        self.assertEqual(motion._text, 'text')

        motion.reason = 'reason'
        self.assertEqual(motion._reason, 'reason')
Example #6
0
    def test_set_identifier_second_amendment(self):
        """
        If a motion has already an amendment, the second motion gets another
        identifier.
        """
        config['motion_amendments_enabled'] = True
        self.motion.identifier = 'Parent identifier'
        self.motion.save()
        Motion.objects.create(title='Amendment1', parent=self.motion)
        motion = Motion(parent=self.motion)

        motion.set_identifier()

        self.assertEqual(motion.identifier, 'Parent identifier A 2')
Example #7
0
    def test_version_data(self):
        motion = Motion()
        self.assertEqual(motion.title, '')
        with self.assertRaises(AttributeError):
            self._title

        motion.title = 'title'
        self.assertEqual(motion._title, 'title')

        motion.text = 'text'
        self.assertEqual(motion._text, 'text')

        motion.reason = 'reason'
        self.assertEqual(motion._reason, 'reason')
Example #8
0
 def setUp(self):
     self.admin = User(username='******')
     self.admin.save()
     self.anonym = User(username='******')
     self.anonym.save()
     self.app1 = Motion(submitter=self.admin)
     self.app1.save()
Example #9
0
class MotionTest(TestCase):
    def setUp(self):
        self.admin = User(username='******')
        self.admin.save()
        self.anonym = User(username='******')
        self.anonym.save()
        self.app1 = Motion(submitter=self.admin)
        self.app1.save()

    def refresh(self):
        self.app1 = Motion.objects.get(pk=self.app1.id)

    def testVersion(self):
        self.assertTrue(self.app1.versions.exists())
        self.assertEqual(self.app1.last_version, self.app1.versions[0])
        self.assertEqual(self.app1.creation_time, self.app1.last_version.time)

        self.app1.title = "app1"
        self.app1.save()
        self.refresh()

        self.assertEqual(self.app1.versions.count(), 2)
        self.assertEqual(self.app1.last_version, self.app1.versions[1])
Example #10
0
class MotionTest(TestCase):
    def setUp(self):
        self.admin = User(username='******')
        self.admin.save()
        self.anonym = User(username='******')
        self.anonym.save()
        self.app1 = Motion(submitter=self.admin)
        self.app1.save()

    def refresh(self):
        self.app1 = Motion.objects.get(pk=self.app1.id)

    def testVersion(self):
        self.assertTrue(self.app1.versions.exists())
        self.assertEqual(self.app1.last_version, self.app1.versions[0])
        self.assertEqual(self.app1.creation_time, self.app1.last_version.time)

        self.app1.title = "app1"
        self.app1.save()
        self.refresh()

        self.assertEqual(self.app1.versions.count(), 2)
        self.assertEqual(self.app1.last_version, self.app1.versions[1])
Example #11
0
    def test_do_not_create_new_version_when_permit_old_version(self):
        motion = Motion()
        motion.title = 'foo'
        motion.text = 'bar'
        motion.save()
        first_version = motion.get_last_version()

        motion = Motion.objects.get(pk=motion.pk)
        motion.title = 'New Title'
        motion.save(use_version=motion.get_new_version())
        new_version = motion.get_last_version()
        self.assertEqual(motion.versions.count(), 2)

        motion.active_version = new_version
        motion.save()
        self.assertEqual(motion.versions.count(), 2)

        motion.active_version = first_version
        motion.save(use_version=False)
        self.assertEqual(motion.versions.count(), 2)
Example #12
0
def motion_import(request):
    if request.method == 'POST':
        form = MotionImportForm(request.POST, request.FILES)
        if form.is_valid():
            import_permitted = form.cleaned_data['import_permitted']
            try:
                # check for valid encoding (will raise UnicodeDecodeError if not)
                request.FILES['csvfile'].read().decode('utf-8')
                request.FILES['csvfile'].seek(0)

                users_generated = 0
                motions_generated = 0
                motions_modified = 0
                groups_assigned = 0
                groups_generated = 0
                with transaction.commit_on_success():
                    dialect = csv.Sniffer().sniff(request.FILES['csvfile'].readline())
                    dialect = csv_ext.patchup(dialect)
                    request.FILES['csvfile'].seek(0)
                    for (lno, line) in enumerate(csv.reader(request.FILES['csvfile'], dialect=dialect)):
                        # basic input verification
                        if lno < 1:
                            continue
                        try:
                            (number, title, text, reason, first_name, last_name, is_group) = line[:7]
                            if is_group.strip().lower() in ['y', 'j', 't', 'yes', 'ja', 'true', '1', 1]:
                                is_group = True
                            else:
                                is_group = False
                        except ValueError:
                            messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
                            continue
                        form = MotionForm({'title': title, 'text': text, 'reason': reason})
                        if not form.is_valid():
                            messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
                            continue
                        if number:
                            try:
                                number = abs(long(number))
                                if number < 1:
                                    messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
                                    continue
                            except ValueError:
                                messages.error(request, _('Ignoring malformed line %d in import file.') % (lno + 1))
                                continue

                        if is_group:
                            # fetch existing groups or issue an error message
                            try:
                                user = Group.objects.get(name=last_name)
                                if user.group_as_person == False:
                                    messages.error(request, _('Ignoring line %d because the assigned group may not act as a person.') % (lno + 1))
                                    continue
                                else:
                                    user = get_person(user.person_id)

                                groups_assigned += 1
                            except Group.DoesNotExist:
                                group = Group()
                                group.group_as_person = True
                                group.description = _('Created by motion import.')
                                group.name = last_name
                                group.save()
                                groups_generated += 1

                                user = get_person(group.person_id)
                        else:
                            # fetch existing users or create new users as needed
                            try:
                                user = User.objects.get(first_name=first_name, last_name=last_name)
                            except User.DoesNotExist:
                                user = None
                            if user is None:
                                if not first_name or not last_name:
                                    messages.error(request, _('Ignoring line %d because it contains an incomplete first / last name pair.') % (lno + 1))
                                    continue

                                user = User()
                                user.last_name = last_name
                                user.first_name = first_name
                                user.username = gen_username(first_name, last_name)
                                user.structure_level = ''
                                user.committee = ''
                                user.gender = ''
                                user.type = ''
                                user.default_password = gen_password()
                                user.save()
                                user.reset_password()
                                users_generated += 1
                        # create / modify the motion
                        motion = None
                        if number:
                            try:
                                motion = Motion.objects.get(number=number)
                                motions_modified += 1
                            except Motion.DoesNotExist:
                                motion = None
                        if motion is None:
                            motion = Motion(submitter=user)
                            if number:
                                motion.number = number
                            motions_generated += 1

                        motion.title = form.cleaned_data['title']
                        motion.text = form.cleaned_data['text']
                        motion.reason = form.cleaned_data['reason']
                        if import_permitted:
                            motion.status = 'per'

                        motion.save(user, trivial_change=True)

                if motions_generated:
                    messages.success(request, ungettext('%d motion was successfully imported.',
                                                '%d motions were successfully imported.', motions_generated) % motions_generated)
                if motions_modified:
                    messages.success(request, ungettext('%d motion was successfully modified.',
                                                '%d motions were successfully modified.', motions_modified) % motions_modified)
                if users_generated:
                    messages.success(request, ungettext('%d new user was added.', '%d new users were added.', users_generated) % users_generated)

                if groups_generated:
                    messages.success(request, ungettext('%d new group was added.', '%d new groups were added.', groups_generated) % groups_generated)

                if groups_assigned:
                    messages.success(request, ungettext('%d group assigned to motions.', '%d groups assigned to motions.', groups_assigned) % groups_assigned)
                return redirect(reverse('motion_overview'))

            except csv.Error:
                messages.error(request, _('Import aborted because of severe errors in the input file.'))
            except UnicodeDecodeError:
                messages.error(request, _('Import file has wrong character encoding, only UTF-8 is supported!'))
        else:
            messages.error(request, _('Please check the form for errors.'))
    else:
        messages.warning(request, _("Attention: Existing motions will be modified if you import new motions with the same number."))
        messages.warning(request, _("Attention: Importing an motions without a number multiple times will create duplicates."))
        form = MotionImportForm()
    return {
        'form': form,
    }
Example #13
0
def edit(request, motion_id=None):
    """
    View a form to edit or create a motion.
    """
    if request.user.has_perm('motion.can_manage_motion'):
        is_manager = True
    else:
        is_manager = False

    if not is_manager \
    and not request.user.has_perm('motion.can_create_motion'):
        messages.error(request, _("You have not the necessary rights to create or edit motions."))
        return redirect(reverse('motion_overview'))
    if motion_id is not None:
        motion = Motion.objects.get(id=motion_id)
        if not 'edit' in motion.get_allowed_actions(request.user):
            messages.error(request, _("You can not edit this motion."))
            return redirect(reverse('motion_view', args=[motion.id]))
        actions = motion.get_allowed_actions(user=request.user)
    else:
        motion = None
        actions = None

    formclass = MotionFormTrivialChanges \
        if config['motion_allow_trivial_change'] and motion_id \
        else MotionForm

    managerformclass = MotionManagerFormSupporter \
                       if config['motion_min_supporters'] \
                       else MotionManagerForm

    if request.method == 'POST':
        dataform = formclass(request.POST, prefix="data")
        valid = dataform.is_valid()

        if is_manager:
            managerform = managerformclass(request.POST,
                            instance=motion,
                            prefix="manager")
            valid = valid and managerform.is_valid()
        else:
            managerform = None

        if valid:
            if is_manager:
                motion = managerform.save(commit=False)
            elif motion_id is None:
                motion = Motion(submitter=request.user)
            motion.title = dataform.cleaned_data['title']
            motion.text = dataform.cleaned_data['text']
            motion.reason = dataform.cleaned_data['reason']

            try:
                trivial_change = config['motion_allow_trivial_change'] \
                    and dataform.cleaned_data['trivial_change']
            except KeyError:
                trivial_change = False
            motion.save(request.user, trivial_change=trivial_change)
            if is_manager:
                try:
                    new_supporters = set(managerform.cleaned_data['supporter'])
                except KeyError:
                    # The managerform has no field for the supporters
                    pass
                else:
                    old_supporters = set(motion.supporters)
                    # add new supporters
                    for supporter in new_supporters.difference(old_supporters):
                        motion.support(supporter)
                    # remove old supporters
                    for supporter in old_supporters.difference(new_supporters):
                        motion.unsupport(supporter)

            if motion_id is None:
                messages.success(request, _('New motion was successfully created.'))
            else:
                messages.success(request, _('Motion was successfully modified.'))

            if not 'apply' in request.POST:
                return redirect(reverse('motion_view', args=[motion.id]))
            if motion_id is None:
                return redirect(reverse('motion_edit', args=[motion.id]))
        else:
            messages.error(request, _('Please check the form for errors.'))
    else:
        if motion_id is None:
            initial = {'text': config['motion_preamble']}
        else:
            if motion.status == "pub" and motion.supporters:
                if request.user.has_perm('motion.can_manage_motion'):
                    messages.warning(request, _("Attention: Do you really want to edit this motion? The supporters will <b>not</b> be removed automatically because you can manage motions. Please check if the supports are valid after your changing!"))
                else:
                    messages.warning(request, _("Attention: Do you really want to edit this motion? All <b>%s</b> supporters will be removed! Try to convince the supporters again.") % motion.count_supporters() )
            initial = {'title': motion.title,
                       'text': motion.text,
                       'reason': motion.reason}

        dataform = formclass(initial=initial, prefix="data")
        if is_manager:
            if motion_id is None:
                initial = {'submitter': request.user.person_id}
            else:
                initial = {'submitter': motion.submitter.person_id,
                    'supporter': [supporter.person_id for supporter in motion.supporters]}
            managerform = managerformclass(initial=initial,
                instance=motion, prefix="manager")
        else:
            managerform = None
    return {
        'form': dataform,
        'managerform': managerform,
        'motion': motion,
        'actions': actions,
    }
Example #14
0
    def test_do_not_create_new_version_when_permit_old_version(self):
        motion = Motion()
        motion.title = 'foo'
        motion.text = 'bar'
        motion.save()
        first_version = motion.get_last_version()

        motion = Motion.objects.get(pk=motion.pk)
        motion.title = 'New Title'
        motion.save(use_version=motion.get_new_version())
        new_version = motion.get_last_version()
        self.assertEqual(motion.versions.count(), 2)

        motion.active_version = new_version
        motion.save()
        self.assertEqual(motion.versions.count(), 2)

        motion.active_version = first_version
        motion.save(use_version=False)
        self.assertEqual(motion.versions.count(), 2)
Example #15
0
def motion_import(request):
    if request.method == 'POST':
        form = MotionImportForm(request.POST, request.FILES)
        if form.is_valid():
            import_permitted = form.cleaned_data['import_permitted']
            try:
                # check for valid encoding (will raise UnicodeDecodeError if not)
                request.FILES['csvfile'].read().decode('utf-8')
                request.FILES['csvfile'].seek(0)

                users_generated = 0
                motions_generated = 0
                motions_modified = 0
                groups_assigned = 0
                groups_generated = 0
                with transaction.commit_on_success():
                    dialect = csv.Sniffer().sniff(
                        request.FILES['csvfile'].readline())
                    dialect = csv_ext.patchup(dialect)
                    request.FILES['csvfile'].seek(0)
                    for (lno, line) in enumerate(
                            csv.reader(request.FILES['csvfile'],
                                       dialect=dialect)):
                        # basic input verification
                        if lno < 1:
                            continue
                        try:
                            (number, title, text, reason, first_name,
                             last_name, is_group) = line[:7]
                            if is_group.strip().lower() in [
                                    'y', 'j', 't', 'yes', 'ja', 'true', '1', 1
                            ]:
                                is_group = True
                            else:
                                is_group = False
                        except ValueError:
                            messages.error(
                                request,
                                _('Ignoring malformed line %d in import file.')
                                % (lno + 1))
                            continue
                        form = MotionForm({
                            'title': title,
                            'text': text,
                            'reason': reason
                        })
                        if not form.is_valid():
                            messages.error(
                                request,
                                _('Ignoring malformed line %d in import file.')
                                % (lno + 1))
                            continue
                        if number:
                            try:
                                number = abs(long(number))
                                if number < 1:
                                    messages.error(
                                        request,
                                        _('Ignoring malformed line %d in import file.'
                                          ) % (lno + 1))
                                    continue
                            except ValueError:
                                messages.error(
                                    request,
                                    _('Ignoring malformed line %d in import file.'
                                      ) % (lno + 1))
                                continue

                        if is_group:
                            # fetch existing groups or issue an error message
                            try:
                                user = Group.objects.get(name=last_name)
                                if user.group_as_person == False:
                                    messages.error(
                                        request,
                                        _('Ignoring line %d because the assigned group may not act as a person.'
                                          ) % (lno + 1))
                                    continue
                                else:
                                    user = get_person(user.person_id)

                                groups_assigned += 1
                            except Group.DoesNotExist:
                                group = Group()
                                group.group_as_person = True
                                group.description = _(
                                    'Created by motion import.')
                                group.name = last_name
                                group.save()
                                groups_generated += 1

                                user = get_person(group.person_id)
                        else:
                            # fetch existing users or create new users as needed
                            try:
                                user = User.objects.get(first_name=first_name,
                                                        last_name=last_name)
                            except User.DoesNotExist:
                                user = None
                            if user is None:
                                if not first_name or not last_name:
                                    messages.error(
                                        request,
                                        _('Ignoring line %d because it contains an incomplete first / last name pair.'
                                          ) % (lno + 1))
                                    continue

                                user = User()
                                user.last_name = last_name
                                user.first_name = first_name
                                user.username = gen_username(
                                    first_name, last_name)
                                user.structure_level = ''
                                user.committee = ''
                                user.gender = ''
                                user.type = ''
                                user.default_password = gen_password()
                                user.save()
                                user.reset_password()
                                users_generated += 1
                        # create / modify the motion
                        motion = None
                        if number:
                            try:
                                motion = Motion.objects.get(number=number)
                                motions_modified += 1
                            except Motion.DoesNotExist:
                                motion = None
                        if motion is None:
                            motion = Motion(submitter=user)
                            if number:
                                motion.number = number
                            motions_generated += 1

                        motion.title = form.cleaned_data['title']
                        motion.text = form.cleaned_data['text']
                        motion.reason = form.cleaned_data['reason']
                        if import_permitted:
                            motion.status = 'per'

                        motion.save(user, trivial_change=True)

                if motions_generated:
                    messages.success(
                        request,
                        ungettext('%d motion was successfully imported.',
                                  '%d motions were successfully imported.',
                                  motions_generated) % motions_generated)
                if motions_modified:
                    messages.success(
                        request,
                        ungettext('%d motion was successfully modified.',
                                  '%d motions were successfully modified.',
                                  motions_modified) % motions_modified)
                if users_generated:
                    messages.success(
                        request,
                        ungettext('%d new user was added.',
                                  '%d new users were added.', users_generated)
                        % users_generated)

                if groups_generated:
                    messages.success(
                        request,
                        ungettext('%d new group was added.',
                                  '%d new groups were added.',
                                  groups_generated) % groups_generated)

                if groups_assigned:
                    messages.success(
                        request,
                        ungettext('%d group assigned to motions.',
                                  '%d groups assigned to motions.',
                                  groups_assigned) % groups_assigned)
                return redirect(reverse('motion_overview'))

            except csv.Error:
                messages.error(
                    request,
                    _('Import aborted because of severe errors in the input file.'
                      ))
            except UnicodeDecodeError:
                messages.error(
                    request,
                    _('Import file has wrong character encoding, only UTF-8 is supported!'
                      ))
        else:
            messages.error(request, _('Please check the form for errors.'))
    else:
        messages.warning(
            request,
            _("Attention: Existing motions will be modified if you import new motions with the same number."
              ))
        messages.warning(
            request,
            _("Attention: Importing an motions without a number multiple times will create duplicates."
              ))
        form = MotionImportForm()
    return {
        'form': form,
    }
Example #16
0
def edit(request, motion_id=None):
    """
    View a form to edit or create a motion.
    """
    if request.user.has_perm('motion.can_manage_motion'):
        is_manager = True
    else:
        is_manager = False

    if not is_manager \
    and not request.user.has_perm('motion.can_create_motion'):
        messages.error(
            request,
            _("You have not the necessary rights to create or edit motions."))
        return redirect(reverse('motion_overview'))
    if motion_id is not None:
        motion = Motion.objects.get(id=motion_id)
        if not 'edit' in motion.get_allowed_actions(request.user):
            messages.error(request, _("You can not edit this motion."))
            return redirect(reverse('motion_view', args=[motion.id]))
        actions = motion.get_allowed_actions(user=request.user)
    else:
        motion = None
        actions = None

    formclass = MotionFormTrivialChanges \
        if config['motion_allow_trivial_change'] and motion_id \
        else MotionForm

    managerformclass = MotionManagerFormSupporter \
                       if config['motion_min_supporters'] \
                       else MotionManagerForm

    if request.method == 'POST':
        dataform = formclass(request.POST, prefix="data")
        valid = dataform.is_valid()

        if is_manager:
            managerform = managerformclass(request.POST,
                                           instance=motion,
                                           prefix="manager")
            valid = valid and managerform.is_valid()
        else:
            managerform = None

        if valid:
            if is_manager:
                motion = managerform.save(commit=False)
            elif motion_id is None:
                motion = Motion(submitter=request.user)
            motion.title = dataform.cleaned_data['title']
            motion.text = dataform.cleaned_data['text']
            motion.reason = dataform.cleaned_data['reason']

            try:
                trivial_change = config['motion_allow_trivial_change'] \
                    and dataform.cleaned_data['trivial_change']
            except KeyError:
                trivial_change = False
            motion.save(request.user, trivial_change=trivial_change)
            if is_manager:
                try:
                    new_supporters = set(managerform.cleaned_data['supporter'])
                except KeyError:
                    # The managerform has no field for the supporters
                    pass
                else:
                    old_supporters = set(motion.supporters)
                    # add new supporters
                    for supporter in new_supporters.difference(old_supporters):
                        motion.support(supporter)
                    # remove old supporters
                    for supporter in old_supporters.difference(new_supporters):
                        motion.unsupport(supporter)

            if motion_id is None:
                messages.success(request,
                                 _('New motion was successfully created.'))
            else:
                messages.success(request,
                                 _('Motion was successfully modified.'))

            if not 'apply' in request.POST:
                return redirect(reverse('motion_view', args=[motion.id]))
            if motion_id is None:
                return redirect(reverse('motion_edit', args=[motion.id]))
        else:
            messages.error(request, _('Please check the form for errors.'))
    else:
        if motion_id is None:
            initial = {'text': config['motion_preamble']}
        else:
            if motion.status == "pub" and motion.supporters:
                if request.user.has_perm('motion.can_manage_motion'):
                    messages.warning(
                        request,
                        _("Attention: Do you really want to edit this motion? The supporters will <b>not</b> be removed automatically because you can manage motions. Please check if the supports are valid after your changing!"
                          ))
                else:
                    messages.warning(
                        request,
                        _("Attention: Do you really want to edit this motion? All <b>%s</b> supporters will be removed! Try to convince the supporters again."
                          ) % motion.count_supporters())
            initial = {
                'title': motion.title,
                'text': motion.text,
                'reason': motion.reason
            }

        dataform = formclass(initial=initial, prefix="data")
        if is_manager:
            if motion_id is None:
                initial = {'submitter': request.user.person_id}
            else:
                initial = {
                    'submitter':
                    motion.submitter.person_id,
                    'supporter':
                    [supporter.person_id for supporter in motion.supporters]
                }
            managerform = managerformclass(initial=initial,
                                           instance=motion,
                                           prefix="manager")
        else:
            managerform = None
    return {
        'form': dataform,
        'managerform': managerform,
        'motion': motion,
        'actions': actions,
    }