Skip to content

Commit

Permalink
Merge pull request #147 from aceleradora-TW/106/refactor-login-para-s…
Browse files Browse the repository at this point in the history
…erver-side

106/refactor login para server side
  • Loading branch information
stephanybrazeir0 authored Feb 11, 2025
2 parents 839984e + 13ac547 commit da5466e
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 98 deletions.
14 changes: 6 additions & 8 deletions src/app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import NextAuth from "next-auth"
import { getAuthProviders } from "../../../helpers/providers";
import { getAuthProviders } from "../../../helpers/providers"

const handler = NextAuth({
providers: getAuthProviders(),

callbacks: {
async jwt({ token, user, account }) {
if (user && account) {
token.id = user.id;
token.provider = account.provider;
token.accessToken = account.access_token;
token.id = user.id
token.provider = account.provider
token.accessToken = account.access_token
}
return token;
return token
},
},
});

})

export { handler as GET, handler as POST }
18 changes: 9 additions & 9 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,29 @@ const menuItems = ["Nivelamento", "Autoestudo"];

const inter = Inter({ subsets: ["latin"] });

export const session = async () => await getServerSession()

export const metadata: Metadata = {
title: "E-acelera - Plataforma de Estudo para Desenvolvedores",
description:
"O E-acelera é uma plataforma inovadora que faz parte do programa Aceleradora Ágil. A plataforma oferece nivelamentos e desafios para desenvolvedores aprimorarem suas habilidades em programação.",
};

export default function RootLayout({
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const session = await getServerSession()

return (
<html lang="pt-br">
<body className={inter.className}>
<ClientSessionProvider>
<ThemeProvider theme={theme}>
<Box sx={{ marginBottom: "80px" }}>
<ResponsiveAppBar list={menuItems} />
</Box>
{children}
</ThemeProvider>
<ThemeProvider theme={theme}>
<Box sx={{ marginBottom: "80px" }}>
<ResponsiveAppBar list={menuItems} session={session} />
</Box>
{children}
</ThemeProvider>
</ClientSessionProvider>
</body>
</html>
Expand Down
42 changes: 6 additions & 36 deletions src/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,13 @@
"use client"

import { CardLogin } from "@/components/CardLogin"
import { LayoutPage } from "@/components/PageElements/LayoutPage"
import { useSession } from "next-auth/react"
import { useRouter, useSearchParams } from "next/navigation"
import { Suspense, useEffect } from "react"
import { Loading } from "@/components/Loading"

function LoginContent() {
const { data: session, status } = useSession()
const router = useRouter()
const searchParams = useSearchParams()
const callbackUrl = searchParams?.get("callbackUrl") || "/"

useEffect(() => {
if (status === "authenticated") {
router.push(callbackUrl)
}
}, [status, router, callbackUrl])


if (status === "loading") {
return <Loading />
}
export default function LoginPage() {

if (status === "unauthenticated") {
return (
<LayoutPage>
<CardLogin />
</LayoutPage>
)
}

return null
return (
<LayoutPage>
<CardLogin />
</LayoutPage>
)
}

export default function Login() {

return (<Suspense fallback={<Loading />}>
<LoginContent />
</Suspense>)
}
18 changes: 11 additions & 7 deletions src/components/NavBar/WebNavBar/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { WebMenu } from '@/components/NavBar/WebNavBar'
import { WebMenu } from '@/components/NavBar/WebNavBar'
import { useSession } from 'next-auth/react'

jest.mock('next/image', () => ({
Expand All @@ -27,9 +27,9 @@ describe('Testes do botão de Login do componente WebMenu', () => {
it('Deve mostrar o botão de login quando não houver sessão', () => {
(useSession as jest.Mock).mockReturnValue({ data: null })

render(<WebMenu list={['Nivelamento', 'Autoestudo']} />)
render(<WebMenu list={['Nivelamento', 'Autoestudo']} session={null} />)

const loginButton = screen.queryByText('LOGIN')
const loginButton = screen.getByRole('button', { name: /login/i })
expect(loginButton).toBeInTheDocument()
})

Expand All @@ -39,13 +39,17 @@ describe('Testes do botão de Login do componente WebMenu', () => {
user: {
image: 'url-da-imagem',
name: 'Usuário Teste'
}
},
expires: '2025-01-01T00:00:00Z'
}
})

render(<WebMenu list={['Nivelamento', 'Autoestudo']} />)
render(<WebMenu list={['Nivelamento', 'Autoestudo']} session={{
user: { image: 'url-da-imagem', name: 'Usuário Teste' },
expires: '2025-01-01T00:00:00Z'
}} />)

const loginButton = screen.queryByText('LOGIN')
const loginButton = screen.queryByRole('button', { name: /login/i })
expect(loginButton).not.toBeInTheDocument()
})
})
})
5 changes: 3 additions & 2 deletions src/components/NavBar/WebNavBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown"
import { useSession, signOut } from "next-auth/react"
import { useState } from "react"
import LogoutIcon from "@mui/icons-material/Logout"
import { Session } from "next-auth"

interface WebMenuProps {
list: string[]
session: Session | null
}

export const WebMenu: React.FC<WebMenuProps> = ({ list }) => {
export const WebMenu: React.FC<WebMenuProps> = ({ list, session }) => {
const router = useRouter()
const pathname = usePathname()
const { data: session } = useSession()
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null)

const handleOpenMenu = (event: React.MouseEvent<HTMLElement>) => {
Expand Down
52 changes: 16 additions & 36 deletions src/components/NavBar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,19 @@
"use client";
import React, { useState } from "react";
import AppBar from "@mui/material/AppBar";
import Toolbar from "@mui/material/Toolbar";
import Container from "@mui/material/Container";
import { Box, Avatar, Menu, MenuItem, Typography, IconButton, Tooltip } from "@mui/material";
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
import { theme } from "../../app/config/theme";
import { MobileMenu } from "./MobileNavBar";
import { WebMenu } from "./WebNavBar";
import { useSession, signOut } from "next-auth/react";
import LogoutIcon from '@mui/icons-material/Logout';
import Divider from '@mui/material/Divider';

"use client"
import AppBar from "@mui/material/AppBar"
import Toolbar from "@mui/material/Toolbar"
import Container from "@mui/material/Container"
import { Box } from "@mui/material"
import { theme } from "../../app/config/theme"
import { MobileMenu } from "./MobileNavBar"
import { WebMenu } from "./WebNavBar"
import { Session } from "next-auth"

interface NavBarProps {
list: string[];
list: string[]
session: Session | null
}


const ResponsiveAppBar: React.FC<NavBarProps> = ({ list }) => {
const { data: session } = useSession();
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);


const handleOpenMenu = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};


const handleCloseMenu = () => {
setAnchorEl(null);
};

const ResponsiveAppBar: React.FC<NavBarProps> = ({ list, session }) => {

return (
<AppBar
Expand All @@ -44,16 +26,14 @@ const ResponsiveAppBar: React.FC<NavBarProps> = ({ list }) => {
disableGutters
sx={{ display: "flex", alignItems: "center" }}
>

<MobileMenu list={list} />
<WebMenu list={list} />

<WebMenu list={list} session={session} />
</Toolbar>
</Container>
</Box>
</AppBar>
);
};
)
}


export default ResponsiveAppBar;
export default ResponsiveAppBar
23 changes: 23 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"

export async function middleware(request: NextRequest) {
const sessionToken =
request.cookies.get("next-auth.session-token") ||
request.cookies.get("__Secure-next-auth.session-token")

const callbackUrl =
new URLSearchParams(request.nextUrl.search).get("callbackUrl") || "/"

const parsedUrl = new URL(callbackUrl, request.url)

if (request.nextUrl.pathname.startsWith("/login") && sessionToken) {
return NextResponse.redirect(parsedUrl)
}

return NextResponse.next()
}

export const config = {
matcher: ["/login"],
}
13 changes: 13 additions & 0 deletions src/types/next-auth.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import NextAuth, { DefaultSession } from "next-auth";

declare module "next-auth" {
/**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
*/
interface Session {
user: {
/** Oauth access token */
token?: accessToken;
} & DefaultSession["user"];
}
}

0 comments on commit da5466e

Please sign in to comment.