diff --git a/authentication/views.py b/authentication/views.py index 91a8a1e91b..6b66c59d93 100644 --- a/authentication/views.py +++ b/authentication/views.py @@ -1,15 +1,13 @@ """Authentication views""" import logging -from urllib.parse import urljoin +from django.conf import settings from django.contrib.auth import logout from django.shortcuts import redirect from django.utils.http import url_has_allowed_host_and_scheme, urlencode -from django.utils.text import slugify from django.views import View -from main import settings from main.middleware.apisix_user import ApisixUserMiddleware, decode_apisix_headers log = logging.getLogger(__name__) @@ -80,6 +78,7 @@ def get( """ redirect_url = get_redirect_url(request, ["next"]) signup_redirect_url = get_redirect_url(request, ["signup_next", "next"]) + should_skip_onboarding = request.GET.get("skip_onboarding", "0") != "0" if not request.user.is_anonymous: profile = request.user.profile @@ -91,31 +90,16 @@ def get( ) if user_organizations: - # First-time login for org user: redirect to org dashboard - if not profile.has_logged_in: - first_org_name = next(iter(user_organizations.keys())) - org_slug = slugify(first_org_name) - - log.info( - "User %s belongs to organization: %s (slug: %s)", - request.user.email, - first_org_name, - org_slug, - ) - - redirect_url = urljoin( - settings.APP_BASE_URL, f"/dashboard/organization/{org_slug}" - ) - # first-time non-org users - elif not profile.has_logged_in: - if request.GET.get("skip_onboarding", "0") == "0": + should_skip_onboarding = True + + if not profile.has_logged_in: + if should_skip_onboarding: + redirect_url = signup_redirect_url + else: params = urlencode({"next": signup_redirect_url}) redirect_url = f"{settings.MITOL_NEW_USER_LOGIN_URL}?{params}" profile.save() - else: - redirect_url = signup_redirect_url - if not profile.has_logged_in: profile.has_logged_in = True profile.save() diff --git a/authentication/views_test.py b/authentication/views_test.py index c88a610335..8ed8545d4f 100644 --- a/authentication/views_test.py +++ b/authentication/views_test.py @@ -2,6 +2,7 @@ import json from base64 import b64encode +from typing import NamedTuple from unittest.mock import MagicMock from urllib.parse import urljoin @@ -29,7 +30,7 @@ (["allowed-2"], "https://good.com/url-2"), ], ) -def test_get_redirect_url(mocker, param_names, expected_redirect): +def test_get_redirect_url(mocker, param_names, expected_redirect, settings): """Next url should be respected if host is allowed""" GET = { "exists-a": "/url-a", @@ -38,10 +39,7 @@ def test_get_redirect_url(mocker, param_names, expected_redirect): "disallowed-a": "https://malicious.com/url-1", "allowed-2": "https://good.com/url-2", } - mocker.patch( - "authentication.views.settings.ALLOWED_REDIRECT_HOSTS", - ["good.com"], - ) + settings.ALLOWED_REDIRECT_HOSTS = ["good.com"] mock_request = mocker.MagicMock(GET=GET) assert get_redirect_url(mock_request, param_names) == expected_redirect @@ -50,6 +48,7 @@ def test_get_redirect_url(mocker, param_names, expected_redirect): @pytest.mark.parametrize( "test_params", [ + # has_apisix_header, next_url (True, "/search"), (True, None), (False, "/search"), @@ -129,8 +128,9 @@ def test_next_logout(mocker, client, user, test_params, settings): @pytest.mark.parametrize("is_authenticated", [True, False]) @pytest.mark.parametrize("has_next", [True, False]) -def test_custom_logout_view(mocker, client, user, is_authenticated, has_next): +def test_custom_logout_view(mocker, client, user, is_authenticated, has_next, settings): # noqa: PLR0913 """Test logout redirect""" + settings.ALLOWED_REDIRECT_HOSTS = ["ocw.mit.edu"] next_url = "https://ocw.mit.edu" if has_next else "" mock_request = mocker.MagicMock(user=user, META={}) if is_authenticated: @@ -245,23 +245,43 @@ def test_custom_login_view_first_time_login_sets_has_logged_in(mocker): mock_profile.save.assert_called_once() +class LoginOrgUserRedirectParams(NamedTuple): + """Parameters for testing org user login redirect behavior""" + + has_logged_in: bool + login_url: str + expected_redirect: str + + @pytest.mark.parametrize( - "test_case", + "params", [ - ( - False, - "/dashboard/organization/test-organization", - ), # First-time login → org dashboard - ( - True, - "/app", - ), # Subsequent login → normal app + LoginOrgUserRedirectParams( + has_logged_in=False, + login_url="/login/?next=/dashboard", + expected_redirect="/dashboard", + ), + LoginOrgUserRedirectParams( + has_logged_in=False, + login_url="/login/?next=/dashboard&signup_next=/somewhere-else", + expected_redirect="/somewhere-else", + ), + LoginOrgUserRedirectParams( + has_logged_in=True, + login_url="/login/?next=/dashboard&signup_next=/somewhere-else", + expected_redirect="/dashboard", + ), ], ) -def test_login_org_user_redirect(mocker, client, user, test_case, settings): +def test_login_org_user_redirect( + mocker, + client, + user, + params, + settings, +): """Test organization user redirect behavior - org users skip onboarding regardless of login history""" - # Unpack test case - has_logged_in, expected_url = test_case + has_logged_in, login_url, expected_redirect = params # Set up user profile based on test scenario user.profile.has_logged_in = has_logged_in @@ -284,15 +304,18 @@ def test_login_org_user_redirect(mocker, client, user, test_case, settings): ) client.force_login(user) response = client.get( - "/login/", + login_url, follow=False, HTTP_X_USERINFO=header_str, ) assert response.status_code == 302 # Handle environment differences - in some envs it returns full URL, in others just path - expected_full_url = urljoin(settings.APP_BASE_URL, expected_url) - assert response.url in [expected_url, expected_full_url] + expected_full_redirect = urljoin(settings.APP_BASE_URL, expected_redirect) + assert response.url in [expected_redirect, expected_full_redirect] # Verify that org users are never sent to onboarding # (onboarding URL would contain settings.MITOL_NEW_USER_LOGIN_URL) assert settings.MITOL_NEW_USER_LOGIN_URL not in response.url + + user.profile.refresh_from_db() + assert user.profile.has_logged_in is True diff --git a/frontends/main/src/app-pages/EnrollmentCodePage/EnrollmentCodePage.test.tsx b/frontends/main/src/app-pages/EnrollmentCodePage/EnrollmentCodePage.test.tsx index a81d6d7757..af357581de 100644 --- a/frontends/main/src/app-pages/EnrollmentCodePage/EnrollmentCodePage.test.tsx +++ b/frontends/main/src/app-pages/EnrollmentCodePage/EnrollmentCodePage.test.tsx @@ -1,15 +1,10 @@ import React from "react" import { renderWithProviders, setMockResponse, waitFor } from "@/test-utils" -import { urls } from "api/test-utils" -import { - urls as b2bUrls, - factories as mitxOnlineFactories, - urls as mitxOnlineUrls, -} from "api/mitxonline-test-utils" +import { makeRequest, urls } from "api/test-utils" +import { urls as b2bUrls } from "api/mitxonline-test-utils" import * as commonUrls from "@/common/urls" import { Permission } from "api/hooks/user" import EnrollmentCodePage from "./EnrollmentCodePage" -import invariant from "tiny-invariant" // Mock next-nprogress-bar for App Router const mockPush = jest.fn() @@ -30,8 +25,9 @@ describe("EnrollmentCodePage", () => { [Permission.Authenticated]: false, }) - setMockResponse.get(mitxOnlineUrls.userMe.get(), null) - setMockResponse.post(b2bUrls.b2bAttach.b2bAttachView("test-code"), []) + setMockResponse.post(b2bUrls.b2bAttach.b2bAttachView("test-code"), [], { + code: 403, + }) renderWithProviders(, { url: commonUrls.B2B_ATTACH_VIEW, @@ -42,14 +38,15 @@ describe("EnrollmentCodePage", () => { }) const url = new URL(mockPush.mock.calls[0][0]) - expect(url.searchParams.get("skip_onboarding")).toBe("1") - const nextUrl = url.searchParams.get("next") - const signupNextUrl = url.searchParams.get("signup_next") - invariant(nextUrl) - invariant(signupNextUrl) - const attachView = commonUrls.b2bAttachView("test-code") - expect(new URL(nextUrl).pathname).toBe(attachView) - expect(new URL(signupNextUrl).pathname).toBe(attachView) + url.searchParams.sort() + const expectedParams = new URLSearchParams({ + skip_onboarding: "1", + next: `http://test.learn.odl.local:8062${commonUrls.b2bAttachView("test-code")}`, + }) + expectedParams.sort() + expect([...url.searchParams.entries()]).toEqual([ + ...expectedParams.entries(), + ]) }) test("Renders when logged in", async () => { @@ -57,11 +54,6 @@ describe("EnrollmentCodePage", () => { [Permission.Authenticated]: true, }) - setMockResponse.get( - mitxOnlineUrls.userMe.get(), - mitxOnlineFactories.user.user(), - ) - setMockResponse.post(b2bUrls.b2bAttach.b2bAttachView("test-code"), []) renderWithProviders(, { @@ -70,36 +62,21 @@ describe("EnrollmentCodePage", () => { }) test("Redirects to dashboard on successful attachment", async () => { - const orgSlug = "test-org" - const mitxOnlineUser = mitxOnlineFactories.user.user({ - b2b_organizations: [ - { - id: 1, - name: "Test Organization", - description: "A test organization", - logo: "https://example.com/logo.png", - slug: `org-${orgSlug}`, - contracts: [], - }, - ], - }) - setMockResponse.get(urls.userMe.get(), { [Permission.Authenticated]: true, }) - setMockResponse.get(mitxOnlineUrls.userMe.get(), mitxOnlineUser) - - setMockResponse.post(b2bUrls.b2bAttach.b2bAttachView("test-code"), []) + const attachUrl = b2bUrls.b2bAttach.b2bAttachView("test-code") + setMockResponse.post(attachUrl, []) renderWithProviders(, { url: commonUrls.B2B_ATTACH_VIEW, }) await waitFor(() => { - expect(mockPush).toHaveBeenCalledWith( - commonUrls.organizationView(orgSlug), - ) + expect(makeRequest).toHaveBeenCalledWith("post", attachUrl, undefined) }) + + expect(mockPush).toHaveBeenCalledWith(commonUrls.DASHBOARD_HOME) }) }) diff --git a/frontends/main/src/app-pages/EnrollmentCodePage/EnrollmentCodePage.tsx b/frontends/main/src/app-pages/EnrollmentCodePage/EnrollmentCodePage.tsx index 2f95b44ff7..ade2e949f4 100644 --- a/frontends/main/src/app-pages/EnrollmentCodePage/EnrollmentCodePage.tsx +++ b/frontends/main/src/app-pages/EnrollmentCodePage/EnrollmentCodePage.tsx @@ -3,7 +3,6 @@ import React from "react" import { styled, Breadcrumbs, Container, Typography } from "ol-components" import * as urls from "@/common/urls" import { useB2BAttachMutation } from "api/mitxonline-hooks/organizations" -import { useMitxOnlineUserMe } from "api/mitxonline-hooks/user" import { userQueries } from "api/hooks/user" import { useQuery } from "@tanstack/react-query" import { useRouter } from "next-nprogress-bar" @@ -18,11 +17,7 @@ const InterstitialMessage = styled(Typography)(({ theme }) => ({ })) const EnrollmentCodePage: React.FC = ({ code }) => { - const { - mutate: attach, - isSuccess, - isPending, - } = useB2BAttachMutation({ + const enrollment = useB2BAttachMutation({ enrollment_code: code, }) const router = useRouter() @@ -31,11 +26,13 @@ const EnrollmentCodePage: React.FC = ({ code }) => { ...userQueries.me(), staleTime: 0, }) - const { data: mitxOnlineUser } = useMitxOnlineUserMe() + const enrollAsync = enrollment.mutateAsync React.useEffect(() => { - attach?.() - }, [attach]) + if (user?.is_authenticated) { + enrollAsync().then(() => router.push(urls.DASHBOARD_HOME)) + } + }, [user?.is_authenticated, enrollAsync, router]) React.useEffect(() => { if (userLoading) { @@ -43,12 +40,7 @@ const EnrollmentCodePage: React.FC = ({ code }) => { } if (!user?.is_authenticated) { const loginUrlString = urls.auth({ - loginNext: { - pathname: urls.b2bAttachView(code), - searchParams: null, - }, - // On signup, redirect to the attach page so attachment can occur. - signupNext: { + next: { pathname: urls.b2bAttachView(code), searchParams: null, }, @@ -57,13 +49,7 @@ const EnrollmentCodePage: React.FC = ({ code }) => { loginUrl.searchParams.set("skip_onboarding", "1") router.push(loginUrl.toString()) } - if (isSuccess) { - const org = mitxOnlineUser?.b2b_organizations?.[0] - if (org) { - router.push(urls.organizationView(org.slug.replace("org-", ""))) - } - } - }, [isSuccess, userLoading, user, mitxOnlineUser, code, router]) + }, [userLoading, user, code, router]) return ( @@ -72,7 +58,7 @@ const EnrollmentCodePage: React.FC = ({ code }) => { ancestors={[{ href: urls.HOME, label: "Home" }]} current="Use Enrollment Code" /> - {isPending && ( + {enrollment.isPending && ( Validating code "{code}"... )} diff --git a/frontends/main/src/app-pages/ErrorPage/ForbiddenPage.test.tsx b/frontends/main/src/app-pages/ErrorPage/ForbiddenPage.test.tsx index 252a9d1ca9..6d35e52f27 100644 --- a/frontends/main/src/app-pages/ErrorPage/ForbiddenPage.test.tsx +++ b/frontends/main/src/app-pages/ErrorPage/ForbiddenPage.test.tsx @@ -54,7 +54,7 @@ test("Fetches auth data afresh and redirects unauthenticated users to auth", asy await waitFor(() => { expect(mockedRedirect).toHaveBeenCalledWith( routes.auth({ - loginNext: { + next: { pathname: "/foo", searchParams: new URLSearchParams({ cat: "meow" }), }, diff --git a/frontends/main/src/app-pages/HomePage/HomePage.test.tsx b/frontends/main/src/app-pages/HomePage/HomePage.test.tsx index 27f1ab5897..1ea97356d7 100644 --- a/frontends/main/src/app-pages/HomePage/HomePage.test.tsx +++ b/frontends/main/src/app-pages/HomePage/HomePage.test.tsx @@ -296,7 +296,7 @@ describe("Home Page personalize section", () => { expect(link).toHaveAttribute( "href", routes.auth({ - loginNext: { + next: { pathname: routes.DASHBOARD_HOME, searchParams: null, }, diff --git a/frontends/main/src/app-pages/HomePage/PersonalizeSection.tsx b/frontends/main/src/app-pages/HomePage/PersonalizeSection.tsx index e1d2167ae6..fa7a6e76c7 100644 --- a/frontends/main/src/app-pages/HomePage/PersonalizeSection.tsx +++ b/frontends/main/src/app-pages/HomePage/PersonalizeSection.tsx @@ -77,7 +77,7 @@ const AUTH_TEXT_DATA = { linkProps: { children: "Sign Up for Free", href: urls.auth({ - loginNext: { pathname: urls.DASHBOARD_HOME, searchParams: null }, + next: { pathname: urls.DASHBOARD_HOME, searchParams: null }, }), }, }, diff --git a/frontends/main/src/common/client-utils.ts b/frontends/main/src/common/client-utils.ts index 4003ef0feb..0a93fd759f 100644 --- a/frontends/main/src/common/client-utils.ts +++ b/frontends/main/src/common/client-utils.ts @@ -54,54 +54,34 @@ const getCsrfToken = () => { /** * Returns a URL to authentication that redirects to current page after auth. * - * By default, new users will be redirected to default signup destination. - * If `signup` is true, they will be redirected to the current page. + * NOTES: + * 1. This is reactive; if current URL changes, the result of this hook + * will update and trigger re-renders. This makes it suitable for use as + * an href. + * 2. However, the use of search params / pathname hooks may require Suspense + * or NextJS's dynamic rendering. */ -const useAuthToCurrent = ({ signup }: { signup?: boolean } = {}) => { - /** - * NOTES: - * 1. This is reactive; if current URL changes, the result of this hook - * will update and trigger re-renders. This makes it suitable for use as - * an href. - * 2. However, the use of search params / pathname hooks may require Suspense - * or NextJS's dynamic rendering. - * - */ +const useAuthToCurrent = () => { const pathname = usePathname() const searchParams = useSearchParams() const current = { pathname, searchParams } - return auth({ - loginNext: current, - signupNext: signup ? current : undefined, - }) + return auth({ next: current }) } /** - * Redirect user to auth. After auth: - * - existing users redirected to their current URL - * - new users redirected to the default signup destination, unless `signup` is true. + * Redirect user to auth. After auth, users come back to current page. */ -const redirectAuthToCurrent = ({ - signup, -}: { - /** - * Whether to redirect signup to current; by default, false. New users - * will be redirected to the default signup destination. - */ - signup?: boolean -} = {}): never => { - const current = { - pathname: window.location.pathname, - searchParams: new URLSearchParams(window.location.search), - } +const redirectAuthToCurrent = (): never => { redirect( /** * Calculating the ?next= via window.location is appropriate * here since it happens time of redirect call. */ auth({ - loginNext: current, - signupNext: signup ? current : undefined, + next: { + pathname: window.location.pathname, + searchParams: new URLSearchParams(window.location.search), + }, }), ) } diff --git a/frontends/main/src/common/urls.test.ts b/frontends/main/src/common/urls.test.ts index 2f35dbdb49..5e1b514f77 100644 --- a/frontends/main/src/common/urls.test.ts +++ b/frontends/main/src/common/urls.test.ts @@ -2,34 +2,52 @@ import { auth } from "./urls" const MITOL_API_BASE_URL = process.env.NEXT_PUBLIC_MITOL_API_BASE_URL -test("login encodes the next parameter appropriately", () => { - expect( - auth({ - loginNext: { pathname: null, searchParams: null }, - }), - ).toBe( - `${MITOL_API_BASE_URL}/login?next=http://test.learn.odl.local:8062/&signup_next=http://test.learn.odl.local:8062/dashboard`, - ) - - expect( - auth({ - loginNext: { - pathname: "/foo/bar", - searchParams: null, - }, - }), - ).toBe( - `${MITOL_API_BASE_URL}/login?next=http://test.learn.odl.local:8062/foo/bar&signup_next=http://test.learn.odl.local:8062/dashboard`, - ) - - expect( - auth({ - loginNext: { - pathname: "/foo/bar", - searchParams: new URLSearchParams("?cat=meow"), - }, - }), - ).toBe( - `${MITOL_API_BASE_URL}/login?next=http://test.learn.odl.local:8062/foo/bar%3Fcat%3Dmeow&signup_next=http://test.learn.odl.local:8062/dashboard`, - ) -}) +test.each([ + { + loginNext: { pathname: "/", searchParams: null }, + expected: [ + "http://api.test.learn.odl.local:8063/login", + "?next=http%3A%2F%2Ftest.learn.odl.local%3A8062%2F", + ].join(""), + }, + { + loginNext: { + pathname: "/courses/course-v1:edX+DemoX+Demo_Course", + searchParams: null, + }, + expected: [ + "http://api.test.learn.odl.local:8063/login", + "?next=http%3A%2F%2Ftest.learn.odl.local%3A8062%2Fcourses%2Fcourse-v1%3AedX%2BDemoX%2BDemo_Course", + ].join(""), + }, + { + loginNext: { + pathname: "/courses/course-v1:edX+DemoX+Demo_Course", + searchParams: new URLSearchParams({ foo: "bar" }), + }, + expected: [ + `${MITOL_API_BASE_URL}/login`, + "?next=http%3A%2F%2Ftest.learn.odl.local%3A8062%2Fcourses%2Fcourse-v1%3AedX%2BDemoX%2BDemo_Course%3Ffoo%3Dbar", + ].join(""), + }, + { + loginNext: { + pathname: "/courses/course-v1:edX+DemoX+Demo_Course", + searchParams: new URLSearchParams({ foo: "bar" }), + }, + signupNext: { + pathname: "/somewhere/else", + searchParams: null, + }, + expected: [ + `${MITOL_API_BASE_URL}/login`, + "?next=http%3A%2F%2Ftest.learn.odl.local%3A8062%2Fcourses%2Fcourse-v1%3AedX%2BDemoX%2BDemo_Course%3Ffoo%3Dbar", + "&signup_next=http%3A%2F%2Ftest.learn.odl.local%3A8062%2Fsomewhere%2Felse", + ].join(""), + }, +])( + "login encodes the next parameter appropriately", + ({ loginNext, signupNext, expected }) => { + expect(auth({ next: loginNext, signupNext })).toBe(expected) + }, +) diff --git a/frontends/main/src/common/urls.ts b/frontends/main/src/common/urls.ts index c74d2c693b..a468eab4b3 100644 --- a/frontends/main/src/common/urls.ts +++ b/frontends/main/src/common/urls.ts @@ -49,6 +49,7 @@ export const makeChannelManageWidgetsPath = ( ) => generatePath(CHANNEL_EDIT_WIDGETS, { channelType, name }) const ORIGIN = process.env.NEXT_PUBLIC_ORIGIN +invariant(ORIGIN, "NEXT_PUBLIC_ORIGIN must be set") if (process.env.NODE_ENV !== "production") { invariant(!ORIGIN?.endsWith("/"), "NEXT_PUBLIC_ORIGIN should not end with /") } @@ -136,26 +137,28 @@ export const LOGIN = `${MITOL_API_BASE_URL}/login` export const LOGOUT = `${MITOL_API_BASE_URL}/logout/` type UrlDescriptor = { - pathname: string | null + pathname: string searchParams: URLSearchParams | null - hash?: string | null } export type LoginUrlOpts = { /** - * URL to redirect to after login. + * URL to redirect to after login + signup. */ - loginNext: UrlDescriptor + next: UrlDescriptor /** - * URL to redirect to after signup. + * URL to redirect to after signup, overriding `next` for signup if provided. */ signupNext?: UrlDescriptor } -const DEFAULT_SIGNUP_NEXT: UrlDescriptor = { - pathname: DASHBOARD_HOME, - searchParams: null, +const stringifyUrlDescriptor = (val: UrlDescriptor) => { + const url = new URL(ORIGIN) + url.pathname = val.pathname + if (val.searchParams) { + val.searchParams.forEach((v, k) => url.searchParams.set(k, v)) + } + return url.toString() } - /** * Returns the URL to the authentication page (login and signup). * @@ -166,25 +169,14 @@ const DEFAULT_SIGNUP_NEXT: UrlDescriptor = { * for values to skip them if desired. */ export const auth = (opts: LoginUrlOpts) => { - const { loginNext, signupNext = DEFAULT_SIGNUP_NEXT } = opts - const encode = (value: UrlDescriptor) => { - const pathname = value.pathname ?? "/" - const searchParams = value.searchParams ?? new URLSearchParams() - const hash = value.hash ?? "" - /** - * To include search parameters in the next URL, we need to encode them. - * If we pass `?next=/foo/bar?cat=meow` directly, Django receives two separate - * parameters: `next` and `cat`. - * - * There's no need to encode the path parameter (it might contain slashes, - * but those are allowed in search parameters) so let's keep it readable. - */ - const search = searchParams?.toString() ? `?${searchParams.toString()}` : "" - return `${ORIGIN}${pathname}${encodeURIComponent(search)}${encodeURIComponent(hash)}` + const { next: loginNext, signupNext } = opts + + const url = new URL(LOGIN) + url.searchParams.set("next", stringifyUrlDescriptor(loginNext)) + if (signupNext) { + url.searchParams.set("signup_next", stringifyUrlDescriptor(signupNext)) } - const loginNextHref = encode(loginNext) - const signupNextHref = encode(signupNext) - return `${LOGIN}?next=${loginNextHref}&signup_next=${signupNextHref}` + return url.toString() } export const ECOMMERCE_CART = "/cart/" as const diff --git a/frontends/main/src/page-components/Header/Header.test.tsx b/frontends/main/src/page-components/Header/Header.test.tsx index 379f7e49c5..e51aa8db4c 100644 --- a/frontends/main/src/page-components/Header/Header.test.tsx +++ b/frontends/main/src/page-components/Header/Header.test.tsx @@ -61,9 +61,9 @@ describe("UserMenu", () => { const isAuthenticated = false const initialUrl = "/foo/bar?cat=meow" const expectedUrl = urlConstants.auth({ - loginNext: { - pathname: "/foo/bar", - searchParams: new URLSearchParams("?cat=meow"), + next: { + pathname: urlConstants.DASHBOARD_HOME, + searchParams: null, }, }) setMockResponse.get(urls.userMe.get(), { diff --git a/frontends/main/src/page-components/Header/UserMenu.tsx b/frontends/main/src/page-components/Header/UserMenu.tsx index af1260b316..acbb11c597 100644 --- a/frontends/main/src/page-components/Header/UserMenu.tsx +++ b/frontends/main/src/page-components/Header/UserMenu.tsx @@ -12,7 +12,6 @@ import { } from "@remixicon/react" import { useUserMe, User } from "api/hooks/user" import MITLogoLink from "@/components/MITLogoLink/MITLogoLink" -import { useAuthToCurrent } from "@/common/client-utils" const FlexContainer = styled.div({ display: "flex", @@ -124,8 +123,12 @@ type UserMenuProps = { const UserMenu: React.FC = ({ variant }) => { const [visible, setVisible] = useState(false) - - const loginUrl = useAuthToCurrent() + const loginUrl = urls.auth({ + next: { + pathname: urls.DASHBOARD_HOME, + searchParams: null, + }, + }) const { isLoading, data: user } = useUserMe() if (isLoading) { @@ -138,14 +141,12 @@ const UserMenu: React.FC = ({ variant }) => { key: "dashboard", allow: !!user?.is_authenticated, href: urls.DASHBOARD_HOME, - // LinkComponent: Link }, { label: "Learning Paths", key: "learningpaths", allow: !!user?.is_learning_path_editor, href: urls.LEARNINGPATH_LISTING, - // LinkComponent: Link }, { label: "Log Out", diff --git a/frontends/main/src/page-components/SignupPopover/SignupPopover.test.tsx b/frontends/main/src/page-components/SignupPopover/SignupPopover.test.tsx index 0e9b9cac6f..b597dbf3b6 100644 --- a/frontends/main/src/page-components/SignupPopover/SignupPopover.test.tsx +++ b/frontends/main/src/page-components/SignupPopover/SignupPopover.test.tsx @@ -16,11 +16,7 @@ test("SignupPopover shows link to sign up", async () => { invariant(link instanceof HTMLAnchorElement) expect(link.href).toMatch( urls.auth({ - loginNext: { - pathname: "/some-path", - searchParams: new URLSearchParams("dog=woof"), - }, - signupNext: { + next: { pathname: "/some-path", searchParams: new URLSearchParams("dog=woof"), }, diff --git a/frontends/main/src/page-components/SignupPopover/SignupPopover.tsx b/frontends/main/src/page-components/SignupPopover/SignupPopover.tsx index d70fb5bb89..6e0da9c580 100644 --- a/frontends/main/src/page-components/SignupPopover/SignupPopover.tsx +++ b/frontends/main/src/page-components/SignupPopover/SignupPopover.tsx @@ -32,7 +32,7 @@ type SignupPopoverProps = Pick< "anchorEl" | "onClose" | "placement" > const SignupPopover: React.FC = (props) => { - const loginUrl = useAuthToCurrent({ signup: true }) + const loginUrl = useAuthToCurrent() return (