feat(10-02): Google Calendar OAuth endpoints and per-tenant calendar tool
- Add calendar_auth.py: OAuth install/callback/status endpoints with HMAC-signed state - Replace calendar_lookup.py service account stub with per-tenant OAuth token lookup - Support list, check_availability, and create actions with natural language responses - Token auto-refresh: write updated credentials back to channel_connections on refresh - Add migration 013: add google_calendar to channel_type CHECK constraint - Add unit tests: 16 tests covering all actions, not-connected path, token refresh write-back
This commit is contained in:
52
migrations/versions/013_google_calendar_channel.py
Normal file
52
migrations/versions/013_google_calendar_channel.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""Add google_calendar to channel_type CHECK constraint
|
||||
|
||||
Revision ID: 013
|
||||
Revises: 012
|
||||
Create Date: 2026-03-26
|
||||
|
||||
Adds 'google_calendar' to the valid channel types in channel_connections.
|
||||
This enables per-tenant Google Calendar OAuth token storage alongside
|
||||
existing Slack/WhatsApp/web connections.
|
||||
|
||||
Steps:
|
||||
1. Drop old CHECK constraint on channel_connections.channel_type
|
||||
2. Re-create it with the updated list including 'google_calendar'
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from alembic import op
|
||||
|
||||
# Alembic revision identifiers
|
||||
revision: str = "013"
|
||||
down_revision: str | None = "012"
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
# All valid channel types including 'google_calendar'
|
||||
_CHANNEL_TYPES = (
|
||||
"slack", "whatsapp", "mattermost", "rocketchat", "teams", "telegram", "signal", "web", "google_calendar"
|
||||
)
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# Drop the existing CHECK constraint (added in 008_web_chat.py as chk_channel_type)
|
||||
op.execute("ALTER TABLE channel_connections DROP CONSTRAINT IF EXISTS chk_channel_type")
|
||||
|
||||
# Re-create with the updated list
|
||||
op.execute(
|
||||
"ALTER TABLE channel_connections ADD CONSTRAINT chk_channel_type "
|
||||
f"CHECK (channel_type IN {tuple(_CHANNEL_TYPES)})"
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# Restore 008's constraint (without google_calendar)
|
||||
_PREV_TYPES = (
|
||||
"slack", "whatsapp", "mattermost", "rocketchat", "teams", "telegram", "signal", "web"
|
||||
)
|
||||
op.execute("ALTER TABLE channel_connections DROP CONSTRAINT IF EXISTS chk_channel_type")
|
||||
op.execute(
|
||||
"ALTER TABLE channel_connections ADD CONSTRAINT chk_channel_type "
|
||||
f"CHECK (channel_type IN {tuple(_PREV_TYPES)})"
|
||||
)
|
||||
Reference in New Issue
Block a user