1
1
import os
2
2
import re
3
- import time
3
+ from datetime import timedelta
4
4
from io import StringIO
5
5
from unittest import mock
6
6
from unittest .mock import patch
7
7
from urllib .parse import quote
8
8
9
9
import orjson
10
10
import pyvips
11
+ import time_machine
11
12
from django .conf import settings
12
13
from django .utils .timezone import now as timezone_now
13
14
from pyvips import at_least_libvips
@@ -304,21 +305,43 @@ def test_serve_local_file_unauthed_token_expires(self) -> None:
304
305
self .login ("hamlet" )
305
306
fp = StringIO ("zulip!" )
306
307
fp .name = "zulip.txt"
307
- result = self .client_post ("/json/user_uploads" , {"file" : fp })
308
- response_dict = self .assert_json_success (result )
309
- url = "/json" + response_dict ["url" ]
308
+ now = timezone_now ()
309
+ with time_machine .travel (now , tick = False ):
310
+ result = self .client_post ("/json/user_uploads" , {"file" : fp })
311
+ response_dict = self .assert_json_success (result )
312
+ url = "/json" + response_dict ["url" ]
310
313
311
- start_time = time .time ()
312
- with mock .patch ("django.core.signing.time.time" , return_value = start_time ):
313
314
result = self .client_get (url )
314
315
data = self .assert_json_success (result )
315
316
url_only_url = data ["url" ]
316
-
317
317
self .logout ()
318
318
self .assertEqual (self .client_get (url_only_url ).getvalue (), b"zulip!" )
319
319
320
+ with time_machine .travel (now + timedelta (seconds = 30 ), tick = False ):
321
+ self .assertEqual (self .client_get (url_only_url ).getvalue (), b"zulip!" )
322
+
320
323
# After over 60 seconds, the token should become invalid:
321
- with mock .patch ("django.core.signing.time.time" , return_value = start_time + 61 ):
324
+ with time_machine .travel (now + timedelta (seconds = 61 ), tick = False ):
325
+ result = self .client_get (url_only_url )
326
+ self .assert_json_error (result , "Invalid token" )
327
+
328
+ def test_serve_local_file_unauthed_token_deleted (self ) -> None :
329
+ self .login ("hamlet" )
330
+ fp = StringIO ("zulip!" )
331
+ fp .name = "zulip.txt"
332
+ now = timezone_now ()
333
+ with time_machine .travel (now , tick = False ):
334
+ result = self .client_post ("/json/user_uploads" , {"file" : fp })
335
+ response_dict = self .assert_json_success (result )
336
+ url = "/json" + response_dict ["url" ]
337
+
338
+ result = self .client_get (url )
339
+ data = self .assert_json_success (result )
340
+ url_only_url = data ["url" ]
341
+
342
+ path_id = response_dict ["url" ].removeprefix ("/user_uploads/" )
343
+ Attachment .objects .get (path_id = path_id ).delete ()
344
+
322
345
result = self .client_get (url_only_url )
323
346
self .assert_json_error (result , "Invalid token" )
324
347
@@ -909,6 +932,7 @@ def check_xsend_links(
909
932
name_str_for_test : str ,
910
933
content_disposition : str = "" ,
911
934
download : bool = False ,
935
+ returned_attachment : bool = False ,
912
936
) -> None :
913
937
self .login ("hamlet" )
914
938
fp = StringIO ("zulip!" )
@@ -927,27 +951,74 @@ def check_xsend_links(
927
951
response ["X-Accel-Redirect" ],
928
952
"/internal/local/uploads/" + fp_path + "/" + name_str_for_test ,
929
953
)
930
- if content_disposition != "" :
954
+ if returned_attachment :
931
955
self .assertIn ("attachment;" , response ["Content-disposition" ])
932
- self .assertIn (content_disposition , response ["Content-disposition" ])
933
956
else :
934
957
self .assertIn ("inline;" , response ["Content-disposition" ])
958
+ if content_disposition != "" :
959
+ self .assertIn (content_disposition , response ["Content-disposition" ])
935
960
self .assertEqual (set (response ["Cache-Control" ].split (", " )), {"private" , "immutable" })
936
961
937
- check_xsend_links ("zulip.txt" , "zulip.txt" , 'filename="zulip.txt"' )
962
+ check_xsend_links (
963
+ "zulip.txt" , "zulip.txt" , 'filename="zulip.txt"' , returned_attachment = True
964
+ )
938
965
check_xsend_links (
939
966
"áéБД.txt" ,
940
967
"%C3%A1%C3%A9%D0%91%D0%94.txt" ,
941
968
"filename*=utf-8''%C3%A1%C3%A9%D0%91%D0%94.txt" ,
969
+ returned_attachment = True ,
970
+ )
971
+ check_xsend_links (
972
+ "zulip.html" ,
973
+ "zulip.html" ,
974
+ 'filename="zulip.html"' ,
975
+ returned_attachment = True ,
976
+ )
977
+ check_xsend_links (
978
+ "zulip.sh" ,
979
+ "zulip.sh" ,
980
+ 'filename="zulip.sh"' ,
981
+ returned_attachment = True ,
982
+ )
983
+ check_xsend_links (
984
+ "zulip.jpeg" ,
985
+ "zulip.jpeg" ,
986
+ 'filename="zulip.jpeg"' ,
987
+ returned_attachment = False ,
988
+ )
989
+ check_xsend_links (
990
+ "zulip.jpeg" ,
991
+ "zulip.jpeg" ,
992
+ download = True ,
993
+ content_disposition = 'filename="zulip.jpeg"' ,
994
+ returned_attachment = True ,
995
+ )
996
+ check_xsend_links (
997
+ "áéБД.pdf" ,
998
+ "%C3%A1%C3%A9%D0%91%D0%94.pdf" ,
999
+ "filename*=utf-8''%C3%A1%C3%A9%D0%91%D0%94.pdf" ,
1000
+ returned_attachment = False ,
1001
+ )
1002
+ check_xsend_links (
1003
+ "some file (with spaces).png" ,
1004
+ "some-file-with-spaces.png" ,
1005
+ 'filename="some file (with spaces).png"' ,
1006
+ returned_attachment = False ,
1007
+ )
1008
+ check_xsend_links (
1009
+ "some file (with spaces).png" ,
1010
+ "some-file-with-spaces.png" ,
1011
+ 'filename="some file (with spaces).png"' ,
1012
+ download = True ,
1013
+ returned_attachment = True ,
942
1014
)
943
- check_xsend_links ("zulip.html" , "zulip.html" , 'filename="zulip.html"' )
944
- check_xsend_links ("zulip.sh" , "zulip.sh" , 'filename="zulip.sh"' )
945
- check_xsend_links ("zulip.jpeg" , "zulip.jpeg" )
946
1015
check_xsend_links (
947
- "zulip.jpeg" , "zulip.jpeg" , download = True , content_disposition = 'filename="zulip.jpeg"'
1016
+ ".()." ,
1017
+ "uploaded-file" ,
1018
+ 'filename=".()."' ,
1019
+ returned_attachment = True ,
948
1020
)
949
- check_xsend_links ("áéБД.pdf" , "%C3%A1%C3%A9%D0%91%D0%94.pdf" )
950
- check_xsend_links ("zulip" , "zulip" , 'filename="zulip"' )
1021
+ check_xsend_links ("zulip" , "zulip" , 'filename="zulip"' , returned_attachment = True )
951
1022
952
1023
953
1024
class AvatarTest (UploadSerializeMixin , ZulipTestCase ):
0 commit comments