@@ -8,7 +8,7 @@ class ActionText::Markdown::UploadsControllerTest < ActionDispatch::IntegrationT
88 test "attach a file" do
99 assert_changes -> { ActiveStorage ::Attachment . count } , 1 do
1010 post action_text_markdown_uploads_url , params : {
11- record_gid : pages ( :welcome ) . to_signed_global_id . to_s ,
11+ record_gid : uploads_signed_id_for ( pages ( :welcome ) ) ,
1212 attribute_name : "body" ,
1313 file : fixture_file_upload ( "reading.webp" , "image/webp" )
1414 } , as : :xhr
@@ -20,15 +20,139 @@ class ActionText::Markdown::UploadsControllerTest < ActionDispatch::IntegrationT
2020 assert JSON . parse ( response . body ) [ "fileUrl" ] . start_with? ( "/" )
2121 end
2222
23- test "view attached file" do
24- markdown = pages ( :welcome ) . body . tap ( &:save! )
25- markdown . uploads . attach fixture_file_upload ( "reading.webp" , "image/webp" )
23+ test "a signed id minted for some other purpose can't be used to upload" do
24+ assert_no_changes -> { ActiveStorage ::Attachment . count } do
25+ post action_text_markdown_uploads_url , params : {
26+ record_gid : pages ( :welcome ) . to_signed_global_id . to_s ,
27+ attribute_name : "body" ,
28+ file : fixture_file_upload ( "reading.webp" , "image/webp" )
29+ } , as : :xhr
30+ end
31+
32+ assert_response :not_found
33+ end
34+
35+ test "an expired signed id can't be used to upload" do
36+ record_gid = uploads_signed_id_for ( pages ( :welcome ) )
37+
38+ travel ActionText ::Markdown ::UPLOADS_SIGNED_ID_EXPIRY + 1 . hour do
39+ assert_no_changes -> { ActiveStorage ::Attachment . count } do
40+ post action_text_markdown_uploads_url , params : {
41+ record_gid : record_gid ,
42+ attribute_name : "body" ,
43+ file : fixture_file_upload ( "reading.webp" , "image/webp" )
44+ } , as : :xhr
45+ end
46+ end
47+
48+ assert_response :not_found
49+ end
50+
51+ test "a revoked collaborator can't upload with a signed id minted while an editor" do
52+ record_gid = uploads_signed_id_for ( pages ( :welcome ) )
53+ accesses ( :kevin_handbook ) . destroy!
54+
55+ assert_no_changes -> { ActiveStorage ::Attachment . count } do
56+ post action_text_markdown_uploads_url , params : {
57+ record_gid : record_gid ,
58+ attribute_name : "body" ,
59+ file : fixture_file_upload ( "reading.webp" , "image/webp" )
60+ } , as : :xhr
61+ end
62+
63+ assert_response :not_found
64+ end
65+
66+ test "a downgraded editor can't upload" do
67+ record_gid = uploads_signed_id_for ( pages ( :welcome ) )
68+ accesses ( :kevin_handbook ) . update! level : :reader
69+
70+ assert_no_changes -> { ActiveStorage ::Attachment . count } do
71+ post action_text_markdown_uploads_url , params : {
72+ record_gid : record_gid ,
73+ attribute_name : "body" ,
74+ file : fixture_file_upload ( "reading.webp" , "image/webp" )
75+ } , as : :xhr
76+ end
77+
78+ assert_response :forbidden
79+ end
80+
81+ test "a reader can't upload" do
82+ sign_in :jz
2683
27- attachment = pages ( :welcome ) . body . uploads . last
84+ assert_no_changes -> { ActiveStorage ::Attachment . count } do
85+ post action_text_markdown_uploads_url , params : {
86+ record_gid : uploads_signed_id_for ( pages ( :welcome ) ) ,
87+ attribute_name : "body" ,
88+ file : fixture_file_upload ( "reading.webp" , "image/webp" )
89+ } , as : :xhr
90+ end
91+
92+ assert_response :forbidden
93+ end
94+
95+ test "view attached file" do
96+ books ( :handbook ) . update! published : true
97+ attachment = attach_upload_to_welcome_page
2898
2999 get action_text_markdown_upload_url ( slug : attachment . slug )
30100
31101 assert_response :redirect
32102 assert_match /\/ rails\/ active_storage\/ .*\/ reading\. webp/ , @response . redirect_url
33103 end
104+
105+ test "an attachment of a published book is publicly cacheable" do
106+ books ( :handbook ) . update! published : true
107+ attachment = attach_upload_to_welcome_page
108+
109+ get action_text_markdown_upload_url ( slug : attachment . slug )
110+
111+ assert_match "public" , @response . headers [ "Cache-Control" ]
112+ end
113+
114+ test "an attachment of an unpublished book is not served to anonymous clients" do
115+ books ( :handbook ) . update! published : false
116+ attachment = attach_upload_to_welcome_page
117+
118+ reset!
119+ get action_text_markdown_upload_url ( slug : attachment . slug )
120+
121+ assert_response :not_found
122+ end
123+
124+ test "an attachment of an unpublished book is not served to a user without access" do
125+ books ( :handbook ) . update! published : false
126+ attachment = attach_upload_to_welcome_page
127+
128+ accesses ( :kevin_handbook ) . destroy!
129+ get action_text_markdown_upload_url ( slug : attachment . slug )
130+
131+ assert_response :not_found
132+ end
133+
134+ test "an attachment of an unpublished book is served to a reader, but not publicly cached" do
135+ books ( :handbook ) . update! published : false
136+ attachment = attach_upload_to_welcome_page
137+
138+ sign_in :jz
139+ get action_text_markdown_upload_url ( slug : attachment . slug )
140+
141+ assert_response :redirect
142+ assert_no_match "public" , @response . headers [ "Cache-Control" ] . to_s
143+ end
144+
145+ private
146+ def uploads_signed_id_for ( record )
147+ record . to_signed_global_id (
148+ expires_in : ActionText ::Markdown ::UPLOADS_SIGNED_ID_EXPIRY ,
149+ for : ActionText ::Markdown ::UPLOADS_SIGNED_ID_PURPOSE
150+ ) . to_s
151+ end
152+
153+ def attach_upload_to_welcome_page
154+ markdown = pages ( :welcome ) . body . tap ( &:save! )
155+ markdown . uploads . attach fixture_file_upload ( "reading.webp" , "image/webp" )
156+ pages ( :welcome ) . body . uploads . last
157+ end
34158end
0 commit comments