1 from datetime import datetime
2 from tests.test_basics import BasicTest
6 # no specific rights required
7 class GeneralTests(BasicTest):
20 def test_main_page(self):
21 response = self.app.get('/', environ_base={'USER_ROLES': user}, follow_redirects=True)
22 self.assertEqual(response.status_code, 200)
24 def test_basic_results_data(self):
25 result = self.app.get('/', environ_base={'USER_ROLES': user}, follow_redirects=True)
26 testtext= '<div class="motion card" id="motion-3">\n <div class="motion-title card-heading alert-warning">'\
27 + '\n <span class="title-text">Motion C</span> (Canceled)\n <span class="motion-type">group1</span>'\
28 + '\n <div># g1.20200402.003'\
29 + '\n <a class="btn btn-primary" href="/motion/g1.20200402.003" role="button">Result</a>'\
30 + '\n </div>\n <div class="date">'\
31 + '\n <div>Proposed: 2020-04-02 21:47:24 (UTC) by User A</div>'\
32 + '\n <div>Canceled: 2020-04-03 21:48:24 (UTC) by User A</div>\n </div>\n </div>'\
33 + '\n <div class="card-body">\n <p><p>A third motion</p></p>'\
34 + '\n <p>\nYes <span class="badge badge-pill badge-secondary">1</span><br>'\
35 + '\nNo <span class="badge badge-pill badge-secondary">0</span><br>'\
36 + '\nAbstain <span class="badge badge-pill badge-secondary">0</span><br>\n </p>'\
37 + '\n <p>Cancelation reason: Entered with wrong text</p>\n </div>\n</div>\n'
38 self.assertIn(str.encode(testtext), result.data)
39 testtext= '<div class="motion card" id="motion-2">\n <div class="motion-title card-heading alert-danger">'\
40 + '\n <span class="title-text">Motion B</span> (Finished)\n <span class="motion-type">group1</span>'\
41 + '\n <div># g1.20200402.002'\
42 + '\n <a class="btn btn-primary" href="/motion/g1.20200402.002" role="button">Result</a>'\
43 + '\n </div>\n <div class="date">\n <div>Proposed: 2020-04-02 21:41:26 (UTC) by User A</div>'\
44 + '\n <div>Votes until: 2020-04-04 21:41:26 (UTC)</div>\n </div>\n </div>'\
45 + '\n <div class="card-body">\n <p><p>A second motion</p></p>\n <p>'\
46 + '\nYes <span class="badge badge-pill badge-secondary">1</span><br>'\
47 + '\nNo <span class="badge badge-pill badge-secondary">2</span><br>'\
48 + '\nAbstain <span class="badge badge-pill badge-secondary">0</span><br>\n </p>\n </div>\n</div>\n'
49 self.assertIn(str.encode(testtext), result.data)
50 testtext= '<div class="motion card" id="motion-1">\n <div class="motion-title card-heading alert-success">'\
51 + '\n <span class="title-text">Motion A</span> (Finished)\n <span class="motion-type">group1</span>'\
52 + '\n <div># g1.20200402.001'\
53 + '\n <a class="btn btn-primary" href="/motion/g1.20200402.001" role="button">Result</a>'\
54 + '\n </div>\n <div class="date">\n <div>Proposed: 2020-04-02 21:40:33 (UTC) by User A</div>'\
55 + '\n <div>Votes until: 2020-04-02 21:40:33 (UTC)</div>\n </div>\n </div>'\
56 + '\n <div class="card-body">\n <p><p>My special motion</p></p>\n <p>'\
57 + '\nYes <span class="badge badge-pill badge-secondary">2</span><br>'\
58 + '\nNo <span class="badge badge-pill badge-secondary">1</span><br>'\
59 + '\nAbstain <span class="badge badge-pill badge-secondary">0</span><br>\n </p>\n </div>\n</div>\n'
60 self.assertIn(str.encode(testtext), result.data)
61 testtext= 'Proxy management'
62 self.assertNotIn(str.encode(testtext), result.data)
64 # start with second motion
65 result = self.app.get('/', environ_base={'USER_ROLES': user}, query_string=dict(start=2))
66 testtext= 'id=\"motion-3\">'
67 self.assertNotIn(str.encode(testtext), result.data)
68 testtext= 'id=\"motion-2">'
69 self.assertIn(str.encode(testtext), result.data)
70 testtext= 'id=\"motion-1\">'
71 self.assertIn(str.encode(testtext), result.data)
73 def test_basic_results_data_details(self):
74 motion='g1.20200402.002'
75 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
76 testtext= '<p>A second motion</p></p>\n </div>\n</div>\n<a href=\"/?start=2#motion-2\" class=\"btn btn-primary\">Back</a>'
77 self.assertIn(str.encode(testtext), result.data)
80 motion='g1.20200402.004'
81 response = self.createVote(user, motion, 'yes', userid)
82 self.assertEqual(response.status_code, 403)
83 self.assertIn(str.encode('Forbidden'), response.data)
85 def test_no_user(self):
86 result = self.app.get('/', follow_redirects=True)
87 self.assertEqual(result.status_code, 500)
88 self.assertIn(str.encode('Server misconfigured'), result.data)
90 def test_user_invalid(self):
91 result = self.app.get('/', environ_base={'USER_ROLES': '<invalid>/'}, follow_redirects=True)
92 self.assertEqual(result.status_code, 403)
93 self.assertIn(str.encode('Access denied'), result.data)
95 def test_basic_env(self):
96 result = self.app.get('/', environ_base={'USER': 'testuser', 'ROLES':''}, follow_redirects=True)
97 testtext= 'id=\"motion-3\">'
98 self.assertIn(str.encode(testtext), result.data)
100 def test_basic_results_data_details_not_given(self):
101 motion='g1.30190402.001'
102 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
103 self.assertEqual(result.status_code, 404)
104 self.assertIn(str.encode('Error, Not found'), result.data)
106 def test_no_proxy(self):
107 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
108 self.assertEqual(result.status_code, 403)
109 self.assertIn(str.encode('Forbidden'), result.data)
111 def test_no_proxy_add(self):
112 result = self.app.post('proxy/add', environ_base={'USER_ROLES': user}, follow_redirects=True)
113 self.assertEqual(result.status_code, 403)
114 self.assertIn(str.encode('Forbidden'), result.data)
116 def test_no_proxy_revoke(self):
117 result = self.app.post('proxy/revoke', environ_base={'USER_ROLES': user}, follow_redirects=True)
118 self.assertEqual(result.status_code, 403)
119 self.assertIn(str.encode('Forbidden'), result.data)
121 def test_no_proxy_revokeAll(self):
122 result = self.app.post('proxy/revokeall', environ_base={'USER_ROLES': user}, follow_redirects=True)
123 self.assertEqual(result.status_code, 403)
124 self.assertIn(str.encode('Forbidden'), result.data)
126 class VoterTests(BasicTest):
131 user='testuser/vote:*'
139 def test_main_page(self):
140 response = self.app.get('/', environ_base={'USER_ROLES': user}, follow_redirects=True)
141 self.assertEqual(response.status_code, 200)
143 def test_home_data(self):
144 result = self.app.get('/', environ_base={'USER_ROLES': user})
145 self.assertNotIn("<select class=\"float form-control\" name=\"category\">", str(result.data) )
147 def test_vote_yes(self):
148 motion='g1.20200402.004'
149 response = self.createVote(user, motion, 'yes', userid)
150 self.assertEqual(response.status_code, 302)
151 result = self.app.get('/', environ_base={'USER_ROLES': user})
152 resulttext=self.buildResultText('A fourth motion', 1, 0, 0)
153 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
154 testtext= 'class=\"btn btn-success\" name=\"vote\" value="yes" id="vote-yes">Yes</button>'
155 self.assertIn(str.encode(testtext), result.data)
156 testtext= 'class=\"btn btn-primary\" name=\"vote\" value=\"no\" id=\"vote-no\">No</button>'
157 self.assertIn(str.encode(testtext), result.data)
158 testtext= 'class=\"btn btn-primary\" name=\"vote\" value=\"abstain\" id=\"vote-abstain\">Abstain</button>'
159 self.assertIn(str.encode(testtext), result.data)
161 def test_vote_no(self):
162 motion='g1.20200402.004'
163 response = self.createVote(user, motion, 'no', userid)
164 self.assertEqual(response.status_code, 302)
165 result = self.app.get('/', environ_base={'USER_ROLES': user})
166 resulttext=self.buildResultText('A fourth motion', 0, 1, 0)
167 self.assertIn(str.encode(resulttext), result.data)
168 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
169 testtext= 'class="btn btn-primary" name="vote\" value=\"yes\" id=\"vote-yes\">Yes</button>'
170 self.assertIn(str.encode(testtext), result.data)
171 testtext= 'class=\"btn btn-success\" name=\"vote\" value=\"no\" id=\"vote-no\">No</button>'
172 self.assertIn(str.encode(testtext), result.data)
173 testtext= 'class=\"btn btn-primary\" name=\"vote\" value=\"abstain\" id=\"vote-abstain\">Abstain</button>'
174 self.assertIn(str.encode(testtext), result.data)
176 def test_vote_abstain(self):
177 motion='g1.20200402.004'
178 response = self.createVote(user, motion, 'abstain', userid)
179 self.assertEqual(response.status_code, 302)
180 result = self.app.get('/', environ_base={'USER_ROLES': user})
181 resulttext=self.buildResultText('A fourth motion', 0, 0, 1)
182 self.assertIn(str.encode(resulttext), result.data)
183 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
184 testtext= 'class=\"btn btn-primary\" name=\"vote\" value=\"yes\" id=\"vote-yes\">Yes</button>'
185 self.assertIn(str.encode(testtext), result.data)
186 testtext= 'class=\"btn btn-primary\" name=\"vote\" value=\"no\" id=\"vote-no\">No</button>'
187 self.assertIn(str.encode(testtext), result.data)
188 testtext= 'class=\"btn btn-success\" name=\"vote\" value=\"abstain\" id=\"vote-abstain\">Abstain</button>'
189 self.assertIn(str.encode(testtext), result.data)
191 def test_vote_change(self):
192 motion='g1.20200402.004'
193 response = self.createVote(user, motion, 'yes', userid)
194 self.assertEqual(response.status_code, 302)
195 result = self.app.get('/', environ_base={'USER_ROLES': user})
196 resulttext=self.buildResultText('A fourth motion', 1, 0, 0)
197 self.assertIn(str.encode(resulttext), result.data)
198 response = self.createVote(user, motion, 'no', userid)
199 self.assertEqual(response.status_code, 302)
200 result = self.app.get('/', environ_base={'USER_ROLES': user})
201 resulttext=self.buildResultText('A fourth motion', 0, 1, 0)
202 self.assertIn(str.encode(resulttext), result.data)
203 response = self.createVote(user, motion, 'abstain', userid)
204 self.assertEqual(response.status_code, 302)
205 result = self.app.get('/', environ_base={'USER_ROLES': user})
206 resulttext=self.buildResultText('A fourth motion', 0, 0, 1)
207 self.assertIn(str.encode(resulttext), result.data)
209 def test_vote_group(self):
210 motion='g1.20200402.004'
211 response = self.createVote(user, motion, 'yes', userid)
212 self.assertEqual(response.status_code, 302)
214 motion='g1.20200402.004'
215 user1='testuser/vote:group1'
216 response = self.createVote(user1, motion, 'yes', userid)
217 self.assertEqual(response.status_code, 302)
219 motion='g1.20200402.004'
220 user1='testuser/vote:group1 vote:group2'
221 response = self.createVote(user1, motion, 'yes', userid)
222 self.assertEqual(response.status_code, 302)
224 def test_vote_wrong_group(self):
225 motion='g1.20200402.004'
226 user1='testuser/vote:group2'
227 response = self.createVote(user1, motion, 'yes', userid)
228 self.assertEqual(response.status_code, 403)
229 self.assertIn(str.encode('Forbidden'), response.data)
231 def test_vote_closed(self):
232 motion='g1.20200402.002'
233 response = self.createVote(user, motion, 'abstain', userid)
234 self.assertEqual(response.status_code, 403)
235 self.assertIn(str.encode('Error, out of time'), response.data)
237 def test_vote_canceled(self):
238 motion='g1.20200402.003'
239 response = self.createVote(user, motion, 'abstain', userid)
240 self.assertEqual(response.status_code, 403)
241 self.assertIn(str.encode('Error, motion was canceled'), response.data)
243 def test_vote_not_given(self):
244 motion='g1.30190402.001'
245 response = self.createVote(user, motion, 'abstain', userid)
246 self.assertEqual(response.status_code, 404)
247 self.assertIn(str.encode('Error, Not found'), response.data)
249 def test_cancelMotion(self):
250 motion='g1.20200402.004'
252 response = self.cancelMotion(user, motion, reason)
253 self.assertEqual(response.status_code, 403)
254 self.assertIn(str.encode('Forbidden'), response.data)
256 def test_finishMotion(self):
257 motion='g1.20200402.004'
258 response = self.finishMotion(user, motion)
259 self.assertEqual(response.status_code, 403)
260 self.assertIn(str.encode('Forbidden'), response.data)
262 def test_see_old_vote(self):
263 motion='g1.20200402.002'
264 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
265 testtext= '<div>Proposed: 2020-04-02 21:41:26 (UTC) by User A</div>\n <div>Votes until: 2020-04-04 21:41:26 (UTC)</div>'\
266 + '\n </div>\n </div>\n <div class="card-body">\n <p><p>A second motion</p></p>\n </div>\n</div>'\
267 + '\n<a href="/?start=2#motion-2" class="btn btn-primary">Back</a>'
268 self.assertIn(str.encode(testtext), result.data)
270 def test_createMotion(self):
273 response = self.createMotion(user, title, content, '3', 'group1')
274 self.assertEqual(response.status_code, 403)
275 self.assertIn(str.encode('Forbidden'), response.data)
278 class CreateMotionTests(BasicTest):
283 user='testuser/vote:* create:* cancel:* finish:*'
289 def test_main_page(self):
290 response = self.app.get('/', environ_base={'USER_ROLES': user}, follow_redirects=True)
291 self.assertEqual(response.status_code, 200)
293 def test_home_data(self):
294 result = self.app.get('/', environ_base={'USER_ROLES': user})
296 # assert the response data
297 self.assertIn(b'User: testuser', result.data)
298 self.assertIn("<select class=\"float form-control\" name=\"category\">", str(result.data) )
300 def test_createMotion(self):
303 response = self.createMotion(user, title, content, '3', 'group1')
304 self.assertEqual(response.status_code, 302)
305 result = self.app.get('/', environ_base={'USER_ROLES': user})
306 self.assertIn(str.encode(title), result.data)
307 self.assertIn(str.encode(content), result.data)
308 self.assertIn(str.encode('g1.'+datetime.today().strftime('%Y%m%d')+'.001'), result.data)
309 testtext='<a class=\"btn btn-primary" href=\"/motion/g1.'+datetime.today().strftime('%Y%m%d')+'.001\" role=\"button\">Vote</a>'
310 self.assertIn(str.encode(testtext), result.data)
314 response = self.createMotion(user, title, content, '3', 'group1')
315 self.assertEqual(response.status_code, 302)
316 result = self.app.get('/', environ_base={'USER_ROLES': user})
317 self.assertIn(str.encode(title), result.data)
318 self.assertIn(str.encode(content), result.data)
319 self.assertIn(str.encode('g1.'+datetime.today().strftime('%Y%m%d')+'.002'), result.data)
323 response = self.createMotion(user, title, content, '3', 'group2')
324 self.assertEqual(response.status_code, 302)
325 result = self.app.get('/', environ_base={'USER_ROLES': user})
326 self.assertIn(str.encode(title), result.data)
327 self.assertIn(str.encode(content), result.data)
328 self.assertIn(str.encode('g2.'+datetime.today().strftime('%Y%m%d')+'.001'), result.data)
332 user1='testuser/vote:* create:group1 cancel:*'
333 response = self.createMotion(user1, title, content, '3', 'group1')
334 self.assertEqual(response.status_code, 302)
338 user1='testuser/vote:* create:group1 create:group2 cancel:*'
339 response = self.createMotion(user1, title, content, '3', 'group1')
340 self.assertEqual(response.status_code, 302)
343 def test_createMotionMarkdown(self):
344 title='Markdown Test'
345 content= 'MyMotionBody MD [text](https//domain.tld/link)'
346 response = self.createMotion(user, title, content, '3', 'group1')
347 self.assertEqual(response.status_code, 302)
348 result = self.app.get('/', environ_base={'USER_ROLES': user})
349 self.assertIn(str.encode(title), result.data)
350 self.assertIn(b'MyMotionBody MD <a href=\"https//domain.tld/link\">text</a>', result.data)
352 def test_createMotionMarkdownDirectLink(self):
353 title='Markdown Test Link'
354 content='MyMotionBody MD <a href=\"https//domain.tld/link\">direct</a'
355 response = self.createMotion(user, title, content, '3', 'group1')
356 self.assertEqual(response.status_code, 302)
357 result = self.app.get('/', environ_base={'USER_ROLES': user})
358 self.assertIn(str.encode(title), result.data)
359 self.assertIn(b'MyMotionBody MD <a href="https//domain.tld/link">direct</a', result.data)
361 def test_createMotionMarkdownCombined(self):
362 title='Markdown Test Link'
363 content='Body [combined](https//domain.tld/link) <a href=\"https//domain.tld/link\">combined1</a'
364 response = self.createMotion(user, title, content, '3', 'group1')
365 self.assertEqual(response.status_code, 302)
366 result = self.app.get('/', environ_base={'USER_ROLES': user})
367 self.assertIn(str.encode(title), result.data)
368 self.assertIn(b'Body <a href=\"https//domain.tld/link\">combined</a> <a href="https//domain.tld/link">combined1</a', result.data)
370 def test_createMotionWrongDayLength(self):
373 response = self.createMotion(user, title, content, '21', 'group1')
374 self.assertEqual(response.status_code, 400)
375 self.assertIn(str.encode('Error, invalid length'), response.data)
377 def test_createMotionMissingData(self):
380 response = self.createMotion(user, title, content, '3', 'group1')
381 self.assertEqual(response.status_code, 400)
382 self.assertIn(str.encode('Error, missing title'), response.data)
384 response = self.createMotion(user, title, content, '3', 'group1')
385 self.assertEqual(response.status_code, 400)
386 self.assertIn(str.encode('Error, missing content'), response.data)
388 content='New Content'
389 response = self.createMotion(user, title, content, '3', 'group1')
390 self.assertEqual(response.status_code, 400)
391 self.assertIn(str.encode('Error, missing title'), response.data)
393 def test_createMotionWrongGroup(self):
396 response = self.createMotion(user, title, content, '3', 'test1')
397 self.assertEqual(response.status_code, 403)
398 self.assertIn(str.encode('Forbidden'), response.data)
400 user1='testuser/vote:* create:group1 cancel:*'
401 response = self.createMotion(user1, title, content, '3', 'group2')
402 self.assertEqual(response.status_code, 403)
403 self.assertIn(str.encode('Forbidden'), response.data)
405 def test_SeeCancelMotion(self):
408 motion='g1.20200402.004'
409 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
410 testtext= '<button type="submit" class="btn btn-danger" name="cancel" value="cancel" id="cancel">Cancel</button>'
411 self.assertIn(str.encode(testtext), result.data)
413 motion='g1.20200402.004'
414 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': 'testuser/vote:*'}, follow_redirects=True)
415 testtext= '<button type="submit" class="btn btn-danger" name="cancel" value="cancel" id="cancel">Cancel</button>'
416 self.assertNotIn(str.encode(testtext), result.data)
418 def test_cancelMotion(self):
421 motion='g1.20200402.004'
423 response = self.cancelMotion(user, motion, reason)
424 self.assertEqual(response.status_code, 500)
425 self.assertIn(str.encode('Error, form requires reason'), response.data)
428 response = self.cancelMotion(user, motion, reason)
429 self.assertEqual(response.status_code, 302)
430 result = self.app.get('/', environ_base={'USER_ROLES': user})
431 self.assertIn(b'Cancelation reason: ' + str.encode(reason), result.data)
433 motion='g1.20190402.001'
435 response = self.cancelMotion(user, motion, reason)
436 self.assertEqual(response.status_code, 404)
437 self.assertIn(str.encode('Error, Not found'), response.data)
439 motion='g1.30200402.001'
441 response = self.cancelMotion(user, motion, reason)
442 self.assertEqual(response.status_code, 404)
443 self.assertIn(str.encode('Error, Not found'), response.data)
445 motion='g1.20200402.004'
446 response = self.cancelMotion(user, motion, reason)
447 self.assertEqual(response.status_code, 403)
448 self.assertIn(str.encode('Error, motion was canceled'), response.data)
450 def test_SeeFinishMotion(self):
453 motion='g1.20200402.004'
454 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
455 testtext= '<button type="submit" class="btn btn-danger" name="finish" value="finish" id="finish">Finish</button>'
456 self.assertIn(str.encode(testtext), result.data)
458 motion='g1.20200402.004'
459 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': 'testuser/vote:*'}, follow_redirects=True)
460 testtext= '<button type="submit" class="btn btn-danger" name="finish" value="finish" id="finish">Finish</button>'
461 self.assertNotIn(str.encode(testtext), result.data)
463 def test_finishMotion(self):
466 motion='g1.20200402.004'
467 response = self.finishMotion(user, motion)
468 self.assertEqual(response.status_code, 302)
469 result = self.app.get('/', environ_base={'USER_ROLES': user})
470 self.assertIn(b'Motion D</span> (Finished)', result.data)
472 motion='g1.30190402.001'
473 response = self.finishMotion(user, motion)
474 self.assertEqual(response.status_code, 404)
475 self.assertIn(str.encode('Error, Not found'), response.data)
477 motion='g1.20200402.001'
478 response = self.finishMotion(user, motion)
479 self.assertEqual(response.status_code, 403)
480 self.assertIn(str.encode('Error, out of time'), response.data)
482 class AuditMotionTests(BasicTest):
487 user='testuser/audit:*'
493 def test_see_old_vote(self):
494 motion='g1.20200402.002'
495 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
496 testtext= '<div class="motion card" id="votes">\n <div class="card-heading text-white bg-info">\n Motion Votes\n </div>'\
497 + '\n <div class="card-body">\n <div>User A: yes</div>\n <div>User B: no</div>'\
498 + '\n <div>User C: no</div>\n </div>\n</div>\n<a href="/?start=2#motion-2" class="btn btn-primary">Back</a>'
499 self.assertIn(str.encode(testtext), result.data)
501 class ProxyManagementTests(BasicTest):
506 user='testuser/proxyadmin:*'
514 def test_see_proxy(self):
515 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
516 testtext= 'div class="container">\n<form action="/proxy/add" method="POST">'
517 self.assertIn(str.encode(testtext), result.data)
518 testtext= 'proxy granted to:'
519 self.assertNotIn(str.encode(testtext), result.data)
520 testtext= 'holds proxy of:'
521 self.assertNotIn(str.encode(testtext), result.data)
522 testtext= '<select class="float form-control" name="voter">\n '\
523 + '<option>User A</option>\n <option>User B</option>\n '\
524 + '<option>User C</option>\n '\
525 + '<option>testuser</option>\n '\
527 self.assertIn(str.encode(testtext), result.data)
528 testtext= '<select class="float form-control" name="proxy">\n '\
529 + '<option>User A</option>\n '\
530 + '<option>User B</option>\n '\
531 + '<option>User C</option>\n '\
532 + '<option>testuser</option>\n '\
534 self.assertIn(str.encode(testtext), result.data)
535 testtext= '<table>\n '\
537 + '<th>Voter</th>\n <th>Proxy</th>\n <th></th>\n </thead>\n '\
539 self.assertIn(str.encode(testtext), result.data)
540 testtext= '<a class="nav-link" href="/proxy">Proxy management</a>'
541 self.assertIn(str.encode(testtext), result.data)
543 def test_add_proxy(self):
546 response = self.addProxy(user, voter, proxy)
547 self.assertEqual(response.status_code, 400)
548 self.assertIn(str.encode('Error, voter equals proxy.'), response.data)
551 response = self.addProxy(user, voter, proxy)
552 self.assertEqual(response.status_code, 400)
553 self.assertIn(str.encode('Error, proxy not found.'), response.data)
556 response = self.addProxy(user, voter, proxy)
557 self.assertEqual(response.status_code, 400)
558 self.assertIn(str.encode('Error, voter not found.'), response.data)
562 response = self.addProxy(user, voter, proxy)
563 self.assertEqual(response.status_code, 400)
564 self.assertIn(str.encode('Error, voter not found.'), response.data)
568 response = self.addProxy(user, voter, proxy)
569 self.assertEqual(response.status_code, 400)
570 self.assertIn(str.encode('Error, voter equals proxy.'), response.data)
574 response = self.addProxy(user, voter, proxy)
575 self.assertEqual(response.status_code, 400)
576 self.assertIn(str.encode('Error, proxy not found.'), response.data)
580 response = self.addProxy(user, voter, proxy)
581 self.assertEqual(response.status_code, 302)
582 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
583 testtext= '<form action="/proxy/revoke" method="POST">'
584 self.assertIn(str.encode(testtext), result.data)
585 testtext= '<table>\n '\
587 + '<th>Voter</th>\n '\
588 + '<th>Proxy</th>\n <th></th>\n </thead>\n '\
589 + '<tr>\n <td>User A</td>\n <td>User B</td>\n '\
590 + '<td><button type="submit" class="btn btn-danger" name="id" value="1">Revoke</button></td>\n '\
591 + '</tr>\n </table>\n'
592 self.assertIn(str.encode(testtext), result.data)
594 response = self.addProxy(user, voter, proxy)
595 self.assertEqual(response.status_code, 400)
596 self.assertIn(str.encode('Error, proxy allready given.'), response.data)
600 response = self.addProxy(user, voter, proxy)
601 self.assertEqual(response.status_code, 400)
602 self.assertIn(str.encode('Error, proxy allready given.'), response.data)
606 response = self.addProxy(user, voter, proxy)
607 self.assertEqual(response.status_code, 302)
608 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
609 testtext= '<table>\n '\
611 + '<th>Voter</th>\n '\
612 + '<th>Proxy</th>\n <th></th>\n </thead>\n '\
613 + '<tr>\n <td>User A</td>\n <td>User B</td>\n '\
614 + '<td><button type="submit" class="btn btn-danger" name="id" value="1">Revoke</button></td>\n </tr>\n '\
615 + '<tr>\n <td>User C</td>\n <td>User B</td>\n '\
616 + '<td><button type="submit" class="btn btn-danger" name="id" value="2">Revoke</button></td>\n '\
617 + '</tr>\n </table>\n'
618 self.assertIn(str.encode(testtext), result.data)
619 testtext= 'proxy granted to:'
620 self.assertNotIn(str.encode(testtext), result.data)
621 testtext= 'holds proxy of:'
622 self.assertNotIn(str.encode(testtext), result.data)
626 response = self.addProxy(user, voter, proxy)
627 self.assertEqual(response.status_code, 400)
628 self.assertIn(str.encode('Error, Max proxy for \'User B\' reached.'), response.data)
632 response = self.addProxy(user, voter, proxy)
633 self.assertEqual(response.status_code, 302)
634 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
635 testtext= '<table>\n '\
637 + '<th>Voter</th>\n <th>Proxy</th>\n <th></th>\n </thead>\n '\
638 + '<tr>\n <td>testuser</td>\n <td>User A</td>\n '\
639 + '<td><button type="submit" class="btn btn-danger" name="id" value="3">Revoke</button></td>\n </tr>\n '\
640 + '<tr>\n <td>User A</td>\n <td>User B</td>\n '\
641 + '<td><button type="submit" class="btn btn-danger" name="id" value="1">Revoke</button></td>\n </tr>\n '\
642 + '<tr>\n <td>User C</td>\n <td>User B</td>\n '\
643 + '<td><button type="submit" class="btn btn-danger" name="id" value="2">Revoke</button></td>\n '\
644 + '</tr>\n </table>\n'
645 self.assertIn(str.encode(testtext), result.data)
646 testtext= 'proxy granted to: User A\n'
647 self.assertIn(str.encode(testtext), result.data)
648 testtext= 'holds proxy of:'
649 self.assertNotIn(str.encode(testtext), result.data)
653 response = self.addProxy(user, voter, proxy)
654 self.assertEqual(response.status_code, 302)
655 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
656 testtext= '<table>\n '\
658 + '<th>Voter</th>\n <th>Proxy</th>\n <th></th>\n </thead>\n '\
659 + '<tr>\n <td>testuser</td>\n <td>User A</td>\n '\
660 + '<td><button type="submit" class="btn btn-danger" name="id" value="3">Revoke</button></td>\n </tr>\n '\
661 + '<tr>\n <td>User A</td>\n <td>User B</td>\n '\
662 + '<td><button type="submit" class="btn btn-danger" name="id" value="1">Revoke</button></td>\n </tr>\n '\
663 + '<tr>\n <td>User B</td>\n <td>testuser</td>\n '\
664 + '<td><button type="submit" class="btn btn-danger" name="id" value="4">Revoke</button></td>\n </tr>\n '\
665 + '<tr>\n <td>User C</td>\n <td>User B</td>\n '\
666 + '<td><button type="submit" class="btn btn-danger" name="id" value="2">Revoke</button></td>\n '\
667 + '</tr>\n </table>\n'
668 self.assertIn(str.encode(testtext), result.data)
669 testtext= 'proxy granted to: User A\n'
670 self.assertIn(str.encode(testtext), result.data)
671 testtext= 'holds proxy of: User B\n'
672 self.assertIn(str.encode(testtext), result.data)
674 response = self.revokeProxy(user, userid)
675 self.assertEqual(response.status_code, 302)
676 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
677 testtext= '<table>\n '\
679 + '<th>Voter</th>\n <th>Proxy</th>\n <th></th>\n </thead>\n '\
680 + '<tr>\n <td>testuser</td>\n <td>User A</td>\n '\
681 + '<td><button type="submit" class="btn btn-danger" name="id" value="3">Revoke</button></td>\n </tr>\n '\
682 + '<tr>\n <td>User A</td>\n <td>User B</td>\n '\
683 + '<td><button type="submit" class="btn btn-danger" name="id" value="1">Revoke</button></td>\n </tr>\n '\
684 + '<tr>\n <td>User C</td>\n <td>User B</td>\n '\
685 + '<td><button type="submit" class="btn btn-danger" name="id" value="2">Revoke</button></td>\n '\
686 + '</tr>\n </table>\n'
687 self.assertIn(str.encode(testtext), result.data)
688 testtext= 'proxy granted to: User A\n'
689 self.assertIn(str.encode(testtext), result.data)
690 testtext= 'holds proxy of:'
691 self.assertNotIn(str.encode(testtext), result.data)
693 response = self.revokeProxy(user, 3)
694 self.assertEqual(response.status_code, 302)
695 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
696 testtext= '<table>\n '\
698 + '<th>Voter</th>\n <th>Proxy</th>\n <th></th>\n </thead>\n '\
699 + '<tr>\n <td>User A</td>\n <td>User B</td>\n '\
700 + '<td><button type="submit" class="btn btn-danger" name="id" value="1">Revoke</button></td>\n </tr>\n '\
701 + '<tr>\n <td>User C</td>\n <td>User B</td>\n '\
702 + '<td><button type="submit" class="btn btn-danger" name="id" value="2">Revoke</button></td>\n '\
703 + '</tr>\n </table>\n'
704 self.assertIn(str.encode(testtext), result.data)
705 testtext= 'proxy granted to:'
706 self.assertNotIn(str.encode(testtext), result.data)
707 testtext= 'holds proxy of:'
708 self.assertNotIn(str.encode(testtext), result.data)
710 result = self.app.post('proxy/revokeall', environ_base={'USER_ROLES': user}, follow_redirects=True)
711 self.assertEqual(response.status_code, 302)
712 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
713 testtext= '<table>\n '\
715 + '<th>Voter</th>\n <th>Proxy</th>\n <th></th>\n </thead>\n'\
717 self.assertNotIn(str.encode(testtext), result.data)
719 proxytest="proxytest"
720 with self.open_DB() as db:
721 db.prepare("INSERT INTO voter(\"email\", \"host\") VALUES($1, $2)")(proxytest, '127.0.0.1:5001')
722 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
724 response = self.addProxy(user, proxytest, 'testuser')
725 self.assertEqual(response.status_code, 400)
726 self.assertIn(str.encode('Error, voter not found.'), response.data)
728 response = self.addProxy(user, 'testuser', proxytest)
729 self.assertEqual(response.status_code, 400)
730 self.assertIn(str.encode('Error, proxy not found.'), response.data)
732 def test_see_proxy_host_only(self):
733 proxytest="proxytest"
734 with self.open_DB() as db:
735 db.prepare("INSERT INTO voter(\"email\", \"host\") VALUES($1, $2)")(proxytest, '127.0.0.1:5001')
736 result = self.app.get('proxy', environ_base={'USER_ROLES': user}, follow_redirects=True)
737 testtext= 'div class="container">\n<form action="/proxy/add" method="POST">'
738 self.assertIn(str.encode(testtext), result.data)
739 testtext= 'proxy granted to:'
740 self.assertNotIn(str.encode(testtext), result.data)
741 testtext= 'holds proxy of:'
742 self.assertNotIn(str.encode(testtext), result.data)
743 testtext= '<select class="float form-control" name="voter">\n '\
744 + '<option>User A</option>\n <option>User B</option>\n '\
745 + '<option>User C</option>\n '\
746 + '<option>testuser</option>\n '\
748 self.assertIn(str.encode(testtext), result.data)
749 testtext= '<select class="float form-control" name="proxy">\n '\
750 + '<option>User A</option>\n '\
751 + '<option>User B</option>\n '\
752 + '<option>User C</option>\n '\
753 + '<option>testuser</option>\n '\
755 self.assertIn(str.encode(testtext), result.data)
756 self.assertNotIn(str.encode(proxytest), result.data)
758 class ProxyVoteTests(BasicTest):
763 user='testuser/vote:* proxyadmin:*'
769 def test_proxy_vote(self):
773 proxyuser='User B/vote:*'
775 response = self.addProxy(user, proxy, voter)
776 self.assertEqual(response.status_code, 302)
778 motion='g1.20200402.004'
779 response = self.createVote(user, motion, 'yes', proxyid)
780 self.assertEqual(response.status_code, 302)
783 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
784 # own vote without change
785 testtext= '<form action="/motion/g1.20200402.004/vote/4" method="POST">\n'\
786 + '<button type="submit" class="btn btn-primary" name="vote" value="yes" id="vote-yes">Yes</button>\n'\
787 + '<button type="submit" class="btn btn-primary" name="vote" value="no" id="vote-no">No</button>\n'\
788 + '<button type="submit" class="btn btn-primary" name="vote" value="abstain" id="vote-abstain">Abstain</button>\n</form>'
789 self.assertIn(str.encode(testtext), result.data)
790 # proxy vote with change
791 testtext= '<form action="/motion/g1.20200402.004/vote/2" method="POST">\n'\
792 + '<button type="submit" class="btn btn-success" name="vote" value="yes" id="vote-yes">Yes</button>\n'\
793 + '<button type="submit" class="btn btn-primary" name="vote" value="no" id="vote-no">No</button>\n'\
794 + '<button type="submit" class="btn btn-primary" name="vote" value="abstain" id="vote-abstain">Abstain</button>\n</form>\n'
795 self.assertIn(str.encode(testtext), result.data)
798 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': proxyuser}, follow_redirects=True)
799 # own vote without change
800 testtext= '<h3>My vote</h3>\nGiven by testuser\n'\
801 + '<form action="/motion/g1.20200402.004/vote/2" method="POST">\n'\
802 + '<button type="submit" class="btn btn-success" name="vote" value="yes" id="vote-yes">Yes</button>\n'\
803 + '<button type="submit" class="btn btn-primary" name="vote" value="no" id="vote-no">No</button>\n'\
804 + '<button type="submit" class="btn btn-primary" name="vote" value="abstain" id="vote-abstain">Abstain</button>\n</form>'
805 self.assertIn(str.encode(testtext), result.data)
808 response = self.createVote(user, motion, 'no', proxyid)
809 self.assertEqual(response.status_code, 302)
811 result = self.app.get('/motion/' + motion, environ_base={'USER_ROLES': user}, follow_redirects=True)
812 testtext= '<form action="/motion/g1.20200402.004/vote/2" method="POST">\n'\
813 + '<button type="submit" class="btn btn-primary" name="vote" value="yes" id="vote-yes">Yes</button>\n'\
814 + '<button type="submit" class="btn btn-success" name="vote" value="no" id="vote-no">No</button>\n'\
815 + '<button type="submit" class="btn btn-primary" name="vote" value="abstain" id="vote-abstain">Abstain</button>\n</form>\n'
816 self.assertIn(str.encode(testtext), result.data)
818 def test_proxy_vote_no_proxy(self):
824 response = self.addProxy(user, proxy, voter)
825 self.assertEqual(response.status_code, 302)
827 motion='g1.20200402.004'
828 response = self.createVote(user, motion, 'yes', proxyid)
829 self.assertEqual(response.status_code, 400)
830 self.assertIn(str.encode('Error, proxy not found'), response.data)
835 motion='g1.20200402.004'
836 response = self.createVote(user, motion, 'yes', proxyid)
837 self.assertEqual(response.status_code, 400)
838 self.assertIn(str.encode('Error, proxy not found'), response.data)
840 def test_proxy_vote_no_voter(self):
845 response = self.addProxy(user, proxy, voter)
846 self.assertEqual(response.status_code, 302)
849 motion='g1.20200402.004'
850 response = self.createVote(user1, motion, 'yes', proxyid)
851 self.assertEqual(response.status_code, 403)
852 self.assertIn(str.encode('Forbidden'), response.data)
856 if __name__ == "__main__":