|
2 | 2 |
|
3 | 3 | from django.conf import settings
|
4 | 4 | from django.db import IntegrityError
|
5 |
| -from django.db.models import Count, Q |
6 | 5 | from drf_spectacular.utils import extend_schema
|
7 | 6 | from rest_framework import serializers, status
|
8 | 7 | from rest_framework.request import Request
|
|
13 | 12 | from sentry.api.api_publish_status import ApiPublishStatus
|
14 | 13 | from sentry.api.base import Endpoint, region_silo_endpoint
|
15 | 14 | from sentry.api.bases.organization import OrganizationPermission
|
16 |
| -from sentry.api.paginator import DateTimePaginator, OffsetPaginator |
17 | 15 | from sentry.api.serializers import serialize
|
18 | 16 | from sentry.api.serializers.models.organization import (
|
19 | 17 | BaseOrganizationSerializer,
|
|
24 | 22 | from sentry.apidocs.parameters import CursorQueryParam, OrganizationParams
|
25 | 23 | from sentry.apidocs.utils import inline_sentry_response_serializer
|
26 | 24 | from sentry.auth.superuser import is_active_superuser
|
27 |
| -from sentry.db.models.query import in_iexact |
28 | 25 | from sentry.hybridcloud.rpc import IDEMPOTENCY_KEY_LENGTH
|
29 |
| -from sentry.models.organization import Organization, OrganizationStatus |
30 |
| -from sentry.models.organizationmember import OrganizationMember |
31 |
| -from sentry.models.projectplatform import ProjectPlatform |
32 |
| -from sentry.search.utils import tokenize_query |
| 26 | +from sentry.models.organization import Organization |
| 27 | +from sentry.organizations.services.organization import organization_service |
33 | 28 | from sentry.services.organization import (
|
34 | 29 | OrganizationOptions,
|
35 | 30 | OrganizationProvisioningOptions,
|
36 | 31 | PostProvisionOptions,
|
37 | 32 | )
|
38 | 33 | from sentry.services.organization.provisioning import organization_provisioning_service
|
39 | 34 | from sentry.signals import org_setup_complete, terms_accepted
|
40 |
| -from sentry.users.services.user.service import user_service |
41 |
| -from sentry.utils.pagination_factory import PaginatorLike |
42 | 35 |
|
43 | 36 | logger = logging.getLogger(__name__)
|
44 | 37 |
|
@@ -95,113 +88,22 @@ def get(self, request: Request) -> Response:
|
95 | 88 | Return a list of organizations available to the authenticated session in a region.
|
96 | 89 | This is particularly useful for requests with a user bound context. For API key-based requests this will only return the organization that belongs to the key.
|
97 | 90 | """
|
98 |
| - owner_only = request.GET.get("owner") in ("1", "true") |
99 |
| - |
100 |
| - queryset = Organization.objects.distinct() |
101 |
| - |
102 |
| - if request.auth and not request.user.is_authenticated: |
103 |
| - if hasattr(request.auth, "project"): |
104 |
| - queryset = queryset.filter(id=request.auth.project.organization_id) |
105 |
| - elif request.auth.organization_id is not None: |
106 |
| - queryset = queryset.filter(id=request.auth.organization_id) |
107 |
| - |
108 |
| - elif owner_only and request.user.is_authenticated: |
109 |
| - # This is used when closing an account |
110 |
| - |
111 |
| - # also fetches organizations in which you are a member of an owner team |
112 |
| - queryset = Organization.objects.get_organizations_where_user_is_owner( |
113 |
| - user_id=request.user.id |
114 |
| - ) |
115 |
| - org_results = [] |
116 |
| - for org in sorted(queryset, key=lambda x: x.name): |
117 |
| - # O(N) query |
118 |
| - org_results.append( |
119 |
| - {"organization": serialize(org), "singleOwner": org.has_single_owner()} |
120 |
| - ) |
121 |
| - |
122 |
| - return Response(org_results) |
123 |
| - |
124 |
| - elif not (is_active_superuser(request) and request.GET.get("show") == "all"): |
125 |
| - queryset = queryset.filter( |
126 |
| - id__in=OrganizationMember.objects.filter(user_id=request.user.id).values( |
127 |
| - "organization" |
128 |
| - ) |
129 |
| - ) |
130 |
| - if request.auth and request.auth.organization_id is not None and queryset.count() > 1: |
131 |
| - # If a token is limited to one organization, this endpoint should only return that one organization |
132 |
| - queryset = queryset.filter(id=request.auth.organization_id) |
133 |
| - |
134 |
| - query = request.GET.get("query") |
135 |
| - if query: |
136 |
| - tokens = tokenize_query(query) |
137 |
| - for key, value in tokens.items(): |
138 |
| - if key == "query": |
139 |
| - query_value = " ".join(value) |
140 |
| - user_ids = { |
141 |
| - u.id |
142 |
| - for u in user_service.get_many_by_email( |
143 |
| - emails=[query_value], is_verified=False |
144 |
| - ) |
145 |
| - } |
146 |
| - queryset = queryset.filter( |
147 |
| - Q(name__icontains=query_value) |
148 |
| - | Q(slug__icontains=query_value) |
149 |
| - | Q(member_set__user_id__in=user_ids) |
150 |
| - ) |
151 |
| - elif key == "slug": |
152 |
| - queryset = queryset.filter(in_iexact("slug", value)) |
153 |
| - elif key == "email": |
154 |
| - user_ids = { |
155 |
| - u.id |
156 |
| - for u in user_service.get_many_by_email(emails=value, is_verified=False) |
157 |
| - } |
158 |
| - queryset = queryset.filter(Q(member_set__user_id__in=user_ids)) |
159 |
| - elif key == "platform": |
160 |
| - queryset = queryset.filter( |
161 |
| - project__in=ProjectPlatform.objects.filter(platform__in=value).values( |
162 |
| - "project_id" |
163 |
| - ) |
164 |
| - ) |
165 |
| - elif key == "id": |
166 |
| - queryset = queryset.filter(id__in=value) |
167 |
| - elif key == "status": |
168 |
| - try: |
169 |
| - queryset = queryset.filter( |
170 |
| - status__in=[OrganizationStatus[v.upper()] for v in value] |
171 |
| - ) |
172 |
| - except KeyError: |
173 |
| - queryset = queryset.none() |
174 |
| - elif key == "member_id": |
175 |
| - queryset = queryset.filter( |
176 |
| - id__in=OrganizationMember.objects.filter(id__in=value).values( |
177 |
| - "organization" |
178 |
| - ) |
179 |
| - ) |
180 |
| - else: |
181 |
| - queryset = queryset.none() |
182 |
| - |
183 |
| - sort_by = request.GET.get("sortBy") |
184 |
| - paginator_cls: type[PaginatorLike] |
185 |
| - if sort_by == "members": |
186 |
| - queryset = queryset.annotate(member_count=Count("member_set")) |
187 |
| - order_by = "-member_count" |
188 |
| - paginator_cls = OffsetPaginator |
189 |
| - elif sort_by == "projects": |
190 |
| - queryset = queryset.annotate(project_count=Count("project")) |
191 |
| - order_by = "-project_count" |
192 |
| - paginator_cls = OffsetPaginator |
193 |
| - else: |
194 |
| - order_by = "-date_added" |
195 |
| - paginator_cls = DateTimePaginator |
196 |
| - |
197 |
| - return self.paginate( |
198 |
| - request=request, |
199 |
| - queryset=queryset, |
200 |
| - order_by=order_by, |
201 |
| - on_results=lambda x: serialize(x, request.user), |
202 |
| - paginator_cls=paginator_cls, |
| 91 | + result = organization_service.list_organizations( |
| 92 | + actor_user_id=request.user.id, |
| 93 | + owner_only=request.GET.get("owner") in ("1", "true"), |
| 94 | + query=request.GET.get("query"), |
| 95 | + sort_by=request.GET.get("sortBy"), |
| 96 | + show=request.GET.get("show"), |
| 97 | + actor_organization_id=request.auth.organization_id if request.auth else None, |
| 98 | + actor_project_id=request.auth.project_id if request.auth else None, |
| 99 | + actor_is_active_superuser=is_active_superuser(request), |
| 100 | + as_user=request.user, |
203 | 101 | )
|
204 | 102 |
|
| 103 | + response = Response(result["results"]) |
| 104 | + self.add_cursor_headers(request, response, result["cursor"]) |
| 105 | + return response |
| 106 | + |
205 | 107 | # XXX: endpoint useless for end-users as it needs user context.
|
206 | 108 | def post(self, request: Request) -> Response:
|
207 | 109 | """
|
|
0 commit comments