-
-
Notifications
You must be signed in to change notification settings - Fork 250
Update owasp app event model with calendar attributes and add reminder models #2128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
cf0e49e
1fbe17d
6673f32
7a81715
86cd277
b29136f
f68b281
526c74f
c2a4add
2e345a7
b986d25
bb07ef6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| # Generated by Django 5.2.4 on 2025-09-02 13:29 | ||
|
|
||
| import django.db.models.deletion | ||
| from django.db import migrations, models | ||
|
|
||
|
|
||
| class Migration(migrations.Migration): | ||
| dependencies = [ | ||
| ("nest", "0007_alter_googleaccountauthorization_options_and_more"), | ||
| ("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")), | ||
| ( | ||
| "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": "Nest Reminder", | ||
| "verbose_name_plural": "Nest Reminders", | ||
| "db_table": "nest_reminders", | ||
| }, | ||
| ), | ||
| migrations.CreateModel( | ||
ahmedxgouda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| name="ReminderSchedule", | ||
| fields=[ | ||
| ( | ||
| "id", | ||
| models.BigAutoField( | ||
| auto_created=True, primary_key=True, serialize=False, verbose_name="ID" | ||
| ), | ||
| ), | ||
| ("scheduled_time", models.DateTimeField(verbose_name="Scheduled Time")), | ||
| ( | ||
| "recurrence", | ||
| models.CharField( | ||
| choices=[ | ||
| ("once", "Once"), | ||
| ("daily", "Daily"), | ||
| ("weekly", "Weekly"), | ||
| ("monthly", "Monthly"), | ||
| ], | ||
| default="once", | ||
| max_length=50, | ||
| verbose_name="Recurrence", | ||
| ), | ||
| ), | ||
| ( | ||
| "reminder", | ||
| models.ForeignKey( | ||
| on_delete=django.db.models.deletion.CASCADE, | ||
| related_name="schedules", | ||
| to="nest.reminder", | ||
| verbose_name="Nest Reminder", | ||
| ), | ||
| ), | ||
| ], | ||
| options={ | ||
| "verbose_name": "Nest Reminder Schedule", | ||
| "verbose_name_plural": "Nest Reminder Schedules", | ||
| "db_table": "nest_reminder_schedules", | ||
| }, | ||
| ), | ||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| from .api_key import ApiKey | ||
| from .badge import Badge | ||
| from .google_account_authorization import GoogleAccountAuthorization | ||
| from .reminder import Reminder | ||
| from .reminder_schedule import ReminderSchedule | ||
| from .user import User | ||
| from .user_badge import UserBadge |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| """Nest Reminder model.""" | ||
|
|
||
| from django.db import models | ||
|
|
||
|
|
||
| class Reminder(models.Model): | ||
| """Model representing a reminder.""" | ||
|
|
||
| class Meta: | ||
| db_table = "nest_reminders" | ||
| verbose_name = "Nest Reminder" | ||
| verbose_name_plural = "Nest 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") | ||
|
|
||
| def __str__(self) -> str: | ||
| """Reminder human readable representation.""" | ||
| return f"Reminder for {self.member} in channel: {self.channel_id}: {self.message}" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| """Nest Reminder Schedule model.""" | ||
|
|
||
| from django.db import models | ||
|
|
||
|
|
||
| class ReminderSchedule(models.Model): | ||
| """Model representing a reminder schedule.""" | ||
|
|
||
| class Meta: | ||
| db_table = "nest_reminder_schedules" | ||
| verbose_name = "Nest Reminder Schedule" | ||
| verbose_name_plural = "Nest Reminder Schedules" | ||
|
|
||
| class Recurrence(models.TextChoices): | ||
| ONCE = "once", "Once" | ||
| DAILY = "daily", "Daily" | ||
| WEEKLY = "weekly", "Weekly" | ||
| MONTHLY = "monthly", "Monthly" | ||
|
|
||
| reminder = models.ForeignKey( | ||
| "nest.Reminder", | ||
| verbose_name="Nest Reminder", | ||
| on_delete=models.CASCADE, | ||
| related_name="schedules", | ||
| ) | ||
| scheduled_time = models.DateTimeField(verbose_name="Scheduled Time") | ||
| recurrence = models.CharField( | ||
| verbose_name="Recurrence", | ||
| max_length=50, | ||
| choices=Recurrence.choices, | ||
| default=Recurrence.ONCE, | ||
| ) | ||
|
|
||
| def __str__(self) -> str: | ||
| """Reminder Schedule human readable representation.""" | ||
| return f"Schedule for {self.reminder} at {self.scheduled_time} ({self.recurrence})" |
| 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", | ||
| ), | ||
| ), | ||
ahmedxgouda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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", | ||
| ), | ||
ahmedxgouda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ), | ||
| 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"), | ||
| ), | ||
| ] | ||
ahmedxgouda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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", | ||
| ), | ||
ahmedxgouda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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", | ||
| ), | ||
| ), | ||
| ] | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,23 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Generated by Django 5.2.4 on 2025-09-02 13:15 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from django.db import migrations, models | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class Migration(migrations.Migration): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dependencies = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ("owasp", "0051_remove_event_event_type_idx_remove_event_channel_id_and_more"), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| operations = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| migrations.RemoveField( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model_name="event", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name="calendar_id", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| migrations.AddField( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model_name="event", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name="google_calendar_id", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| field=models.CharField( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| blank=True, default="", max_length=1024, verbose_name="Google Calendar ID" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+11
to
+23
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Preserve data: use RenameField (then AlterField) instead of Remove/Add. Removing then re-adding drops existing values in calendar_id. Prefer a rename to keep data, followed by an AlterField for the label. - migrations.RemoveField(
- model_name="event",
- name="calendar_id",
- ),
- migrations.AddField(
- model_name="event",
- name="google_calendar_id",
- field=models.CharField(
- blank=True, default="", max_length=1024, verbose_name="Google Calendar ID"
- ),
- ),
+ migrations.RenameField(
+ model_name="event",
+ old_name="calendar_id",
+ new_name="google_calendar_id",
+ ),
+ migrations.AlterField(
+ model_name="event",
+ name="google_calendar_id",
+ field=models.CharField(
+ blank=True, default="", max_length=1024, verbose_name="Google Calendar Event ID"
+ ),
+ ),📝 Committable suggestion
Suggested change
🤖 Prompt for AI AgentsThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The old migrations are not migrated yet There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain@ahmedxgouda, thanks for the clarification! If the old migrations haven't been applied yet, you have a few cleaner options: Option 1: Modify the original migration Option 2: Squash the migrations If you choose to keep the current approach, you're right that data preservation isn't a concern since no data exists yet. The RemoveField+AddField pattern will work fine in this case. 🏁 Script executed: Length of output: 1171 Perfect! Since migrations 0049-0052 haven't been applied yet, here's the cleanest approach: Recommended: Squash the migrations This will create a single, clean migration that:
Alternative: Keep current approach Quick verification - check migration state: If none show 🏁 Script executed: Length of output: 334 🏁 Script executed: Length of output: 311 @ahmedxgouda, the sandbox environment doesn't have the Django dependencies installed, but I can still provide guidance based on your confirmation that the migrations haven't been applied yet. Since migrations 0049-0052 haven't run, you have these options: Option 1: Keep your current approach (simplest) Option 2: Squash migrations (cleanest for production) cd backend
python manage.py squashmigrations owasp 0049 0052 --name=update_event_model_calendarThis creates a single migration replacing 0049-0052, avoiding the field churn. Option 3: Manual edit (if you prefer) Recommendation: Since you've already written migration 0052 and confirmed no data exists, go ahead with your current approach. It's functionally equivalent to the alternatives and avoids additional work. The data preservation concern in my original comment only applies when migrations have been applied and contain real data. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.