-
-
Notifications
You must be signed in to change notification settings - Fork 183
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Robin Louarn
committed
Feb 28, 2024
1 parent
a4f30b4
commit 6d543c9
Showing
23 changed files
with
536 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
AUTH_SECRET= # Linux: `openssl rand -hex 32` or go to https://generate-secret.vercel.app/32 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
.DS_Store | ||
|
||
node_modules/ | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
lerna-debug.log* | ||
.yarn-integrity | ||
.npm | ||
|
||
.eslintcache | ||
|
||
*.tsbuildinfo | ||
next-env.d.ts | ||
|
||
.next | ||
.vercel | ||
.env*.local |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import createNextIntlPlugin from "next-intl/plugin"; | ||
|
||
const withNextIntl = createNextIntlPlugin("src/i18n.ts"); | ||
|
||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
reactStrictMode: true, | ||
}; | ||
|
||
export default withNextIntl(nextConfig); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "example-app-router-next-auth-v5", | ||
"private": true, | ||
"scripts": { | ||
"dev": "next", | ||
"build": "next build", | ||
"start": "next start" | ||
}, | ||
"dependencies": { | ||
"next": "latest", | ||
"next-auth": "beta", | ||
"next-intl": "3.9.1", | ||
"react": "18.2.0", | ||
"react-dom": "18.2.0" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "20.11.21", | ||
"@types/react": "18.2.60", | ||
"@types/react-dom": "18.2.19", | ||
"typescript": "5.3.3" | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
examples/example-app-router-next-auth-v5/src/app/[locale]/components/auth-components.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
"use client"; | ||
|
||
import { signIn, signOut } from "next-auth/react"; | ||
import { useTranslations } from "next-intl"; | ||
import { FC } from "react"; | ||
|
||
type SignInProps = { | ||
provider?: string; | ||
}; | ||
|
||
export const SignIn: FC<SignInProps> = ({ provider }) => { | ||
const t = useTranslations("SignIn"); | ||
return <button onClick={() => signIn(provider)}>{t("label")}</button>; | ||
}; | ||
|
||
export const SignOut: FC = () => { | ||
const t = useTranslations("SignOut"); | ||
return <button onClick={() => signOut()}>{t("label")}</button>; | ||
}; |
18 changes: 18 additions & 0 deletions
18
examples/example-app-router-next-auth-v5/src/app/[locale]/components/locale-switch.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
"use client"; | ||
|
||
import { locales } from "@/i18n"; | ||
import { Link, usePathname } from "@/navigation"; | ||
import { FC } from "react"; | ||
|
||
export const LocaleSwitch: FC = () => { | ||
const pathname = usePathname(); | ||
return ( | ||
<div style={{ display: "flex", gap: 5 }}> | ||
{locales.map((locale) => ( | ||
<Link key={locale} href={pathname} locale={locale}> | ||
{locale} | ||
</Link> | ||
))} | ||
</div> | ||
); | ||
}; |
22 changes: 22 additions & 0 deletions
22
examples/example-app-router-next-auth-v5/src/app/[locale]/components/main-navigation.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { useTranslations } from "next-intl"; | ||
import { Link } from "@/navigation"; | ||
import { FC } from "react"; | ||
|
||
const pages = { | ||
"/": "home", | ||
"/profile": "profile", | ||
} as const; | ||
|
||
export const MainNavigation: FC = () => { | ||
const t = useTranslations("Navigation"); | ||
|
||
return ( | ||
<div style={{ display: "flex", gap: 5 }}> | ||
{Object.entries(pages).map(([path, key]) => ( | ||
<Link key={path} href={path}> | ||
{t(key)} | ||
</Link> | ||
))} | ||
</div> | ||
); | ||
}; |
35 changes: 35 additions & 0 deletions
35
examples/example-app-router-next-auth-v5/src/app/[locale]/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { auth } from "@/auth"; | ||
import { PropsWithLocale, getMessages, timeZone } from "@/i18n"; | ||
import { SessionProvider } from "next-auth/react"; | ||
import { NextIntlClientProvider, useMessages } from "next-intl"; | ||
import { LocaleSwitch } from "./components/locale-switch"; | ||
import { MainNavigation } from "./components/main-navigation"; | ||
import { FC, PropsWithChildren } from "react"; | ||
|
||
type LocaleLayoutProps = PropsWithChildren<PropsWithLocale>; | ||
|
||
const LocaleLayout: FC<LocaleLayoutProps> = async ({ | ||
children, | ||
params: { locale }, | ||
}) => { | ||
const session = await auth(); | ||
const messages = await getMessages(locale); | ||
|
||
return ( | ||
<html lang={locale}> | ||
<body> | ||
<NextIntlClientProvider messages={messages}> | ||
<SessionProvider session={session}> | ||
<main> | ||
<MainNavigation /> | ||
<LocaleSwitch /> | ||
{children} | ||
</main> | ||
</SessionProvider> | ||
</NextIntlClientProvider> | ||
</body> | ||
</html> | ||
); | ||
}; | ||
|
||
export default LocaleLayout; |
54 changes: 54 additions & 0 deletions
54
examples/example-app-router-next-auth-v5/src/app/[locale]/login/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"use client"; | ||
|
||
import { signIn } from "next-auth/react"; | ||
import { useTranslations } from "next-intl"; | ||
import { useSearchParams } from "next/navigation"; | ||
import { FormEvent, useState } from "react"; | ||
|
||
export default function Login() { | ||
const t = useTranslations("Login"); | ||
const searchParams = useSearchParams(); | ||
const [error, setError] = useState<string>(); | ||
|
||
const onSubmit = async (event: FormEvent<HTMLFormElement>) => { | ||
event.preventDefault(); | ||
if (error) setError(undefined); | ||
|
||
const formData = new FormData(event.currentTarget); | ||
|
||
const result = await signIn("credentials", { | ||
username: formData.get("username"), | ||
password: formData.get("password"), | ||
callbackUrl: searchParams.get("callbackUrl") ?? undefined, | ||
}); | ||
|
||
if (result?.error) setError(result.error); | ||
}; | ||
|
||
return ( | ||
<form | ||
onSubmit={onSubmit} | ||
style={{ | ||
display: "flex", | ||
flexDirection: "column", | ||
gap: 10, | ||
width: 300, | ||
}} | ||
> | ||
<label style={{ display: "flex" }}> | ||
<span style={{ display: "inline-block", flexGrow: 1, minWidth: 100 }}> | ||
{t("username")} | ||
</span> | ||
<input name="username" type="text" /> | ||
</label> | ||
<label style={{ display: "flex" }}> | ||
<span style={{ display: "inline-block", flexGrow: 1, minWidth: 100 }}> | ||
{t("password")} | ||
</span> | ||
<input name="password" type="password" /> | ||
</label> | ||
{error && <p>{t("error", { error })}</p>} | ||
<button type="submit">{t("submit")}</button> | ||
</form> | ||
); | ||
} |
11 changes: 11 additions & 0 deletions
11
examples/example-app-router-next-auth-v5/src/app/[locale]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { auth } from "@/auth"; | ||
import { SignIn, SignOut } from "./components/auth-components"; | ||
import { FC } from "react"; | ||
|
||
const IndexPage: FC = async () => { | ||
const session = await auth(); | ||
|
||
return <div>{session ? <SignOut /> : <SignIn />}</div>; | ||
}; | ||
|
||
export default IndexPage; |
10 changes: 10 additions & 0 deletions
10
examples/example-app-router-next-auth-v5/src/app/[locale]/profile/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { auth } from "@/auth"; | ||
import { FC } from "react"; | ||
|
||
const ProfilePage: FC = async () => { | ||
const session = await auth(); | ||
|
||
return <pre>{JSON.stringify(session, null, 2)}</pre>; | ||
}; | ||
|
||
export default ProfilePage; |
3 changes: 3 additions & 0 deletions
3
examples/example-app-router-next-auth-v5/src/app/api/auth/[...nextauth]/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { GET, POST } from "@/auth"; | ||
|
||
export const runtime = "edge"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { FC, PropsWithChildren } from "react"; | ||
|
||
type RootLayoutProps = PropsWithChildren; | ||
|
||
const RootLayout: FC<RootLayoutProps> = ({ children }) => <>{children}</>; | ||
|
||
export default RootLayout; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import NextAuth from "next-auth"; | ||
import CredentialsProvider from "next-auth/providers/credentials"; | ||
import { NextResponse } from "next/server"; | ||
import { locales } from "./i18n"; | ||
|
||
const publicPagesPathnameRegex = RegExp( | ||
`^(/(${locales.join("|")}))?(${["/", "/login"] | ||
.flatMap((p) => (p === "/" ? ["", "/"] : p)) | ||
.join("|")})/?$`, | ||
"i" | ||
); | ||
|
||
const authPagesPathnameRegex = RegExp( | ||
`^(/(${locales.join("|")}))?(${["/login"] | ||
.flatMap((p) => (p === "/" ? ["", "/"] : p)) | ||
.join("|")})/?$`, | ||
"i" | ||
); | ||
|
||
export const { | ||
handlers: { GET, POST }, | ||
auth, | ||
signIn, | ||
signOut, | ||
} = NextAuth({ | ||
providers: [ | ||
CredentialsProvider({ | ||
name: "Credentials", | ||
credentials: { | ||
username: { type: "text" }, | ||
password: { type: "password" }, | ||
}, | ||
authorize(credentials) { | ||
if ( | ||
credentials?.username === "admin" && | ||
credentials?.password === "admin" | ||
) { | ||
return { id: "1", name: "admin" }; | ||
} | ||
|
||
return null; | ||
}, | ||
}), | ||
], | ||
callbacks: { | ||
authorized: ({ | ||
auth, | ||
request: { | ||
nextUrl: { pathname, origin, basePath, searchParams, href }, | ||
}, | ||
}) => { | ||
const signInUrl = new URL("/login", origin); | ||
signInUrl.searchParams.append("callbackUrl", href); | ||
|
||
const isAuthenticated = !!auth; | ||
const isPublicPage = publicPagesPathnameRegex.test(pathname); | ||
const isAuthPage = authPagesPathnameRegex.test(pathname); | ||
|
||
if (!(isAuthenticated || isPublicPage)) | ||
return NextResponse.redirect(signInUrl); | ||
|
||
if (isAuthenticated && isAuthPage) | ||
return NextResponse.redirect( | ||
new URL(searchParams.get("callbackUrl") ?? new URL(origin), origin) | ||
); | ||
|
||
return isAuthenticated || isPublicPage; | ||
}, | ||
}, | ||
pages: { | ||
signIn: "/login", | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import messages from "@/messages/fr.json"; | ||
import { getRequestConfig } from "next-intl/server"; | ||
|
||
export const locales = ["fr", "en"] as const; | ||
export const defaultLocale = locales[0]; | ||
export const timeZone = "Europe/Paris"; | ||
|
||
export type PropsWithLocale<T = unknown> = T & { params: { locale: string } }; | ||
export type Messages = typeof messages; | ||
declare global { | ||
interface IntlMessages extends Messages {} | ||
} | ||
|
||
export const getMessages = async (locale: string): Promise<Messages> => | ||
(await import(`@/messages/${locale}.json`)).default; | ||
|
||
export default getRequestConfig(async ({ locale }) => ({ | ||
timeZone, | ||
messages: await getMessages(locale), | ||
})); |
19 changes: 19 additions & 0 deletions
19
examples/example-app-router-next-auth-v5/src/messages/en.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"Navigation": { | ||
"home": "Home", | ||
"profile": "Profile" | ||
}, | ||
"SignIn": { | ||
"label": "Sign In" | ||
}, | ||
"SignOut": { | ||
"label": "Sign Out" | ||
}, | ||
"Login": { | ||
"title": "Login", | ||
"username": "Username", | ||
"password": "Password", | ||
"submit": "Login", | ||
"error": "{error, select, CredentialsSignin {Invalid username or password} other {Unknown error}}" | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
examples/example-app-router-next-auth-v5/src/messages/fr.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"Navigation": { | ||
"home": "Acceuil", | ||
"profile": "Profile" | ||
}, | ||
"SignIn": { | ||
"label": "Se connecter" | ||
}, | ||
"SignOut": { | ||
"label": "Se déconnecter" | ||
}, | ||
"Login": { | ||
"title": "Connexion", | ||
"username": "Nom d'utilisateur", | ||
"password": "Mot de passe", | ||
"submit": "Connexion", | ||
"error": "{error, select, CredentialsSignin {Nom d'utilisateur ou mot de passe incorrect} other {Erreur inconnue}}" | ||
} | ||
} |
Oops, something went wrong.