Add secret management guide, client-side performance monitoring, and search accessibility enhancements

- Introduced a comprehensive Secret Management Guide detailing best practices, secret classification, development setup, production management, rotation procedures, and emergency protocols.
- Implemented a client-side performance monitoring script to track various metrics including page load performance, paint metrics, layout shifts, and memory usage.
- Enhanced search accessibility with keyboard navigation support for search results, ensuring compliance with WCAG standards and improving user experience.
This commit is contained in:
pacnpal
2025-12-23 16:41:42 -05:00
parent ae31e889d7
commit edcd8f2076
155 changed files with 22046 additions and 4645 deletions

View File

@@ -78,13 +78,20 @@ class EditSubmission(StateMachineMixin, TrackedModel):
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="edit_submissions",
help_text="User who submitted this edit",
)
# What is being edited (Park or Ride)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
content_type = models.ForeignKey(
ContentType,
on_delete=models.CASCADE,
help_text="Type of object being edited",
)
object_id = models.PositiveIntegerField(
null=True, blank=True
) # Null for new objects
null=True,
blank=True,
help_text="ID of object being edited (null for new objects)",
)
content_object = GenericForeignKey("content_type", "object_id")
# Type of submission
@@ -127,13 +134,18 @@ class EditSubmission(StateMachineMixin, TrackedModel):
null=True,
blank=True,
related_name="handled_submissions",
help_text="Moderator who handled this submission",
)
handled_at = models.DateTimeField(
null=True, blank=True, help_text="When this submission was handled"
)
handled_at = models.DateTimeField(null=True, blank=True)
notes = models.TextField(
blank=True, help_text="Notes from the moderator about this submission"
)
class Meta(TrackedModel.Meta):
verbose_name = "Edit Submission"
verbose_name_plural = "Edit Submissions"
ordering = ["-created_at"]
indexes = [
models.Index(fields=["content_type", "object_id"]),
@@ -344,14 +356,16 @@ class ModerationReport(StateMachineMixin, TrackedModel):
reported_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='moderation_reports_made'
related_name='moderation_reports_made',
help_text="User who made this report",
)
assigned_moderator = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='assigned_moderation_reports'
related_name='assigned_moderation_reports',
help_text="Moderator assigned to handle this report",
)
# Resolution
@@ -359,13 +373,21 @@ class ModerationReport(StateMachineMixin, TrackedModel):
max_length=100, blank=True, help_text="Action taken to resolve")
resolution_notes = models.TextField(
blank=True, help_text="Notes about the resolution")
resolved_at = models.DateTimeField(null=True, blank=True)
resolved_at = models.DateTimeField(
null=True, blank=True, help_text="When this report was resolved"
)
# Timestamps
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(
auto_now_add=True, help_text="When this report was created"
)
updated_at = models.DateTimeField(
auto_now=True, help_text="When this report was last updated"
)
class Meta(TrackedModel.Meta):
verbose_name = "Moderation Report"
verbose_name_plural = "Moderation Reports"
ordering = ['-created_at']
indexes = [
models.Index(fields=['status', 'priority']),
@@ -428,9 +450,12 @@ class ModerationQueue(StateMachineMixin, TrackedModel):
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='assigned_queue_items'
related_name='assigned_queue_items',
help_text="Moderator assigned to this item",
)
assigned_at = models.DateTimeField(
null=True, blank=True, help_text="When this item was assigned"
)
assigned_at = models.DateTimeField(null=True, blank=True)
estimated_review_time = models.PositiveIntegerField(
default=30, help_text="Estimated time in minutes")
@@ -440,7 +465,8 @@ class ModerationQueue(StateMachineMixin, TrackedModel):
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='flagged_queue_items'
related_name='flagged_queue_items',
help_text="User who flagged this item",
)
tags = models.JSONField(default=list, blank=True,
help_text="Tags for categorization")
@@ -451,14 +477,21 @@ class ModerationQueue(StateMachineMixin, TrackedModel):
on_delete=models.CASCADE,
null=True,
blank=True,
related_name='queue_items'
related_name='queue_items',
help_text="Related moderation report",
)
# Timestamps
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(
auto_now_add=True, help_text="When this item was created"
)
updated_at = models.DateTimeField(
auto_now=True, help_text="When this item was last updated"
)
class Meta(TrackedModel.Meta):
verbose_name = "Moderation Queue Item"
verbose_name_plural = "Moderation Queue Items"
ordering = ['priority', 'created_at']
indexes = [
models.Index(fields=['status', 'priority']),
@@ -503,12 +536,14 @@ class ModerationAction(TrackedModel):
moderator = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='moderation_actions_taken'
related_name='moderation_actions_taken',
help_text="Moderator who took this action",
)
target_user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='moderation_actions_received'
related_name='moderation_actions_received',
help_text="User this action was taken against",
)
# Related objects
@@ -517,14 +552,21 @@ class ModerationAction(TrackedModel):
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='actions_taken'
related_name='actions_taken',
help_text="Related moderation report",
)
# Timestamps
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
created_at = models.DateTimeField(
auto_now_add=True, help_text="When this action was created"
)
updated_at = models.DateTimeField(
auto_now=True, help_text="When this action was last updated"
)
class Meta(TrackedModel.Meta):
verbose_name = "Moderation Action"
verbose_name_plural = "Moderation Actions"
ordering = ['-created_at']
indexes = [
models.Index(fields=['target_user', 'is_active']),
@@ -605,16 +647,25 @@ class BulkOperation(StateMachineMixin, TrackedModel):
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='bulk_operations_created'
related_name='bulk_operations_created',
help_text="User who created this operation",
)
# Timestamps
created_at = models.DateTimeField(auto_now_add=True)
started_at = models.DateTimeField(null=True, blank=True)
completed_at = models.DateTimeField(null=True, blank=True)
updated_at = models.DateTimeField(auto_now=True)
started_at = models.DateTimeField(
null=True, blank=True, help_text="When this operation started"
)
completed_at = models.DateTimeField(
null=True, blank=True, help_text="When this operation completed"
)
updated_at = models.DateTimeField(
auto_now=True, help_text="When this operation was last updated"
)
class Meta(TrackedModel.Meta):
verbose_name = "Bulk Operation"
verbose_name_plural = "Bulk Operations"
ordering = ['-created_at']
indexes = [
models.Index(fields=['status', 'priority']),
@@ -645,11 +696,18 @@ class PhotoSubmission(StateMachineMixin, TrackedModel):
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="photo_submissions",
help_text="User who submitted this photo",
)
# What the photo is for (Park or Ride)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_type = models.ForeignKey(
ContentType,
on_delete=models.CASCADE,
help_text="Type of object this photo is for",
)
object_id = models.PositiveIntegerField(
help_text="ID of object this photo is for"
)
content_object = GenericForeignKey("content_type", "object_id")
# The photo itself
@@ -658,8 +716,10 @@ class PhotoSubmission(StateMachineMixin, TrackedModel):
on_delete=models.CASCADE,
help_text="Photo submission stored on Cloudflare Images"
)
caption = models.CharField(max_length=255, blank=True)
date_taken = models.DateField(null=True, blank=True)
caption = models.CharField(max_length=255, blank=True, help_text="Photo caption")
date_taken = models.DateField(
null=True, blank=True, help_text="Date the photo was taken"
)
# Metadata
status = RichFSMField(
@@ -677,14 +737,19 @@ class PhotoSubmission(StateMachineMixin, TrackedModel):
null=True,
blank=True,
related_name="handled_photos",
help_text="Moderator who handled this submission",
)
handled_at = models.DateTimeField(
null=True, blank=True, help_text="When this submission was handled"
)
handled_at = models.DateTimeField(null=True, blank=True)
notes = models.TextField(
blank=True,
help_text="Notes from the moderator about this photo submission",
)
class Meta(TrackedModel.Meta):
verbose_name = "Photo Submission"
verbose_name_plural = "Photo Submissions"
ordering = ["-created_at"]
indexes = [
models.Index(fields=["content_type", "object_id"]),