prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [Project Transfer] Request Approval Email Uses Incorrect Customer Subdomain
  r### Environment
  
  SaaS (https://sentry.io/)
  
  ### Version
  
  n/a
  
  ### Link
  
  [relevant transaction](https://sentry.sentry.io/discover/javascript:31e672a100fd44f5ab3ac36d4be4dbd3/?field=title&field=event.type&field=project&field=user.display&field=timestamp&field=replayId&homepage=true&name=All+Events&project=11276&query=url%3A%22https%3A%2F%2Fmagiclamp-mobile-website-appli.sentry.io%2F%2A%22&sort=-timestamp&statsPeriod=14d&yAxis=count%28%29)
  
  ### DSN
  
  n/a
  
  ### Steps to Reproduce
  
  1. Org A requests a project transfer - supplies an owner email for Org B
  2. Org B owner clicks link in resulting "Request for Project Transfer" email
  3. Link directs Org B owner to **org-a**.sentry.io/accept-transfer/?data=<some_hash>
  
  ### Expected Result
  
  ...
  3. Link directs Org B owner to **org-b**.sentry.io/accept-transfer/?data=<some_hash>
  
  ### Actual Result
  
  Because Org B owner is not authenticated with orb-a.sentry.io they're asked to login, which will result in a variety of issues.
  
  Here's [a transaction where this happened](https://sentry.sentry.io/discover/javascript:31e672a100fd44f5ab3ac36d4be4dbd3/)
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/sentry/api/endpoints/project_transfer.py`
  Content:
  ```
  1 import logging
  2 from urllib.parse import urlencode
  3 from uuid import uuid4
  4 
  5 from django.utils import timezone
  6 from rest_framework import status
  7 from rest_framework.request import Request
  8 from rest_framework.response import Response
  9 
  10 from sentry import audit_log, options, roles
  11 from sentry.api.base import region_silo_endpoint
  12 from sentry.api.bases.project import ProjectEndpoint, ProjectPermission
  13 from sentry.api.decorators import sudo_required
  14 from sentry.models import OrganizationMember
  15 from sentry.utils.email import MessageBuilder
  16 from sentry.utils.signing import sign
  17 
  18 delete_logger = logging.getLogger("sentry.deletions.api")
  19 
  20 
  21 class RelaxedProjectPermission(ProjectPermission):
  22     scope_map = {"POST": ["project:admin"]}
  23 
  24 
  25 @region_silo_endpoint
  26 class ProjectTransferEndpoint(ProjectEndpoint):
  27     permission_classes = [RelaxedProjectPermission]
  28 
  29     @sudo_required
  30     def post(self, request: Request, project) -> Response:
  31         """
  32         Transfer a Project
  33         ````````````````
  34 
  35         Schedules a project for transfer to a new organization.
  36 
  37         :pparam string organization_slug: the slug of the organization the
  38                                           project belongs to.
  39         :pparam string project_slug: the slug of the project to delete.
  40         :param string email: email of new owner. must be an organization owner
  41         :auth: required
  42         """
  43         if project.is_internal_project():
  44             return Response(
  45                 '{"error": "Cannot transfer projects internally used by Sentry."}',
  46                 status=status.HTTP_403_FORBIDDEN,
  47             )
  48 
  49         email = request.data.get("email")
  50 
  51         if email is None:
  52             return Response(status=status.HTTP_400_BAD_REQUEST)
  53 
  54         if not request.user.is_authenticated:
  55             return Response(status=status.HTTP_403_FORBIDDEN)
  56 
  57         try:
  58             owner = OrganizationMember.objects.get_members_by_email_and_role(
  59                 email=email, role=roles.get_top_dog().id
  60             )[0]
  61         except IndexError:
  62             return Response(
  63                 {"detail": "Could not find an organization owner with that email"},
  64                 status=status.HTTP_404_NOT_FOUND,
  65             )
  66 
  67         organization = project.organization
  68         transaction_id = uuid4().hex
  69         url_data = sign(
  70             actor_id=request.user.id,
  71             from_organization_id=organization.id,
  72             project_id=project.id,
  73             user_id=owner.user_id,
  74             transaction_id=transaction_id,
  75         )
  76 
  77         context = {
  78             "email": email,
  79             "from_org": project.organization.name,
  80             "project_name": project.slug,
  81             "request_time": timezone.now(),
  82             "url": organization.absolute_url(
  83                 "/accept-transfer/", query=urlencode({"data": url_data})
  84             ),
  85             "requester": request.user,
  86         }
  87         MessageBuilder(
  88             subject="{}Request for Project Transfer".format(options.get("mail.subject-prefix")),
  89             template="sentry/emails/transfer_project.txt",
  90             html_template="sentry/emails/transfer_project.html",
  91             type="org.confirm_project_transfer_request",
  92             context=context,
  93         ).send_async([email])
  94 
  95         self.create_audit_entry(
  96             request=request,
  97             organization=project.organization,
  98             target_object=project.id,
  99             event=audit_log.get_event_id("PROJECT_REQUEST_TRANSFER"),
  100             data=project.get_audit_log_data(),
  101             transaction_id=transaction_id,
  102         )
  103 
  104         return Response(status=status.HTTP_204_NO_CONTENT)
  105
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/src/sentry/api/endpoints/project_transfer.py b/src/sentry/api/endpoints/project_transfer.py
  --- a/src/sentry/api/endpoints/project_transfer.py
  +++ b/src/sentry/api/endpoints/project_transfer.py
  @@ -13,6 +13,7 @@
   from sentry.api.decorators import sudo_required
   from sentry.models import OrganizationMember
   from sentry.utils.email import MessageBuilder
  +from sentry.utils.http import absolute_uri
   from sentry.utils.signing import sign
   
   delete_logger = logging.getLogger("sentry.deletions.api")
  @@ -79,9 +80,7 @@
               "from_org": project.organization.name,
               "project_name": project.slug,
               "request_time": timezone.now(),
  -            "url": organization.absolute_url(
  -                "/accept-transfer/", query=urlencode({"data": url_data})
  -            ),
  +            "url": absolute_uri(f"/accept-transfer/?{urlencode({'data': url_data})}"),
               "requester": request.user,
           }
           MessageBuilder(
  
verification_info: {"golden_diff": "diff --git a/src/sentry/api/endpoints/project_transfer.py b/src/sentry/api/endpoints/project_transfer.py\n--- a/src/sentry/api/endpoints/project_transfer.py\n+++ b/src/sentry/api/endpoints/project_transfer.py\n@@ -13,6 +13,7 @@\n from sentry.api.decorators import sudo_required\n from sentry.models import OrganizationMember\n from sentry.utils.email import MessageBuilder\n+from sentry.utils.http import absolute_uri\n from sentry.utils.signing import sign\n \n delete_logger = logging.getLogger(\"sentry.deletions.api\")\n@@ -79,9 +80,7 @@\n             \"from_org\": project.organization.name,\n             \"project_name\": project.slug,\n             \"request_time\": timezone.now(),\n-            \"url\": organization.absolute_url(\n-                \"/accept-transfer/\", query=urlencode({\"data\": url_data})\n-            ),\n+            \"url\": absolute_uri(f\"/accept-transfer/?{urlencode({'data': url_data})}\"),\n             \"requester\": request.user,\n         }\n         MessageBuilder(\n", "issue": "[Project Transfer] Request Approval Email Uses Incorrect Customer Subdomain\nr### Environment\r\n\r\nSaaS (https://sentry.io/)\r\n\r\n### Version\r\n\r\nn/a\r\n\r\n### Link\r\n\r\n[relevant transaction](https://sentry.sentry.io/discover/javascript:31e672a100fd44f5ab3ac36d4be4dbd3/?field=title&field=event.type&field=project&field=user.display&field=timestamp&field=replayId&homepage=true&name=All+Events&project=11276&query=url%3A%22https%3A%2F%2Fmagiclamp-mobile-website-appli.sentry.io%2F%2A%22&sort=-timestamp&statsPeriod=14d&yAxis=count%28%29)\r\n\r\n### DSN\r\n\r\nn/a\r\n\r\n### Steps to Reproduce\r\n\r\n1. Org A requests a project transfer - supplies an owner email for Org B\r\n2. Org B owner clicks link in resulting \"Request for Project Transfer\" email\r\n3. Link directs Org B owner to **org-a**.sentry.io/accept-transfer/?data=<some_hash>\r\n\r\n### Expected Result\r\n\r\n...\r\n3. Link directs Org B owner to **org-b**.sentry.io/accept-transfer/?data=<some_hash>\r\n\r\n### Actual Result\r\n\r\nBecause Org B owner is not authenticated with orb-a.sentry.io they're asked to login, which will result in a variety of issues.\r\n\r\nHere's [a transaction where this happened](https://sentry.sentry.io/discover/javascript:31e672a100fd44f5ab3ac36d4be4dbd3/)\n", "before_files": [{"content": "import logging\nfrom urllib.parse import urlencode\nfrom uuid import uuid4\n\nfrom django.utils import timezone\nfrom rest_framework import status\nfrom rest_framework.request import Request\nfrom rest_framework.response import Response\n\nfrom sentry import audit_log, options, roles\nfrom sentry.api.base import region_silo_endpoint\nfrom sentry.api.bases.project import ProjectEndpoint, ProjectPermission\nfrom sentry.api.decorators import sudo_required\nfrom sentry.models import OrganizationMember\nfrom sentry.utils.email import MessageBuilder\nfrom sentry.utils.signing import sign\n\ndelete_logger = logging.getLogger(\"sentry.deletions.api\")\n\n\nclass RelaxedProjectPermission(ProjectPermission):\n    scope_map = {\"POST\": [\"project:admin\"]}\n\n\n@region_silo_endpoint\nclass ProjectTransferEndpoint(ProjectEndpoint):\n    permission_classes = [RelaxedProjectPermission]\n\n    @sudo_required\n    def post(self, request: Request, project) -> Response:\n        \"\"\"\n        Transfer a Project\n        ````````````````\n\n        Schedules a project for transfer to a new organization.\n\n        :pparam string organization_slug: the slug of the organization the\n                                          project belongs to.\n        :pparam string project_slug: the slug of the project to delete.\n        :param string email: email of new owner. must be an organization owner\n        :auth: required\n        \"\"\"\n        if project.is_internal_project():\n            return Response(\n                '{\"error\": \"Cannot transfer projects internally used by Sentry.\"}',\n                status=status.HTTP_403_FORBIDDEN,\n            )\n\n        email = request.data.get(\"email\")\n\n        if email is None:\n            return Response(status=status.HTTP_400_BAD_REQUEST)\n\n        if not request.user.is_authenticated:\n            return Response(status=status.HTTP_403_FORBIDDEN)\n\n        try:\n            owner = OrganizationMember.objects.get_members_by_email_and_role(\n                email=email, role=roles.get_top_dog().id\n            )[0]\n        except IndexError:\n            return Response(\n                {\"detail\": \"Could not find an organization owner with that email\"},\n                status=status.HTTP_404_NOT_FOUND,\n            )\n\n        organization = project.organization\n        transaction_id = uuid4().hex\n        url_data = sign(\n            actor_id=request.user.id,\n            from_organization_id=organization.id,\n            project_id=project.id,\n            user_id=owner.user_id,\n            transaction_id=transaction_id,\n        )\n\n        context = {\n            \"email\": email,\n            \"from_org\": project.organization.name,\n            \"project_name\": project.slug,\n            \"request_time\": timezone.now(),\n            \"url\": organization.absolute_url(\n                \"/accept-transfer/\", query=urlencode({\"data\": url_data})\n            ),\n            \"requester\": request.user,\n        }\n        MessageBuilder(\n            subject=\"{}Request for Project Transfer\".format(options.get(\"mail.subject-prefix\")),\n            template=\"sentry/emails/transfer_project.txt\",\n            html_template=\"sentry/emails/transfer_project.html\",\n            type=\"org.confirm_project_transfer_request\",\n            context=context,\n        ).send_async([email])\n\n        self.create_audit_entry(\n            request=request,\n            organization=project.organization,\n            target_object=project.id,\n            event=audit_log.get_event_id(\"PROJECT_REQUEST_TRANSFER\"),\n            data=project.get_audit_log_data(),\n            transaction_id=transaction_id,\n        )\n\n        return Response(status=status.HTTP_204_NO_CONTENT)\n", "path": "src/sentry/api/endpoints/project_transfer.py"}], "after_files": [{"content": "import logging\nfrom urllib.parse import urlencode\nfrom uuid import uuid4\n\nfrom django.utils import timezone\nfrom rest_framework import status\nfrom rest_framework.request import Request\nfrom rest_framework.response import Response\n\nfrom sentry import audit_log, options, roles\nfrom sentry.api.base import region_silo_endpoint\nfrom sentry.api.bases.project import ProjectEndpoint, ProjectPermission\nfrom sentry.api.decorators import sudo_required\nfrom sentry.models import OrganizationMember\nfrom sentry.utils.email import MessageBuilder\nfrom sentry.utils.http import absolute_uri\nfrom sentry.utils.signing import sign\n\ndelete_logger = logging.getLogger(\"sentry.deletions.api\")\n\n\nclass RelaxedProjectPermission(ProjectPermission):\n    scope_map = {\"POST\": [\"project:admin\"]}\n\n\n@region_silo_endpoint\nclass ProjectTransferEndpoint(ProjectEndpoint):\n    permission_classes = [RelaxedProjectPermission]\n\n    @sudo_required\n    def post(self, request: Request, project) -> Response:\n        \"\"\"\n        Transfer a Project\n        ````````````````\n\n        Schedules a project for transfer to a new organization.\n\n        :pparam string organization_slug: the slug of the organization the\n                                          project belongs to.\n        :pparam string project_slug: the slug of the project to delete.\n        :param string email: email of new owner. must be an organization owner\n        :auth: required\n        \"\"\"\n        if project.is_internal_project():\n            return Response(\n                '{\"error\": \"Cannot transfer projects internally used by Sentry.\"}',\n                status=status.HTTP_403_FORBIDDEN,\n            )\n\n        email = request.data.get(\"email\")\n\n        if email is None:\n            return Response(status=status.HTTP_400_BAD_REQUEST)\n\n        if not request.user.is_authenticated:\n            return Response(status=status.HTTP_403_FORBIDDEN)\n\n        try:\n            owner = OrganizationMember.objects.get_members_by_email_and_role(\n                email=email, role=roles.get_top_dog().id\n            )[0]\n        except IndexError:\n            return Response(\n                {\"detail\": \"Could not find an organization owner with that email\"},\n                status=status.HTTP_404_NOT_FOUND,\n            )\n\n        organization = project.organization\n        transaction_id = uuid4().hex\n        url_data = sign(\n            actor_id=request.user.id,\n            from_organization_id=organization.id,\n            project_id=project.id,\n            user_id=owner.user_id,\n            transaction_id=transaction_id,\n        )\n\n        context = {\n            \"email\": email,\n            \"from_org\": project.organization.name,\n            \"project_name\": project.slug,\n            \"request_time\": timezone.now(),\n            \"url\": absolute_uri(f\"/accept-transfer/?{urlencode({'data': url_data})}\"),\n            \"requester\": request.user,\n        }\n        MessageBuilder(\n            subject=\"{}Request for Project Transfer\".format(options.get(\"mail.subject-prefix\")),\n            template=\"sentry/emails/transfer_project.txt\",\n            html_template=\"sentry/emails/transfer_project.html\",\n            type=\"org.confirm_project_transfer_request\",\n            context=context,\n        ).send_async([email])\n\n        self.create_audit_entry(\n            request=request,\n            organization=project.organization,\n            target_object=project.id,\n            event=audit_log.get_event_id(\"PROJECT_REQUEST_TRANSFER\"),\n            data=project.get_audit_log_data(),\n            transaction_id=transaction_id,\n        )\n\n        return Response(status=status.HTTP_204_NO_CONTENT)\n", "path": "src/sentry/api/endpoints/project_transfer.py"}]}