added redirect to default to sign-in/up/out

This commit is contained in:
Zai Shi 2024-03-13 10:17:48 +08:00
parent c0151a8e5d
commit 9d50641a45
13 changed files with 36 additions and 94 deletions

View File

@ -18,10 +18,6 @@ export default function CustomCredentialSignIn() {
// It is better to handle each error code separately, but for simplicity, we will just show the error code directly
if (errorCode) {
setError(errorCode);
} else {
// redirectToXXX will refresh the page so server components can be updated
// you can also router.push if you don't have any server components using the user info
app.redirectToAfterSignIn();
}
};

View File

@ -1,8 +1,5 @@
import { SignIn } from "@stackframe/stack";
import { stackServerApp } from "src/stack";
import CustomCredentialSignIn from "./custom-credential";
import CustomOAuthSignIn from "./custom-oauth";
export default function Page() {
return <SignIn fullPage redirectUrl={stackServerApp.urls.home} />;
return <SignIn fullPage />;
}

View File

@ -1,13 +1,9 @@
'use client';
import { useStackApp, useUser } from "@stackframe/stack";
import { useUser } from "@stackframe/stack";
import { runAsynchronously } from "@stackframe/stack-shared/dist/utils/promises";
export default function SignOutButton() {
const user = useUser();
const app = useStackApp();
return (<button onClick={() => runAsynchronously(async () => {
await user?.signOut();
app.redirectToAfterSignOut();
})}>Sign out</button>);
return (<button onClick={() => runAsynchronously(user?.signOut())}>Sign out</button>);
}

View File

@ -6,7 +6,7 @@ export const stackServerApp = new StackServerApp({
tokenStore: "nextjs-cookie",
urls: {
signIn: "/signin",
afterSignIn: "/after-signin",
afterSignUp: "/after-signup",
// afterSignIn: "/after-signin",
// afterSignUp: "/after-signup",
}
});

View File

@ -94,10 +94,7 @@ You can sign out the user by redirecting them to `/handler/signout` or simply by
export default function SignOutButton() {
const user = useUser();
return <button onClick={async () => {
await user?.signOut()
// redirectToXXX will redirect and reload the page so server components can re-render
// you can also use router.push if you don't have any server components that uses the user
app.redirectToAfterSignOut();
await user?.signOut();
}>
Sign Out
</button>;

View File

@ -77,7 +77,6 @@ export default function CustomCredentialSignIn() {
if (errorCode) {
setError(errorCode);
}
app.redirectToSignInRedirect();
};
return (

View File

@ -99,10 +99,7 @@ function AvatarSection() {
}}
onClick={isSigningOut ? undefined : () => {
setIsSigningOut(true);
runAsynchronously((async () => {
await user.signOut();
app.redirectToAfterSignOut();
})().finally(() => setIsSigningOut(false)));
runAsynchronously(user.signOut().finally(() => setIsSigningOut(false)));
}}
variant='plain'
>

View File

@ -11,12 +11,7 @@ export default function OAuthCallback () {
useEffect(() => runAsynchronously(async () => {
if (called.current) return;
called.current = true;
const { newUser } = await app.callOAuthCallback();
if (newUser) {
await app.redirectToAfterSignUp();
} else {
await app.redirectToAfterSignIn();
}
await app.callOAuthCallback();
}), []);
return <MessageCard title='Redirecting...' fullPage />;

View File

@ -9,10 +9,7 @@ export default function Signout() {
const app = useStackApp();
if (user) {
use((async () => {
await user.signOut();
await app.redirectToAfterSignOut();
})());
use(user.signOut());
}
return <GoHomeMessageCard type='signedOut' fullPage />;

View File

@ -46,7 +46,7 @@ export default function CredentialSignIn() {
}
case undefined: {
// success
await app.redirectToAfterSignIn();
break;
}
}
};

View File

@ -59,7 +59,7 @@ export default function CredentialSignUp() {
}
case undefined: {
// success
await app.redirectToAfterSignIn();
break;
}
}
};

View File

@ -2,7 +2,6 @@ import { StackClientInterface } from "@stackframe/stack-shared";
import { saveVerifierAndState, getVerifierAndState } from "./cookie";
import { constructRedirectUrl } from "../utils/url";
import { TokenStore } from "@stackframe/stack-shared/dist/interface/clientInterface";
import { SignInErrorCode, SignUpErrorCode } from "@stackframe/stack-shared/dist/utils/types";
export async function signInWithOAuth(
iface: StackClientInterface,
@ -94,49 +93,4 @@ export async function callOAuthCallback(
console.error("Error signing in during OAuth callback", e);
throw new Error("Error signing in. Please try again.");
}
}
export async function signInWithCredential(
iface: StackClientInterface,
tokenStore: TokenStore,
{
email,
password,
redirectUrl,
}: {
email: string,
password: string,
redirectUrl?: string,
}
): Promise<SignInErrorCode | undefined>{
const errorCode = await iface.signInWithCredential(email, password, tokenStore);
if (!errorCode) {
redirectUrl = constructRedirectUrl(redirectUrl);
window.location.assign(redirectUrl);
}
return errorCode;
}
export async function signUpWithCredential(
iface: StackClientInterface,
tokenStore: TokenStore,
{
email,
password,
redirectUrl,
emailVerificationRedirectUrl,
}: {
email: string,
password: string,
redirectUrl?: string,
emailVerificationRedirectUrl: string,
}
): Promise<SignUpErrorCode | undefined>{
emailVerificationRedirectUrl = constructRedirectUrl(emailVerificationRedirectUrl);
const errorCode = await iface.signUpWithCredential(email, password, emailVerificationRedirectUrl, tokenStore);
if (!errorCode) {
redirectUrl = constructRedirectUrl(redirectUrl);
window.location.assign(redirectUrl);
}
return errorCode;
}
}

View File

@ -8,7 +8,7 @@ import { suspendIfSsr } from "@stackframe/stack-shared/dist/utils/react";
import { AsyncStore } from "@stackframe/stack-shared/dist/utils/stores";
import { ClientProjectJson, UserCustomizableJson, UserJson, TokenObject, TokenStore, ProjectJson, EmailConfigJson, DomainConfigJson, ReadonlyTokenStore, getProductionModeErrors, ProductionModeError } from "@stackframe/stack-shared/dist/interface/clientInterface";
import { isClient } from "../utils/next";
import { callOAuthCallback, signInWithCredential, signInWithOAuth, signUpWithCredential } from "./auth";
import { callOAuthCallback, signInWithOAuth } from "./auth";
import { RedirectType, redirect, useRouter } from "next/navigation";
import { ReadonlyJson } from "@stackframe/stack-shared/dist/utils/json";
import { constructRedirectUrl } from "../utils/url";
@ -527,7 +527,11 @@ class _StackClientAppImpl<HasTokenStore extends boolean, ProjectId extends strin
}): Promise<SignInErrorCode | undefined> {
this._ensurePersistentTokenStore();
const tokenStore = getTokenStore(this._tokenStoreOptions);
return await signInWithCredential(this._interface, tokenStore, options);
const errorCode = await this._interface.signInWithCredential(options.email, options.password, tokenStore);
if (!errorCode) {
window.location.assign(this.urls.afterSignIn);
}
return errorCode;
}
async signUpWithCredential(options: {
@ -536,23 +540,33 @@ class _StackClientAppImpl<HasTokenStore extends boolean, ProjectId extends strin
}): Promise<SignUpErrorCode | undefined>{
this._ensurePersistentTokenStore();
const tokenStore = getTokenStore(this._tokenStoreOptions);
return await signUpWithCredential(this._interface, tokenStore, {
...options,
emailVerificationRedirectUrl: this.urls.emailVerification,
});
const emailVerificationRedirectUrl = constructRedirectUrl(this.urls.emailVerification);
const errorCode = await this._interface.signUpWithCredential(
options.email,
options.password,
emailVerificationRedirectUrl,
tokenStore
);
if (!errorCode) {
window.location.assign(this.urls.afterSignUp);
}
return errorCode;
}
async callOAuthCallback() {
this._ensurePersistentTokenStore();
const tokenStore = getTokenStore(this._tokenStoreOptions);
const result = await callOAuthCallback(this._interface, tokenStore, this.urls.oauthCallback);
return {
newUser: !!result.newUser,
};
if (result.newUser) {
await window.location.replace(this.urls.afterSignUp);
} else {
await window.location.replace(this.urls.afterSignIn);
}
}
protected async _signOut(tokenStore: TokenStore): Promise<void> {
await this._interface.signOut(tokenStore);
window.location.assign(this.urls.afterSignOut);
}
async signOut(): Promise<void> {
@ -1113,7 +1127,7 @@ export type StackClientApp<HasTokenStore extends boolean = boolean, ProjectId ex
signInWithOAuth(provider: string): Promise<void>,
signInWithCredential(options: { email: string, password: string }): Promise<SignInErrorCode | undefined>,
signUpWithCredential(options: { email: string, password: string }): Promise<SignUpErrorCode | undefined>,
callOAuthCallback(): Promise<{ newUser: boolean }>,
callOAuthCallback(): Promise<void>,
sendForgotPasswordEmail(email: string): Promise<void>,
resetPassword(options: { code: string, password: string }): Promise<PasswordResetLinkErrorCode | undefined>,
verifyPasswordResetCode(code: string): Promise<PasswordResetLinkErrorCode | undefined>,