Files
smoothschedule/smoothschedule/config/urls.py
poduck 3ab0306191 Add staff email client with WebSocket real-time updates
Implements a complete email client for platform staff members:

Backend:
- Add routing_mode field to PlatformEmailAddress (PLATFORM/STAFF)
- Create staff_email app with models for folders, emails, attachments, labels
- IMAP service for fetching emails with folder mapping
- SMTP service for sending emails with attachment support
- Celery tasks for periodic sync and full sync operations
- WebSocket consumer for real-time notifications
- Comprehensive API viewsets with filtering and actions

Frontend:
- Thunderbird-style three-pane email interface
- Multi-account support with drag-and-drop ordering
- Email composer with rich text editor
- Email viewer with thread support
- Real-time WebSocket updates for new emails and sync status
- 94 unit tests covering models, serializers, views, services, and consumers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 01:50:40 -05:00

199 lines
10 KiB
Python

from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import include
from django.urls import path
from django.views import defaults as default_views
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import TemplateView
from drf_spectacular.views import SpectacularAPIView
from drf_spectacular.views import SpectacularSwaggerView
from rest_framework.authtoken.views import obtain_auth_token
from smoothschedule.identity.users.api_views import (
login_view, current_user_view, logout_view, send_verification_email, verify_email,
hijack_acquire_view, hijack_release_view,
staff_invitations_view, cancel_invitation_view, resend_invitation_view,
invitation_details_view, accept_invitation_view, decline_invitation_view,
check_subdomain_view, signup_view, signup_setup_intent, send_customer_verification, verify_and_register_customer
)
from smoothschedule.identity.users.mfa_api_views import (
mfa_status, send_phone_verification, verify_phone, enable_sms_mfa,
setup_totp, verify_totp_setup, generate_backup_codes, backup_codes_status,
disable_mfa, mfa_login_send_code, mfa_login_verify,
list_trusted_devices, revoke_trusted_device, revoke_all_trusted_devices
)
from smoothschedule.scheduling.schedule.api_views import (
current_business_view, update_business_view,
oauth_settings_view, oauth_credentials_view,
custom_domains_view, custom_domain_detail_view,
custom_domain_verify_view, custom_domain_set_primary_view,
sandbox_status_view, sandbox_toggle_view, sandbox_reset_view
)
from smoothschedule.identity.core.email_autoconfig import (
MozillaAutoconfigView,
MicrosoftAutodiscoverView,
AppleConfigProfileView,
WellKnownAutoconfigView,
)
from smoothschedule.identity.core.api_views import (
quota_status_view,
quota_resources_view,
quota_archive_view,
quota_unarchive_view,
quota_overage_detail_view,
)
urlpatterns = [
# Django Admin, use {% url 'admin:index' %}
path(settings.ADMIN_URL, admin.site.urls),
# User management
path("users/", include("smoothschedule.identity.users.urls", namespace="users")),
path("accounts/", include("allauth.urls")),
# Django Hijack (masquerade) - for admin interface
path("hijack/", include("hijack.urls")),
# Email Autoconfiguration (for email clients)
path("mail/config-v1.1.xml", MozillaAutoconfigView.as_view(), name="autoconfig"),
path(".well-known/autoconfig/mail/config-v1.1.xml", WellKnownAutoconfigView.as_view(), name="autoconfig-wellknown"),
path("autodiscover/autodiscover.xml", MicrosoftAutodiscoverView.as_view(), name="autodiscover"),
path("Autodiscover/Autodiscover.xml", MicrosoftAutodiscoverView.as_view(), name="autodiscover-caps"),
path("email/apple-profile.mobileconfig", AppleConfigProfileView.as_view(), name="apple-config"),
# Your stuff: custom urls includes go here
# ...
# Media files
*static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT),
]
# API URLS
urlpatterns += [
# Staff Invitations API - MUST come before schedule.urls to avoid conflict with /staff/ viewset
path("staff/invitations/", staff_invitations_view, name="staff_invitations"),
path("staff/invitations/<int:invitation_id>/", cancel_invitation_view, name="cancel_invitation"),
path("staff/invitations/<int:invitation_id>/resend/", resend_invitation_view, name="resend_invitation"),
path("staff/invitations/token/<str:token>/", invitation_details_view, name="invitation_details"),
path("staff/invitations/token/<str:token>/accept/", accept_invitation_view, name="accept_invitation"),
path("staff/invitations/token/<str:token>/decline/", decline_invitation_view, name="decline_invitation"),
# Stripe Webhooks (dj-stripe built-in handler)
path("stripe/", include("djstripe.urls", namespace="djstripe")),
# Public API v1 (for third-party integrations)
path("v1/", include("smoothschedule.platform.api.urls", namespace="public_api")),
# Tenant Sites API (Site Builder & Public Page)
path("", include("smoothschedule.platform.tenant_sites.urls")),
# Schedule API (internal)
path("", include("smoothschedule.scheduling.schedule.urls")),
# Automations API
path("", include("smoothschedule.scheduling.automations.urls")),
# Analytics API
path("", include("smoothschedule.scheduling.analytics.urls")),
# Payments API
path("payments/", include("smoothschedule.commerce.payments.urls")),
# Contracts API
path("contracts/", include("smoothschedule.scheduling.contracts.urls")),
# Communication Credits API
path("communication-credits/", include("smoothschedule.communication.credits.urls", namespace="comms_credits")),
# Field Mobile API (for field employee mobile app)
path("mobile/", include("smoothschedule.communication.mobile.urls", namespace="field_mobile")),
# Tickets API
path("tickets/", include("smoothschedule.commerce.tickets.urls")),
# Notifications API
path("notifications/", include("smoothschedule.communication.notifications.urls")),
# Messaging API (broadcast messages)
path("messages/", include("smoothschedule.communication.messaging.urls")),
# Staff Email API (platform staff inbox)
path("staff-email/", include("smoothschedule.communication.staff_email.urls", namespace="staff_email")),
# Billing API
path("", include("smoothschedule.billing.api.urls", namespace="billing")),
# Platform API
path("platform/", include("smoothschedule.platform.admin.urls", namespace="platform")),
# OAuth Email Integration API
path("oauth/", include("smoothschedule.identity.core.oauth_urls", namespace="oauth")),
path("auth/oauth/", include("smoothschedule.identity.core.oauth_urls", namespace="auth_oauth")),
# Auth API
path("auth-token/", csrf_exempt(obtain_auth_token), name="obtain_auth_token"),
path("auth/signup/check-subdomain/", check_subdomain_view, name="check_subdomain"),
path("auth/signup/setup-intent/", signup_setup_intent, name="signup_setup_intent"),
path("auth/signup/", signup_view, name="signup"),
path("auth/login/", login_view, name="login"),
path("auth/me/", current_user_view, name="current_user"),
path("auth/logout/", logout_view, name="logout"),
path("auth/email/verify/send/", send_verification_email, name="send_verification_email"),
path("auth/email/verify/", verify_email, name="verify_email"),
# Customer verification for booking flow
path("auth/send-verification/", send_customer_verification, name="send_customer_verification"),
path("auth/verify-and-register/", verify_and_register_customer, name="verify_and_register_customer"),
# Hijack (masquerade) API
path("auth/hijack/acquire/", hijack_acquire_view, name="hijack_acquire"),
path("auth/hijack/release/", hijack_release_view, name="hijack_release"),
# Business API
path("business/current/", current_business_view, name="current_business"),
path("business/current/update/", update_business_view, name="update_business"),
path("business/oauth-settings/", oauth_settings_view, name="oauth_settings"),
path("business/oauth-credentials/", oauth_credentials_view, name="oauth_credentials"),
# Custom Domains API
path("business/domains/", custom_domains_view, name="custom_domains"),
path("business/domains/<int:domain_id>/", custom_domain_detail_view, name="custom_domain_detail"),
path("business/domains/<int:domain_id>/verify/", custom_domain_verify_view, name="custom_domain_verify"),
path("business/domains/<int:domain_id>/set-primary/", custom_domain_set_primary_view, name="custom_domain_set_primary"),
# Sandbox Mode API
path("sandbox/status/", sandbox_status_view, name="sandbox_status"),
path("sandbox/toggle/", sandbox_toggle_view, name="sandbox_toggle"),
path("sandbox/reset/", sandbox_reset_view, name="sandbox_reset"),
# Quota Management API
path("quota/status/", quota_status_view, name="quota_status"),
path("quota/resources/<str:quota_type>/", quota_resources_view, name="quota_resources"),
path("quota/archive/", quota_archive_view, name="quota_archive"),
path("quota/unarchive/", quota_unarchive_view, name="quota_unarchive"),
path("quota/overages/<int:overage_id>/", quota_overage_detail_view, name="quota_overage_detail"),
# MFA (Two-Factor Authentication) API
path("auth/mfa/status/", mfa_status, name="mfa_status"),
path("auth/mfa/phone/send/", send_phone_verification, name="mfa_phone_send"),
path("auth/mfa/phone/verify/", verify_phone, name="mfa_phone_verify"),
path("auth/mfa/sms/enable/", enable_sms_mfa, name="mfa_sms_enable"),
path("auth/mfa/totp/setup/", setup_totp, name="mfa_totp_setup"),
path("auth/mfa/totp/verify/", verify_totp_setup, name="mfa_totp_verify"),
path("auth/mfa/backup-codes/", generate_backup_codes, name="mfa_backup_codes"),
path("auth/mfa/backup-codes/status/", backup_codes_status, name="mfa_backup_codes_status"),
path("auth/mfa/disable/", disable_mfa, name="mfa_disable"),
path("auth/mfa/login/send/", mfa_login_send_code, name="mfa_login_send"),
path("auth/mfa/login/verify/", mfa_login_verify, name="mfa_login_verify"),
path("auth/mfa/devices/", list_trusted_devices, name="mfa_devices_list"),
path("auth/mfa/devices/<int:device_id>/", revoke_trusted_device, name="mfa_device_revoke"),
path("auth/mfa/devices/revoke-all/", revoke_all_trusted_devices, name="mfa_devices_revoke_all"),
# API Docs
path("schema/", SpectacularAPIView.as_view(), name="api-schema"),
path(
"docs/",
SpectacularSwaggerView.as_view(url_name="api-schema"),
name="api-docs",
),
]
if settings.DEBUG:
urlpatterns += [
path(
"400/",
default_views.bad_request,
kwargs={"exception": Exception("Bad Request!")},
),
path(
"403/",
default_views.permission_denied,
kwargs={"exception": Exception("Permission Denied")},
),
path(
"404/",
default_views.page_not_found,
kwargs={"exception": Exception("Page not Found")},
),
path("500/", default_views.server_error),
]
if "debug_toolbar" in settings.INSTALLED_APPS:
import debug_toolbar
urlpatterns = [
path("__debug__/", include(debug_toolbar.urls)),
*urlpatterns,
]