Add OWASP compliance mapping and security test case templates, and document version control implementation phases

This commit is contained in:
pacnpal
2025-02-07 10:51:11 -05:00
parent d353f24f9d
commit 2c4d2daf34
38 changed files with 5313 additions and 94 deletions

View File

@@ -1,7 +1,10 @@
from django.db import models
from django.urls import reverse
from django.utils.text import slugify
from django.contrib.contenttypes.fields import GenericRelation
from history_tracking.models import HistoricalModel
from django.contrib.contenttypes.models import ContentType
from history_tracking.models import HistoricalModel, VersionBranch, ChangeSet
from history_tracking.signals import get_current_branch, ChangesetContextManager
# Shared choices that will be used by multiple models
@@ -42,9 +45,51 @@ class RideModel(HistoricalModel):
class Meta:
ordering = ['manufacturer', 'name']
unique_together = ['manufacturer', 'name']
def __str__(self) -> str:
return self.name if not self.manufacturer else f"{self.manufacturer.name} {self.name}"
def save(self, *args, **kwargs) -> None:
# Get the branch from context or use default
current_branch = get_current_branch()
if current_branch:
# Save in the context of the current branch
super().save(*args, **kwargs)
else:
# If no branch context, save in main branch
main_branch, _ = VersionBranch.objects.get_or_create(
name='main',
defaults={'metadata': {'type': 'default_branch'}}
)
with ChangesetContextManager(branch=main_branch):
super().save(*args, **kwargs)
def get_version_info(self) -> dict:
"""Get version control information for this ride model"""
content_type = ContentType.objects.get_for_model(self)
latest_changes = ChangeSet.objects.filter(
content_type=content_type,
object_id=self.pk,
status='applied'
).order_by('-created_at')[:5]
active_branches = VersionBranch.objects.filter(
changesets__content_type=content_type,
changesets__object_id=self.pk,
is_active=True
).distinct()
return {
'latest_changes': latest_changes,
'active_branches': active_branches,
'current_branch': get_current_branch(),
'total_changes': latest_changes.count()
}
def get_absolute_url(self) -> str:
return reverse("rides:model_detail", kwargs={"pk": self.pk})
def __str__(self) -> str:
return self.name if not self.manufacturer else f"{self.manufacturer.name} {self.name}"
class Ride(HistoricalModel):
@@ -145,7 +190,66 @@ class Ride(HistoricalModel):
def save(self, *args, **kwargs) -> None:
if not self.slug:
self.slug = slugify(self.name)
super().save(*args, **kwargs)
# Get the branch from context or use default
current_branch = get_current_branch()
if current_branch:
# Save in the context of the current branch
super().save(*args, **kwargs)
else:
# If no branch context, save in main branch
main_branch, _ = VersionBranch.objects.get_or_create(
name='main',
defaults={'metadata': {'type': 'default_branch'}}
)
with ChangesetContextManager(branch=main_branch):
super().save(*args, **kwargs)
def get_version_info(self) -> dict:
"""Get version control information for this ride"""
content_type = ContentType.objects.get_for_model(self)
latest_changes = ChangeSet.objects.filter(
content_type=content_type,
object_id=self.pk,
status='applied'
).order_by('-created_at')[:5]
active_branches = VersionBranch.objects.filter(
changesets__content_type=content_type,
changesets__object_id=self.pk,
is_active=True
).distinct()
return {
'latest_changes': latest_changes,
'active_branches': active_branches,
'current_branch': get_current_branch(),
'total_changes': latest_changes.count(),
'parent_park_branch': self.park.get_version_info()['current_branch']
}
def get_absolute_url(self) -> str:
return reverse("rides:ride_detail", kwargs={
"park_slug": self.park.slug,
"ride_slug": self.slug
})
@classmethod
def get_by_slug(cls, slug: str) -> tuple['Ride', bool]:
"""Get ride by current or historical slug"""
try:
return cls.objects.get(slug=slug), False
except cls.DoesNotExist:
# Check historical slugs
history = cls.history.filter(slug=slug).order_by("-history_date").first()
if history:
try:
return cls.objects.get(pk=history.instance.pk), True
except cls.DoesNotExist as e:
raise cls.DoesNotExist("No ride found with this slug") from e
raise cls.DoesNotExist("No ride found with this slug")
class RollerCoasterStats(models.Model):