Skip to content

Commit b221ebb

Browse files
committed
Fix the retire and restore buttons in classic template. Change others:
Update devel and responsive templates with new javascript and anti-csrf deployment mechanism for retire operation. Restore operation not implemented yet, but somebody could do the work based on classic template changes.
1 parent 6568af0 commit b221ebb

File tree

4 files changed

+102
-30
lines changed

4 files changed

+102
-30
lines changed

CHANGES.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,9 @@ Fixed:
454454
subject is "showing template sources to all".
455455
- issue2550945: OpenPGP: Extends newissuecopy.py to encrypt if configured.
456456
(Bernhard Reiter)
457-
457+
- CSRF protection broke the retire function for query edit. Fix
458+
javascript and make sure csrf tokens are provided in the right
459+
places. (John Rouillard)
458460

459461
2016-01-11: 1.5.1
460462

share/roundup/templates/classic/html/query.edit.html

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,25 @@
66
<span metal:fill-slot="body_title" tal:omit-tag="python:1"
77
i18n:translate="">"Your Queries" Editing</span>
88

9-
<td class="content" metal:fill-slot="content">
9+
<td class="content" metal:fill-slot="content"
10+
tal:define="anti_csrf_this_page python:utils.anti_csrf_nonce()" >
1011

1112
<span tal:condition="not:context/is_edit_ok"
1213
i18n:translate="">You are not allowed to edit queries.</span>
1314

14-
<script language="javascript">
15+
<script tal:attributes="nonce request/client/client_nonce"
16+
language="javascript">
1517
// This allows us to make the delete button an immediate action.
1618
// The post_to_url function comes from:
1719
// http://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit
18-
function retire(qid) {
19-
post_to_url('query'+qid, {'@action': 'retire', '@template': 'edit'});
20+
function retire(qid, csrf) {
21+
post_to_url('query'+qid, {'@action': 'retire', '@template':'edit',
22+
'@csrf': csrf});
2023
}
2124

22-
function restore(qid) {
23-
post_to_url('query'+qid, {'@action': 'restore', '@template': 'edit'});
25+
function restore(qid, csrf) {
26+
post_to_url('query'+qid, {'@action': 'restore', '@template': 'edit',
27+
'@csrf': csrf});
2428
}
2529
function post_to_url(path, params, method) {
2630
method = method || "post"; // Set method to post by default if not specified.
@@ -93,7 +97,7 @@
9397

9498
<td>
9599
<input type="button" value="Delete" i18n:attributes="value"
96-
tal:attributes="onClick python:'''retire('%s')'''%query.id">
100+
tal:attributes="onClick python:'''retire('%s','%s')'''%(query.id,anti_csrf_this_page)">
97101
</td>
98102
</tal:block>
99103
</tr>
@@ -135,7 +139,7 @@
135139
<td colspan="3" tal:condition="python: query.creator == uid" i18n:translate="">[query is retired]</td>
136140
<td tal:condition="python:query.creator == uid">
137141
<input type="button" value="Restore" i18n:attributes="value"
138-
tal:attributes="onClick python:'''restore('%s')'''%query.id">
142+
tal:attributes="onClick python:'''restore('%s','%s')'''%(query.id,anti_csrf_this_page)">
139143
</td>
140144
<td colspan="1" tal:condition="python:not query.creator == uid" tal:content="query/creator" i18n:translate="">put query owner here</td>
141145
</tal:block>
@@ -150,17 +154,17 @@
150154
<td colspan="2" i18n:translate="">[query is private]</td>
151155
<td tal:condition="python:query.creator == uid">
152156
<input type="button" value="Restore" i18n:attributes="value"
153-
tal:attributes="onClick python:'''restore('%s')'''%query.id">
157+
tal:attributes="onClick python:'''restore('%s','%s')'''%(query.id,anti_csrf_this_page)">
154158
</td>
155159
<td colspan="1" tal:content="query/creator" i18n:translate="">put query owner here</td>
156160
</tal:block>
157161
</tr>
158162
</tal:block>
159163
<tr><td colspan="5">
160-
<input name="@csrf" type="hidden"
161-
tal:attributes="value python:utils.anti_csrf_nonce()">
162164
<input type="hidden" name="@action" value="edit">
163165
<input type="hidden" name="@template" value="edit">
166+
<input name="@csrf" type="hidden"
167+
tal:attributes="value anti_csrf_this_page">
164168
<input type="submit" value="Save Selection" i18n:attributes="value">
165169
</td></tr>
166170

share/roundup/templates/devel/html/query.edit.html

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,50 @@
55
<span metal:fill-slot="body_title" tal:omit-tag="python:1"
66
i18n:translate="">"Your Queries" Editing</span>
77

8-
<td class="content" metal:fill-slot="content">
8+
<td class="content" metal:fill-slot="content"
9+
tal:define="anti_csrf_this_page python:utils.anti_csrf_nonce()" >
910

1011
<span tal:condition="not:context/is_edit_ok"
1112
i18n:translate="">You are not allowed to edit queries.</span>
1213

13-
<script language="javascript">
14-
// This exists solely because I can't figure how to get the & into an
15-
// attributes TALES expression, and so it keeps getting quoted.
16-
function retire(qid) {
17-
window.location = 'query'+qid+'?@action=retire&@template=edit';
14+
<script tal:attributes="nonce request/client/client_nonce"
15+
language="javascript" >
16+
// This allows us to make the delete button an immediate action.
17+
// The post_to_url function comes from:
18+
// http://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit
19+
function retire(qid, csrf) {
20+
post_to_url('query'+qid, {'@action': 'retire', '@template':'edit',
21+
'@csrf': csrf});
1822
}
23+
24+
function restore(qid, csrf) {
25+
post_to_url('query'+qid, {'@action': 'restore', '@template': 'edit',
26+
'@csrf': csrf});
27+
}
28+
function post_to_url(path, params, method) {
29+
method = method || "post"; // Set method to post by default if not specified.
30+
31+
var form = document.createElement("form");
32+
form.setAttribute("method", method);
33+
form.setAttribute("action", path);
34+
35+
for(var key in params) {
36+
if(params.hasOwnProperty(key)) {
37+
var hiddenField = document.createElement("input");
38+
hiddenField.setAttribute("type", "hidden");
39+
hiddenField.setAttribute("name", key);
40+
hiddenField.setAttribute("value", params[key]);
41+
42+
form.appendChild(hiddenField);
43+
}
44+
}
45+
46+
document.body.appendChild(form);
47+
form.submit();
48+
}
49+
50+
// note restore() is defined above but not yet used in this template.
51+
// see classic template and integrate it.
1952
</script>
2053

2154
<form method="POST" onSubmit="return submit_once()" action="query"
@@ -28,7 +61,7 @@
2861
<th i18n:translate="">Include in "Your Queries"</th>
2962
<th i18n:translate="">Edit</th>
3063
<th i18n:translate="">Private to you?</th>
31-
<th>&nbsp;</th>
64+
<th i18n:translate="">delete/restore<br> (javascript<br>required)</th>
3265
</tr>
3366

3467
<tr tal:repeat="query mine">
@@ -76,7 +109,7 @@
76109

77110
<td>
78111
<input type="button" value="Delete" i18n:attributes="value"
79-
tal:attributes="onClick python:'''retire('%s')'''%query.id">
112+
tal:attributes="onClick python:'''retire('%s','%s')'''%(query.id,anti_csrf_this_page)">
80113
</td>
81114
</tr>
82115

@@ -97,7 +130,7 @@
97130

98131
<tr><td colspan="5">
99132
<input name="@csrf" type="hidden"
100-
tal:attributes="value python:utils.anti_csrf_nonce()">
133+
tal:attributes="value anti_csrf_this_page">
101134
<input type="hidden" name="@action" value="edit">
102135
<input type="hidden" name="@template" value="edit">
103136
<input type="submit" value="Save Selection" i18n:attributes="value">

share/roundup/templates/responsive/html/query.edit.html

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,50 @@
55
<span metal:fill-slot="body_title" tal:omit-tag="python:1"
66
i18n:translate="">"Your Queries" Editing</span>
77

8-
<td class="content" metal:fill-slot="content">
8+
<td class="content" metal:fill-slot="content"
9+
tal:define="anti_csrf_this_page python:utils.anti_csrf_nonce()" >
910

1011
<span tal:condition="not:context/is_edit_ok"
1112
i18n:translate="">You are not allowed to edit queries.</span>
1213

13-
<script language="javascript">
14-
// This exists solely because I can't figure how to get the & into an
15-
// attributes TALES expression, and so it keeps getting quoted.
16-
function retire(qid) {
17-
window.location = 'query'+qid+'?@action=retire&@template=edit';
14+
<script tal:attributes="nonce request/client/client_nonce"
15+
language="javascript" >
16+
// This allows us to make the delete button an immediate action.
17+
// The post_to_url function comes from:
18+
// http://stackoverflow.com/questions/133925/javascript-post-request-like-a-form-submit
19+
function retire(qid, csrf) {
20+
post_to_url('query'+qid, {'@action': 'retire', '@template':'edit',
21+
'@csrf': csrf});
1822
}
23+
24+
function restore(qid, csrf) {
25+
post_to_url('query'+qid, {'@action': 'restore', '@template': 'edit',
26+
'@csrf': csrf});
27+
}
28+
function post_to_url(path, params, method) {
29+
method = method || "post"; // Set method to post by default if not specified.
30+
31+
var form = document.createElement("form");
32+
form.setAttribute("method", method);
33+
form.setAttribute("action", path);
34+
35+
for(var key in params) {
36+
if(params.hasOwnProperty(key)) {
37+
var hiddenField = document.createElement("input");
38+
hiddenField.setAttribute("type", "hidden");
39+
hiddenField.setAttribute("name", key);
40+
hiddenField.setAttribute("value", params[key]);
41+
42+
form.appendChild(hiddenField);
43+
}
44+
}
45+
46+
document.body.appendChild(form);
47+
form.submit();
48+
}
49+
50+
// note restore() is defined above but not yet used in this template.
51+
// see classic template and integrate it.
1952
</script>
2053

2154
<form method="POST" onSubmit="return submit_once()" action="query"
@@ -28,7 +61,7 @@
2861
<th i18n:translate="">Include in "Your Queries"</th>
2962
<th i18n:translate="">Edit</th>
3063
<th i18n:translate="">Private to you?</th>
31-
<th>&nbsp;</th>
64+
<th i18n:translate="">delete/restore<br> (javascript<br>required)</th>
3265
</tr>
3366

3467
<tr tal:repeat="query mine">
@@ -76,7 +109,7 @@
76109

77110
<td>
78111
<input type="button" value="Delete" i18n:attributes="value"
79-
tal:attributes="onClick python:'''retire('%s')'''%query.id">
112+
tal:attributes="onClick python:'''retire('%s','%s')'''%(query.id,anti_csrf_this_page)">
80113
</td>
81114
</tr>
82115

@@ -97,7 +130,7 @@
97130

98131
<tr><td colspan="5">
99132
<input name="@csrf" type="hidden"
100-
tal:attributes="value python:utils.anti_csrf_nonce()">
133+
tal:attributes="value anti_csrf_this_page">
101134
<input type="hidden" name="@action" value="edit">
102135
<input type="hidden" name="@template" value="edit">
103136
<input type="submit" value="Save Selection" i18n:attributes="value">

0 commit comments

Comments
 (0)