Skip to content

Commit

Permalink
Merge fa73eab into 283d23a
Browse files Browse the repository at this point in the history
  • Loading branch information
dchhabda committed Feb 23, 2023
2 parents 283d23a + fa73eab commit 29c5171
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 31 deletions.
4 changes: 3 additions & 1 deletion pybossa/forms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ class ProjectUpdateForm(ProjectForm):
short_name = TextField(label=None, widget=HiddenInput())
long_description = TextAreaField(lazy_gettext('Long Description'))
allow_anonymous_contributors = BooleanField(lazy_gettext('Allow Anonymous Contributors'))
allow_taskrun_edit = BooleanField(lazy_gettext('Allow Editing of Task Submissions'))
private_instance = data_access.data_access_levels.get("valid_access_levels", []) == ["L1", "L2", "L3", "L4"]
if not private_instance:
allow_taskrun_edit = BooleanField(lazy_gettext('Allow Editing of Task Submissions'))
zip_download = BooleanField(lazy_gettext('Allow ZIP data download'))
category_id = SelectField(lazy_gettext('Category'), coerce=int)
hidden = BooleanField(lazy_gettext('Hide?'))
Expand Down
70 changes: 41 additions & 29 deletions pybossa/view/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,8 @@ def handle_valid_form(form):
'input_data': form.input_data_class.data,
'output_data': form.output_data_class.data
}
new_project.info["allow_taskrun_edit"] = form.allow_taskrun_edit.data
if "allow_taskrun_edit" in form:
new_project.info["allow_taskrun_edit"] = form.allow_taskrun_edit.data

project_repo.update(new_project)
auditlogger.add_log_entry(old_project, new_project, current_user)
Expand Down Expand Up @@ -854,7 +855,7 @@ def handle_valid_form(form):
project.kpi = project.info.get('kpi')
project.input_data_class = project.info.get('data_classification', {}).get('input_data')
project.output_data_class = project.info.get('data_classification', {}).get('output_data')
project.allow_taskrun_edit = project.info.get("allow_taskrun_edit")
project.allow_taskrun_edit = project.info.get("allow_taskrun_edit", False)
ensure_amp_config_applied_to_project(project, project.info.get('annotation_config', {}))
form = dynamic_project_form(ProjectUpdateForm, None, data_access_levels, obj=project,
products=prodsubprods, data_classes=data_classes)
Expand Down Expand Up @@ -1349,40 +1350,51 @@ def task_presenter(short_name, task_id, task_submitter_id=None):
tp_code = process_table_component(tp_code, user_response, task)
template_args["project"]["info"]["task_presenter"] = tp_code

# with edit submission, pass task run id so that taskrun can be updated
if request.args.get("mode") == "edit_submission":
template_args["taskrun_id"] = taskruns[0].id
template_args["taskrun_user_id"] = taskruns[0].user_id

def respond(tmpl):
response = dict(template=tmpl, **template_args)
return handle_content_type(response)

if not (task.project_id == project.id):
return respond('/projects/task/wrong.html')

guard = ContributionsGuard(sentinel.master,
timeout=project.info.get('timeout'))
guard.stamp(task, get_user_id_or_ip())

# Verify the worker has an unexpired lock on the task. Otherwise, task will fail to submit.
timeout, ttl = fetch_lock_for_user(task.project_id, task_id, user_id)
remaining_time = float(ttl) - time.time() if ttl else None
if (not remaining_time or remaining_time <= 0) and mode != 'read_only':
current_app.logger.info("unable to lock task or task expired. \
project %s, task %s, user %s, remaining time %s, mode %s",
task.project_id, task_id, user_id, remaining_time, mode)
flash(gettext("Unable to lock task or task expired. Please cancel and begin a new task."), "error")
else:
if mode != 'read_only':
# Set the original timeout seconds to display in the message.
template_args['project']['original_timeout'] = timeout
# Set the seconds remaining to display in the message.
template_args['project']['timeout'] = remaining_time
current_app.logger.info("User %s present task %s, remaining time %s, original timeout %s",
user_id, task_id, remaining_time, timeout)

if not guard.check_task_presented_timestamp(task, get_user_id_or_ip()):
guard.stamp_presented_time(task, get_user_id_or_ip())

if has_no_presenter(project):
flash(gettext("Sorry, but this project is still a draft and does "
"not have a task presenter."), "error")
# bypass lock check for the submitter when submitter can edit their response
bypass_lock_check = request.args.get("mode") == "edit_submission" and \
project.info.get("allow_taskrun_edit") and \
current_user.id == task_submitter_id

if not bypass_lock_check:
guard = ContributionsGuard(sentinel.master,
timeout=project.info.get('timeout'))
guard.stamp(task, get_user_id_or_ip())

# Verify the worker has an unexpired lock on the task. Otherwise, task will fail to submit.
timeout, ttl = fetch_lock_for_user(task.project_id, task_id, user_id)
remaining_time = float(ttl) - time.time() if ttl else None
if (not remaining_time or remaining_time <= 0) and mode != 'read_only':
current_app.logger.info("unable to lock task or task expired. \
project %s, task %s, user %s, remaining time %s, mode %s",
task.project_id, task_id, user_id, remaining_time, mode)
flash(gettext("Unable to lock task or task expired. Please cancel and begin a new task."), "error")
else:
if mode != 'read_only':
# Set the original timeout seconds to display in the message.
template_args['project']['original_timeout'] = timeout
# Set the seconds remaining to display in the message.
template_args['project']['timeout'] = remaining_time
current_app.logger.info("User %s present task %s, remaining time %s, original timeout %s",
user_id, task_id, remaining_time, timeout)

if not guard.check_task_presented_timestamp(task, get_user_id_or_ip()):
guard.stamp_presented_time(task, get_user_id_or_ip())

if has_no_presenter(project):
flash(gettext("Sorry, but this project is still a draft and does "
"not have a task presenter."), "error")

return respond('/projects/presenter.html')

Expand Down
30 changes: 30 additions & 0 deletions test/test_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -3461,6 +3461,36 @@ def test_task_presenter_with_allow_taskrun_edit_raises_forbidden(self):
res = self.app.get('/project/%s/task/%s' % (project_short_name, task.id))
assert res.status_code == 403, res.status_code

@with_context
def test_task_presenter_with_allow_taskrun_edit_allows_submission(self):
"""Test WEB with taskrun edit is permitted with task_submitter_id passed"""
self.register()
self.signin()
self.create()
project = db.session.query(Project).get(1)
project.info = dict(allow_taskrun_edit=True)
db.session.commit()
self.new_task(project.id)
project_short_name = project.short_name

task = db.session.query(Task).filter(Task.project_id == 1).first()
# user = db.session.query(User).first()
regular_user = UserFactory.create(id=999, subadmin=False, admin=False)
regular_user.set_password('1234')
user_repo.save(regular_user)
self.signin(email=regular_user.email_addr, password='1234')
task_run = TaskRun(project_id=project.id, task_id=task.id,
info={'answer': 1,
'odfoa': {'version': 1, 'source-uri': 'http://fake.com', 'odf': {}, 'oa': {}},
'fake': {'b': 27}},
user_id=regular_user.id)
db.session.add(task_run)
db.session.commit()

# task_submitter_id is passed to fetch task response recorded by the user
res = self.app.get('/project/%s/task/%s/%s?mode=edit_submission' % (project_short_name, task.id, regular_user.id))
assert res.status_code == 200, res.status_code

@with_context
@patch('pybossa.view.projects.uploader.upload_file', return_value=True)
def test_25_get_wrong_task_app(self, mock):
Expand Down

0 comments on commit 29c5171

Please sign in to comment.