diff --git a/authentication/views/social.py b/authentication/views/social.py index 9e1a2d7c4c..d1669b1b1f 100644 --- a/authentication/views/social.py +++ b/authentication/views/social.py @@ -1,6 +1,6 @@ from django.conf import settings from django.utils.module_loading import import_string -from rest_framework import serializers +from rest_framework import serializers, status from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import AllowAny from rest_framework.response import Response @@ -37,7 +37,7 @@ def social_providers_api_view(request): class SocialCodeAuth(SocialTokenOnlyAuthView): - def post(self, request, provider: str, *args, **kwargs): - # TODO: migrate social relations + def respond_error(self, error): + response = super().respond_error(error) - return super().post(request, provider, *args, **kwargs) + return Response({"detail": response.data}, status=status.HTTP_400_BAD_REQUEST) diff --git a/front_end/src/app/(main)/accounts/social/[provider]/actions.ts b/front_end/src/app/(main)/accounts/social/[provider]/actions.ts new file mode 100644 index 0000000000..aa27529957 --- /dev/null +++ b/front_end/src/app/(main)/accounts/social/[provider]/actions.ts @@ -0,0 +1,20 @@ +"use server"; + +import AuthApi from "@/services/auth"; +import { setServerSession } from "@/services/session"; +import { SocialProviderType } from "@/types/auth"; + +export async function exchangeSocialOauthCode( + provider: SocialProviderType, + code: string +) { + const response = await AuthApi.exchangeSocialOauthCode( + provider, + code, + `${process.env.APP_URL}/accounts/social/${provider}` + ); + + if (response?.token) { + setServerSession(response.token); + } +} diff --git a/front_end/src/app/(main)/accounts/social/[provider]/page.tsx b/front_end/src/app/(main)/accounts/social/[provider]/page.tsx new file mode 100644 index 0000000000..532b2d8152 --- /dev/null +++ b/front_end/src/app/(main)/accounts/social/[provider]/page.tsx @@ -0,0 +1,37 @@ +"use client"; + +import { useRouter } from "next/navigation"; +import React, { useEffect, useState } from "react"; + +import { exchangeSocialOauthCode } from "@/app/(main)/accounts/social/[provider]/actions"; +import GlobalErrorBoundary from "@/components/global_error_boundary"; +import LoadingIndicator from "@/components/ui/loading_indicator"; +import { SocialProviderType } from "@/types/auth"; +import { SearchParams } from "@/types/navigation"; + +export default function SocialAuth({ + params: { provider }, + searchParams, +}: { + params: { provider: SocialProviderType }; + searchParams: SearchParams; +}) { + const [error, setError] = useState(); + const router = useRouter(); + + useEffect(() => { + exchangeSocialOauthCode(provider, searchParams.code as string) + .then(() => router.push("/")) + .catch(setError); + }, [provider, searchParams.code, router]); + + if (error) { + return router.push("/")} />; + } + + return ( +
+ +
+ ); +} diff --git a/front_end/src/app/(main)/accounts/social/[provider]/route.ts b/front_end/src/app/(main)/accounts/social/[provider]/route.ts deleted file mode 100644 index f50683a5c8..0000000000 --- a/front_end/src/app/(main)/accounts/social/[provider]/route.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { redirect } from "next/navigation"; - -import AuthApi from "@/services/auth"; -import { setServerSession } from "@/services/session"; -import { SocialProviderType } from "@/types/auth"; - -export async function GET( - request: Request, - { params }: { params: { provider: SocialProviderType } } -) { - const url = new URL(request.url); - const search_params = Object.fromEntries(url.searchParams.entries()); - - if (search_params.code) { - const response = await AuthApi.exchangeSocialOauthCode( - params.provider, - search_params.code, - `${process.env.APP_URL}${url.pathname}` - ); - - if (response?.token) { - setServerSession(response.token); - } - } - - return redirect("/"); -} diff --git a/front_end/src/services/auth.ts b/front_end/src/services/auth.ts index 82799195f3..e50b727473 100644 --- a/front_end/src/services/auth.ts +++ b/front_end/src/services/auth.ts @@ -29,18 +29,13 @@ class AuthApi { code: string, redirect_uri: string ): Promise { - try { - return await post< - SocialAuthResponse, - { code: string; redirect_uri: string } - >(`/auth/social/${provider}/`, { + return post( + `/auth/social/${provider}/`, + { code, redirect_uri, - }); - } catch (err) { - console.error("Error getting social providers:", err); - return null; - } + } + ); } static async signIn(login: string, password: string) { diff --git a/metaculus_web/settings.py b/metaculus_web/settings.py index ea50bcb250..3cc25ba012 100644 --- a/metaculus_web/settings.py +++ b/metaculus_web/settings.py @@ -202,6 +202,7 @@ # Google SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = os.environ.get("SOCIAL_AUTH_GOOGLE_OAUTH2_KEY") SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.environ.get("SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET") +REST_SOCIAL_VERBOSE_ERRORS=True # Email configuration # https://anymail.dev/