Skip to content

Commit d06ccaa

Browse files
committed
[ci] Implement missing backend tests for admin file handler
1 parent eb1f5df commit d06ccaa

File tree

5 files changed

+88
-48
lines changed

5 files changed

+88
-48
lines changed

backend/globaleaks/handlers/admin/file.py

+9-7
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,15 @@ class FileInstance(BaseHandler):
108108
]
109109

110110
def permission_check(self, name):
111-
if name in ['css', 'favicon', 'script'] and \
112-
not self.session.has_permission('can_upload_files'):
113-
raise errors.InvalidAuthentication
111+
if self.session.role == 'admin':
112+
if name not in ['logo'] and \
113+
not self.session.has_permission('can_upload_files'):
114+
raise errors.InvalidAuthentication
114115

115-
if self.session.role != 'admin' and \
116-
not self.session.has_permission('can_edit_general_settings'):
117-
raise errors.InvalidAuthentication
116+
else:
117+
if name not in ['logo'] or \
118+
not self.session.has_permission('can_edit_general_settings'):
119+
raise errors.InvalidAuthentication
118120

119121
@inlineCallbacks
120122
def post(self, name):
@@ -130,7 +132,7 @@ def post(self, name):
130132
self.allowed_mimetypes = ['text/javascript']
131133

132134
if self.uploaded_file['type'] not in self.allowed_mimetypes:
133-
raise errors.ForbiddenOperation
135+
raise errors.InputValidationError
134136

135137
if name in special_files or re.match(requests.uuid_regexp, name):
136138
self.uploaded_file['name'] = name

backend/globaleaks/tests/handlers/admin/test_file.py

+52-22
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,78 @@
22
from twisted.internet.defer import inlineCallbacks
33

44
from globaleaks.handlers.admin import file
5+
from globaleaks.rest import errors
56
from globaleaks.tests import helpers
67

8+
files = [
9+
{'handler': 'css', 'name': 'file.css'},
10+
{'handler': 'script', 'name': 'file.js'},
11+
{'handler': 'logo', 'name': 'file.png'},
12+
{'handler': 'favicon', 'name': 'file.ico'},
13+
{'handler': 'custom', 'name': 'file.txt'},
14+
]
15+
716

817
class TestFileInstance(helpers.TestHandler):
918
_handler = file.FileInstance
1019

1120
@inlineCallbacks
12-
def test_post(self):
13-
handler = self.request({}, role='admin')
21+
def test_post_prevent_unauthorized_admin_uploads(self):
22+
for f in files:
23+
handler = self.request({}, role='admin', attachment=self.get_dummy_attachment(f['name']))
24+
if f['handler'] == 'logo':
25+
yield handler.post(f['handler'])
26+
else:
27+
yield self.assertFailure(handler.post(f['handler']), errors.InvalidAuthentication)
28+
29+
@inlineCallbacks
30+
def test_post_prevent_wrong_filetypes(self):
31+
permissions = {'can_upload_files': True}
1432

15-
yield handler.post(u'file.pdf')
33+
for f in files:
34+
handler = self.request({}, role='admin', permissions=permissions, attachment=self.get_dummy_attachment(f['name'] + ".wrong.ext"))
35+
yield self.assertFailure(handler.post(f['handler']), errors.InputValidationError)
1636

1737
@inlineCallbacks
18-
def test_delete(self):
19-
handler = self.request({}, role='admin')
20-
yield handler.delete(u'file.pdf')
38+
def test_post_accepts_correct_files(self):
39+
permissions = {'can_upload_files': True}
2140

41+
for f in files:
42+
handler = self.request({}, role='admin', permissions=permissions, attachment=self.get_dummy_attachment(f['name']))
43+
yield handler.post(f['handler'])
2244

23-
class TestFileCollection(helpers.TestHandler):
24-
_handler = file.FileCollection
45+
@inlineCallbacks
46+
def test_post_prevent_unauthorized_recipients_to_upload_any_file(self):
47+
for f in files:
48+
handler = self.request({}, role='receiver', attachment=self.get_dummy_attachment(f['name']))
49+
yield self.assertFailure(handler.post(f['handler']), errors.InvalidAuthentication)
2550

2651
@inlineCallbacks
27-
def test_get(self):
28-
self._handler = file.FileInstance
29-
handler = self.request({}, role='admin')
30-
yield handler.post(u'custom')
52+
def test_post_enable_authorized_recipients_to_upload_the_logo_and_only_it(self):
53+
permissions = {'can_edit_general_settings': True}
3154

32-
self._handler = file.FileCollection
33-
handler = self.request(role='admin')
34-
response = yield handler.get()
55+
for f in files:
56+
handler = self.request({}, role='receiver', permissions=permissions, attachment=self.get_dummy_attachment(f['name']))
57+
if f['handler'] == 'logo':
58+
yield handler.post(f['handler'])
59+
else:
60+
yield self.assertFailure(handler.post(f['handler']), errors.InvalidAuthentication)
3561

36-
self.assertEqual(len(response), 1)
3762

63+
class TestFileCollection(helpers.TestHandler):
64+
_handler = file.FileCollection
65+
66+
@inlineCallbacks
67+
def test_get(self):
3868
self._handler = file.FileInstance
39-
handler = self.request({}, role='admin')
40-
yield handler.post(u'custom')
4169

42-
handler = self.request({}, role='admin')
43-
yield handler.post(u'custom')
70+
permissions = {'can_upload_files': True}
71+
for f in files:
72+
handler = self.request({}, role='admin', permissions=permissions, attachment=self.get_dummy_attachment(f['name']))
73+
yield handler.post(f['handler'])
4474

4575
self._handler = file.FileCollection
46-
handler = self.request(role='admin')
76+
handler = self.request(role='admin', permissions=permissions)
4777
response = yield handler.get()
4878

49-
self.assertEqual(len(response), 3)
79+
self.assertEqual(len(response), 5)

backend/globaleaks/tests/handlers/recipient/test_rfile.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from globaleaks.jobs.delivery import Delivery
77
from globaleaks.tests import helpers
88

9-
attachment = b'hello world'
9+
file_content = b'Hello World'
1010

1111

1212
class TestWBFileWorkFlow(helpers.TestHandlerWithPopulatedDB):
@@ -19,7 +19,8 @@ def test_get(self):
1919
self._handler = rtip.ReceiverFileUpload
2020
rtips_desc = yield self.get_rtips()
2121
for rtip_desc in rtips_desc:
22-
handler = self.request(role='receiver', user_id=rtip_desc['receiver_id'], attached_file=attachment)
22+
attachment = self.get_dummy_attachment(content=file_content)
23+
handler = self.request(role='receiver', user_id=rtip_desc['receiver_id'], attachment=attachment)
2324
yield handler.post(rtip_desc['id'])
2425

2526
yield Delivery().run()
@@ -31,7 +32,7 @@ def test_get(self):
3132
for rfile_desc in rfiles_desc:
3233
handler = self.request(role='whistleblower', user_id=wbtip_desc['id'])
3334
yield handler.get(rfile_desc['id'])
34-
self.assertEqual(handler.request.getResponseBody(), attachment)
35+
self.assertEqual(handler.request.getResponseBody(), file_content)
3536

3637
self._handler = rtip.ReceiverFileDownload
3738
rtips_desc = yield self.get_rtips()

backend/globaleaks/tests/handlers/test_file.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def test_get(self):
1616
yield self.assertFailure(handler.get(u'custom'), ResourceNotFound)
1717

1818
self._handler = admin_file.FileInstance
19-
handler = self.request({}, role='admin')
19+
handler = self.request({}, role='admin', permissions={'can_upload_files': True})
2020
yield handler.post('custom')
2121

2222
self._handler = admin_file.FileCollection

backend/globaleaks/tests/helpers.py

+22-15
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Utilities and basic TestCases.
44
"""
55
import json
6+
import mimetypes
67
import os
78
import shutil
89

@@ -421,13 +422,14 @@ def __init__(self):
421422
}
422423

423424

424-
def get_dummy_file(content=None):
425-
filename = generateRandomKey() + ".pdf"
425+
def get_dummy_attachment(name=None, content=None):
426+
if name is None:
427+
name = generateRandomKey() + ".pdf"
426428

427-
content_type = 'application/pdf'
429+
content_type, _ = mimetypes.guess_type(name)
428430

429431
if content is None:
430-
content = Base64Encoder.decode(VALID_BASE64_IMG)
432+
content = name.encode()
431433

432434
temporary_file = SecureTemporaryFile(Settings.tmp_path)
433435

@@ -437,9 +439,9 @@ def get_dummy_file(content=None):
437439
State.TempUploadFiles[os.path.basename(temporary_file.filepath)] = temporary_file
438440

439441
return {
440-
'id': filename,
442+
'id': name,
441443
'date': datetime_now(),
442-
'name': filename,
444+
'name': name,
443445
'description': 'description',
444446
'body': temporary_file,
445447
'size': len(content),
@@ -459,7 +461,7 @@ def check_confirmation(self):
459461

460462

461463
def get_file_upload(self):
462-
return get_dummy_file()
464+
return get_dummy_attachment()
463465

464466

465467
BaseHandler.get_file_upload = get_file_upload
@@ -718,8 +720,8 @@ def get_dummy_submission(self, context_id):
718720
'receipt': GCE.derive_key(GCE.generate_receipt(), VALID_SALT)
719721
})
720722

721-
def get_dummy_file(self, content=None):
722-
return get_dummy_file(content)
723+
def get_dummy_attachment(self, name=None, content=None):
724+
return get_dummy_attachment(name=name, content=content)
723725

724726
def get_dummy_redirect(self, x=''):
725727
return {
@@ -732,7 +734,7 @@ def emulate_file_upload(self, session, n):
732734
This emulates the file upload of an incomplete submission
733735
"""
734736
for _ in range(n):
735-
session.files.append(self.get_dummy_file())
737+
session.files.append(self.get_dummy_attachment())
736738

737739
def pollute_events(self, number_of_times=10):
738740
for _ in range(number_of_times):
@@ -886,7 +888,7 @@ def perform_submission_start(self):
886888

887889
def perform_submission_uploads(self, submission_id):
888890
for _ in range(self.population_of_attachments):
889-
Sessions.get(submission_id).files.append(self.get_dummy_file())
891+
Sessions.get(submission_id).files.append(self.get_dummy_attachment())
890892

891893
@inlineCallbacks
892894
def perform_submission_actions(self, session_id):
@@ -973,14 +975,16 @@ class TestHandler(TestGLWithPopulatedDB):
973975
#
974976
# }
975977
# }
978+
can_upload_files = True
976979

977980
def setUp(self):
978981
return TestGL.setUp(self)
979982

980983
def request(self, body='', uri=b'https://www.globaleaks.org/',
981-
user_id=None, role=None, multilang=False, headers=None, args=None,
982-
client_addr=b'127.0.0.1', handler_cls=None, attached_file=None,
983-
kwargs=None, token=False):
984+
user_id=None, role=None, multilang=False, headers=None, token=False, permissions=None,
985+
client_addr=b'127.0.0.1',
986+
handler_cls=None, attachment=None,
987+
args=None, kwargs=None):
984988
"""
985989
Constructs a handler for preforming mock requests using the bag of params described below.
986990
"""
@@ -1012,6 +1016,9 @@ def request(self, body='', uri=b'https://www.globaleaks.org/',
10121016
else:
10131017
session = Sessions.new(1, user_id, 1, role, USER_PRV_KEY, USER_ESCROW_PRV_KEY if role == 'admin' else '')
10141018

1019+
if permissions:
1020+
session.permissions = permissions
1021+
10151022
headers[b'x-session'] = session.id
10161023

10171024
# during unit tests a token is always provided to any handler
@@ -1041,7 +1048,7 @@ def request(self, body='', uri=b'https://www.globaleaks.org/',
10411048
request.language = None
10421049

10431050
if handler.upload_handler:
1044-
handler.uploaded_file = self.get_dummy_file(attached_file)
1051+
handler.uploaded_file = attachment if attachment else self.get_dummy_attachment()
10451052

10461053
return handler
10471054

0 commit comments

Comments
 (0)