+
Bug Bounties
{% if not bug_bounties %}
-
No bug bounties data available!
+
No bug bounties data available!
{% else %}
{% endif %}
diff --git a/website/templatetags/string_filters.py b/website/templatetags/string_filters.py
new file mode 100644
index 0000000000..e2543a88db
--- /dev/null
+++ b/website/templatetags/string_filters.py
@@ -0,0 +1,11 @@
+from django import template
+
+register = template.Library()
+
+
+@register.filter
+def split(value, arg):
+ """Split a string by the given separator."""
+ if value:
+ return value.split(arg)
+ return []
diff --git a/website/views/user.py b/website/views/user.py
index adc178e2f0..410777a1c8 100644
--- a/website/views/user.py
+++ b/website/views/user.py
@@ -58,6 +58,41 @@
logger = logging.getLogger(__name__)
+def extract_github_username(github_url):
+ """
+ Extract GitHub username from a GitHub URL for avatar display.
+
+ Args:
+ github_url (str): GitHub URL like 'https://github.com/username' or 'https://github.com/apps/dependabot'
+
+ Returns:
+ str or None: The username part of the URL, or None if invalid/empty
+ """
+ if not github_url or not isinstance(github_url, str):
+ return None
+
+ # Strip trailing slashes and whitespace
+ github_url = github_url.strip().rstrip("/")
+
+ # Validate that this is a GitHub URL
+ if not github_url.startswith(("https://github.com/", "http://github.com/")):
+ return None
+
+ # Ensure URL contains at least one slash after the domain
+ if "/" not in github_url:
+ return None
+
+ # Split on "/" and get the last segment
+ segments = github_url.split("/")
+ username = segments[-1] if segments else None
+
+ # Return username only if it's non-empty and not just domain parts
+ if username and username not in ["github.com", "www.github.com", ""]:
+ return username
+
+ return None
+
+
@receiver(user_signed_up)
def handle_user_signup(request, user, **kwargs):
referral_token = request.session.get("ref")
@@ -480,9 +515,15 @@ def get_context_data(self, *args, **kwargs):
context["leaderboard"] = self.get_leaderboard()[:10] # Limit to 10 entries
- # Pull Request Leaderboard
+ # Pull Request Leaderboard - Only show PRs from tracked repositories
pr_leaderboard = (
- GitHubIssue.objects.filter(type="pull_request", is_merged=True)
+ GitHubIssue.objects.filter(
+ type="pull_request",
+ is_merged=True,
+ repo__isnull=False, # Only include PRs from tracked repositories
+ )
+ .exclude(user_profile__isnull=True) # Exclude PRs without user profiles
+ .select_related("user_profile__user", "repo") # Optimize database queries
.values(
"user_profile__user__username",
"user_profile__user__email",
@@ -491,11 +532,19 @@ def get_context_data(self, *args, **kwargs):
.annotate(total_prs=Count("id"))
.order_by("-total_prs")[:10]
)
+ # Extract GitHub username from URL for avatar display
+ # Note: Processing in a loop is acceptable here since we're limited to top 10 entries
+ # and URL parsing cannot be done efficiently in the database
+ for leader in pr_leaderboard:
+ github_username = extract_github_username(leader.get("user_profile__github_url"))
+ if github_username:
+ leader["github_username"] = github_username
context["pr_leaderboard"] = pr_leaderboard
# Reviewed PR Leaderboard - Fixed query to properly count reviews
reviewed_pr_leaderboard = (
- GitHubReview.objects.values(
+ GitHubReview.objects.filter(reviewer__user__isnull=False)
+ .values(
"reviewer__user__username",
"reviewer__user__email",
"reviewer__github_url",
@@ -503,6 +552,13 @@ def get_context_data(self, *args, **kwargs):
.annotate(total_reviews=Count("id"))
.order_by("-total_reviews")[:10]
)
+ # Extract GitHub username from URL for avatar display
+ # Note: Processing in a loop is acceptable here since we're limited to top 10 entries
+ # and URL parsing cannot be done efficiently in the database
+ for leader in reviewed_pr_leaderboard:
+ github_username = extract_github_username(leader.get("reviewer__github_url"))
+ if github_username:
+ leader["github_username"] = github_username
context["code_review_leaderboard"] = reviewed_pr_leaderboard
# Top visitors leaderboard