4545 f"{ settings .MEDIA_URL :s} (?P<pk>{ UUID_REGEX :s} )/"
4646 f"(?P<key>{ ATTACHMENTS_FOLDER :s} /{ UUID_REGEX :s} { FILE_EXT_REGEX :s} )$"
4747)
48+ COLLABORATION_WS_URL_PATTERN = re .compile (rf"(?:^|&)room=(?P<pk>{ UUID_REGEX } )(?:&|$)" )
4849
4950# pylint: disable=too-many-ancestors
5051
@@ -620,6 +621,10 @@ def _authorize_subrequest(self, request, pattern):
620621 parsed_url = urlparse (original_url )
621622 match = pattern .search (parsed_url .path )
622623
624+ # If the path does not match the pattern, try to extract the parameters from the query
625+ if not match :
626+ match = pattern .search (parsed_url .query )
627+
623628 if not match :
624629 logger .debug (
625630 "Subrequest URL '%s' did not match pattern '%s'" ,
@@ -645,17 +650,19 @@ def _authorize_subrequest(self, request, pattern):
645650 except models .Document .DoesNotExist as exc :
646651 logger .debug ("Document with ID '%s' does not exist" , pk )
647652 raise drf .exceptions .PermissionDenied () from exc
648- print (document )
649- if not document .get_abilities (request .user ).get (self .action , False ):
653+
654+ user_abilities = document .get_abilities (request .user )
655+
656+ if not user_abilities .get (self .action , False ):
650657 logger .debug (
651658 "User '%s' lacks permission for document '%s'" , request .user , pk
652659 )
653- # raise drf.exceptions.PermissionDenied()
660+ raise drf .exceptions .PermissionDenied ()
654661
655662 logger .debug (
656663 "Subrequest authorization successful. Extracted parameters: %s" , url_params
657664 )
658- return url_params
665+ return url_params , user_abilities , request . user . id
659666
660667 @drf .decorators .action (detail = False , methods = ["get" ], url_path = "media-auth" )
661668 def media_auth (self , request , * args , ** kwargs ):
@@ -668,14 +675,36 @@ def media_auth(self, request, *args, **kwargs):
668675 annotation. The request will then be proxied to the object storage backend who will
669676 respond with the file after checking the signature included in headers.
670677 """
671- url_params = self ._authorize_subrequest (request , MEDIA_STORAGE_URL_PATTERN )
678+ url_params , _ , _ = self ._authorize_subrequest (
679+ request , MEDIA_STORAGE_URL_PATTERN
680+ )
672681 pk , key = url_params .values ()
673682
674683 # Generate S3 authorization headers using the extracted URL parameters
675684 request = utils .generate_s3_authorization_headers (f"{ pk :s} /{ key :s} " )
676685
677686 return drf .response .Response ("authorized" , headers = request .headers , status = 200 )
678687
688+ @drf .decorators .action (detail = False , methods = ["get" ], url_path = "collaboration-auth" )
689+ def collaboration_auth (self , request , * args , ** kwargs ):
690+ """
691+ This view is used by an Nginx subrequest to control access to a document's
692+ collaboration server.
693+ """
694+ _ , user_abilities , user_id = self ._authorize_subrequest (
695+ request , COLLABORATION_WS_URL_PATTERN
696+ )
697+ can_edit = user_abilities ["partial_update" ]
698+
699+ # Add the collaboration server secret token to the headers
700+ headers = {
701+ "Authorization" : settings .COLLABORATION_SERVER_SECRET ,
702+ "X-Can-Edit" : str (can_edit ),
703+ "X-User-Id" : str (user_id ),
704+ }
705+
706+ return drf .response .Response ("authorized" , headers = headers , status = 200 )
707+
679708 @drf .decorators .action (
680709 detail = True ,
681710 methods = ["post" ],
0 commit comments