diff --git a/frontend/src/pages/platform/PlatformDashboard.tsx b/frontend/src/pages/platform/PlatformDashboard.tsx index 45c1f79..c237950 100644 --- a/frontend/src/pages/platform/PlatformDashboard.tsx +++ b/frontend/src/pages/platform/PlatformDashboard.tsx @@ -63,7 +63,7 @@ const PlatformDashboard: React.FC = () => { {/* MRR Chart */}

{t('platform.mrrGrowth')}

-
+
diff --git a/smoothschedule/config/settings/local.py b/smoothschedule/config/settings/local.py index 7c3a9fc..196a109 100644 --- a/smoothschedule/config/settings/local.py +++ b/smoothschedule/config/settings/local.py @@ -2,6 +2,43 @@ from .multitenancy import * # noqa from .multitenancy import env, INSTALLED_APPS, MIDDLEWARE +# ============================================================================= +# CONTENT SECURITY POLICY (CSP) +# Explicitly imported/re-defined here to ensure they are active in local dev +# ============================================================================= +CSP_DEFAULT_SRC = ("'self'",) +CSP_SCRIPT_SRC = ( + "'self'", + "https://js.stripe.com", + "https://connect-js.stripe.com", + "https://www.googletagmanager.com", + "https://www.google-analytics.com", + "blob:", # Required for Stripe +) +CSP_STYLE_SRC = ( + "'self'", + "'unsafe-inline'", # Required for Stripe and many UI libraries +) +CSP_IMG_SRC = ( + "'self'", + "data:", + "https://*.stripe.com", + "https://www.google-analytics.com", +) +CSP_CONNECT_SRC = ( + "'self'", + "https://api.stripe.com", + "https://www.google-analytics.com", + "https://stats.g.doubleclick.net", +) +CSP_FRAME_SRC = ( + "'self'", + "https://js.stripe.com", + "https://hooks.stripe.com", + "https://connect-js.stripe.com", +) + + # GENERAL # ------------------------------------------------------------------------------ # https://docs.djangoproject.com/en/dev/ref/settings/#debug diff --git a/smoothschedule/config/urls.py b/smoothschedule/config/urls.py index 528ee46..82953ab 100644 --- a/smoothschedule/config/urls.py +++ b/smoothschedule/config/urls.py @@ -10,7 +10,7 @@ from drf_spectacular.views import SpectacularAPIView from drf_spectacular.views import SpectacularSwaggerView from rest_framework.authtoken.views import obtain_auth_token -from smoothschedule.users.api_views import current_user_view +from smoothschedule.users.api_views import current_user_view, logout_view from schedule.api_views import current_business_view urlpatterns = [ @@ -36,6 +36,7 @@ urlpatterns += [ # Auth API path("api/auth-token/", csrf_exempt(obtain_auth_token), name="obtain_auth_token"), path("api/auth/me/", current_user_view, name="current_user"), + path("api/auth/logout/", logout_view, name="logout"), # Business API path("api/business/current/", current_business_view, name="current_business"), # API Docs diff --git a/smoothschedule/smoothschedule/users/api_views.py b/smoothschedule/smoothschedule/users/api_views.py index 693c0fd..aace65e 100644 --- a/smoothschedule/smoothschedule/users/api_views.py +++ b/smoothschedule/smoothschedule/users/api_views.py @@ -47,3 +47,15 @@ def current_user_view(request): } return Response(user_data, status=status.HTTP_200_OK) + + +@api_view(['POST']) +@permission_classes([IsAuthenticated]) +def logout_view(request): + """ + Logout the current user + POST /api/auth/logout/ + """ + from django.contrib.auth import logout + logout(request) + return Response({"detail": "Successfully logged out."}, status=status.HTTP_200_OK)