Skip to content

Commit

Permalink
Merge branch 'OWASP:main' into fix/redirection-of-links
Browse files Browse the repository at this point in the history
  • Loading branch information
KaranNegi20Feb authored Mar 3, 2025
2 parents 71990ac + 98af4c1 commit b2524fd
Show file tree
Hide file tree
Showing 25 changed files with 845 additions and 36 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/update-nest-test-images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ jobs:
with:
cache-from: type=registry,ref=${{ env.DOCKERHUB_USERNAME }}/owasp-nest-test-backend:cache
cache-to: type=registry,ref=${{ env.DOCKERHUB_USERNAME }}/owasp-nest-test-backend:cache,mode=max
context: frontend
file: frontend/docker/Dockerfile.test
context: backend
file: backend/docker/Dockerfile.test
platforms: linux/amd64
push: true
tags: ${{ env.DOCKERHUB_USERNAME }}/owasp-nest-test-backend:latest
Expand Down
10 changes: 8 additions & 2 deletions backend/apps/github/graphql/nodes/release.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
"""GitHub release GraphQL node."""

from graphene import Field
import graphene

from apps.common.graphql.nodes import BaseNode
from apps.github.graphql.nodes.user import UserNode
from apps.github.models.release import Release
from apps.owasp.constants import OWASP_ORGANIZATION_NAME


class ReleaseNode(BaseNode):
"""GitHub release node."""

author = Field(UserNode)
author = graphene.Field(UserNode)
project_name = graphene.String()

class Meta:
model = Release
Expand All @@ -21,3 +23,7 @@ class Meta:
"published_at",
"tag_name",
)

def resolve_project_name(self, info):
"""Return project name."""
return self.repository.project.name.lstrip(OWASP_ORGANIZATION_NAME)
3 changes: 3 additions & 0 deletions backend/apps/owasp/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class SnapshotAdmin(admin.ModelAdmin):
"new_users",
)
list_display = (
"title",
"start_at",
"end_at",
"status",
Expand All @@ -133,6 +134,8 @@ class SnapshotAdmin(admin.ModelAdmin):
)
ordering = ("-start_at",)
search_fields = (
"title",
"key",
"status",
"error_message",
)
Expand Down
57 changes: 57 additions & 0 deletions backend/apps/owasp/graphql/nodes/snapshot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""OWASP snapshot GraphQL node."""

import graphene

from apps.github.graphql.nodes.issue import IssueNode
from apps.github.graphql.nodes.release import ReleaseNode
from apps.github.graphql.nodes.user import UserNode
from apps.owasp.graphql.nodes.chapter import ChapterNode
from apps.owasp.graphql.nodes.common import GenericEntityNode
from apps.owasp.graphql.nodes.project import ProjectNode
from apps.owasp.models.snapshot import Snapshot

RECENT_ISSUES_LIMIT = 100


class SnapshotNode(GenericEntityNode):
"""Snapshot node."""

key = graphene.String()
new_chapters = graphene.List(ChapterNode)
new_issues = graphene.List(IssueNode)
new_projects = graphene.List(ProjectNode)
new_releases = graphene.List(ReleaseNode)
new_users = graphene.List(UserNode)

class Meta:
model = Snapshot
fields = (
"created_at",
"end_at",
"start_at",
"title",
)

def resolve_key(self, info):
"""Resolve key."""
return self.key

def resolve_new_chapters(self, info):
"""Resolve new chapters."""
return self.new_chapters.all()

def resolve_new_issues(self, info):
"""Resolve recent new issues."""
return self.new_issues.order_by("-created_at")[:RECENT_ISSUES_LIMIT]

def resolve_new_projects(self, info):
"""Resolve recent new projects."""
return self.new_projects.order_by("-created_at")

def resolve_new_releases(self, info):
"""Resolve recent new releases."""
return self.new_releases.order_by("-published_at")

def resolve_new_users(self, info):
"""Resolve recent new users."""
return self.new_users.order_by("-created_at")
5 changes: 4 additions & 1 deletion backend/apps/owasp/graphql/queries/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
from .committee import CommitteeQuery
from .event import EventQuery
from .project import ProjectQuery
from .snapshot import SnapshotQuery
from .stats import StatsQuery


class OwaspQuery(ChapterQuery, CommitteeQuery, EventQuery, ProjectQuery, StatsQuery):
class OwaspQuery(
ChapterQuery, CommitteeQuery, EventQuery, ProjectQuery, SnapshotQuery, StatsQuery
):
"""OWASP queries."""
32 changes: 32 additions & 0 deletions backend/apps/owasp/graphql/queries/snapshot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""OWASP snapshot GraphQL queries."""

import graphene

from apps.common.graphql.queries import BaseQuery
from apps.owasp.graphql.nodes.snapshot import SnapshotNode
from apps.owasp.models.snapshot import Snapshot


class SnapshotQuery(BaseQuery):
"""Snapshot queries."""

snapshot = graphene.Field(
SnapshotNode,
key=graphene.String(required=True),
)

recent_snapshots = graphene.List(
SnapshotNode,
limit=graphene.Int(default_value=8),
)

def resolve_snapshot(root, info, key):
"""Resolve snapshot by key."""
try:
return Snapshot.objects.get(key=key)
except Snapshot.DoesNotExist:
return None

def resolve_recent_snapshots(root, info, limit):
"""Resolve recent snapshots."""
return Snapshot.objects.order_by("-created_at")[:limit]
27 changes: 27 additions & 0 deletions backend/apps/owasp/migrations/0019_alter_event_category.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 5.1.6 on 2025-03-03 01:32

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("owasp", "0018_merge_20250302_1945"),
]

operations = [
migrations.AlterField(
model_name="event",
name="category",
field=models.CharField(
choices=[
("appsec_days", "AppSec Days"),
("global", "Global"),
("other", "Other"),
("partner", "Partner"),
],
default="other",
max_length=11,
verbose_name="Category",
),
),
]
23 changes: 23 additions & 0 deletions backend/apps/owasp/migrations/0020_snapshot_key_snapshot_title.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.1.6 on 2025-03-03 02:18

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("owasp", "0019_alter_event_category"),
]

operations = [
migrations.AddField(
model_name="snapshot",
name="key",
field=models.CharField(default="", max_length=10, unique=True),
preserve_default=False,
),
migrations.AddField(
model_name="snapshot",
name="title",
field=models.CharField(default="", max_length=255),
),
]
17 changes: 17 additions & 0 deletions backend/apps/owasp/migrations/0021_alter_snapshot_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.1.6 on 2025-03-03 02:23

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("owasp", "0020_snapshot_key_snapshot_title"),
]

operations = [
migrations.AlterField(
model_name="snapshot",
name="key",
field=models.CharField(blank=True, max_length=10, unique=True),
),
]
2 changes: 1 addition & 1 deletion backend/apps/owasp/models/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Category(models.TextChoices):

category = models.CharField(
verbose_name="Category",
max_length=20,
max_length=11,
choices=Category.choices,
default=Category.OTHER,
)
Expand Down
13 changes: 12 additions & 1 deletion backend/apps/owasp/models/snapshot.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""OWASP app snapshot models."""

from django.db import models
from django.utils.timezone import now


class Snapshot(models.Model):
Expand All @@ -16,6 +17,9 @@ class Status(models.TextChoices):
COMPLETED = "completed", "Completed"
ERROR = "error", "Error"

title = models.CharField(max_length=255, default="")
key = models.CharField(max_length=10, unique=True, blank=True)

created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

Expand All @@ -33,4 +37,11 @@ class Status(models.TextChoices):

def __str__(self):
"""Return a string representation of the snapshot."""
return f"Snapshot {self.start_at} to {self.end_at} ({self.status})"
return self.title

def save(self, *args, **kwargs):
"""Save snapshot."""
if not self.key: # automatically set the key
self.key = now().strftime("%Y-%m")

super().save(*args, **kwargs)
1 change: 1 addition & 0 deletions backend/tests/github/graphql/nodes/release_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def test_meta_configuration(self):
"author",
"is_pre_release",
"name",
"project_name",
"published_at",
"tag_name",
}
Expand Down
7 changes: 7 additions & 0 deletions backend/tests/owasp/models/snapshot_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def setUp(self):
"""Set up a mocked snapshot object."""
self.snapshot = MagicMock(spec=Snapshot) # Mock entire model
self.snapshot.id = 1 # Set an ID to avoid ManyToMany errors
self.snapshot.title = "Mock Snapshot Title"
self.snapshot.key = "2025-02"
self.snapshot.start_at = "2025-02-21"
self.snapshot.end_at = "2025-02-21"
self.snapshot.status = Snapshot.Status.PROCESSING
Expand All @@ -27,3 +29,8 @@ def test_mocked_many_to_many_relations(self):
"""Test ManyToMany relationships using mocks."""
self.snapshot.new_chapters.set(["Mock Chapter"])
self.snapshot.new_chapters.set.assert_called_once_with(["Mock Chapter"])

def test_snapshot_attributes(self):
"""Test that title and key are correctly assigned."""
assert self.snapshot.title == "Mock Snapshot Title"
assert self.snapshot.key == "2025-02"
1 change: 1 addition & 0 deletions frontend/__tests__/unit/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jest.mock('pages', () => ({
RepositoryDetailsPage: () => (
<div data-testid="repository-details-page">RepositoryDetails Page</div>
),
SnapshotDetailsPage: () => <div data-testid="snapshot-details-page">SnapshotDetails Page</div>,
UserDetailsPage: () => <div data-testid="user-details-page">UserDetails Page</div>,
UsersPage: () => <div data-testid="users-page">Users Page</div>,
}))
Expand Down
87 changes: 87 additions & 0 deletions frontend/__tests__/unit/data/mockSnapshotData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
export const mockSnapshotDetailsData = {
snapshot: {
title: 'New Snapshot',
key: '2024-12',
updatedAt: '2025-03-02T20:33:46.880330+00:00',
createdAt: '2025-03-01T22:00:34.361937+00:00',
startAt: '2024-12-01T00:00:00+00:00',
endAt: '2024-12-31T22:00:30+00:00',
status: 'completed',
errorMessage: '',
newReleases: [
{
name: 'v0.9.2',
publishedAt: '2024-12-13T14:43:46+00:00',
tagName: 'v0.9.2',
projectName: 'test-project-1',
},
{
name: 'Latest pre-release',
publishedAt: '2024-12-13T13:17:30+00:00',
tagName: 'pre-release',
projectName: 'test-project-2',
},
],
newProjects: [
{
key: 'nest',
name: 'OWASP Nest',
summary:
'OWASP Nest is a code project aimed at improving how OWASP manages its collection of projects...',
starsCount: 14,
forksCount: 19,
contributorsCount: 14,
level: 'INCUBATOR',
isActive: true,
repositoriesCount: 2,
topContributors: [
{
avatarUrl: 'https://avatars.githubusercontent.com/u/2201626?v=4',
contributionsCount: 170,
login: 'arkid15r',
name: 'Arkadii Yakovets',
},
{
avatarUrl: 'https://avatars.githubusercontent.com/u/97700473?v=4',
contributionsCount: 5,
login: 'test-user',
name: 'test user',
},
],
},
],
newChapters: [
{
key: 'sivagangai',
name: 'OWASP Sivagangai',
createdAt: '2024-07-30T10:07:33+00:00',
suggestedLocation: 'Sivagangai, Tamil Nadu, India',
region: 'Asia',
summary:
'OWASP Sivagangai is a new local chapter that focuses on AI and application security...',
topContributors: [
{
avatarUrl: 'https://avatars.githubusercontent.com/u/95969896?v=4',
contributionsCount: 14,
login: 'acs-web-tech',
name: 'P.ARUN',
},
{
avatarUrl: 'https://avatars.githubusercontent.com/u/56408064?v=4',
contributionsCount: 1,
login: 'test-user-1',
name: '',
},
],
updatedAt: 1727353371.0,
url: 'https://owasp.org/www-chapter-sivagangai',
relatedUrls: [],
geoLocation: {
lat: 9.9650599,
lng: 78.7204283237222,
},
isActive: true,
},
],
},
}
Loading

0 comments on commit b2524fd

Please sign in to comment.