Skip to content

Commit 91f08bc

Browse files
committed
feat: Migrate organizations list to control
1 parent 8246cf3 commit 91f08bc

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import logging
2+
from enum import Enum
3+
4+
from django.db.models import Count, Q
5+
from rest_framework.response import Response
6+
7+
from sentry.api.paginator import DateTimePaginator, OffsetPaginator
8+
from sentry.api.serializers import serialize
9+
from sentry.db.models.query import in_iexact
10+
from sentry.models.organization import Organization, OrganizationStatus
11+
from sentry.models.organizationmember import OrganizationMember
12+
from sentry.models.projectplatform import ProjectPlatform
13+
from sentry.search.utils import tokenize_query
14+
from sentry.users.services.user.service import user_service
15+
from sentry.utils.pagination_factory import PaginatorLike
16+
17+
logger = logging.getLogger(__name__)
18+
19+
20+
class SortBy(Enum):
21+
MEMBERS = "members"
22+
PROJECTS = "projects"
23+
DATE_ADDED = "date"
24+
25+
26+
class Show(Enum):
27+
ALL = "all"
28+
29+
30+
def list_organizations(
31+
*,
32+
owner_only: bool = False,
33+
query: str | None = None,
34+
show: Show | None = None,
35+
sort_by: SortBy | None = "date",
36+
# actor specific stuff
37+
actor_user_id: int,
38+
actor_is_active_superuser: bool = False,
39+
actor_organization_id: int | None = None,
40+
actor_project_id: int | None = None,
41+
):
42+
"""
43+
Return a list of organizations available to the authenticated session in a region.
44+
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.
45+
"""
46+
queryset = Organization.objects.distinct()
47+
48+
if actor_project_id is not None:
49+
queryset = queryset.filter(id=actor_project_id.organization_id)
50+
elif actor_organization_id is not None:
51+
queryset = queryset.filter(id=actor_organization_id)
52+
53+
if owner_only:
54+
# This is used when closing an account
55+
# also fetches organizations in which you are a member of an owner team
56+
queryset = Organization.objects.get_organizations_where_user_is_owner(user_id=actor_user_id)
57+
org_results = []
58+
for org in sorted(queryset, key=lambda x: x.name):
59+
# O(N) query
60+
org_results.append(
61+
{"organization": serialize(org), "singleOwner": org.has_single_owner()}
62+
)
63+
64+
return Response(org_results)
65+
66+
elif not (actor_is_active_superuser and show == "all"):
67+
queryset = queryset.filter(
68+
id__in=OrganizationMember.objects.filter(user_id=actor_user_id).values("organization")
69+
)
70+
if actor_organization_id is not None and queryset.count() > 1:
71+
# If a token is limited to one organization, this endpoint should only return that one organization
72+
queryset = queryset.filter(id=actor_organization_id)
73+
74+
if query:
75+
tokens = tokenize_query(query)
76+
for key, value in tokens.items():
77+
if key == "query":
78+
query_value = " ".join(value)
79+
user_ids = {
80+
u.id
81+
for u in user_service.get_many_by_email(emails=[query_value], is_verified=False)
82+
}
83+
queryset = queryset.filter(
84+
Q(name__icontains=query_value)
85+
| Q(slug__icontains=query_value)
86+
| Q(member_set__user_id__in=user_ids)
87+
)
88+
elif key == "slug":
89+
queryset = queryset.filter(in_iexact("slug", value))
90+
elif key == "email":
91+
user_ids = {
92+
u.id for u in user_service.get_many_by_email(emails=value, is_verified=False)
93+
}
94+
queryset = queryset.filter(Q(member_set__user_id__in=user_ids))
95+
elif key == "platform":
96+
queryset = queryset.filter(
97+
project__in=ProjectPlatform.objects.filter(platform__in=value).values(
98+
"project_id"
99+
)
100+
)
101+
elif key == "id":
102+
queryset = queryset.filter(id__in=value)
103+
elif key == "status":
104+
try:
105+
queryset = queryset.filter(
106+
status__in=[OrganizationStatus[v.upper()] for v in value]
107+
)
108+
except KeyError:
109+
queryset = queryset.none()
110+
elif key == "member_id":
111+
queryset = queryset.filter(
112+
id__in=OrganizationMember.objects.filter(id__in=value).values("organization")
113+
)
114+
else:
115+
queryset = queryset.none()
116+
117+
paginator_cls: type[PaginatorLike]
118+
if sort_by == "members":
119+
queryset = queryset.annotate(member_count=Count("member_set"))
120+
order_by = "-member_count"
121+
paginator_cls = OffsetPaginator
122+
elif sort_by == "projects":
123+
queryset = queryset.annotate(project_count=Count("project"))
124+
order_by = "-project_count"
125+
paginator_cls = OffsetPaginator
126+
else:
127+
order_by = "-date_added"
128+
paginator_cls = DateTimePaginator
129+
130+
# return paginate(
131+
# request=request,
132+
# queryset=queryset,
133+
# order_by=order_by,
134+
# on_results=lambda x: serialize(x, request.user),
135+
# paginator_cls=paginator_cls,
136+
# )

0 commit comments

Comments
 (0)