Skip to content

Commit 2a04662

Browse files
Dhirajsharma2060arkid15rrasesh-herekasyaaddresskrish
authored
Feature/daily badge sync job 1763 (#2047)
* test: add unit tests for SortBy component * test: update SortBy component tests for prop naming and accessibility * test: import React in SortBy component tests for consistency * made some chnages * test: update SortBy component tests for improved accessibility and clarity * test: ensure order toggle button functionality in SortBy component tests * feat: add has_full_name filter to top contributors query and model * fix: update regex for user name filtering in RepositoryContributor queryset * Update code * test: enhance RepositoryContributor tests with full name filter validations * refactor: use class constants for regex pattern and mock data in RepositoryContributor tests * test: fix regex filter call in has_full_name filter validation * Update code * Update tests * Update code * Update tests * Update test * feat: periodic job to sync OWASP Employee badges (#1762) * fix: optimize badge assignment logic and improve test coverage for sync_user_badges command * refactor: clean up comments in sync_user_badges test cases for clarity * refactor: remove unused mock_badge fixture from sync_user_badges test * feat: add management command to sync OWASP Staff badges and corresponding tests * refactor: optimize badge assignment logic for OWASP Staff badge sync * Update code * feat: add badges field to User model and update badge sync logic for OWASP staff feat:add badges field to User model and updated badge sync logic OWASP staff * feat: add badges field to User model and update related tests for badge synchronization * test: ensure no badge operations are performed when no employees are eligible * test: enhance user filter logic and improve badge assignment messages in tests suggested by coderabbit * test: refine user filter logic for badge assignment and enhance handling of keyword and positional arguments * test: refactor user filter logic in badge assignment tests for improved clarity and functionality * test: simplify user filter logic in badge assignment tests for improved readability and maintainability * test: simplify user filter logic by extracting helper functions for improved clarity and maintainability * test: update patch paths for badge and user objects in sync_user_badges tests for consistency * Update code * test: update patch paths for badge and user objects in TestSyncUserBadgesCommand for consistency * Fix #1912: Added test for SecondaryCard component (#2069) * Fix #1912: Added test for SecondaryCard component * Added newline at end of SecondaryCard.test.tsx * Fix make check --------- Co-authored-by: Kate Golovanova <[email protected]> * test: add unit tests for GeneralCompliantComponent (#2018) * test: add unit tests for GeneralCompliantComponent * fix(#1835): Refactor tests based on reviewer feedback * Fix make check and revert unnecessary changes * Fix issues --------- Co-authored-by: Kate Golovanova <[email protected]> * Added Light Theme Support for Contribution HeatMap (#2072) * Added Light Theme Support for Contribution HeatMap * Added Light Theme Support for Contribution HeatMap (Updated) * Added Light Theme Support for Contribution HeatMap (Updated) * Update color scheme for the heatmap * Update code --------- Co-authored-by: Kate Golovanova <[email protected]> Co-authored-by: Arkadii Yakovets <[email protected]> Co-authored-by: Arkadii Yakovets <[email protected]> * feat: add comprehensive unit tests for DisplayIcon component (#2048) * feat: add comprehensive unit tests for DisplayIcon component - 30+ test cases covering rendering, props, edge cases, and accessibility - Mock all dependencies and ensure SonarQube compliance - Test both snake_case and camelCase property conventions * Fixed issues flagged by the bot * Fixed issues flagged by the bot * Fixed issues flagged by the bot and added unhover word in cspell/custom-dict.txt --------- Co-authored-by: Kate Golovanova <[email protected]> * enhance:change-hover-color-action-button (#1978) * enhance:change-hover-color-action-button * Update colors and tests * Add comprehensive hover state check --------- Co-authored-by: Kate <[email protected]> * Test: add unit tests for BarChart component #1801 (#1904) * Add unit tests for BarChart component - Added comprehensive test cases for BarChart component - Tests cover rendering, data handling, and prop validation - Follows project testing standards * Add unit tests for BarChart component * Add unit tests for BarChart component * Fix linting issues * Fixed unit tests for BarChart component * Fixed unit tests for BarChart component By CodeRabbit * Fixed unit tests for BarChart component By CodeRabbit * Fix tests and make check issues * Fixed unit tests for BarChart component * Fix issues and add more tests --------- Co-authored-by: Kate Golovanova <[email protected]> * Project Dasbored Drop Down Test case has been made (#2052) * Project Dasbored Drop Down Test case has been made * Changes made * Made the changes for the code check and test cases * Changes has been made so that it works with eslint * Fix make check issues --------- Co-authored-by: Kate Golovanova <[email protected]> * fix: update command references in badge management tests * Update code * fix: update badge management command to correctly filter users by badge relationship * style: format code for better readability in badge assignment logic * fix: update badge assignment logic to use UserBadge model and remove unnecessary user management calls * fix: include owasp Makefile in backend Makefile * fix: improve badge removal logic for non-OWASP employees * fix: add unique constraint for user and badge in UserBadge model * Update code * Revert volumes * feat: add is_active field to UserBadge model and update badge assignment logic * style: format migration file for userbadge is_active field * test: mock return value for UserBadge get_or_create in badge sync tests * fix: correct docstring for nest_update_badges management command tests * Update code --------- Co-authored-by: Arkadii Yakovets <[email protected]> Co-authored-by: Arkadii Yakovets <[email protected]> Co-authored-by: rasesh <[email protected]> Co-authored-by: Kate Golovanova <[email protected]> Co-authored-by: Karmjeet Chauhan <[email protected]> Co-authored-by: Abhay Bahuguna <[email protected]> Co-authored-by: Rizwaan Ansari <[email protected]> Co-authored-by: Vijesh Shetty <[email protected]> Co-authored-by: Mohd Waqar Ahemed <[email protected]> Co-authored-by: SOHAMPAL23 <[email protected]>
1 parent 6009980 commit 2a04662

File tree

15 files changed

+480
-3
lines changed

15 files changed

+480
-3
lines changed

backend/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
include backend/apps/ai/Makefile
22
include backend/apps/github/Makefile
3+
include backend/apps/nest/Makefile
34
include backend/apps/owasp/Makefile
45
include backend/apps/slack/Makefile
56

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Generated by Django 5.2.5 on 2025-08-16 02:30
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
dependencies = [
8+
("github", "0034_merge_20250804_1817"),
9+
]
10+
11+
operations = [
12+
migrations.AlterField(
13+
model_name="user",
14+
name="bio",
15+
field=models.TextField(blank=True, default="", max_length=1000, verbose_name="Bio"),
16+
),
17+
migrations.AlterField(
18+
model_name="user",
19+
name="is_owasp_staff",
20+
field=models.BooleanField(
21+
default=False,
22+
help_text="Indicates if the user is OWASP Foundation staff.",
23+
verbose_name="Is OWASP Staff",
24+
),
25+
),
26+
]

backend/apps/github/models/user.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class Meta:
2727
]
2828
verbose_name_plural = "Users"
2929

30-
bio = models.TextField(verbose_name="Bio", max_length=1000, default="")
30+
bio = models.TextField(verbose_name="Bio", max_length=1000, blank=True, default="")
3131
is_hireable = models.BooleanField(verbose_name="Is hireable", default=False)
3232
twitter_username = models.CharField(
3333
verbose_name="Twitter username", max_length=50, default="", blank=True
@@ -37,8 +37,8 @@ class Meta:
3737

3838
is_owasp_staff = models.BooleanField(
3939
default=False,
40-
verbose_name="OWASP Staff",
41-
help_text="Indicates if the user is an OWASP staff member.",
40+
verbose_name="Is OWASP Staff",
41+
help_text="Indicates if the user is OWASP Foundation staff.",
4242
)
4343

4444
contributions_count = models.PositiveIntegerField(

backend/apps/nest/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
nest-update-badges:
2+
@echo "Updating Nest user badges"
3+
@CMD="python manage.py nest_update_badges" $(MAKE) exec-backend-command

backend/apps/nest/admin/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
from .api_key import ApiKeyAdmin
44
from .badge import BadgeAdmin
55
from .user import UserAdmin
6+
from .user_badge import UserBadgeAdmin

backend/apps/nest/admin/user_badge.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""Admin configuration for the user badge model in the OWASP app."""
2+
3+
from django.contrib import admin
4+
5+
from apps.nest.models.user_badge import UserBadge
6+
7+
8+
class UserBadgeAdmin(admin.ModelAdmin):
9+
"""Admin for UserBadge model."""
10+
11+
autocomplete_fields = (
12+
"badge",
13+
"user",
14+
)
15+
list_display = (
16+
"user",
17+
"badge",
18+
"note",
19+
"nest_created_at",
20+
"nest_updated_at",
21+
)
22+
list_filter = ("is_active", "badge__name")
23+
readonly_fields = (
24+
"nest_created_at",
25+
"nest_updated_at",
26+
)
27+
search_fields = (
28+
"badge__name",
29+
"note",
30+
"user__login",
31+
"user__name",
32+
)
33+
34+
35+
admin.site.register(UserBadge, UserBadgeAdmin)

backend/apps/nest/management/__init__.py

Whitespace-only changes.

backend/apps/nest/management/commands/__init__.py

Whitespace-only changes.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""Management command to sync badges for users based on their roles/attributes."""
2+
3+
import logging
4+
5+
from django.core.management.base import BaseCommand
6+
7+
from apps.github.models.user import User
8+
from apps.nest.models.badge import Badge
9+
from apps.nest.models.user_badge import UserBadge
10+
11+
logger = logging.getLogger(__name__)
12+
13+
OWASP_STAFF_BADGE_NAME = "OWASP Staff"
14+
15+
16+
class Command(BaseCommand):
17+
"""Sync badges for users based on their roles and attributes."""
18+
19+
help = "Sync badges for users based on their roles and attributes"
20+
21+
def handle(self, *args, **options):
22+
"""Execute the command."""
23+
self.stdout.write("Syncing user badges...")
24+
self.update_owasp_staff_badge()
25+
self.stdout.write(self.style.SUCCESS("User badges sync completed"))
26+
27+
def update_owasp_staff_badge(self):
28+
"""Sync OWASP Staff badge for users."""
29+
# Get or create the OWASP Staff badge
30+
badge, created = Badge.objects.get_or_create(
31+
name=OWASP_STAFF_BADGE_NAME,
32+
defaults={
33+
"description": "Official OWASP Staff",
34+
"css_class": "fa-user-shield",
35+
"weight": 100, # High weight for importance
36+
},
37+
)
38+
39+
if created:
40+
logger.info("Created '%s' badge", OWASP_STAFF_BADGE_NAME)
41+
self.stdout.write(f"Created badge: {badge.name}")
42+
43+
# Assign badge to employees who don't have it.
44+
employees_without_badge = User.objects.filter(is_owasp_staff=True).exclude(
45+
badges__badge=badge
46+
)
47+
count = employees_without_badge.count()
48+
49+
if count:
50+
for user in employees_without_badge:
51+
user_badge, created = UserBadge.objects.get_or_create(user=user, badge=badge)
52+
if not user_badge.is_active:
53+
user_badge.is_active = True
54+
user_badge.save(update_fields=["is_active"])
55+
56+
logger.info("Added '%s' badge to %s users", OWASP_STAFF_BADGE_NAME, count)
57+
self.stdout.write(f"Added badge to {count} employees")
58+
59+
# Remove badge from non-OWASP employees.
60+
non_employees = User.objects.filter(
61+
is_owasp_staff=False,
62+
badges__badge=badge,
63+
).distinct()
64+
removed_count = non_employees.count()
65+
66+
if removed_count:
67+
UserBadge.objects.filter(
68+
user_id__in=non_employees.values_list("id", flat=True),
69+
badge=badge,
70+
).update(is_active=False)
71+
72+
logger.info("Removed '%s' badge from %s users", OWASP_STAFF_BADGE_NAME, removed_count)
73+
self.stdout.write(f"Removed badge from {removed_count} non-employees")
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Generated by Django 5.2.5 on 2025-08-28 01:15
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
dependencies = [
9+
("github", "0035_alter_user_bio_alter_user_is_owasp_staff"),
10+
("nest", "0003_badge"),
11+
]
12+
13+
operations = [
14+
migrations.CreateModel(
15+
name="UserBadge",
16+
fields=[
17+
(
18+
"id",
19+
models.BigAutoField(
20+
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
21+
),
22+
),
23+
("nest_created_at", models.DateTimeField(auto_now_add=True)),
24+
("nest_updated_at", models.DateTimeField(auto_now=True)),
25+
(
26+
"is_active",
27+
models.BooleanField(
28+
default=True,
29+
help_text="Indicates if the badge assignment is active.",
30+
verbose_name="Is active",
31+
),
32+
),
33+
(
34+
"note",
35+
models.CharField(
36+
blank=True,
37+
default="",
38+
help_text="Optional note of the user badge.",
39+
max_length=255,
40+
verbose_name="Note",
41+
),
42+
),
43+
(
44+
"badge",
45+
models.ForeignKey(
46+
on_delete=django.db.models.deletion.CASCADE,
47+
related_name="users",
48+
to="nest.badge",
49+
verbose_name="Badge",
50+
),
51+
),
52+
(
53+
"user",
54+
models.ForeignKey(
55+
on_delete=django.db.models.deletion.CASCADE,
56+
related_name="badges",
57+
to="github.user",
58+
verbose_name="User",
59+
),
60+
),
61+
],
62+
options={
63+
"verbose_name_plural": "User badges",
64+
"db_table": "nest_user_badges",
65+
"unique_together": {("badge", "user")},
66+
},
67+
),
68+
]

0 commit comments

Comments
 (0)