@@ -241,6 +241,7 @@ async def get_local_media(
241241 requester : Optional [Requester ] = None ,
242242 allow_authenticated : bool = True ,
243243 federation : bool = False ,
244+ allow_media_linked_to_redacted_event : bool = False ,
244245 ) -> None :
245246 raise NotImplementedError (
246247 "Sorry Mario, your MediaRepository related function is in another castle"
@@ -312,7 +313,10 @@ async def validate_media_restriction(
312313 return attachments
313314
314315 async def is_media_visible (
315- self , requesting_user : UserID , media_info_object : Union [LocalMedia , RemoteMedia ]
316+ self ,
317+ requesting_user : UserID ,
318+ media_info_object : Union [LocalMedia , RemoteMedia ],
319+ allow_media_linked_to_redacted_event : bool = False ,
316320 ) -> None :
317321 """
318322 Verify that media requested for download should be visible to the user making
@@ -349,11 +353,13 @@ async def is_media_visible(
349353
350354 if attached_event_id :
351355 event_base = await self .store .get_event (attached_event_id )
352- if event_base .internal_metadata .is_redacted ():
353- # If the event the media is attached to is redacted, don't server that
356+ if (
357+ event_base .internal_metadata .is_redacted ()
358+ and not allow_media_linked_to_redacted_event
359+ ):
360+ # If the event the media is attached to is redacted, don't serve that
354361 # media to the user. Moderators and admins should probably be excluded
355362 # from this restriction
356- # XXX: better error code?
357363 raise NotFoundError ()
358364
359365 if event_base .is_state ():
@@ -951,7 +957,11 @@ def respond_not_yet_uploaded(self, request: SynapseRequest) -> None:
951957 )
952958
953959 async def get_local_media_info (
954- self , request : SynapseRequest , media_id : str , max_timeout_ms : int
960+ self ,
961+ request : SynapseRequest ,
962+ media_id : str ,
963+ max_timeout_ms : int ,
964+ allow_media_linked_to_redacted_event : bool = False ,
955965 ) -> Optional [LocalMedia ]:
956966 """Gets the info dictionary for given local media ID. If the media has
957967 not been uploaded yet, this function will wait up to ``max_timeout_ms``
@@ -963,6 +973,7 @@ async def get_local_media_info(
963973 the file_id for local content.)
964974 max_timeout_ms: the maximum number of milliseconds to wait for the
965975 media to be uploaded.
976+ allow_media_linked_to_redacted_event:
966977
967978 Returns:
968979 Either the info dictionary for the given local media ID or
@@ -986,7 +997,11 @@ async def get_local_media_info(
986997 # The file has been uploaded, so stop looping
987998 if media_info .media_length is not None :
988999 if isinstance (request .requester , Requester ):
989- await self .is_media_visible (request .requester .user , media_info )
1000+ await self .is_media_visible (
1001+ request .requester .user ,
1002+ media_info ,
1003+ allow_media_linked_to_redacted_event ,
1004+ )
9901005 return media_info
9911006
9921007 # Check if the media ID has expired and still hasn't been uploaded to.
@@ -1015,6 +1030,7 @@ async def get_local_media(
10151030 requester : Optional [Requester ] = None ,
10161031 allow_authenticated : bool = True ,
10171032 federation : bool = False ,
1033+ allow_media_linked_to_redacted_event : bool = False ,
10181034 ) -> None :
10191035 """Responds to requests for local media, if exists, or returns 404.
10201036
@@ -1026,6 +1042,7 @@ async def get_local_media(
10261042 the filename in the Content-Disposition header of the response.
10271043 max_timeout_ms: the maximum number of milliseconds to wait for the
10281044 media to be uploaded.
1045+ allow_media_linked_to_redacted_event:
10291046 requester: The user making the request, to verify restricted media. Only
10301047 used for local users, not over federation
10311048 allow_authenticated: whether media marked as authenticated may be served to this request
@@ -1034,7 +1051,9 @@ async def get_local_media(
10341051 Returns:
10351052 Resolves once a response has successfully been written to request
10361053 """
1037- media_info = await self .get_local_media_info (request , media_id , max_timeout_ms )
1054+ media_info = await self .get_local_media_info (
1055+ request , media_id , max_timeout_ms , allow_media_linked_to_redacted_event
1056+ )
10381057 if not media_info :
10391058 return
10401059
@@ -1049,7 +1068,9 @@ async def get_local_media(
10491068 if requester is not None :
10501069 # Only check media visibility if this is for a local request. This will
10511070 # raise directly back to the client if not visible
1052- await self .is_media_visible (requester .user , media_info )
1071+ await self .is_media_visible (
1072+ requester .user , media_info , allow_media_linked_to_redacted_event
1073+ )
10531074 restrictions = await self .validate_media_restriction (
10541075 request , media_info , None , federation
10551076 )
@@ -1103,6 +1124,7 @@ async def get_remote_media(
11031124 use_federation_endpoint : bool ,
11041125 requester : Optional [Requester ] = None ,
11051126 allow_authenticated : bool = True ,
1127+ allow_media_linked_to_redacted_event : bool = False ,
11061128 ) -> None :
11071129 """Respond to requests for remote media.
11081130
@@ -1121,6 +1143,7 @@ async def get_remote_media(
11211143 used for local users, not over federation
11221144 allow_authenticated: whether media marked as authenticated may be served to this
11231145 request
1146+ allow_media_linked_to_redacted_event:
11241147
11251148 Returns:
11261149 Resolves once a response has successfully been written to request
@@ -1153,7 +1176,8 @@ async def get_remote_media(
11531176 ip_address ,
11541177 use_federation_endpoint ,
11551178 allow_authenticated ,
1156- requester ,
1179+ allow_media_linked_to_redacted_event = allow_media_linked_to_redacted_event ,
1180+ requester = requester ,
11571181 )
11581182
11591183 # Check if the media is cached on the client, if so return 304. We need
@@ -1189,6 +1213,7 @@ async def get_remote_media_info(
11891213 use_federation : bool ,
11901214 allow_authenticated : bool ,
11911215 requester : Optional [Requester ] = None ,
1216+ allow_media_linked_to_redacted_event : bool = False ,
11921217 ) -> RemoteMedia :
11931218 """Gets the media info associated with the remote file, downloading
11941219 if necessary.
@@ -1205,6 +1230,7 @@ async def get_remote_media_info(
12051230 request
12061231 requester: The user making the request, to verify restricted media. Only
12071232 used for local users, not over federation
1233+ allow_media_linked_to_redacted_event:
12081234
12091235 Returns:
12101236 The media info of the file
@@ -1227,7 +1253,8 @@ async def get_remote_media_info(
12271253 ip_address ,
12281254 use_federation ,
12291255 allow_authenticated ,
1230- requester ,
1256+ allow_media_linked_to_redacted_event = allow_media_linked_to_redacted_event ,
1257+ requester = requester ,
12311258 )
12321259
12331260 # Ensure we actually use the responder so that it releases resources
@@ -1246,6 +1273,7 @@ async def _get_remote_media_impl(
12461273 ip_address : str ,
12471274 use_federation_endpoint : bool ,
12481275 allow_authenticated : bool ,
1276+ allow_media_linked_to_redacted_event : bool = False ,
12491277 requester : Optional [Requester ] = None ,
12501278 ) -> Tuple [Optional [Responder ], RemoteMedia ]:
12511279 """Looks for media in local cache, if not there then attempt to
@@ -1263,6 +1291,7 @@ async def _get_remote_media_impl(
12631291 use_federation_endpoint: whether to request the remote media over the new federation
12641292 /download endpoint
12651293 allow_authenticated:
1294+ allow_media_linked_to_redacted_event:
12661295 requester: The user making the request, to verify restricted media. Only
12671296 used for local users, not over federation
12681297
@@ -1284,7 +1313,9 @@ async def _get_remote_media_impl(
12841313 # retrieved from the remote.
12851314 if self .msc3911_config .enabled and requester is not None :
12861315 # This will raise directly back to the client if not visible
1287- await self .is_media_visible (requester .user , media_info )
1316+ await self .is_media_visible (
1317+ requester .user , media_info , allow_media_linked_to_redacted_event
1318+ )
12881319
12891320 # file_id is the ID we use to track the file locally. If we've already
12901321 # seen the file then reuse the existing ID, otherwise generate a new
@@ -1344,7 +1375,9 @@ async def _get_remote_media_impl(
13441375 and requester is not None
13451376 ):
13461377 # This will raise directly back to the client if not visible
1347- await self .is_media_visible (requester .user , media_info )
1378+ await self .is_media_visible (
1379+ requester .user , media_info , allow_media_linked_to_redacted_event
1380+ )
13481381
13491382 file_id = media_info .filesystem_id
13501383
0 commit comments