Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit ec56480

Browse files
fix: Remove ordering on account organizations list (#900)
1 parent 33fc91b commit ec56480

File tree

9 files changed

+52
-114
lines changed

9 files changed

+52
-114
lines changed

graphql_api/helpers/mutation.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,22 @@ def authenticated_resolver(queried_owner, info, *args, **kwargs):
7575
return authenticated_resolver
7676

7777

78+
def require_shared_account_or_part_of_org(resolver):
79+
def authenticated_resolver(queried_owner, info, *args, **kwargs):
80+
current_user = info.context["request"].user
81+
if (
82+
current_user
83+
and current_user.is_authenticated
84+
and queried_owner
85+
and queried_owner.account
86+
and current_user in queried_owner.account.users.all()
87+
):
88+
return resolver(queried_owner, info, *args, **kwargs)
89+
90+
return require_part_of_org(resolver)(queried_owner, info, *args, **kwargs)
91+
92+
return authenticated_resolver
93+
94+
7895
def resolve_union_error_type(error, *_):
7996
return error.get_graphql_type()

graphql_api/tests/test_account.py

Lines changed: 3 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -126,55 +126,9 @@ def test_fetch_organizations(self) -> None:
126126
for node in result["owner"]["account"]["organizations"]["edges"]
127127
]
128128

129-
assert orgs == ["owner-2", "owner-1", "owner-0"]
130-
131-
def test_fetch_organizations_order_by_activated_users_asc(self) -> None:
132-
account = AccountFactory(name="account")
133-
owner = OwnerFactory(
134-
username="owner-0",
135-
plan_activated_users=[],
136-
account=account,
137-
)
138-
OwnerFactory(
139-
username="owner-1",
140-
plan_activated_users=[0],
141-
account=account,
142-
)
143-
OwnerFactory(
144-
username="owner-2",
145-
plan_activated_users=[0, 1],
146-
account=account,
147-
)
148-
149-
query = """
150-
query {
151-
owner(username: "%s") {
152-
account {
153-
organizations(first: 20, ordering: ACTIVATED_USERS, orderingDirection: ASC) {
154-
edges {
155-
node {
156-
username
157-
activatedUserCount
158-
}
159-
}
160-
}
161-
}
162-
}
163-
}
164-
""" % (owner.username)
165-
166-
result = self.gql_request(query, owner=owner)
167-
168-
assert "errors" not in result
169-
170-
orgs = [
171-
node["node"]["username"]
172-
for node in result["owner"]["account"]["organizations"]["edges"]
173-
]
174-
175129
assert orgs == ["owner-0", "owner-1", "owner-2"]
176130

177-
def test_fetch_organizations_order_by_name(self) -> None:
131+
def test_fetch_organizations_desc(self) -> None:
178132
account = AccountFactory(name="account")
179133
owner = OwnerFactory(
180134
username="owner-0",
@@ -196,7 +150,7 @@ def test_fetch_organizations_order_by_name(self) -> None:
196150
query {
197151
owner(username: "%s") {
198152
account {
199-
organizations(first: 20, ordering: NAME) {
153+
organizations(first: 20, orderingDirection: DESC) {
200154
edges {
201155
node {
202156
username
@@ -220,52 +174,6 @@ def test_fetch_organizations_order_by_name(self) -> None:
220174

221175
assert orgs == ["owner-2", "owner-1", "owner-0"]
222176

223-
def test_fetch_organizations_order_by_name_asc(self) -> None:
224-
account = AccountFactory(name="account")
225-
owner = OwnerFactory(
226-
username="owner-0",
227-
plan_activated_users=[],
228-
account=account,
229-
)
230-
OwnerFactory(
231-
username="owner-1",
232-
plan_activated_users=[0],
233-
account=account,
234-
)
235-
OwnerFactory(
236-
username="owner-2",
237-
plan_activated_users=[0, 1],
238-
account=account,
239-
)
240-
241-
query = """
242-
query {
243-
owner(username: "%s") {
244-
account {
245-
organizations(first: 20, ordering: NAME, orderingDirection: ASC) {
246-
edges {
247-
node {
248-
username
249-
activatedUserCount
250-
}
251-
}
252-
}
253-
}
254-
}
255-
}
256-
""" % (owner.username)
257-
258-
result = self.gql_request(query, owner=owner)
259-
260-
assert "errors" not in result
261-
262-
orgs = [
263-
node["node"]["username"]
264-
for node in result["owner"]["account"]["organizations"]["edges"]
265-
]
266-
267-
assert orgs == ["owner-0", "owner-1", "owner-2"]
268-
269177
def test_fetch_organizations_pagination(self) -> None:
270178
account = AccountFactory(name="account")
271179
owner = OwnerFactory(
@@ -318,7 +226,7 @@ def test_fetch_organizations_pagination(self) -> None:
318226
for node in result["owner"]["account"]["organizations"]["edges"]
319227
]
320228

321-
assert orgs == ["owner-2", "owner-1"]
229+
assert orgs == ["owner-0", "owner-1"]
322230

323231
hasNextPage = result["owner"]["account"]["organizations"]["pageInfo"][
324232
"hasNextPage"

graphql_api/tests/test_owner.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
from freezegun import freeze_time
88
from graphql import GraphQLError
99
from prometheus_client import REGISTRY
10-
from shared.django_apps.codecov_auth.tests.factories import OktaSettingsFactory
10+
from shared.django_apps.codecov_auth.tests.factories import (
11+
AccountsUsersFactory,
12+
OktaSettingsFactory,
13+
)
1114
from shared.django_apps.reports.models import ReportType
1215
from shared.upload.utils import UploaderType, insert_coverage_measurement
1316

@@ -1027,3 +1030,23 @@ def test_fetch_activated_user_count_returns_null_if_not_in_org(self):
10271030
""" % (owner.username)
10281031
data = self.gql_request(query, owner=user)
10291032
assert data["owner"]["activatedUserCount"] is None
1033+
1034+
def test_fetch_activated_user_count_when_not_in_org_but_has_shared_account(self):
1035+
owner = OwnerFactory(username="sample-user")
1036+
AccountsUsersFactory(user=owner.user, account=self.account)
1037+
user2 = OwnerFactory(username="sample-user-2")
1038+
user3 = OwnerFactory(username="sample-user-3")
1039+
other_owner = OwnerFactory(
1040+
username="sample-org",
1041+
plan_activated_users=[user2.ownerid, user3.ownerid],
1042+
account=self.account,
1043+
)
1044+
1045+
query = """{
1046+
owner(username: "%s") {
1047+
activatedUserCount
1048+
}
1049+
}
1050+
""" % (other_owner.username)
1051+
data = self.gql_request(query, owner=owner)
1052+
assert data["owner"]["activatedUserCount"] == 2

graphql_api/types/account/account.graphql

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ type Account {
44
totalSeatCount: Int!
55
activatedUserCount: Int!
66
organizations(
7-
ordering: AccountOrganizationOrdering
87
orderingDirection: OrderingDirection
98
first: Int
109
after: String

graphql_api/types/account/account.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
build_connection_graphql,
99
queryset_to_connection,
1010
)
11-
from graphql_api.types.enums.enums import AccountOrganizationOrdering, OrderingDirection
11+
from graphql_api.types.enums.enums import OrderingDirection
1212

1313
account = ariadne_load_local_graphql(__file__, "account.graphql")
1414
account = account + build_connection_graphql("AccountOrganizationConnection", "Owner")
@@ -43,13 +43,12 @@ def resolve_activated_user_count(account: Account, info: GraphQLResolveInfo) ->
4343
def resolve_organizations(
4444
account: Account,
4545
info: GraphQLResolveInfo,
46-
ordering=AccountOrganizationOrdering.ACTIVATED_USERS,
47-
ordering_direction=OrderingDirection.DESC,
46+
ordering_direction=OrderingDirection.ASC,
4847
**kwargs,
4948
):
5049
return queryset_to_connection(
5150
account.organizations,
52-
ordering=(ordering,),
51+
ordering=("username",),
5352
ordering_direction=ordering_direction,
5453
**kwargs,
5554
)

graphql_api/types/enums/account_organization_ordering.graphql

Lines changed: 0 additions & 4 deletions
This file was deleted.

graphql_api/types/enums/enum_types.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from timeseries.models import MeasurementName
1212

1313
from .enums import (
14-
AccountOrganizationOrdering,
1514
AssetOrdering,
1615
BundleLoadTypes,
1716
CoverageLine,
@@ -57,5 +56,4 @@
5756
EnumType("TestResultsOrderingParameter", TestResultsOrderingParameter),
5857
EnumType("TestResultsFilterParameter", TestResultsFilterParameter),
5958
EnumType("AssetOrdering", AssetOrdering),
60-
EnumType("AccountOrganizationOrdering", AccountOrganizationOrdering),
6159
]

graphql_api/types/enums/enums.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,6 @@ class RepositoryOrdering(enum.Enum):
4141
NAME = "name"
4242

4343

44-
class AccountOrganizationOrdering(enum.Enum):
45-
NAME = "username"
46-
ACTIVATED_USERS = "plan_activated_users"
47-
48-
4944
class OrderingDirection(enum.Enum):
5045
ASC = "ascending"
5146
DESC = "descending"

graphql_api/types/owner/owner.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@
3131
build_connection_graphql,
3232
queryset_to_connection,
3333
)
34-
from graphql_api.helpers.mutation import require_part_of_org
34+
from graphql_api.helpers.mutation import (
35+
require_part_of_org,
36+
require_shared_account_or_part_of_org,
37+
)
3538
from graphql_api.types.enums import OrderingDirection, RepositoryOrdering
3639
from graphql_api.types.errors.errors import NotFoundError, OwnerNotActivatedError
3740
from plan.constants import FREE_PLAN_REPRESENTATIONS, PlanData, PlanName
@@ -389,6 +392,6 @@ def resolve_upload_token_required(
389392

390393
@owner_bindable.field("activatedUserCount")
391394
@sync_to_async
392-
@require_part_of_org
395+
@require_shared_account_or_part_of_org
393396
def resolve_activated_user_count(owner: Owner, info: GraphQLResolveInfo) -> int:
394397
return owner.activated_user_count

0 commit comments

Comments
 (0)