mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2026-09-02 21:03:34 +03:00
fix(profile-pictures): declare schema ownership and serve avatars as png with nosniff
This commit is contained in:
+5
-1
@@ -132,10 +132,14 @@ public class ProfilePictureController {
|
||||
}
|
||||
StoredImage image = stored.get();
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType(image.contentType()))
|
||||
// store() re-encodes every upload, so the stored type is always PNG; parsing it
|
||||
// back would only add a 500 path for a row written by anything else.
|
||||
.contentType(MediaType.IMAGE_PNG)
|
||||
// Same URI for every user, so a shared browser must not reuse it. The client keeps
|
||||
// the blob for the session anyway, so there is nothing to gain from caching here.
|
||||
.cacheControl(CacheControl.noStore())
|
||||
.header("X-Content-Type-Options", "nosniff")
|
||||
.header("Content-Disposition", "inline; filename=\"avatar.png\"")
|
||||
.body(image.data());
|
||||
}
|
||||
|
||||
|
||||
+16
@@ -12,6 +12,8 @@ import static org.mockito.Mockito.when;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@@ -30,6 +32,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
@@ -142,12 +145,25 @@ class ProfilePictureControllerTest {
|
||||
|
||||
mockMvc.perform(get("/api/v1/user/profile-picture").principal(VIEWER))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.IMAGE_PNG))
|
||||
.andExpect(header().string("X-Content-Type-Options", "nosniff"))
|
||||
.andExpect(
|
||||
result ->
|
||||
assertThat(result.getResponse().getHeader("Cache-Control"))
|
||||
.contains("no-store"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void aStoredTypeThatIsNotAMediaTypeStillServesAsPngRatherThanA500() throws Exception {
|
||||
// Nothing writes this today, but parsing the column back would turn a bad row into a 500.
|
||||
when(profilePictureService.findImage(1L))
|
||||
.thenReturn(Optional.of(new StoredImage(new byte[] {1, 2, 3}, "not a media type")));
|
||||
|
||||
mockMvc.perform(get("/api/v1/user/profile-picture").principal(VIEWER))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.IMAGE_PNG));
|
||||
}
|
||||
|
||||
@Test
|
||||
void anUnknownPrincipalGetsA401RatherThanAnEmptyRoster() throws Exception {
|
||||
when(userService.findByUsernameIgnoreCase("ghost")).thenReturn(Optional.empty());
|
||||
|
||||
@@ -106,6 +106,7 @@ public final class SaasSchemaOwnership {
|
||||
"stored_file_blobs",
|
||||
"stored_files",
|
||||
"user_license_settings",
|
||||
"user_profile_pictures",
|
||||
"user_server_certificates",
|
||||
"workflow_participants",
|
||||
"workflow_sessions");
|
||||
|
||||
Reference in New Issue
Block a user