示例#1
0
    def test_return_task_assignment(self):
        user = User.objects.create_user('testuser', password='******')

        task_assignment = TaskAssignment(assigned_to=user, task=self.task)
        task_assignment.save()

        client = django.test.Client()
        client.login(username='******', password='******')
        response = client.get(
            reverse('return_task_assignment',
                    kwargs={
                        'task_id': self.task.id,
                        'task_assignment_id': task_assignment.id
                    }))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['Location'], reverse('index'))
示例#2
0
def accept_task(request, batch_id, task_id):
    """
    Accept task from preview

    Security behavior:
    - If the user does not have permission to access the Batch+Task, they
      are redirected to the index page with an error message.
    """
    try:
        batch = Batch.objects.get(id=batch_id)
    except ObjectDoesNotExist:
        messages.error(request,
                       u'Cannot find Task Batch with ID {}'.format(batch_id))
        return redirect(index)
    try:
        task = Task.objects.get(id=task_id)
    except ObjectDoesNotExist:
        messages.error(request, u'Cannot find Task with ID {}'.format(task_id))
        return redirect(index)

    try:
        with transaction.atomic():
            # Lock access to the specified Task
            Task.objects.filter(id=task_id).select_for_update()

            # Will throw ObjectDoesNotExist exception if Task no longer available
            batch.available_tasks_for(request.user).get(id=task_id)

            ha = TaskAssignment()
            if request.user.is_authenticated:
                ha.assigned_to = request.user
            else:
                ha.assigned_to = None
            ha.task = task
            ha.save()
            if request.user.is_authenticated:
                logger.info('User(%i) accepted Task(%i)', request.user.id,
                            task.id)
            else:
                logger.info('Anonymous user accepted Task(%i)', task.id)
    except ObjectDoesNotExist:
        messages.error(
            request,
            u'The Task with ID {} is no longer available'.format(task_id))
        return redirect(index)

    return redirect(task_assignment, task.id, ha.id)
示例#3
0
    def test_accept_next_task__no_more_tasks(self):
        User.objects.create_user('testuser', password='******')
        task_assignment = TaskAssignment(completed=True, task=self.task)
        task_assignment.save()
        self.assertEqual(self.task.taskassignment_set.count(), 1)

        client = django.test.Client()
        client.login(username='******', password='******')
        response = client.get(
            reverse('accept_next_task', kwargs={'batch_id': self.batch.id}))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['Location'], reverse('index'))
        self.assertEqual(self.task.taskassignment_set.count(), 1)
        messages = list(get_messages(response.wsgi_request))
        self.assertEqual(len(messages), 1)
        self.assertEqual(
            str(messages[0]),
            'No more Tasks available for Batch {}'.format(self.batch.name))
示例#4
0
    def setUp(self):
        project = Project(name='foo', html_template='<p>${foo}: ${bar}</p>')
        project.save()

        self.batch = Batch(project=project, name='foo', filename='foo.csv')
        self.batch.save()

        task = Task(batch=self.batch,
                    input_csv_fields={
                        'foo': 'fufu',
                        'bar': 'baba'
                    })
        task.save()
        TaskAssignment(answers={
            'a1': 'sauce'
        },
                       assigned_to=None,
                       completed=True,
                       task=task).save()
示例#5
0
    def test_available_tasks_for__aph_is_1(self):
        batch = Batch(assignments_per_task=1, project=self.project)
        batch.save()
        self.assertEqual(batch.total_available_tasks_for(self.user), 0)
        self.assertEqual(batch.next_available_task_for(self.user), None)

        task = Task(batch=batch, )
        task.save()
        self.assertEqual(batch.total_available_tasks_for(self.user), 1)
        self.assertEqual(batch.next_available_task_for(self.user), task)

        task_assignment = TaskAssignment(
            assigned_to=self.user,
            completed=False,
            task=task,
        )
        task_assignment.save()
        self.assertEqual(batch.total_available_tasks_for(self.user), 0)
        self.assertEqual(batch.next_available_task_for(self.user), None)
示例#6
0
def accept_next_task(request, batch_id):
    """
    Accept task from index or auto accept next task

    Security behavior:
    - If the user does not have permission to access the Batch+Task, they
      are redirected to the index page with an error message.
    """
    try:
        with transaction.atomic():
            batch = Batch.objects.get(id=batch_id)

            # Lock access to all Tasks available to current user in the batch
            batch.available_task_ids_for(request.user).select_for_update()

            task_id = _skip_aware_next_available_task_id(request, batch)

            if task_id:
                ha = TaskAssignment()
                if request.user.is_authenticated:
                    ha.assigned_to = request.user
                else:
                    ha.assigned_to = None
                ha.task_id = task_id
                ha.save()
                if request.user.is_authenticated:
                    logger.info('User(%i) accepted Task(%i)', request.user.id,
                                task_id)
                else:
                    logger.info('Anonymous user accepted Task(%i)', task_id)
    except ObjectDoesNotExist:
        messages.error(request,
                       u'Cannot find Task Batch with ID {}'.format(batch_id))
        return redirect(index)

    if task_id:
        return redirect(task_assignment, task_id, ha.id)
    else:
        messages.error(
            request,
            u'No more Tasks available for Batch {}'.format(batch.name))
        return redirect(index)
示例#7
0
    def test_return_task_assignment__anon_user_returns_other_users_task(self):
        user = User.objects.create_user('testuser', password='******')

        task_assignment = TaskAssignment(assigned_to=user, task=self.task)
        task_assignment.save()

        client = django.test.Client()
        response = client.get(
            reverse('return_task_assignment',
                    kwargs={
                        'task_id': self.task.id,
                        'task_assignment_id': task_assignment.id
                    }))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['Location'], reverse('index'))
        messages = list(get_messages(response.wsgi_request))
        self.assertEqual(len(messages), 1)
        self.assertEqual(
            str(messages[0]),
            'The Task you are trying to return belongs to another user')
示例#8
0
    def test_accept_claimed_task(self):
        User.objects.create_superuser('admin', '*****@*****.**', 'secret')
        other_user = User.objects.create_user('testuser', password='******')
        TaskAssignment(assigned_to=other_user, task=self.task).save()
        self.assertEqual(self.task.taskassignment_set.count(), 1)

        client = django.test.Client()
        client.login(username='******', password='******')
        response = client.get(
            reverse('accept_task',
                    kwargs={
                        'batch_id': self.batch.id,
                        'task_id': self.task.id
                    }))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['Location'], reverse('index'))
        messages = list(get_messages(response.wsgi_request))
        self.assertEqual(len(messages), 1)
        self.assertEqual(
            str(messages[0]),
            'The Task with ID {} is no longer available'.format(self.task.id))
示例#9
0
    def test_expire_all_abandoned__dont_delete_completed(self):
        t = timezone.now()
        dt = datetime.timedelta(hours=2)
        past = t - dt

        project = Project(login_required=False)
        project.save()
        batch = Batch(allotted_assignment_time=1, project=project)
        batch.save()
        task = Task(batch=batch)
        task.save()
        ha = TaskAssignment(
            completed=True,
            expires_at=past,
            task=task,
        )
        # Bypass TaskAssignment's save(), which updates expires_at
        super(TaskAssignment, ha).save()
        self.assertEqual(TaskAssignment.objects.count(), 1)
        TaskAssignment.expire_all_abandoned()
        self.assertEqual(TaskAssignment.objects.count(), 1)
示例#10
0
    def test_task_marked_as_completed(self):
        # When assignment_per_task==1, completing 1 Assignment marks Task as complete
        project = Project(name='test',
                          html_template='<p>${number} - ${letter}</p>')
        project.save()
        batch = Batch(project=project)
        batch.save()

        task = Task(batch=batch,
                    input_csv_fields={
                        'number': '1',
                        'letter': 'a'
                    })
        task.save()

        self.assertEqual(batch.assignments_per_task, 1)
        self.assertFalse(task.completed)

        TaskAssignment(assigned_to=None, completed=True, task=task).save()

        task.refresh_from_db()
        self.assertTrue(task.completed)
示例#11
0
    def test_return_completed_task_assignment(self):
        user = User.objects.create_user('testuser', password='******')

        task_assignment = TaskAssignment(assigned_to=user,
                                         completed=True,
                                         task=self.task)
        task_assignment.save()

        client = django.test.Client()
        client.login(username='******', password='******')
        response = client.get(
            reverse('return_task_assignment',
                    kwargs={
                        'task_id': self.task.id,
                        'task_assignment_id': task_assignment.id
                    }))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['Location'], reverse('index'))
        messages = list(get_messages(response.wsgi_request))
        self.assertEqual(len(messages), 1)
        self.assertEqual(
            str(messages[0]),
            "The Task can't be returned because it has been completed")
示例#12
0
    def test_skip_and_accept_next_task(self):
        client = django.test.Client()

        ha_one = TaskAssignment(task=self.task_one)
        ha_one.save()

        # Skip task_one
        response = client.post(
            reverse('skip_and_accept_next_task',
                    kwargs={
                        'batch_id': self.batch.id,
                        'task_id': self.task_one.id,
                        'task_assignment_id': ha_one.id
                    }))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response['Location'],
            reverse('accept_next_task', kwargs={'batch_id': self.batch.id}))

        # Verify that task_one has been skipped
        response = client.get(
            reverse('accept_next_task', kwargs={'batch_id': self.batch.id}))
        self.assertEqual(response.status_code, 302)
        self.assertTrue(
            '{}/assignment/'.format(self.task_two.id) in response['Location'])

        # Skip task_two
        ha_two = self.task_two.taskassignment_set.first()
        response = client.post(
            reverse('skip_and_accept_next_task',
                    kwargs={
                        'batch_id': self.batch.id,
                        'task_id': self.task_two.id,
                        'task_assignment_id': ha_two.id
                    }))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response['Location'],
            reverse('accept_next_task', kwargs={'batch_id': self.batch.id}))

        # Verify that task_two has been skipped
        response = client.get(
            reverse('accept_next_task', kwargs={'batch_id': self.batch.id}))
        self.assertEqual(response.status_code, 302)
        self.assertTrue('{}/assignment/'.format(self.task_three.id) in
                        response['Location'])

        # Skip task_three
        ha_three = self.task_three.taskassignment_set.first()
        response = client.post(
            reverse('skip_and_accept_next_task',
                    kwargs={
                        'batch_id': self.batch.id,
                        'task_id': self.task_three.id,
                        'task_assignment_id': ha_three.id
                    }))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response['Location'],
            reverse('accept_next_task', kwargs={'batch_id': self.batch.id}))

        # Verify that, with all existing Tasks skipped, we have been redirected back to
        # task_one and that info message is displayed about only skipped Tasks remaining
        response = client.get(
            reverse('accept_next_task', kwargs={'batch_id': self.batch.id}))
        self.assertEqual(response.status_code, 302)
        self.assertTrue(
            '{}/assignment/'.format(self.task_one.id) in response['Location'])
        messages = list(get_messages(response.wsgi_request))
        self.assertEqual(len(messages), 1)
        self.assertEqual(str(messages[0]),
                         'Only previously skipped Tasks are available')

        # Skip task_one for a second time
        ha_one = self.task_one.taskassignment_set.first()
        response = client.post(
            reverse('skip_and_accept_next_task',
                    kwargs={
                        'batch_id': self.batch.id,
                        'task_id': self.task_one.id,
                        'task_assignment_id': ha_one.id
                    }))
        self.assertEqual(response.status_code, 302)
        self.assertEqual(
            response['Location'],
            reverse('accept_next_task', kwargs={'batch_id': self.batch.id}))

        # Verify that task_one has been skipped for a second time
        response = client.get(
            reverse('accept_next_task', kwargs={'batch_id': self.batch.id}))
        self.assertEqual(response.status_code, 302)
        self.assertTrue(
            '{}/assignment/'.format(self.task_two.id) in response['Location'])
示例#13
0
    def setUp(self):
        """
        Sets up Project, Task objects, and saves them to the DB.
        The Project form HTML only displays the one input variable.
        The Task has inputs and answers and refers to the Project form.
        """
        admin = User.objects.create_superuser('admin', '*****@*****.**', 'secret')
        project = Project(name='test', html_template="<p>${foo}</p><textarea>")
        project.created_by = admin
        project.updated_by = admin
        save_model(project)
        batch = Batch(name='test', project=project, filename='test.csv')
        batch.created_by = admin
        batch.updated_by = admin
        save_model(batch)

        task = Task(
            batch=batch,
            input_csv_fields={'foo': 'bar'},
            completed=True,
        )
        task.save()
        self.task = task

        self.task_assignment = TaskAssignment(answers={
            "comment": "\u221e",
            "userDisplayLanguage": "",
            "sentence_textbox_3_verb1": "",
            "city": "",
            "sentence_textbox_1_verb6": "",
            "sentence_textbox_1_verb7": "",
            "sentence_textbox_1_verb4": "",
            "sentence_textbox_1_verb5": "",
            "sentence_textbox_1_verb2": "",
            "sentence_textbox_1_verb3": "",
            "sentence_textbox_1_verb1": "",
            "sentence_textbox_2_verb4": "",
            "csrfmiddlewaretoken": "7zxQ9Yyug6Nsnm4nLky9p8ObJwNipdu8",
            "sentence_drop_2_verb3": "foo",
            "sentence_drop_2_verb2": "foo",
            "sentence_drop_2_verb1": "foo",
            "sentence_textbox_2_verb1": "",
            "sentence_textbox_2_verb3": "",
            "sentence_drop_2_verb4": "foo",
            "sentence_textbox_2_verb2": "",
            "submitit": "Submit",
            "browserInfo": "",
            "sentence_drop_1_verb1": "foo",
            "sentence_drop_1_verb2": "foo",
            "sentence_drop_1_verb3": "foo",
            "sentence_drop_1_verb4": "foo",
            "sentence_drop_1_verb5": "foo",
            "sentence_drop_1_verb6": "foo",
            "sentence_drop_1_verb7": "foo",
            "country": "",
            "sentence_drop_3_verb1": "foo",
            "ipAddress": "",
            "region": ""
        },
                                              assigned_to=None,
                                              completed=True,
                                              task=task)
        self.task_assignment.save()