Skip to content

Commit

Permalink
configure redirect paths in the gadget provider and be consistent bet…
Browse files Browse the repository at this point in the history
…ween signed in and signed out
  • Loading branch information
infiton committed Oct 18, 2023
1 parent fbb62fb commit 812192e
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 7 deletions.
6 changes: 6 additions & 0 deletions packages/react/src/GadgetProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface GadgetAuthConfiguration {
signInPath: string;
/** The API identifier of the `User` `signOut` action. Defaults to `signOut` */
signOutActionApiIdentifier: string;
/** The path that users are redirected to after they sign in successfully. */
redirectOnSuccessfulSignInPath: string;
}

/** Provides the api client instance, if present, as well as the Gadget auth configuration for the application. */
Expand Down Expand Up @@ -61,6 +63,7 @@ export interface DeprecatedProviderProps {

const defaultSignInPath = "/";
const defaultSignOutApiIdentifier = "signOut";
const defaultRedirectOnSuccessfulSignInPath = "/";

/**
* Provider wrapper component that passes an api client instance to the other hooks.
Expand Down Expand Up @@ -109,11 +112,13 @@ export function Provider(props: ProviderProps | DeprecatedProviderProps) {

let signInPath = defaultSignInPath;
let signOutActionApiIdentifier = defaultSignOutApiIdentifier;
let redirectOnSuccessfulSignInPath = defaultRedirectOnSuccessfulSignInPath;

if ("auth" in props) {
const { auth } = props;
if (auth?.signInPath) signInPath = auth.signInPath;
if (auth?.signOutActionApiIdentifier) signOutActionApiIdentifier = auth.signOutActionApiIdentifier;
if (auth?.redirectOnSuccessfulSignInPath) redirectOnSuccessfulSignInPath = auth.redirectOnSuccessfulSignInPath;
}

return (
Expand All @@ -124,6 +129,7 @@ export function Provider(props: ProviderProps | DeprecatedProviderProps) {
auth: {
signInPath,
signOutActionApiIdentifier,
redirectOnSuccessfulSignInPath,
},
}}
>
Expand Down
7 changes: 4 additions & 3 deletions packages/react/src/auth/SignedInOrRedirect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useAuth } from "./useAuth.js";
/**
* Renders its `children` if the current `Session` is signed in, otherwise redirects the browser to the `signInPath` configured in the `Provider`. Uses `window.location.assign` to perform the redirect.
*/
export const SignedInOrRedirect = (props: { children: ReactNode }) => {
export const SignedInOrRedirect = (props: { path?: string; children: ReactNode }) => {
const [redirected, setRedirected] = useState(false);

const { user, isSignedIn } = useAuth();
Expand All @@ -16,11 +16,12 @@ export const SignedInOrRedirect = (props: { children: ReactNode }) => {
useEffect(() => {
if (auth && !redirected && (!isSignedIn || !user)) {
setRedirected(true);
const redirectUrl = new URL(auth.signInPath, window.location.origin);
const redirectPath = props.path ?? auth.signInPath;
const redirectUrl = new URL(redirectPath, window.location.origin);
redirectUrl.searchParams.set("redirectTo", window.location.pathname);
window.location.assign(redirectUrl.toString());
}
}, [redirected, isSignedIn, auth]);
}, [props.path, redirected, isSignedIn, auth, user]);

if (user && isSignedIn) {
return <>{props.children}</>;
Expand Down
13 changes: 9 additions & 4 deletions packages/react/src/auth/SignedOutOrRedirect.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import type { ReactNode } from "react";
import React, { useEffect, useState } from "react";
import React, { useContext, useEffect, useState } from "react";
import { GadgetConfigurationContext } from "../GadgetProvider.js";
import { useAuth } from "./useAuth.js";

/**
* Renders its `children` if the current `Session` is signed out, otherwise redirects the browser to the `path` prop. Uses `window.location.assign` to perform the redirect.
*/
export const SignedOutOrRedirect = (props: { path: string; children: ReactNode }) => {
export const SignedOutOrRedirect = (props: { path?: string; children: ReactNode }) => {
const [redirected, setRedirected] = useState(false);
const { path, children } = props;

const { user, isSignedIn } = useAuth();
const context = useContext(GadgetConfigurationContext);
const { auth } = context ?? {};

useEffect(() => {
if (!redirected && (isSignedIn || user)) {
setRedirected(true);
const redirectUrl = new URL(path, window.location.origin);
const searchParams = new URLSearchParams(window.location.search);
const redirectPath = searchParams.get("redirectTo") ?? path ?? auth?.signInPath ?? "/";
const redirectUrl = new URL(redirectPath, window.location.origin);
window.location.assign(redirectUrl.toString());
}
}, [redirected, isSignedIn, path, user]);
}, [redirected, isSignedIn, path, user, auth]);

if (!user && !isSignedIn) {
return <>{children}</>;
Expand Down

0 comments on commit 812192e

Please sign in to comment.