Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 22 additions & 20 deletions backend/apps/github/api/internal/nodes/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,45 +52,47 @@ def created_at(self, root: User) -> float:
"""Resolve created at."""
return root.idx_created_at

@strawberry_django.field
@strawberry_django.field(select_related=["owasp_profile"])
def first_owasp_contribution_at(self, root: User) -> float | None:
"""Resolve first OWASP contribution date."""
if hasattr(root, "owasp_profile") and root.owasp_profile.first_contribution_at:
return root.owasp_profile.first_contribution_at.timestamp()
return None
return (
root.owasp_profile.first_contribution_at.timestamp()
if hasattr(root, "owasp_profile") and root.owasp_profile.first_contribution_at
else None
)

@strawberry_django.field
@strawberry_django.field(select_related=["owasp_profile"])
def is_owasp_board_member(self, root: User) -> bool:
"""Resolve if member is currently on OWASP Board of Directors."""
if hasattr(root, "owasp_profile"):
return root.owasp_profile.is_owasp_board_member
return False
return (
root.owasp_profile.is_owasp_board_member if hasattr(root, "owasp_profile") else False
)

@strawberry_django.field
@strawberry_django.field(select_related=["owasp_profile"])
def is_former_owasp_staff(self, root: User) -> bool:
"""Resolve if member is a former OWASP staff member."""
if hasattr(root, "owasp_profile"):
return root.owasp_profile.is_former_owasp_staff
return False
return (
root.owasp_profile.is_former_owasp_staff if hasattr(root, "owasp_profile") else False
)

@strawberry_django.field
@strawberry_django.field(select_related=["owasp_profile"])
def is_gsoc_mentor(self, root: User) -> bool:
"""Resolve if member is a Google Summer of Code mentor."""
if hasattr(root, "owasp_profile"):
return root.owasp_profile.is_gsoc_mentor
return False
return root.owasp_profile.is_gsoc_mentor if hasattr(root, "owasp_profile") else False

@strawberry_django.field
def issues_count(self, root: User) -> int:
"""Resolve issues count."""
return root.idx_issues_count

@strawberry_django.field
@strawberry_django.field(select_related=["owasp_profile"])
def linkedin_page_id(self, root: User) -> str:
"""Resolve LinkedIn page ID."""
if hasattr(root, "owasp_profile") and root.owasp_profile.linkedin_page_id:
return root.owasp_profile.linkedin_page_id
return ""
return (
root.owasp_profile.linkedin_page_id
if hasattr(root, "owasp_profile") and root.owasp_profile.linkedin_page_id
else ""
)

@strawberry_django.field
def releases_count(self, root: User) -> int:
Expand Down
23 changes: 1 addition & 22 deletions backend/apps/github/api/internal/queries/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,7 @@
class IssueQuery:
"""GraphQL query class for retrieving GitHub issues."""

@strawberry_django.field(
select_related=[
"author__owasp_profile",
"author__user_badges__badge",
"level",
"milestone__author__owasp_profile",
"milestone__author__user_badges__badge",
"milestone__repository__organization",
"repository__organization",
],
prefetch_related=[
"assignees__owasp_profile",
"assignees__user_badges__badge",
"labels",
"participant_interests__user__user_badges",
"pull_requests__author__user_badges__badge",
"pull_requests__labels",
"pull_requests__milestone__author__user_badges",
"pull_requests__milestone__repository__organization",
"pull_requests__repository__organization",
],
)
@strawberry_django.field
def recent_issues(
self,
*,
Expand Down
10 changes: 1 addition & 9 deletions backend/apps/github/api/internal/queries/milestone.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,7 @@ class MilestoneStateEnum(str, enum.Enum):
class MilestoneQuery:
"""Github Milestone Queries."""

@strawberry_django.field(
select_related=["author__owasp_profile", "repository__organization"],
prefetch_related=[
"issues__author__user_badges__badge",
"labels",
"pull_requests__repository__organization",
"pull_requests__author__user_badges__badge",
],
)
@strawberry_django.field
def recent_milestones(
self,
*,
Expand Down
21 changes: 1 addition & 20 deletions backend/apps/github/api/internal/queries/pull_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,7 @@
class PullRequestQuery:
"""Pull request queries."""

@strawberry_django.field(
select_related=[
"author__owasp_profile",
"author__user_badges__badge",
"milestone__author__owasp_profile",
"milestone__author__user_badges__badge",
"repository__organization",
"milestone__repository__organization",
],
prefetch_related=[
"assignees__owasp_profile",
"assignees__user_badges__badge",
"labels",
"related_issues__repository__organization",
"related_issues__assignees__user_badges__badge",
"related_issues__labels",
"related_issues__milestone__author",
"related_issues__level",
],
)
@strawberry_django.field
def recent_pull_requests(
self,
*,
Expand Down
8 changes: 1 addition & 7 deletions backend/apps/github/api/internal/queries/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@
class ReleaseQuery:
"""GraphQL query class for retrieving recent GitHub releases."""

@strawberry_django.field(
select_related=[
"author__owasp_profile",
"author__user_badges__badge",
"repository__organization",
]
)
@strawberry_django.field
def recent_releases(
self,
*,
Expand Down
4 changes: 1 addition & 3 deletions backend/apps/github/api/internal/queries/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ def repository(
except Repository.DoesNotExist:
return None

@strawberry_django.field(
select_related=["organization", "owner__owasp_profile", "owner__user_badges__badge"],
)
@strawberry_django.field
def repositories(
self,
organization: str,
Expand Down
4 changes: 1 addition & 3 deletions backend/apps/github/api/internal/queries/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ def top_contributed_repositories(
.order_by("-contributions_count")
]

@strawberry_django.field(
select_related=["owasp_profile"], prefetch_related=["user_badges__badge"]
)
@strawberry_django.field
def user(
self,
login: str,
Expand Down
2 changes: 1 addition & 1 deletion backend/apps/owasp/api/internal/nodes/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
class GenericEntityNode(strawberry.relay.Node):
"""Base node class for OWASP entities with common fields and resolvers."""

@strawberry_django.field
@strawberry_django.field(prefetch_related=["entity_members__member"])
def entity_leaders(self, root) -> list[EntityMemberNode]:
"""Resolve entity leaders."""
return root.entity_leaders
Expand Down
13 changes: 1 addition & 12 deletions backend/apps/owasp/api/internal/queries/chapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,7 @@ def chapter(self, key: str) -> ChapterNode | None:
except Chapter.DoesNotExist:
return None

@strawberry_django.field(
select_related=[
"owasp_repository__organization",
"owasp_repository__owner__owasp_profile",
],
prefetch_related=[
"leaders__user_badges__badge",
"suggested_leaders__user_badges__badge",
"members__user_badges__badge",
"entity_leaders__member__user_badges__badge",
],
)
@strawberry_django.field
def recent_chapters(self, limit: int = 8) -> list[ChapterNode]:
"""Resolve recent chapters."""
return (
Expand Down
5 changes: 1 addition & 4 deletions backend/apps/owasp/api/internal/queries/member_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,7 @@ def member_snapshot(
except User.DoesNotExist:
return None

@strawberry_django.field(
select_related=["github_user__owasp_profile", "github_user__user_badges__badge"],
prefetch_related=["issues", "pull_requests", "messages"],
)
@strawberry_django.field
def member_snapshots(
self, user_login: str | None = None, limit: int = 10
) -> list[MemberSnapshotNode]:
Expand Down
28 changes: 2 additions & 26 deletions backend/apps/owasp/api/internal/queries/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,7 @@ def project(self, key: str) -> ProjectNode | None:
except Project.DoesNotExist:
return None

@strawberry_django.field(
select_related=[
"owasp_repository__organization",
"owasp_repository__owner__owasp_profile",
"owasp_repository__owner__user_badges__badge",
],
prefetch_related=[
"organizations",
"owners",
"repositories__organization",
"entity_leaders__member",
],
)
@strawberry_django.field
def recent_projects(self, limit: int = 8) -> list[ProjectNode]:
"""Resolve recent projects.

Expand All @@ -63,19 +51,7 @@ def recent_projects(self, limit: int = 8) -> list[ProjectNode]:
else []
)

@strawberry_django.field(
select_related=[
"owasp_repository__organization",
"owasp_repository__owner__owasp_profile",
"owasp_repository__owner__user_badges__badge",
],
prefetch_related=[
"entity_leaders__member",
"organizations",
"owners",
"repositories__organization",
],
)
@strawberry_django.field
def search_projects(self, query: str) -> list[ProjectNode]:
"""Search active projects by name (case-insensitive, partial match)."""
cleaned_query = query.strip()
Expand Down
10 changes: 1 addition & 9 deletions backend/apps/owasp/api/internal/queries/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,7 @@ def snapshot(self, key: str) -> SnapshotNode | None:
except Snapshot.DoesNotExist:
return None

@strawberry_django.field(
prefetch_related=[
"new_chapters",
"new_issues",
"new_projects",
"new_releases",
"new_users",
],
)
@strawberry_django.field
def snapshots(self, limit: int = 12) -> list[SnapshotNode]:
"""Resolve snapshots."""
return (
Expand Down
21 changes: 10 additions & 11 deletions backend/apps/owasp/models/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from urllib.parse import urlparse

import yaml
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models

Expand Down Expand Up @@ -90,20 +91,18 @@ class Meta:
blank=True,
)

# GRs.
entity_members = GenericRelation(
EntityMember,
content_type_field="entity_type",
object_id_field="entity_id",
related_query_name="entity",
)

@cached_property
def entity_leaders(self) -> list[EntityMember]:
"""Return entity's leaders."""
return list(
EntityMember.objects.filter(
entity_id=self.id,
entity_type=ContentType.objects.get_for_model(self.__class__),
is_active=True,
is_reviewed=True,
role=EntityMember.Role.LEADER,
)
.select_related("member")
.order_by("order")
)
return self.entity_members.filter(role=EntityMember.Role.LEADER).order_by("order")

@property
def github_url(self) -> str:
Expand Down
2 changes: 1 addition & 1 deletion backend/tests/apps/owasp/api/internal/nodes/common_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def test_entity_leaders_resolver(self):
mock_entity = Mock()
mock_entity.entity_leaders = [mock_leader1, mock_leader2]

result = GenericEntityNode.entity_leaders(None, mock_entity)
result = GenericEntityNode().entity_leaders(mock_entity)

assert result == [mock_leader1, mock_leader2]

Expand Down
Loading