Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#285 로그인 확인 미들웨어 작성 및 로그인 페이지 변경 #286

Merged
merged 9 commits into from
Feb 9, 2024
10 changes: 2 additions & 8 deletions src/components/Sidebar/ChannelBar/ChannelBar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { DragDropContext, Droppable, Draggable, DropResult } from '@hello-pangea/dnd';
import styled from '@emotion/styled';
import { css } from '@emotion/react';

import SelectChannelType from '@components/Sidebar/ChannelBar/SelectChannelType';
import ChannelCircle from '@components/Sidebar/ChannelCircle/ChannelCircle';
import { ChannelCircleProps } from '@type/channelCircle';
import useChannels from '@hooks/useChannels';
import Modal from '@components/Modal';
import Icon from '@components/Icon';
Expand All @@ -13,14 +11,10 @@ import useMakeGame from '@hooks/useMakeGame';
import MainChannelCircle from '../ChannelCircle/MainChannelCircle';
import { useRouter } from 'next/router';

interface ChannelBarProps {
channels: ChannelCircleProps[];
}

const ChannelBar = ({ channels }: ChannelBarProps) => {
const ChannelBar = () => {
const router = useRouter();

const { dragAndDropChannels } = useChannels();
const { channels, dragAndDropChannels } = useChannels();
const { openModal, closeModal } = useModals();

const { resetState } = useMakeGame();
Expand Down
78 changes: 33 additions & 45 deletions src/components/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,83 +1,71 @@
import { PropsWithChildren, useEffect, useState } from 'react';
import { PropsWithChildren } from 'react';
import styled from '@emotion/styled';

import ChannelBar from '@components/Sidebar/ChannelBar/ChannelBar';
import BoardBar from '@components/Sidebar/BoardBar/BoardBar';
import GlobalStyle from 'src/styles/GlobalStyle';
import Header from '@components/Header/Header';
import useChannels from '@hooks/useChannels';
import useProfile from '@hooks/useProfile';
import NoAuthMain from './Main/NoAuthMain';
import Loading from './Loading/Loading';

import { useRouter } from 'next/router';
import ChannelsProvider from './providers/ChannelsProvider';
import ProfileProvider from './providers/ProfileProvider';
import LastVisitedBoardListsProvider from './providers/LastVisitedBoardListsProvider';
import MakeGameProvider from './providers/MakeGameProvider';

const Layout = ({ children }: PropsWithChildren) => {
const router = useRouter();

const { channels } = useChannels();

const { status } = useProfile();

// 요청했을 때만
if (status === 'pending') {
return (
<>
<CommonLayout>
<GlobalStyle />
<Loading />
</CommonLayout>
</>
);
}

if (status === 'error') {
if (router.pathname.startsWith('/login')) {
return (
<>
<GlobalStyle />
<CommonLayout>
<GlobalStyle />
<NoAuthMain />
<Wrapper>{children}</Wrapper>
</CommonLayout>
</>
);
}

return (
<AuthLayout>
<LayoutContainer>
<ChannelsProvider>
<ProfileProvider>
<LastVisitedBoardListsProvider>
<MakeGameProvider>
<CommonLayout>
<SidebarWrapper>
<ChannelBar />
</SidebarWrapper>
<SidebarWrapper>
<BoardBar />
</SidebarWrapper>
<Wrapper>
<Header />
<Main>{children}</Main>
</Wrapper>
</CommonLayout>
</MakeGameProvider>
</LastVisitedBoardListsProvider>
</ProfileProvider>
</ChannelsProvider>
<GlobalStyle />
<AuthCommonLayout>
<SidebarWrapper>{channels && <ChannelBar channels={channels} />}</SidebarWrapper>
<SidebarWrapper>
<BoardBar />
</SidebarWrapper>
<Wrapper>
<Header />
<Main>{children}</Main>
</Wrapper>
</AuthCommonLayout>
</AuthLayout>
</LayoutContainer>
);
};

const AuthLayout = styled.div`
const LayoutContainer = styled.div`
padding: 2rem;
background-color: ${({ theme }) => theme.bg};
`;

const AuthCommonLayout = styled.div`
display: flex;
height: calc(100vh - 4rem);
`;

const CommonLayout = styled.div`
display: flex;
height: calc(100vh - 4rem);
`;

const Wrapper = styled.div`
width: 100%;
height: 100%;
/* background-image: url('/img/board/main.png');
background-size: 100% 100vh;
background-repeat: no-repeat; */
`;

const SidebarWrapper = styled.div`
Expand Down
3 changes: 0 additions & 3 deletions src/components/providers/ProfileProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useQuery } from '@tanstack/react-query';

import ProfileContext from '@contexts/ProfileContext';
import { Profile } from '@type/profile';
import Cookies from 'js-cookie';
import { fetchProfile } from '@apis/mypage';

interface ProfileAPI {
Expand All @@ -18,8 +17,6 @@ interface ProfileProviderProps {
const ProfileProvider = ({ children }: ProfileProviderProps) => {
// 유저가 로그인 되어있는지 확인

const isHaveAccessToken = Cookies.get('accessToken');

const [profile, setProfile] = useState<Profile | null>(null);

// 유저의 프로필 가져오기
Expand Down
14 changes: 14 additions & 0 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

export function middleware(request: NextRequest) {
if (!request.cookies.get('accessToken')) {
return NextResponse.redirect(new URL('/login', request.url));
}

return NextResponse.next();
}

export const config = {
matcher: ['/', '/mypage', '/contents/:channelLink*'],
};
45 changes: 13 additions & 32 deletions src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ import { useEffect, useState } from 'react';
import { HydrationBoundary, QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

import LastVisitedBoardListsProvider from '@components/providers/LastVisitedBoardListsProvider';
import ProfileProvider from '@components/providers/ProfileProvider';
import MakeGameProvider from '@components/providers/MakeGameProvider';
import ChannelsProvider from '@components/providers/ChannelsProvider';
import Layout from '@components/layout';
import ModalsProvider from '@components/providers/ModalProvider';
import ShowModals from '@components/Modal/showModals';
Expand All @@ -25,6 +21,7 @@ export default function MyApp({ Component, pageProps }: AppProps) {
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
staleTime: 0,
},
},
}),
Expand All @@ -47,20 +44,12 @@ export default function MyApp({ Component, pageProps }: AppProps) {
<QueryClientProvider client={queryClient}>
<HydrationBoundary state={pageProps.dehydratedState}>
<ReactQueryDevtools initialIsOpen={false} />
<ChannelsProvider>
<ProfileProvider>
<LastVisitedBoardListsProvider>
<MakeGameProvider>
<ModalsProvider>
<ShowModals />
<Layout>
<Component {...pageProps} />
</Layout>
</ModalsProvider>
</MakeGameProvider>
</LastVisitedBoardListsProvider>
</ProfileProvider>
</ChannelsProvider>
<ModalsProvider>
<ShowModals />
<Layout>
<Component {...pageProps} />
</Layout>
</ModalsProvider>
</HydrationBoundary>
</QueryClientProvider>
</MSWComponent>
Expand All @@ -73,20 +62,12 @@ export default function MyApp({ Component, pageProps }: AppProps) {
<QueryClientProvider client={queryClient}>
<HydrationBoundary state={pageProps.dehydratedState}>
<ReactQueryDevtools initialIsOpen={false} />
<ChannelsProvider>
<ProfileProvider>
<LastVisitedBoardListsProvider>
<MakeGameProvider>
<ModalsProvider>
<ShowModals />
<Layout>
<Component {...pageProps} />
</Layout>
</ModalsProvider>
</MakeGameProvider>
</LastVisitedBoardListsProvider>
</ProfileProvider>
</ChannelsProvider>
<ModalsProvider>
<ShowModals />
<Layout>
<Component {...pageProps} />
</Layout>
</ModalsProvider>
</HydrationBoundary>
</QueryClientProvider>
</ThemeProvider>
Expand Down
14 changes: 6 additions & 8 deletions src/pages/auth.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import axios from 'axios';
import { serialize } from 'cookie';
import { GetServerSideProps } from 'next';

import { Login } from '@type/login';
import { SERVER_URL } from '@config/index';

import { serialize } from 'cookie';
import { Login } from '@type/login';

const Auth = () => {
return <div></div>;
Expand All @@ -24,14 +23,14 @@ export const getServerSideProps: GetServerSideProps<{ data: Login }> = async (co

const { accessToken, refreshToken } = res.data;

const cookie1 = serialize('accessToken', accessToken, {
const accessTokens = serialize('accessToken', accessToken, {
maxAge: 60 * 60 * 24 * 7,
});
const cookie2 = serialize('refreshToken', refreshToken, {
const refreshTokens = serialize('refreshToken', refreshToken, {
maxAge: 60 * 60 * 24 * 7,
});

context.res.setHeader('set-Cookie', [cookie1, cookie2]);
context.res.setHeader('set-Cookie', [accessTokens, refreshTokens]);

return {
redirect: {
Expand All @@ -40,11 +39,10 @@ export const getServerSideProps: GetServerSideProps<{ data: Login }> = async (co
},
};
} catch (error) {
// 실패 시 login 페이지로 redirect
return {
redirect: {
permanent: false,
destination: '/',
destination: '/login',
},
};
}
Expand Down
4 changes: 2 additions & 2 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export default function Home() {
<List>
{data?.map((notice, index) => {
return (
<Item>
<ItemHeader key={index}>
<Item key={index}>
<ItemHeader>
<ItemIndex>{index + 1}.</ItemIndex>
<ItemLink href={notice.noticeLink} target='_blank'>
{notice.noticeTitle}
Expand Down
Loading
Loading