Skip to content

Commit

Permalink
Merge branch 'main' into RDISCROWD-4848
Browse files Browse the repository at this point in the history
  • Loading branch information
kbecker42 committed Aug 25, 2022
2 parents 213679d + a8ec45a commit b067eb4
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,4 @@ The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.

Documentation and media is under a Creative Commons Attribution License version 3.
Documentation and media is under a Creative Commons Attribution License version 3.
2 changes: 2 additions & 0 deletions pybossa/cache/task_browse_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ def parse_tasks_browse_order_by_args(order_by, display_info_columns):
order_by_dict = dict()

if order_by:
# Convert dict {'task_id': 'asc'} to string "task_id asc".
order_by = re.sub("[{}:'\"]", '', str(order_by)) if type(order_by).__name__ == 'dict' else order_by
order_by_result = order_by.strip()

# allowing custom user added task.info columns to be sortable
Expand Down
5 changes: 5 additions & 0 deletions pybossa/sched.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,11 @@ def get_reserve_task_category_info(reserve_task_config, project_id, timeout, use
if not reserve_task_config:
return sql_filters, category_keys

if current_app.config.get('PRIVATE_INSTANCE'):
current_app.logger.info("Reserve task by category disabled for private instance. project_id %s, reserve_task_config %s",
project_id, str(reserve_task_config))
return sql_filters, category_keys

category = ":".join(["{}:*".format(field) for field in sorted(reserve_task_config)])
lock_manager = LockManager(sentinel.master, timeout)
category_keys = lock_manager.get_task_category_lock(project_id, user_id, category, exclude_user)
Expand Down
15 changes: 10 additions & 5 deletions pybossa/view/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1784,15 +1784,13 @@ def bulk_priority_update(short_name):
@blueprint.route('/<short_name>/tasks/assign-workersupdate', methods=['POST'])
@login_required
def bulk_update_assign_worker(short_name):

response = {}
project, owner, ps = project_by_shortname(short_name)
admin_or_project_owner(current_user, project)
data = json.loads(request.data)

if data.get("add") is None and data.get("remove") is None:
# read data and return users

task_id = data.get("taskId")
bulk_update = False
assign_user_emails = []
Expand All @@ -1813,6 +1811,7 @@ def bulk_update_assign_worker(short_name):
for task_id in task_ids:
t = task_repo.get_task_by(project_id=project.id,
id=int(task_id))
t.user_pref = t.user_pref or {}
assign_user_emails = assign_user_emails.union(set(t.user_pref.get("assign_user", [])))
assign_users = []
for user_email in assign_user_emails:
Expand All @@ -1831,7 +1830,6 @@ def bulk_update_assign_worker(short_name):
all_users = user_repo.get_all()
all_user_data = []
for user in all_users:

# Exclude currently assigned users in the candidate list ONLY for single task update
if user.email_addr in assign_user_emails and not bulk_update:
continue
Expand All @@ -1844,6 +1842,7 @@ def bulk_update_assign_worker(short_name):
# update tasks with assign worker values
assign_workers = data.get('add', [])
remove_workers = data.get('remove', [])
assign_users = []

assign_worker_emails = [w["email"] for w in assign_workers]
remove_worker_emails = [w["email"] for w in remove_workers]
Expand Down Expand Up @@ -1873,12 +1872,18 @@ def bulk_update_assign_worker(short_name):
if remove_user_email in assign_user:
assign_user.remove(remove_user_email)

user_pref["assign_user"] = assign_user
if assign_user:
user_pref["assign_user"] = assign_user
assign_users.append({'taskId': int(task_id), 'assign_user': assign_user})
elif "assign_user" in user_pref:
del user_pref["assign_user"]

t.user_pref = user_pref
flag_modified(t, "user_pref")

task_repo.update(t)
response['assign_users'] = assign_users

return Response(json.dumps(response), 200, mimetype='application/json')

@crossdomain(origin='*', headers=cors_headers)
Expand Down Expand Up @@ -3643,7 +3648,7 @@ def assign_users(short_name):
project.set_project_users(project_users)
project_repo.save(project)
auditlogger.log_event(project, current_user, 'update', 'project.assign_users',
'N/A', users)
'N/A', project_users)
if not project_users:
msg = gettext('Users unassigned or no user assigned to project')
current_app.logger.info('Project id {} users unassigned from project.'.format(project.id))
Expand Down
17 changes: 17 additions & 0 deletions test/test_cache/test_cache_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,3 +485,20 @@ def test_order_by_args_multiple_columns4(self):
assert 'bi' in order_by_dict
assert 'companyBbid' in order_by_dict
assert 'somethingElse' in order_by_dict

@with_context
def test_order_by_args_dict_1(self):
"""Test parse_tasks_browse_order_by_args as dict 1 field."""
order_by_result, order_by_dict = parse_tasks_browse_order_by_args({'task_id': 'asc'}, ['bi', 'companyBbid', 'somethingElse'])

assert order_by_result == "id asc"
assert 'task_id' in order_by_dict

@with_context
def test_order_by_args_dict_2(self):
"""Test parse_tasks_browse_order_by_args as dict 2 fields."""
order_by_result, order_by_dict = parse_tasks_browse_order_by_args({'task_id': 'asc', 'priority': 'desc'}, ['bi', 'companyBbid', 'somethingElse'])

assert order_by_result == "id asc, priority_0 desc"
assert 'task_id' in order_by_dict
assert 'priority' in order_by_dict
7 changes: 7 additions & 0 deletions test/test_reserve_task_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ def test_get_reserve_task_category_info(self, get_task_category_lock):
assert sql_filters == expected_sql_filter and \
category_keys == expected_category_keys, "sql_filters, category_keys must be non empty"

# reserve task disabled for private instance,
with patch.dict(self.flask_app.config, {'PRIVATE_INSTANCE': True}):
sql_filters, category_keys = get_reserve_task_category_info(reserve_task_config, project.id, timeout, owner.id)
assert not sql_filters, "sql_filters must be empty for private instance"
assert not category_keys, "sql_filters must be empty for private instance"


@with_context
def test_acquire_and_release_reserve_task_lock(self):
user = UserFactory.create()
Expand Down
129 changes: 121 additions & 8 deletions test/test_view/test_assign_task_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,24 +103,137 @@ def test_bulk_priority_update(self):
assert task1.priority_0 == .5, task1.priority_0


@with_context
def test_get_assign_workers_by_bulk(self):
"""Test get assign worker by bulk."""
admin = UserFactory.create(admin=True)
admin.set_password('1234')
user_repo.save(admin)

csrf = self.get_csrf('/account/signin')
self.signin(email=admin.email_addr, csrf=csrf)

# Create a project with a worker assigned.
user1 = UserFactory.create(email_addr='a1@a.com', fullname="test_user1")
user2 = UserFactory.create(email_addr='a2@a.com', fullname="test_user2")
project = ProjectFactory.create(published=True, info={'project_users': [user1.id, user2.id]})

task1 = TaskFactory.create(project=project)
task_repo.update(task1)
task2 = TaskFactory.create(project=project)
task_repo.update(task2)

# Assign user to all tasks by filter.
req_data = dict(filters='{"add":[{"fullname":"' + user1.fullname + '","email":"' + user1.email_addr + '"}],"remove":[]}')

url = '/project/%s/tasks/assign-workersupdate?api_key=%s' % (project.short_name, project.owner.api_key)
res = self.app.post(url, content_type='application/json', data=json.dumps(req_data), follow_redirects=True, headers={'X-CSRFToken': csrf})
res_data = json.loads(res.data)

# Verify users are returned.
assert len(res_data['all_users']) > 1
assert res_data['all_users'][0]['email']

# Verify emails are returned.
emails = [user['email'] for user in res_data['all_users']]
assert user1.email_addr in emails
assert user2.email_addr in emails

@with_context
def test_update_assign_workers_by_task_id(self):
"""Test update assign worker by task id."""
admin = UserFactory.create(admin=True)
admin.set_password('1234')
user_repo.save(admin)

csrf = self.get_csrf('/account/signin')
self.signin(email=admin.email_addr, csrf=csrf)

project = ProjectFactory.create(published=True)
user = UserFactory.create(email_addr='a@a.com', fullname="test_user")

task1 = TaskFactory.create(project=project)
task_repo.update(task1)

# Assign user to task by task id.
req_data = dict(taskId=str(task1.id), add=[{'email':user.email_addr}])

url = '/project/%s/tasks/assign-workersupdate?api_key=%s' % (project.short_name, project.owner.api_key)
res = self.app.post(url, content_type='application/json', data=json.dumps(req_data), follow_redirects=True, headers={'X-CSRFToken': csrf})
res_data = json.loads(res.data)

# Verify the user has been assigned to this task.
assert res_data['assign_users'][0]['taskId'] == task1.id
assert res_data['assign_users'][0]['assign_user'][0] == user.email_addr

task1_modified = task_repo.get_task(task1.id)
assert user.email_addr in task1_modified.user_pref.get('assign_user')

@with_context
def test_update_assign_workers(self):
"""Test update assign worker."""
def test_update_assign_workers_by_filter(self):
"""Test update assign worker by filter."""
admin = UserFactory.create(admin=True)
admin.set_password('1234')
user_repo.save(admin)

csrf = self.get_csrf('/account/signin')
self.signin(email=admin.email_addr, csrf=csrf)

project = ProjectFactory.create(published=True)
user = UserFactory.create(email_addr='a@a.com', fullname="test_user")

task1 = TaskFactory.create(project=project)
task_repo.update(task1)

# Assign user to task by filter.
req_data = dict(filters='{"task_id": "' + str(task1.id) + '"}', add=[{'email':user.email_addr}])

url = '/project/%s/tasks/assign-workersupdate?api_key=%s' % (project.short_name, project.owner.api_key)
res = self.app.post(url, content_type='application/json', data=json.dumps(req_data), follow_redirects=True, headers={'X-CSRFToken': csrf})
res_data = json.loads(res.data)

# Verify the user has been assigned to this task.
assert res_data['assign_users'][0]['taskId'] == task1.id
assert res_data['assign_users'][0]['assign_user'][0] == user.email_addr

task1_modified = task_repo.get_task(task1.id)
assert user.email_addr in task1_modified.user_pref.get('assign_user')

@with_context
def test_update_assign_workers_remove(self):
"""Test remove assigned worker."""
admin = UserFactory.create(admin=True)
admin.set_password('1234')
user_repo.save(admin)

csrf = self.get_csrf('/account/signin')
self.signin(email=admin.email_addr, csrf=csrf)

project = ProjectFactory.create(published=True)
user = UserFactory.create(email_addr='a@a.com', fullname="test_user")

task1_user_pref = dict(assign_user=[user.email_addr])

# Create a task with an assigned user.
task1 = TaskFactory.create(project=project, user_pref=task1_user_pref)
task_repo.update(task1)
req_data = dict(taskIds=str(task1.id), add=user)

# Verify the user has been assigned to the task.
assert user.email_addr in task1.user_pref.get('assign_user')

# Load the task and verify the user has been assigned to the task.
task1_modified1 = task_repo.get_task(task1.id)
assert user.email_addr in task1_modified1.user_pref.get('assign_user')

# Remove the user.
req_data = dict(taskId=str(task1.id), remove=[{'email':user.email_addr}])

url = '/project/%s/tasks/assign-workersupdate?api_key=%s' % (project.short_name, project.owner.api_key)
req_data = dict(taskId=None)
res = self.app.post(url, content_type='application/json',
data=json.dumps(req_data))
res = self.app.post(url, content_type='application/json', data=json.dumps(req_data), follow_redirects=True, headers={'X-CSRFToken': csrf})
res_data = json.loads(res.data)
assert res_data['assign_users'][0]['fullname'] == user.fullname
assert res_data['assign_users'][0]['email'] == user.email_addr

assert not res_data['assign_users']

# Verify the assign_user parameter has been deleted from the user_pref.
task1_modified2 = task_repo.get_task(task1.id)
assert not task1_modified2.user_pref.get('assign_user')

0 comments on commit b067eb4

Please sign in to comment.