Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Generated by Django 5.2.4 on 2025-08-26 00:34

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("owasp", "0048_entitymember"),
("slack", "0018_conversation_sync_messages"),
]

operations = [
migrations.AddField(
model_name="event",
name="calendar_id",
field=models.CharField(
blank=True, default="", max_length=1024, verbose_name="Calendar ID"
),
),
migrations.AddField(
model_name="event",
name="channel_id",
field=models.CharField(default="", max_length=15, verbose_name="Channel ID"),
),
migrations.AddField(
model_name="event",
name="member",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="calendar_events",
to="slack.member",
verbose_name="Slack Member",
),
),
migrations.AddField(
model_name="event",
name="status",
field=models.CharField(
choices=[
("confirmed", "Confirmed"),
("tentative", "Tentative"),
("canceled", "Canceled"),
],
default="confirmed",
max_length=11,
verbose_name="Status",
),
),
migrations.AddField(
model_name="event",
name="type",
field=models.CharField(
choices=[("calendar", "Calendar"), ("existing", "Existing")],
default="existing",
max_length=11,
verbose_name="Type",
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Generated by Django 5.2.4 on 2025-08-26 01:52

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("owasp", "0049_event_calendar_id_event_channel_id_event_member_and_more"),
("slack", "0018_conversation_sync_messages"),
]

operations = [
migrations.AlterField(
model_name="event",
name="status",
field=models.CharField(
choices=[
("confirmed", "Confirmed"),
("tentative", "Tentative"),
("cancelled", "Cancelled"),
],
default="confirmed",
max_length=11,
verbose_name="Status",
),
),
migrations.AddIndex(
model_name="event",
index=models.Index(fields=["type"], name="event_type_idx"),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Generated by Django 5.2.4 on 2025-08-28 16:19

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("owasp", "0050_alter_event_status_event_event_type_idx"),
]

operations = [
migrations.RemoveIndex(
model_name="event",
name="event_type_idx",
),
migrations.RemoveField(
model_name="event",
name="channel_id",
),
migrations.RemoveField(
model_name="event",
name="member",
),
migrations.RemoveField(
model_name="event",
name="type",
),
migrations.AlterField(
model_name="event",
name="category",
field=models.CharField(
choices=[
("appsec_days", "AppSec Days"),
("global", "Global"),
("other", "Other"),
("partner", "Partner"),
("community", "Community"),
],
default="other",
max_length=11,
verbose_name="Category",
),
),
migrations.AlterField(
model_name="event",
name="status",
field=models.CharField(
choices=[("confirmed", "Confirmed")],
default="confirmed",
max_length=11,
verbose_name="Status",
),
),
]
17 changes: 17 additions & 0 deletions backend/apps/owasp/models/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,34 @@ class Category(models.TextChoices):
GLOBAL = "global", "Global"
OTHER = "other", "Other"
PARTNER = "partner", "Partner"
COMMUNITY = "community", "Community"

class Status(models.TextChoices):
"""Event status."""

CONFIRMED = "confirmed", "Confirmed"

category = models.CharField(
verbose_name="Category",
max_length=11,
choices=Category.choices,
default=Category.OTHER,
)
# Google Calendar event entity ID
calendar_id = models.CharField(
verbose_name="Calendar ID", max_length=1024, blank=True, default=""
)
name = models.CharField(verbose_name="Name", max_length=100)
start_date = models.DateField(verbose_name="Start Date")
end_date = models.DateField(verbose_name="End Date", null=True, blank=True)
description = models.TextField(verbose_name="Description", default="", blank=True)
key = models.CharField(verbose_name="Key", max_length=100, unique=True)
status = models.CharField(
verbose_name="Status",
max_length=11,
choices=Status.choices,
default=Status.CONFIRMED,
)
summary = models.TextField(verbose_name="Summary", blank=True, default="")
suggested_location = models.CharField(
verbose_name="Suggested Location", max_length=255, blank=True, default=""
Expand All @@ -77,6 +93,7 @@ def upcoming_events():
)
.exclude(
Q(name__exact="") | Q(url__exact=""),
category=Event.Category.COMMUNITY,
)
.order_by(
"start_date",
Expand Down
46 changes: 46 additions & 0 deletions backend/apps/slack/migrations/0019_reminder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Generated by Django 5.2.4 on 2025-09-01 12:52

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("slack", "0018_conversation_sync_messages"),
]

operations = [
migrations.CreateModel(
name="Reminder",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"channel_id",
models.CharField(default="", max_length=15, verbose_name="Channel ID"),
),
("message", models.TextField(verbose_name="Reminder Message")),
("remind_at", models.DateTimeField(verbose_name="Reminder Time")),
("periodic", models.BooleanField(default=False, verbose_name="Is Periodic")),
(
"member",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="reminders",
to="slack.member",
verbose_name="Slack Member",
),
),
],
options={
"verbose_name": "Slack Reminder",
"verbose_name_plural": "Slack Reminders",
"db_table": "slack_reminders",
},
),
]
1 change: 1 addition & 0 deletions backend/apps/slack/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
from .event import Event
from .member import Member
from .message import Message
from .reminder import Reminder
from .workspace import Workspace
31 changes: 31 additions & 0 deletions backend/apps/slack/models/reminder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Slack reminder model."""

from django.db import models


class Reminder(models.Model):
"""Model representing a slack channel reminder."""

class Meta:
db_table = "slack_reminders"
verbose_name = "Slack Reminder"
verbose_name_plural = "Slack Reminders"

member = models.ForeignKey(
"slack.Member",
verbose_name="Slack Member",
on_delete=models.SET_NULL,
related_name="reminders",
null=True,
)
channel_id = models.CharField(verbose_name="Channel ID", max_length=15, default="")
message = models.TextField(verbose_name="Reminder Message")
remind_at = models.DateTimeField(verbose_name="Reminder Time")
periodic = models.BooleanField(default=False, verbose_name="Is Periodic")

def __str__(self) -> str:
"""Reminder human readable representation."""
return (
f"Reminder for {self.member} in channel: "
f"{self.channel_id}: {self.message} at {self.remind_at}"
)
41 changes: 41 additions & 0 deletions backend/tests/apps/slack/models/reminder_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Test cases for Reminder model."""

from apps.slack.models.member import Member
from apps.slack.models.reminder import Reminder


class TestReminderModel:
"""Reminder model test cases."""

def test_str_representation(self):
"""Test string representation of the Reminder model."""
member = Member(slack_user_id="U123456", username="Test User")
reminder = Reminder(
member=member,
channel_id="C123456",
message="Test reminder",
remind_at="2023-01-01T12:00:00Z",
periodic=False,
)
assert (
str(reminder)
== f"Reminder for {member} in channel: C123456: Test reminder at 2023-01-01T12:00:00Z"
)

def test_verbose_names(self):
"""Test verbose names of the Reminder model."""
reminder = Reminder(
member=Member(slack_user_id="U123456", username="Test User"),
channel_id="C123456",
message="Test reminder",
remind_at="2023-01-01T12:00:00Z",
periodic=False,
)
assert reminder._meta.verbose_name == "Slack Reminder"
assert reminder._meta.verbose_name_plural == "Slack Reminders"
assert reminder._meta.db_table == "slack_reminders"
assert reminder._meta.get_field("member").verbose_name == "Slack Member"
assert reminder._meta.get_field("channel_id").verbose_name == "Channel ID"
assert reminder._meta.get_field("message").verbose_name == "Reminder Message"
assert reminder._meta.get_field("remind_at").verbose_name == "Reminder Time"
assert reminder._meta.get_field("periodic").verbose_name == "Is Periodic"