Skip to content

Commit

Permalink
[#608] 페이지 접근 권한 부여 (#611)
Browse files Browse the repository at this point in the history
* fix: accessToken 유무에 따라 내 그룹 목록 요청이가도록 쿼리 옵션 추가

* feat: 권한이 없는 페이지 접근 시 redirect 시키는 고차 컴포넌트 작성

* feat: 접근 권한이 필요한 페이지 withAuthRequired 고차 컴포넌트 적용

* refactor: HOC를 export default 부분에서 사용
  • Loading branch information
hanyugeon authored Jun 7, 2024
1 parent a417f47 commit 0a4dc5b
Show file tree
Hide file tree
Showing 8 changed files with 76 additions and 27 deletions.
18 changes: 9 additions & 9 deletions src/app/group/[groupId]/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ import {
import type { APIGroupDetail, APIEditBookGroup } from '@/types/group';

import { SERVICE_ERROR_MESSAGE } from '@/constants';
import {
checkAuthentication,
isAxiosErrorWithCustomCode,
} from '@/utils/helpers';

import { isAxiosErrorWithCustomCode } from '@/utils/helpers';
import useToast from '@/v1/base/Toast/useToast';

import withAuthRequired from '@/hocs/withAuthRequired';
import BookGroupEditDateForm from '@/v1/bookGroup/edit/BookGroupEditDateForm';
import BookGroupEditIntroduceForm from '@/v1/bookGroup/edit/BookGroupEditIntroduceForm';
import BookGroupEditTitleForm from '@/v1/bookGroup/edit/BookGroupEditTitleForm';
Expand All @@ -28,13 +26,15 @@ const BookGroupEditPage = ({
}) => {
const router = useRouter();

const isAuthenticated = checkAuthentication();

const { data: bookGroupData } = useBookGroupEditCurrentInfo(groupId);
const { isOwner, title, description, maxMemberCount, startDate, endDate } =
bookGroupData;

if (!isAuthenticated || !isOwner) {
/**
* @todo
* 401 페이지 만들기 (접근 권한이 없어요)
*/
if (!isOwner) {
notFound();
}

Expand Down Expand Up @@ -99,4 +99,4 @@ const BookGroupEditPage = ({
);
};

export default BookGroupEditPage;
export default withAuthRequired(BookGroupEditPage);
6 changes: 4 additions & 2 deletions src/app/group/[groupId]/join/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { SubmitHandler, useForm } from 'react-hook-form';
import useJoinBookGroup from '@/hooks/group/useJoinBookGroup';

import SSRSafeSuspense from '@/components/SSRSafeSuspense';
import withAuthRequired from '@/hocs/withAuthRequired';

import Loading from '@/v1/base/Loading';
import Input from '@/v1/base/Input';
import InputLength from '@/v1/base/InputLength';
Expand Down Expand Up @@ -36,6 +38,8 @@ const JoinBookGroupPage = ({
);
};

export default withAuthRequired(JoinBookGroupPage);

const BookGroupJoinForm = ({ groupId }: { groupId: number }) => {
const router = useRouter();
const { isMember, hasPassword, question, joinBookGroup } =
Expand Down Expand Up @@ -100,5 +104,3 @@ const BookGroupJoinForm = ({ groupId }: { groupId: number }) => {
</form>
);
};

export default JoinBookGroupPage;
6 changes: 5 additions & 1 deletion src/app/group/create/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
'use client';

import withAuthRequired from '@/hocs/withAuthRequired';

import CreateBookGroupFunnel from '@/v1/bookGroup/create/CreateBookGroupFunnel';

const GroupCreateFunnelPage = () => {
return <CreateBookGroupFunnel />;
};

export default GroupCreateFunnelPage;
export default withAuthRequired(GroupCreateFunnelPage);
8 changes: 5 additions & 3 deletions src/app/profile/me/add/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import useAllJobQuery from '@/queries/job/useAllJobQuery';

import { checkAuthentication } from '@/utils/helpers';

import AddJobProfile from '@/v1/profile/AddJobProfile';
import SSRSafeSuspense from '@/components/SSRSafeSuspense';
import withAuthRequired from '@/hocs/withAuthRequired';

import AddJobProfile from '@/v1/profile/AddJobProfile';

const AddJobProfilePage = () => {
return (
Expand All @@ -15,6 +17,8 @@ const AddJobProfilePage = () => {
);
};

export default withAuthRequired(AddJobProfilePage);

const Contents = () => {
const isAuthenticated = checkAuthentication();
const allJobQuery = useAllJobQuery({ enabled: isAuthenticated });
Expand All @@ -23,5 +27,3 @@ const Contents = () => {
<AddJobProfile jobCategories={allJobQuery.data.jobGroups} />
) : null;
};

export default AddJobProfilePage;
14 changes: 6 additions & 8 deletions src/app/profile/me/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@ import useMyProfileQuery from '@/queries/user/useMyProfileQuery';

import { checkAuthentication } from '@/utils/helpers';

import EditProfile from '@/v1/profile/EditProfile';
import SSRSafeSuspense from '@/components/SSRSafeSuspense';
import withAuthRequired from '@/hocs/withAuthRequired';

/**
* @todo
* Fallback UI 추가하기
*/
import EditProfile from '@/v1/profile/EditProfile';
import Loading from '@/v1/base/Loading';

const EditProfilePage = () => {
return (
<SSRSafeSuspense fallback={null}>
<SSRSafeSuspense fallback={<Loading fullpage />}>
<Contents />
</SSRSafeSuspense>
);
};

export default withAuthRequired(EditProfilePage);

const Contents = () => {
const isAuthenticated = checkAuthentication();
const allJobQuery = useAllJobQuery({ enabled: isAuthenticated });
Expand All @@ -30,5 +30,3 @@ const Contents = () => {
<EditProfile profile={profileData} jobGroups={allJobQuery.data.jobGroups} />
) : null;
};

export default EditProfilePage;
6 changes: 4 additions & 2 deletions src/app/profile/me/group/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import useMyGroupsQuery from '@/queries/group/useMyGroupQuery';
import { checkAuthentication } from '@/utils/helpers';

import SSRSafeSuspense from '@/components/SSRSafeSuspense';
import withAuthRequired from '@/hocs/withAuthRequired';

import BackButton from '@/v1/base/BackButton';
import TopNavigation from '@/v1/base/TopNavigation';
import DetailBookGroupCard from '@/v1/bookGroup/DetailBookGroupCard';
Expand All @@ -24,6 +26,8 @@ const UserGroupPage = () => {
);
};

export default withAuthRequired(UserGroupPage);

const UserGroupContent = () => {
const isAuthenticated = checkAuthentication();
const { data } = useMyGroupsQuery({ enabled: isAuthenticated });
Expand Down Expand Up @@ -65,8 +69,6 @@ const UserGroupContent = () => {
);
};

export default UserGroupPage;

const PageSkeleton = () => (
<ul className="flex animate-pulse flex-col gap-[1rem] pt-[2rem]">
{Array.from({ length: 4 }).map((_, index) => (
Expand Down
36 changes: 36 additions & 0 deletions src/hocs/withAuthRequired.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use client';

import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';

import { checkAuthentication } from '@/utils/helpers';

const withAuthRequired = <P extends object>(
WrappedComponent: React.ComponentType<P>
) => {
const Component = (props: P) => {
const router = useRouter();

const [isAuthenticated, setIsAuthenticated] = useState(false);

useEffect(() => {
const hasAccessToken = checkAuthentication();

if (!hasAccessToken) {
router.push('/login');
} else {
setIsAuthenticated(hasAccessToken);
}
}, [router]);

if (!isAuthenticated) {
return null;
} else {
return <WrappedComponent {...props} />;
}
};

return Component;
};

export default withAuthRequired;
9 changes: 7 additions & 2 deletions src/v1/profile/group/ProfileGroupContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import useMyGroupsQuery from '@/queries/group/useMyGroupQuery';
import useMyProfileQuery from '@/queries/user/useMyProfileQuery';
import { APIUser } from '@/types/user';
import type { APIUser } from '@/types/user';

import { checkAuthentication } from '@/utils/helpers';

import ProfileGroupPresenter from './ProfileGroupPresenter';

const ProfileGroupContainer = ({
userId,
}: {
userId: 'me' | APIUser['userId'];
}) => {
const { data } = useMyGroupsQuery();
const isAuthenticated = checkAuthentication();

const { data } = useMyGroupsQuery({ enabled: isAuthenticated });
const {
data: { userId: myId },
} = useMyProfileQuery({ enabled: userId === 'me' });
Expand Down

0 comments on commit 0a4dc5b

Please sign in to comment.