0001-backoffice-protect-against-overwriting-of-backoffice.patch
tests/test_backoffice_pages.py | ||
---|---|---|
1150 | 1150 |
# check agent name is displayed next to pending submission |
1151 | 1151 |
assert '(%s)' % user.display_name in resp.body |
1152 | 1152 | |
1153 |
def test_backoffice_parallel_submission(pub): |
|
1154 |
user = create_user(pub) |
|
1155 |
create_environment(pub) |
|
1156 | ||
1157 |
app = login(get_app(pub)) |
|
1158 |
resp = app.get('/backoffice/') |
|
1159 |
app.get('/backoffice/submission/', status=403) |
|
1160 | ||
1161 |
formdef = FormDef.get_by_urlname('form-title') |
|
1162 |
formdef.backoffice_submission_roles = user.roles[:] |
|
1163 |
formdef.enable_tracking_codes = True |
|
1164 |
formdef.store() |
|
1165 | ||
1166 |
formdata = formdef.data_class()() |
|
1167 |
formdata.data = {} |
|
1168 |
formdata.status = 'draft' |
|
1169 |
formdata.backoffice_submission = True |
|
1170 |
formdata.submission_context = {'agent_id': user.id} |
|
1171 |
formdata.store() |
|
1172 | ||
1173 |
resp = app.get('/backoffice/submission/') |
|
1174 |
assert 'Submission to complete' in resp.body |
|
1175 |
resp1 = app.get('/backoffice/submission/form-title/%s' % formdata.id) |
|
1176 |
resp1 = resp1.follow() |
|
1177 |
resp2 = app.get('/backoffice/submission/form-title/%s' % formdata.id) |
|
1178 |
resp2 = resp2.follow() |
|
1179 |
resp3 = app.get('/backoffice/submission/form-title/%s' % formdata.id) |
|
1180 |
resp3 = resp3.follow() |
|
1181 | ||
1182 |
resp1.form['f1'] = 'foo' |
|
1183 |
resp1.form['f2'] = 'bar' |
|
1184 |
resp1.form['f3'] = 'C' |
|
1185 |
resp1 = resp1.form.submit('submit') # to validation page |
|
1186 | ||
1187 |
# also move the second form to the validation page |
|
1188 |
resp2.form['f1'] = 'bar' |
|
1189 |
resp2.form['f2'] = 'bar' |
|
1190 |
resp2.form['f3'] = 'C' |
|
1191 |
resp2 = resp2.form.submit('submit') # to validation page |
|
1192 | ||
1193 |
resp1 = resp1.form.submit('submit') # final validation |
|
1194 |
resp1 = resp1.follow() |
|
1195 | ||
1196 |
resp2 = resp2.form.submit('submit') # final validation |
|
1197 |
assert resp2.status_code == 302 |
|
1198 |
resp2 = resp2.follow() |
|
1199 |
assert 'This form has already been submitted.' in resp2.body |
|
1200 | ||
1201 |
# do the third form from the start |
|
1202 |
resp3.form['f1'] = 'baz' |
|
1203 |
resp3.form['f2'] = 'bar' |
|
1204 |
resp3.form['f3'] = 'C' |
|
1205 | ||
1206 |
resp_autosave = app.post('/backoffice/submission/form-title/autosave', |
|
1207 |
params=resp3.form.submit_fields()) |
|
1208 |
assert resp_autosave.json['result'] == 'error' |
|
1209 |
assert resp_autosave.json['reason'] == 'form has already been submitted' |
|
1210 | ||
1211 |
resp3 = resp3.form.submit('submit') # to validation page |
|
1212 |
assert resp3.status_code == 302 |
|
1213 |
resp3 = resp3.follow() |
|
1214 |
assert 'This form has already been submitted.' in resp3.body |
|
1215 | ||
1216 |
assert formdef.data_class().get(formdata.id).data['1'] == 'foo' |
|
1217 | ||
1218 |
# try again, very late. |
|
1219 |
resp4 = app.get('/backoffice/submission/form-title/%s' % formdata.id) |
|
1220 |
resp4 = resp4.follow() |
|
1221 |
assert 'This form has already been submitted.' in resp4.body |
|
1222 | ||
1153 | 1223 |
def test_backoffice_submission_dispatch(pub): |
1154 | 1224 |
user = create_user(pub) |
1155 | 1225 |
create_environment(pub) |
wcs/backoffice/submission.py | ||
---|---|---|
130 | 130 | |
131 | 131 |
def submitted(self, form, *args): |
132 | 132 |
filled = self.get_current_draft() or self.formdef.data_class()() |
133 |
if filled.id and filled.status != 'draft': |
|
134 |
get_session().message = ('error', _('This form has already been submitted.')) |
|
135 |
return redirect(get_publisher().get_backoffice_url() + '/submission/') |
|
133 | 136 |
filled.just_created() |
134 | 137 |
filled.data = self.formdef.get_data(form) |
135 | 138 |
filled.backoffice_submission = True |
... | ... | |
209 | 212 |
welco_url = get_publisher().get_site_option('welco_url', 'options') |
210 | 213 | |
211 | 214 |
r = TemplateIO(html=True) |
215 |
r += get_session().display_message() |
|
212 | 216 |
modes = ['empty', 'create', 'existing'] |
213 | 217 |
if welco_url: |
214 | 218 |
modes.remove('create') |
wcs/forms/root.py | ||
---|---|---|
56 | 56 |
from backoffice import FormDefUI |
57 | 57 | |
58 | 58 | |
59 |
class SubmittedDraftException(Exception): |
|
60 |
pass |
|
61 | ||
62 | ||
59 | 63 |
def html_top(title = None): |
60 | 64 |
template.html_top(title = title, default_org = _('Forms')) |
61 | 65 | |
... | ... | |
737 | 741 |
# if there's a draft (be it because drafts are enabled or |
738 | 742 |
# because the formdata was created as a draft via the |
739 | 743 |
# submission API), update it with current data. |
740 |
self.autosave_draft(draft_id, page_no, form_data) |
|
744 |
try: |
|
745 |
self.autosave_draft(draft_id, page_no, form_data) |
|
746 |
except SubmittedDraftException: |
|
747 |
if get_request().is_in_backoffice(): |
|
748 |
get_session().message = ('error', _('This form has already been submitted.')) |
|
749 |
return redirect(get_publisher().get_backoffice_url() + '/submission/') |
|
750 |
return template.error_page(_('This form has already been submitted.')) |
|
741 | 751 |
elif self.formdef.enable_tracking_codes and not self.edit_mode: |
742 | 752 |
# if there's no draft yet and tracking codes are enabled, create one |
743 | 753 |
filled = self.save_draft(form_data, page_no) |
... | ... | |
856 | 866 |
return |
857 | 867 | |
858 | 868 |
if not formdata.status == 'draft': |
859 |
return
|
|
869 |
raise SubmittedDraftException()
|
|
860 | 870 | |
861 | 871 |
formdata.page_no = page_no |
862 | 872 |
formdata.data = form_data |
... | ... | |
909 | 919 |
if not session.has_form_token(get_request().form.get('_ajax_form_token')): |
910 | 920 |
return result_error('obsolete ajax form token (late check)') |
911 | 921 | |
912 |
draft_formdata = self.save_draft(form_data, page_no) |
|
922 |
try: |
|
923 |
draft_formdata = self.save_draft(form_data, page_no) |
|
924 |
except SubmittedDraftException: |
|
925 |
return result_error('form has already been submitted') |
|
913 | 926 | |
914 | 927 |
return json.dumps({'result': 'success'}) |
915 | 928 | |
916 | 929 |
def save_draft(self, data, page_no): |
917 | 930 |
filled = self.get_current_draft() or self.formdef.data_class()() |
931 |
if filled.id and filled.status != 'draft': |
|
932 |
raise SubmittedDraftException() |
|
918 | 933 |
filled.data = data |
919 | 934 |
filled.status = 'draft' |
920 | 935 |
filled.page_no = page_no |
... | ... | |
1113 | 1128 |
raise errors.TraversalError() |
1114 | 1129 | |
1115 | 1130 |
if not filled.is_draft(): |
1131 |
if get_request().is_in_backoffice(): |
|
1132 |
get_session().message = ('error', _('This form has already been submitted.')) |
|
1133 |
return redirect(get_publisher().get_backoffice_url() + '/submission/') |
|
1116 | 1134 |
return PublicFormStatusPage(self.formdef, filled) |
1117 | 1135 | |
1118 | 1136 |
if not (get_request().is_in_backoffice() or filled.formdef.enable_tracking_codes): |
1119 |
- |