def test_anonymous_taskrun_submission(self):
        owner = UserFactory.create(id=500)

        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = 'locked'
        project_repo.save(project)

        task1 = TaskFactory.create(project=project, info='task 1', n_answers=1)
        task2 = TaskFactory.create(project=project, info='task 2', n_answers=1)

        res = self.app.get('api/project/{}/newtask'.format(project.id))
        rec_task1 = json.loads(res.data)

        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, owner.api_key))
        rec_task2 = json.loads(res.data)

        # users get different tasks
        assert rec_task1['info'] != rec_task2['info']

        tr = {'project_id': project.id, 'task_id': task1.id, 'info': 'hello'}

        # submit answer for the right task
        res = self.app.post('api/taskrun', data=json.dumps(tr))
        assert res.status_code == 200, res.status_code
示例#2
0
def password_protect_hidden_projects():
    import random
    from pybossa.core import project_repo, user_repo, mail
    from pybossa.jobs import enqueue_job, send_mail


    def generate_random_password():
        CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
        password = ''
        for i in range(8):
            password += random.choice(CHARS)
        return password

    def generate_email_for(project_name, owner_name, password):
        subject = "Changes in your hidden project %s" % project_name
        content = (
"""
Dear %s,

We are writing you to let you know that, due to recent changes in Crowdcrafting,
hidden projects will soon no longer be supported. However, you can still
protect your project with a password, allowing only people with it to
access and contribute to it.

We have checked that your project %s is hidden. We don't want to expose it
to the public, so we have protected it with a password instead. The current
password for your project is:

%s

You will be able to change it on your project settings page.

You can find more information about passwords in the documentation
(http://docs.pybossa.com/user/tutorial/#protecting-the-project-with-a-password).

If you have any doubts, please contact us and we will be pleased to help you!

Best regards,

Crowdcrafting team.
""" % (owner_name, project_name, password))

        return subject, content


    with app.app_context():
        for project in project_repo.filter_by(hidden=1):
            password = generate_random_password()
            subject, content = generate_email_for(project.name, project.owner.name, password)
            message = dict(recipients=[project.owner.email_addr],
                           subject=subject,
                           body=content)
            job = dict(name=send_mail,
                       args=[message],
                       kwargs={},
                       timeout=(600),
                       queue='medium')
            enqueue_job(job)
            project.set_password(password)
            project_repo.save(project)
    def test_anonymous_taskrun_submission_external_uid(self):
        owner = UserFactory.create(id=500)

        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = 'locked'
        project_repo.save(project)

        task1 = TaskFactory.create(project=project, info='task 1', n_answers=1)
        task2 = TaskFactory.create(project=project, info='task 2', n_answers=1)

        headers = self.get_headers_jwt(project)

        res = self.app.get('api/project/{}/newtask?external_uid={}'.format(
            project.id, '1xa'),
                           headers=headers)
        rec_task1 = json.loads(res.data)

        res = self.app.get('api/project/{}/newtask?external_uid={}'.format(
            project.id, '2xa'),
                           headers=headers)
        rec_task2 = json.loads(res.data)

        # users get different tasks
        print(rec_task1)
        print(rec_task2)
        assert rec_task1['info'] != rec_task2['info']

        tr = {'project_id': project.id, 'task_id': task1.id, 'info': 'hello'}

        # submit answer for the right task
        res = self.app.post('api/taskrun?external_uid=1xa',
                            data=json.dumps(tr),
                            headers=headers)
        assert res.status_code == 200, res.status_code
示例#4
0
    def test_user_logout_unlocks_locked_tasks(self, release_lock):
        """ Test user logout unlocks/expires all locks locked by user """
        owner = UserFactory.create(id=500)
        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        task1 = TaskFactory.create(project=project,
                                   info='project 1',
                                   n_answers=1)

        project2 = ProjectFactory.create(owner=owner)
        project2.info['sched'] = Schedulers.locked

        task2 = TaskFactory.create(project=project2,
                                   info='project 2',
                                   n_answers=1)

        self.register(name='johndoe')
        self.signin(email='*****@*****.**')

        self.set_proj_passwd_cookie(project, user=None, username='******')
        res = self.app.get('api/project/1/newtask')
        data = json.loads(res.data)
        assert data.get('info'), data

        self.set_proj_passwd_cookie(project2, user=None, username='******')
        res = self.app.get('api/project/2/newtask')
        data = json.loads(res.data)
        assert data.get('info'), data
        self.signout()

        key_args = [args[0] for args, kwargs in release_lock.call_args_list]
        assert get_task_users_key(task1.id) in key_args
        assert get_task_users_key(task2.id) in key_args
示例#5
0
    def test_tasks_assigned_as_per_user_access_levels_l2(self):
        """ Test tasks assigned by locked scheduler are as per access levels set for user, task and project"""

        from pybossa import data_access
        from test_api import get_pwd_cookie

        owner = UserFactory.create(id=500)
        user_l2 = UserFactory.create(id=502, info=dict(data_access=["L2"]))

        project = ProjectFactory.create(owner=owner,
                                        info=dict(data_access=["L1", "L2"]))
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        project2 = ProjectFactory.create(owner=owner,
                                         info=dict(data_access=["L1", "L2"]))
        project2.info['sched'] = Schedulers.user_pref
        project_repo.save(project2)

        task1 = TaskFactory.create(project=project,
                                   info=dict(question='q1',
                                             data_access=["L1"]),
                                   n_answers=1)
        task2 = TaskFactory.create(project=project,
                                   info=dict(question='q2',
                                             data_access=["L2"]),
                                   n_answers=1)
        task3 = TaskFactory.create(project=project2,
                                   info=dict(question='q3',
                                             data_access=["L1"]),
                                   n_answers=1)
        task4 = TaskFactory.create(project=project2,
                                   info=dict(question='q4',
                                             data_access=["L2"]),
                                   n_answers=1)

        self.set_proj_passwd_cookie(project, user_l2)
        with patch.dict(data_access.data_access_levels,
                        self.patch_data_access_levels):
            res = self.app.get('api/project/{}/newtask?api_key={}'.format(
                project.id, user_l2.api_key))
            assert res.status_code == 200, res.status_code

            data = json.loads(res.data)
            assert data[
                'id'] == task2.id, 'user_l2 should have obtained task {}'.format(
                    task2.id)
            assert data['info']['data_access'] == task2.info['data_access'], \
                'user_l2 should have obtained task with level {}'.format(task1.info['data_access'])

            self.set_proj_passwd_cookie(project2, user_l2)
            res = self.app.get('api/project/{}/newtask?api_key={}'.format(
                project2.id, user_l2.api_key))
            assert res.status_code == 200, res.status_code
            data = json.loads(res.data)
            assert data[
                'id'] == task4.id, 'user_l2 should have obtained task {}'.format(
                    task4.id)
            assert data['info']['data_access'] == task4.info['data_access'], \
                'user_l1 should have obtained task with level {}'.format(task4.info['data_access'])
示例#6
0
文件: cli.py 项目: pkdevbox/pybossa
def password_protect_hidden_projects():
    import random
    from pybossa.core import project_repo, user_repo, mail
    from pybossa.jobs import enqueue_job, send_mail


    def generate_random_password():
        CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
        password = ''
        for i in range(8):
            password += random.choice(CHARS)
        return password

    def generate_email_for(project_name, owner_name, password):
        subject = "Changes in your hidden project %s" % project_name
        content = (
"""
Dear %s,

We are writing you to let you know that, due to recent changes in Crowdcrafting,
hidden projects will soon no longer be supported. However, you can still
protect your project with a password, allowing only people with it to
access and contribute to it.

We have checked that your project %s is hidden. We don't want to expose it
to the public, so we have protected it with a password instead. The current
password for your project is:

%s

You will be able to change it on your project settings page.

You can find more information about passwords in the documentation
(http://docs.pybossa.com/en/latest/user/tutorial.html#protecting-the-project-with-a-password).

If you have any doubts, please contact us and we will be pleased to help you!

Best regards,

Crowdcrafting team.
""" % (owner_name, project_name, password))

        return subject, content


    with app.app_context():
        for project in project_repo.filter_by(hidden=1):
            password = generate_random_password()
            subject, content = generate_email_for(project.name, project.owner.name, password)
            message = dict(recipients=[project.owner.email_addr],
                           subject=subject,
                           body=content)
            job = dict(name=send_mail,
                       args=[message],
                       kwargs={},
                       timeout=(600),
                       queue='medium')
            enqueue_job(job)
            project.set_password(password)
            project_repo.save(project)
示例#7
0
    def test_locked_sched_gold_task(self):
        """ Test gold tasks presented with locked scheduler """

        [admin, owner, user] = UserFactory.create_batch(3)
        make_admin(admin)
        make_subadmin(owner)

        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project.set_gold_task_probability(1.0)
        project_repo.save(project)

        tasks = TaskFactory.create_batch(4, project=project, n_answers=1)
        gold_task = tasks[3]
        gold_task.calibration = 1; gold_task.gold_answers = dict(field_3='someans')

        # user #1
        self.set_proj_passwd_cookie(project, user)
        res = self.app.get('api/project/{}/newtask?api_key={}'
                           .format(project.id, user.api_key))
        assert res.status_code == 200, res.status_code
        resp = json.loads(res.data)
        assert resp['id'] == gold_task.id, \
            'task presented to regular user under locked sched should be gold task'
        # submit answer for gold task
        task_run = dict(project_id=project.id, task_id=gold_task.id, info='hi there!')
        res = self.app.post('api/taskrun?api_key={}'.format(user.api_key),
                            data=json.dumps(task_run))
        assert res.status_code == 200, res.status_code

        # user #2 also gets gold_task even when redundancy was set to 1
        res = self.app.get('api/project/{}/newtask?api_key={}'
                           .format(project.id, owner.api_key))
        assert res.status_code == 200, res.status_code
        resp = json.loads(res.data)
        assert resp['id'] == gold_task.id, \
            'task presented to owner under locked sched should be gold task'

        # after two task run submissions for gold task, state is unchanged to ongoing
        task_run = dict(project_id=project.id, task_id=gold_task.id, info='hi there!')
        res = self.app.post('api/taskrun?api_key={}'.format(owner.api_key),
                            data=json.dumps(task_run))
        assert res.status_code == 200, res.status_code
        res = self.app.get('api/task/{}?api_key={}'
                           .format(gold_task.id, admin.api_key))
        assert res.status_code == 200, res.status_code
        resp = json.loads(res.data)
        assert resp['id'] == gold_task.id and resp['state'] == 'ongoing', \
            'gold task state should be unchanged to ongoing'

        project.set_gold_task_probability(0.0)
        res = self.app.get('api/project/{}/newtask?api_key={}'
                           .format(project.id, admin.api_key))
        assert res.status_code == 200, res.status_code
        resp = json.loads(res.data)
        assert resp['id'] == tasks[0].id, \
            'task presented should not be gold task'
示例#8
0
    def test_get_locked_task_gold_first(self):
        owner = UserFactory.create(id=500)
        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        TaskFactory.create(project=project, info='task 1', calibration=0, n_answers=2)
        task2 = TaskFactory.create(project=project, info='task 1', calibration=1, n_answers=2)
        task = get_locked_task(project.id, 1, task_type='gold_first')[0]
        assert task.id == task2.id, (task, task2)
示例#9
0
    def test_get_locked_task_gold_only(self):
        owner = UserFactory.create(id=500)
        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        TaskFactory.create(project=project, info='task 1', calibration=0, n_answers=2)
        assert not get_locked_task(project.id, 1, task_type='gold')
        TaskFactory.create(project=project, info='task 1', calibration=1, n_answers=2)
        assert get_locked_task(project.id, 1, task_type='gold')
示例#10
0
 def test_creator_is_added_as_owner(self):
     """
     Test that project_repo.save includes the creator as an owner even if
     not explicitly specified
     """
     from pybossa.core import project_repo
     self.register()
     project = Fixtures.create_project({'passwd_hash': 'hello'})
     project.owner_id = 1
     project_repo.save(project)
     assert project.owners_ids == [1]
示例#11
0
    def test_taskrun_submission(self):
        """ Test submissions with locked scheduler """
        owner = UserFactory.create(id=500)
        user = UserFactory.create(id=501)

        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        task1 = TaskFactory.create(project=project, info='task 1', n_answers=1)
        task2 = TaskFactory.create(project=project, info='task 2', n_answers=1)

        self.set_proj_passwd_cookie(project, user)
        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, user.api_key))
        user_rec_task = json.loads(res.data)

        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, owner.api_key))
        owner_rec_task = json.loads(res.data)

        # users get different tasks
        assert user_rec_task['info'] != owner_rec_task['info']

        user_task = task1 if task1.id == user_rec_task['id'] else task2
        owner_task = task1 if task1.id == owner_rec_task['id'] else task2

        # submit answer for the wrong task
        # stamp contribution guard first
        guard = ContributionsGuard(sentinel.master)
        guard._remove_task_stamped(owner_task, {'user_id': owner.id})

        tr = {
            'project_id': project.id,
            'task_id': owner_task.id,
            'info': 'hello'
        }
        res = self.app.post('api/taskrun?api_key={}'.format(owner.api_key),
                            data=json.dumps(tr))
        assert res.status_code == 403, (res.status_code, res.data)

        # submit answer for the right task
        guard.stamp(owner_task, {'user_id': owner.id})
        tr['task_id'] = owner_task.id
        res = self.app.post('api/taskrun?api_key={}'.format(owner.api_key),
                            data=json.dumps(tr))
        assert res.status_code == 200, res.status_code

        tr['task_id'] = user_task.id
        res = self.app.post('api/taskrun?api_key={}'.format(user.api_key),
                            data=json.dumps(tr))
        assert res.status_code == 200, res.status_code
示例#12
0
def import_tasks(project_id, current_user_fullname, from_auto=False, **form_data):
    """Import tasks for a project."""
    from pybossa.core import project_repo
    import pybossa.cache.projects as cached_projects

    project = project_repo.get(project_id)
    recipients = [project.owner.email_addr]
    for user in project.coowners:
        recipients.append(user.email_addr)

    try:
        report = importer.create_tasks(task_repo, project, **form_data)
    except JobTimeoutException:
        from pybossa.core import db
        db.session.rollback()
        n_tasks = _num_tasks_imported(project_id)
        subject = 'Your import task has timed out'
        body = '\n'.join(
            ['Hello,\n',
             'Import task to your project {} by {} failed because the file was too large.',
             'It was able to process approximately {} tasks.',
             'Please break up your task upload into smaller CSV files.',
             'Thank you,\n',
             'The {} team.']).format(project.name, current_user_fullname,
                                     n_tasks, current_app.config.get('BRAND'))
        mail_dict = dict(recipients=recipients, subject=subject, body=body)
        send_mail(mail_dict)
        raise
    except Exception as e:
        msg = (u'Import tasks to your project {0} by {1} failed'
               .format(project.name, current_user_fullname))
        subject = 'Tasks Import to your project %s' % project.name
        body = ('Hello,\n\n{0}\n\nPlease contact {1} administrator,\nThe {1} team.'
                .format(msg, current_app.config.get('BRAND')))
        mail_dict = dict(recipients=recipients, subject=subject, body=body)
        send_mail(mail_dict)
        raise

    cached_projects.delete_browse_tasks(project_id)
    if from_auto:
        form_data['last_import_meta'] = report.metadata
        project.set_autoimporter(form_data)
        project_repo.save(project)
    msg = report.message + u' to your project {0} by {1}'.format(project.name, current_user_fullname)

    subject = 'Tasks Import to your project %s' % project.name
    body = 'Hello,\n\n' + msg + '\n\nAll the best,\nThe %s team.'\
        % current_app.config.get('BRAND')
    mail_dict = dict(recipients=recipients, subject=subject, body=body)
    send_mail(mail_dict)
    return msg
示例#13
0
    def test_tasks_assigned_as_per_user_access_levels_l4(self):
        """ Test tasks assigned by locked scheduler are as per access levels set for user, task and project"""

        from pybossa import data_access
        from test_api import get_pwd_cookie

        owner = UserFactory.create(id=500)
        user_l4 = UserFactory.create(id=502, info=dict(data_access=["L4"]))

        project = ProjectFactory.create(owner=owner,
                                        info=dict(data_access=["L1", "L2"]))
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        project2 = ProjectFactory.create(owner=owner,
                                         info=dict(data_access=["L1", "L2"]))
        project2.info['sched'] = Schedulers.user_pref
        project_repo.save(project2)

        task1 = TaskFactory.create(project=project,
                                   info=dict(question='q1',
                                             data_access=["L1"]),
                                   n_answers=1)
        task2 = TaskFactory.create(project=project,
                                   info=dict(question='q2',
                                             data_access=["L2"]),
                                   n_answers=1)
        task3 = TaskFactory.create(project=project,
                                   info=dict(question='q3',
                                             data_access=["L2"]),
                                   n_answers=1)
        task4 = TaskFactory.create(project=project,
                                   info=dict(question='q4',
                                             data_access=["L2"]),
                                   n_answers=1)

        self.set_proj_passwd_cookie(project, user_l4)
        with patch.object(data_access, 'data_access_levels',
                          self.patch_data_access_levels):
            res = self.app.get('api/project/{}/newtask?api_key={}'.format(
                project.id, user_l4.api_key))
            assert res.status_code == 200, res.status_code
            data = json.loads(res.data)
            assert not data, 'user_l4 with L4 access should not have obtained any task under locked scheduler'

            self.set_proj_passwd_cookie(project2, user_l4)
            res = self.app.get('api/project/{}/newtask?api_key={}'.format(
                project2.id, user_l4.api_key))
            assert res.status_code == 200, res.status_code
            data = json.loads(res.data)
            assert not data, 'user_l4 with L4 access should not have obtained any task under user pref scheduler'
示例#14
0
    def test_invalid_offset(self):
        owner = UserFactory.create(id=500)

        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        task1 = TaskFactory.create(project=project, info='task 1', n_answers=2)
        task1 = TaskFactory.create(project=project, info='task 2', n_answers=2)

        res = self.app.get('api/project/{}/newtask?api_key={}&offset=3'.format(
            project.id, owner.api_key))

        assert res.status_code == 400, res.data
示例#15
0
    def test_get_locked_task_randomize(self):
        owner = UserFactory.create(id=500)
        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        TaskFactory.create(project=project, info='task 1', n_answers=2)
        TaskFactory.create(project=project, info='task 2', n_answers=2)

        assert get_locked_task(project.id, 1, rand_within_priority=True)
        assert get_locked_task(project.id, 2, rand_within_priority=True)
        assert get_locked_task(project.id, 3, rand_within_priority=True)
        assert get_locked_task(project.id, 4, rand_within_priority=True)
        assert not get_locked_task(project.id, 5, rand_within_priority=True)
示例#16
0
    def test_get_locked_task_offset(self):
        owner = UserFactory.create(id=500)
        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        task1 = TaskFactory.create(project=project, info='task 1', n_answers=2)
        task2 = TaskFactory.create(project=project, info='task 2', n_answers=2)
        task3 = TaskFactory.create(project=project, info='task 2', n_answers=2)

        t1 = get_locked_task(project.id, 1)
        assert t1[0].id == task1.id
        t2 = get_locked_task(project.id, 1, offset=1)
        assert t2 is None
        t3 = get_locked_task(project.id, 1, offset=2)
        assert t3 is None
示例#17
0
文件: jobs.py 项目: chandra1b/pybossa
def import_tasks(project_id, from_auto=False, **form_data):
    """Import tasks for a project."""
    from pybossa.core import project_repo

    project = project_repo.get(project_id)
    report = importer.create_tasks(task_repo, project_id, **form_data)
    if from_auto:
        form_data["last_import_meta"] = report.metadata
        project.set_autoimporter(form_data)
        project_repo.save(project)
    msg = report.message + " to your project %s!" % project.name
    subject = "Tasks Import to your project %s" % project.name
    body = "Hello,\n\n" + msg + "\n\nAll the best,\nThe %s team." % current_app.config.get("BRAND")
    mail_dict = dict(recipients=[project.owner.email_addr], subject=subject, body=body)
    send_mail(mail_dict)
    return msg
示例#18
0
    def test_one_task(self):
        owner = UserFactory.create(id=500)

        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = 'locked'
        project_repo.save(project)

        task1 = TaskFactory.create(project=project, info='task 1', n_answers=1)

        res = self.app.get('api/project/{}/newtask'.format(project.id))
        rec_task1 = json.loads(res.data)

        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, owner.api_key))
        rec_task2 = json.loads(res.data)
        assert not rec_task2
示例#19
0
 def test_creator_is_added_as_owner(self):
     """
     Test that project_repo.save includes the creator as an owner even if
     not explicitly specified
     """
     from pybossa.core import project_repo
     self.register()
     project = Fixtures.create_project({
         'passwd_hash':
         'hello',
         'data_classification':
         dict(input_data="L4 - public", output_data="L4 - public")
     })
     project.owner_id = 1
     project_repo.save(project)
     assert project.owners_ids == [1]
示例#20
0
def import_tasks(project_id, from_auto=False, **form_data):
    """Import tasks for a project."""
    from pybossa.core import project_repo
    project = project_repo.get(project_id)
    report = importer.create_tasks(task_repo, project_id, **form_data)
    if from_auto:
        form_data['last_import_meta'] = report.metadata
        project.set_autoimporter(form_data)
        project_repo.save(project)
    msg = report.message + ' to your project %s!' % project.name
    subject = 'Tasks Import to your project %s' % project.name
    body = 'Hello,\n\n' + msg + '\n\nAll the best,\nThe %s team.'\
        % current_app.config.get('BRAND')
    mail_dict = dict(recipients=[project.owner.email_addr],
                     subject=subject, body=body)
    send_mail(mail_dict)
    return msg
    def test_get_reserve_task_category_info(self, get_task_category_lock):
        owner = UserFactory.create(id=500)
        project = ProjectFactory.create(owner=owner)
        reserve_task_config = ["field_a", "field_b"]
        timeout = 60 * 60

        # test bad project id, user id returns empty sql_filters, category_keys
        project_id, user_id = -52, 9999
        sql_filters, category_keys = get_reserve_task_category_info(
            reserve_task_config, project_id, timeout, user_id)
        assert sql_filters == "" and category_keys == [], "sql_filters, category_keys must be '', []"

        # empty sql_filters, category_keys for projects with scheduler other than task_queue
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)
        sql_filters, category_keys = get_reserve_task_category_info(
            reserve_task_config, project.id, timeout, owner.id)
        assert sql_filters == "" and category_keys == [], "sql_filters, category_keys must be '', []"

        # with no categories configured under project config
        # empty sql_filters, category_keys for projects with task queue scheduler
        project.info['sched'] = Schedulers.task_queue
        project_repo.save(project)
        sql_filters, category_keys = get_reserve_task_category_info(
            reserve_task_config, project.id, timeout, owner.id)
        assert sql_filters == "" and category_keys == [], "sql_filters, category_keys must be '', []"

        # with categories configured under project config
        # empty sql_filters, category_keys for projects with task queue scheduler
        # when there's no category lock present in redis cache
        project.info['sched'] = Schedulers.task_queue
        project.info['reserve_tasks'] = {"category": reserve_task_config}
        project_repo.save(project)
        get_task_category_lock.return_value = []
        sql_filters, category_keys = get_reserve_task_category_info(
            reserve_task_config, project.id, timeout, owner.id)
        assert sql_filters == "" and category_keys == [], "sql_filters, category_keys must be '', []"

        # with categories configured under project config
        # sql_filters, category_keys for projects with task queue scheduler
        # to be built as per category lock present in redis cache
        project.info['sched'] = Schedulers.task_queue
        project.info['reserve_tasks'] = {"category": reserve_task_config}
        project_repo.save(project)
        expected_category_keys = [
            "reserve_task:project:{}:category:name1:value1:name2:value2:user:1008:task:454"
            .format(project.id),
            "reserve_task:project:{}:category:x:1:y:2:z:3:user:1008:task:2344".
            format(project.id)
        ]
        get_task_category_lock.return_value = expected_category_keys
        sql_filters, category_keys = get_reserve_task_category_info(
            reserve_task_config, project.id, timeout, owner.id)
        assert sql_filters == " AND (task.info->>'y' IN ('2') AND task.info->>'x' IN ('1') AND task.info->>'z' IN ('3') AND task.info->>'name2' IN ('value2') AND task.info->>'name1' IN ('value1')) " and \
            category_keys == expected_category_keys, "sql_filters, category_keys must be non empty"
示例#22
0
def handle_valid_project_form(form, template, volume, category):
    """Handle a valid project form."""
    import_data = volume.get('data', {})
    import_data['type'] = volume.get('importer')

    # Use enhanced IIIF importer for IIIF projects
    if import_data['type'] == 'iiif':
        import_data['type'] = 'iiif-enhanced'

    # Check for parent
    if template['parent_template_id']:
        if volume.get('importer') != 'iiif':
            flash('Only IIIF projects can be built from parents.', 'error')
            return

        parent = get_parent(template['parent_template_id'], volume['id'],
                            category)
        if not parent:
            msg = 'There is no valid parent for this template and volume.'
            flash(msg, 'error')
            return

        import_data['parent_id'] = parent.id

    # Create project
    webhook = '{0}lc/analysis'.format(request.url_root)
    project = Project(name=form.name.data,
                      short_name=form.short_name.data,
                      description=template['description'],
                      long_description='',
                      owner_id=current_user.id,
                      info={
                          'volume_id': volume['id'],
                          'template_id': template['id']
                      },
                      webhook=webhook,
                      published=True,
                      category_id=category.id,
                      owners_ids=[current_user.id])

    add_avatar_to_project_info(project, volume)
    project_repo.save(project)
    return generate_tasks(project, import_data, template)
示例#23
0
    def test_lock_expiration(self):
        owner = UserFactory.create(id=500)

        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = 'locked'
        project_repo.save(project)

        task1 = TaskFactory.create(project=project, info='task 1', n_answers=2)
        task1 = TaskFactory.create(project=project, info='task 2', n_answers=2)

        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, owner.api_key))
        # fake expired user lock
        acquire_lock(task1.id, 1000, 2, -10)

        res = self.app.get('api/project/{}/newtask'.format(project.id))
        rec_task1 = json.loads(res.data)

        assert rec_task1['info'] == 'task 1'
示例#24
0
    def test_taskrun_submission(self):
        owner = UserFactory.create(id=500)
        user = UserFactory.create(id=501)

        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = 'locked'
        project_repo.save(project)

        task1 = TaskFactory.create(project=project, info='task 1', n_answers=1)
        task2 = TaskFactory.create(project=project, info='task 2', n_answers=1)

        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, user.api_key))
        rec_task1 = json.loads(res.data)

        res = self.app.get('api/project/{}/newtask?api_key={}'.format(
            project.id, owner.api_key))
        rec_task2 = json.loads(res.data)

        # users get different tasks
        assert rec_task1['info'] != rec_task2['info']

        # submit answer for the wrong task
        # stamp contribution guard first
        guard = ContributionsGuard(sentinel.master)
        guard.stamp(task1, {'user_id': owner.id})

        tr = {'project_id': project.id, 'task_id': task1.id, 'info': 'hello'}
        res = self.app.post('api/taskrun?api_key={}'.format(owner.api_key),
                            data=json.dumps(tr))
        assert res.status_code == 403, res.status_code

        # submit answer for the right task
        tr['task_id'] = task2.id
        res = self.app.post('api/taskrun?api_key={}'.format(owner.api_key),
                            data=json.dumps(tr))
        assert res.status_code == 200, res.status_code

        tr['task_id'] = task1.id
        res = self.app.post('api/taskrun?api_key={}'.format(user.api_key),
                            data=json.dumps(tr))
        assert res.status_code == 200, res.status_code
    def test_acquire_and_release_reserve_task_lock(self):
        user = UserFactory.create()
        # project w/o reserve_tasks configured don't acquire lock
        project_info = dict(sched="task_queue_scheduler")
        task_info = dict(field_1="abc", field_2=123)
        category_fields = ["field_1", "field_2"]
        project = ProjectFactory.create(owner=user, info=project_info)
        task = TaskFactory.create_batch(1,
                                        project=project,
                                        n_answers=1,
                                        info=task_info)[0]
        timeout = 100

        assert acquire_reserve_task_lock(
            project.id, task.id, user.id, timeout
        ) == False, "reserve task cannot be acquired due to missing required config"
        project.info['reserve_tasks'] = {"category": ["some_field"]}
        project_repo.save(project)
        assert acquire_reserve_task_lock(
            project.id, task.id, user.id,
            timeout) == False, "task not having reserve tasks config fields"

        project.info['reserve_tasks'] = {"category": category_fields}
        project_repo.save(project)
        acquire_reserve_task_lock(project.id, task.id, user.id, timeout)
        category_key = ":".join([
            "{}:{}".format(field, task.info[field])
            for field in category_fields
        ])
        expected_reserve_task_key = "reserve_task:project:{}:category:{}:user:{}:task:{}".format(
            project.id, category_key, user.id, task.id)
        assert expected_reserve_task_key in sentinel.master.keys(
        ), "reserve task key must exist in redis cache"

        # release reserve task lock
        expiry = 1
        release_reserve_task_lock_by_keys([expected_reserve_task_key],
                                          timeout,
                                          expiry=expiry)
        time.sleep(expiry)
        assert expected_reserve_task_key not in sentinel.master.keys(
        ), "reserve task key should not exist in redis cache"
示例#26
0
    def test_sync_L3_without_target(self, mock_cat):
        project_syncer = ProjectSyncer(self.target_url, self.target_key)
        user = UserFactory.create(admin=True, email_addr=u'*****@*****.**')
        project_syncer.syncer = user

        project = ProjectFactory.create()
        project.info['data_classification'] = dict(
            input_data="L3 - community", output_data="L3 - community")
        project_repo.save(project)

        # no sync info by default
        assert not project.info.get("sync")

        payload = project_syncer._build_payload(project)

        # sync existing does put request
        headers = [('Authorization', user.api_key)]
        res = self.app.put("/api/project/{}".format(project.id),
                           headers=headers,
                           data=json.dumps(payload))
        assert res.status_code == 200, 'build_payload output should result in valid api query'
        assert res.json["info"]["sync"] == payload["info"]["sync"]
示例#27
0
    def test_email_notif(self, get_contrib_emails):
        """
        if the project is configured, email notifications will be sent
        """
        owner = UserFactory.create(id=500, user_pref={'languages': ['en']})

        project = ProjectFactory.create(owner=owner, email_notif=True)
        project.info['sched'] = Schedulers.user_pref
        project_repo.save(project)
        tasks = TaskFactory.create_batch(1,
                                         project=project,
                                         n_answers=1,
                                         user_pref={'languages': ['en']})

        TaskRunFactory.create(task=tasks[0], user=owner)

        TaskFactory.create_batch(1,
                                 project=project,
                                 n_answers=1,
                                 user_pref={'languages': ['en']})
        send_email_notifications()
        get_contrib_emails.assert_called()
示例#28
0
    def test_get_locked_task(self):
        owner = UserFactory.create(id=500)
        project = ProjectFactory.create(owner=owner)
        project.info['sched'] = Schedulers.locked
        project_repo.save(project)

        task1 = TaskFactory.create(project=project, info='task 1', n_answers=2)
        task2 = TaskFactory.create(project=project, info='task 2', n_answers=2)

        t1 = get_locked_task(project.id, 11)
        t2 = get_locked_task(project.id, 1)
        assert t1[0].id == task1.id
        assert t2[0].id == task1.id
        t3 = get_locked_task(project.id, 2)
        t4 = get_locked_task(project.id, 3)
        assert t3[0].id == task2.id
        assert t4[0].id == task2.id

        t5 = get_locked_task(project.id, 11)
        assert t5[0].id == task1.id

        t6 = get_locked_task(project.id, 4)
        assert not t6