-
Notifications
You must be signed in to change notification settings - Fork 6
Description
calendar access migration - implementation checklist
overview
migrate myhebrewdates.com from public calendar urls to authenticated user-based subscriptions for enhanced security and user-specific features.
current: myhebrewdates.com/calendars/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d.ics (78 chars)
new: myhebrewdates.com/c/tjqfbixfh3b.ics (43 chars - 35 chars shorter!)
implementation status
✅ phase 1: core infrastructure (completed)
database models
- install
shortuuidpackage (v1.0.13) - create
usercalendarsubscriptionmodel- 11-character short uuid (
subscription_id) - user and calendar foreign keys
-
alarm_timefield (default: 9) -
last_accessedtimestamp - unique constraint on (user, calendar)
- 11-character short uuid (
- update
calendarmodel- add
migrated_attimestamp field - add
subscribersm2m relationship (through usercalendarsubscription) - add
is_migratedproperty - add
migrate_to_authenticated()method
- add
- create migrations
- initial subscription models migration
- add alarm_time field migration
- add calendar subscribers m2m migration
- data migration for existing owner subscriptions
url routing
- add top-level subscription route:
/c/<subscription_id>.ics - add
/calendars/<uuid>/subscribe/endpoint - add htmx alarm update endpoint:
/update-subscription-alarm-htmx/<subscription_id>/
views
-
calendar_subscription_file- serve .ics using subscription_id (uses db alarm_time) -
calendar_subscribe_view- quick subscribe redirect (handles auth via allauth) -
update_subscription_alarm_htmx- update alarm preference via htmx - update
calendar_file- check migration status, return 410 if migrated - update
calendar_detail_view- auto-create subscriptions for authenticated users - update
create_calendar_view- auto-create owner subscription on calendar creation - update
calendar_list_view- show owned + subscribed calendars
templates
-
_calendar_subscribe_links.html- reusable subscription links (apple, google, office365, outlook) -
_calendar_links_htmx.html- htmx wrapper for legacy calendar alarm updates -
calendar_migration_required.html- 410 gone page for migrated calendars - update
calendar_detail.html- show alarm selector for migrated calendars - update
calendar_list.html- conditional subscribed calendars section
admin
-
usercalendarsubscriptionadmin- list display with alarm_time, filters - update
calendaradmin- show migration status, subscription count - admin action: "enable migration" (sets migrated_at, creates owner subscription)
- admin action: "send migration email" (placeholder for future implementation)
📋 phase 2: testing & validation (todo)
unit tests
- usercalendarsubscription model creation with alarm_time
- 11-character subscription_id uniqueness
- alarm time defaults to 9
-
get_calendar_url()returns url without alarm parameter -
calendar_subscription_fileuses subscription.alarm_time from db -
update_subscription_alarm_htmxupdates alarm without changing url - auto-subscription creation on calendar creation
- auto-subscription creation on calendar view (authenticated users)
- legacy calendar_file blocks migrated calendars (410 response)
integration tests
- full subscribe flow: visit url → login redirect → subscription created
- calendar file generation via subscription_id
- alarm time update doesn't change subscription url
- legacy url returns 410 after migration
- reusable template works for both migrated and non-migrated
- admin migration action creates subscriptions
manual testing
- create calendar → verify owner subscription auto-created
- view calendar as authenticated user → verify subscription auto-created
- subscribe to calendar via new flow
- change alarm time → verify url stays the same
- test apple calendar subscription with new url
- test google calendar subscription with new url
- verify subscription url is 35 characters shorter
- test migration required page (410 response)
- test calendar list shows subscribed calendars section
🚀 phase 3: rollout strategy (todo)
week 1-2: deploy & verify
- deploy all changes to production
- run migrations
- verify all calendars remain unmigrated (migrated_at=null)
- test with internal accounts
- verify subscriptions auto-created on calendar creation
- verify subscriptions auto-created when users view calendars
week 3: pilot migration (5-10 calendars)
- select pilot calendars (internal/test users)
- enable migration via admin action
- notify users via email (using placeholder function)
- monitor logs for migration page visits
- gather user feedback
week 4-8: gradual rollout
- week 4: migrate 10% of calendars
- week 5: migrate 25% of calendars
- week 6: migrate 50% of calendars
- week 7: migrate 75% of calendars
- week 8: migrate 100% of calendars
monitoring metrics:
- subscription creation rate
- migration page visits
- support tickets
- user feedback
week 9+: completion
- all calendars migrated
- legacy urls return 410 gone
- monitor stragglers
- document lessons learned
📧 phase 4: email notifications (todo)
- implement
send_migration_notification_email()function - create email template for migration notification
- create email template for migration success
- test email sending with real addresses
- update admin action to send actual emails
key features
alarm time management
✅ database-driven - alarm preference stored on usercalendarsubscription
✅ stable urls - subscription url never changes when alarm is updated
✅ htmx updates - live alarm changes without page reload
✅ user flexibility - change alarm anytime without resubscribing
auto-subscription creation
✅ on calendar creation - owner subscription created automatically
✅ on calendar view - authenticated viewers get subscriptions
✅ pre-migration - subscriptions ready before migration happens
✅ idempotent - get_or_create prevents duplicates
security & privacy
✅ authenticated access - migrated calendars require login
✅ per-user urls - each subscriber gets unique subscription_id
✅ short urls - 11-character ids like youtube (vs 36-char uuids)
✅ backwards compatible - legacy urls work until migration
technical notes
url comparison
legacy: https://myhebrewdates.com/calendars/a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d.ics (78 chars)
new: https://myhebrewdates.com/c/tjqfbixfh3b.ics (43 chars)
savings: 35 characters shorter!
subscription id security
- 11 characters from base57 alphabet
- ~10^19 combinations (extremely low collision risk)
- django-enforced uniqueness at database level
- similar to youtube video ids (familiar ux)
migration states
-
not migrated (
migrated_at = null)- legacy url works:
/calendars/<uuid>.ics - subscription url available but not required
- htmx updates change url with alarm parameter
- legacy url works:
-
migrated (
migrated_at != null)- legacy url returns 410 gone
- only subscription urls work:
/c/<subscription_id>.ics - alarm from db, url stays stable
reference
implementation files:
- models:
my_hebrew_dates/hebcal/models.py - views:
my_hebrew_dates/hebcal/views.py - urls:
my_hebrew_dates/hebcal/urls.py+config/urls.py - templates:
my_hebrew_dates/templates/hebcal/ - admin:
my_hebrew_dates/hebcal/admin.py - migrations:
my_hebrew_dates/hebcal/migrations/