Skip to content

Commit 7f1cd21

Browse files
harryk-imgxxrxn
authored andcommitted
[#608] 페이지 접근 권한 부여 (#611)
* fix: accessToken 유무에 따라 내 그룹 목록 요청이가도록 쿼리 옵션 추가 * feat: 권한이 없는 페이지 접근 시 redirect 시키는 고차 컴포넌트 작성 * feat: 접근 권한이 필요한 페이지 withAuthRequired 고차 컴포넌트 적용 * refactor: HOC를 export default 부분에서 사용
1 parent bac4ff2 commit 7f1cd21

File tree

8 files changed

+76
-27
lines changed

8 files changed

+76
-27
lines changed

src/app/group/[groupId]/edit/page.tsx

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,10 @@ import {
1010
import type { APIGroupDetail, APIEditBookGroup } from '@/types/group';
1111

1212
import { SERVICE_ERROR_MESSAGE } from '@/constants';
13-
import {
14-
checkAuthentication,
15-
isAxiosErrorWithCustomCode,
16-
} from '@/utils/helpers';
17-
13+
import { isAxiosErrorWithCustomCode } from '@/utils/helpers';
1814
import useToast from '@/v1/base/Toast/useToast';
15+
16+
import withAuthRequired from '@/hocs/withAuthRequired';
1917
import BookGroupEditDateForm from '@/v1/bookGroup/edit/BookGroupEditDateForm';
2018
import BookGroupEditIntroduceForm from '@/v1/bookGroup/edit/BookGroupEditIntroduceForm';
2119
import BookGroupEditTitleForm from '@/v1/bookGroup/edit/BookGroupEditTitleForm';
@@ -28,13 +26,15 @@ const BookGroupEditPage = ({
2826
}) => {
2927
const router = useRouter();
3028

31-
const isAuthenticated = checkAuthentication();
32-
3329
const { data: bookGroupData } = useBookGroupEditCurrentInfo(groupId);
3430
const { isOwner, title, description, maxMemberCount, startDate, endDate } =
3531
bookGroupData;
3632

37-
if (!isAuthenticated || !isOwner) {
33+
/**
34+
* @todo
35+
* 401 페이지 만들기 (접근 권한이 없어요)
36+
*/
37+
if (!isOwner) {
3838
notFound();
3939
}
4040

@@ -99,4 +99,4 @@ const BookGroupEditPage = ({
9999
);
100100
};
101101

102-
export default BookGroupEditPage;
102+
export default withAuthRequired(BookGroupEditPage);

src/app/group/[groupId]/join/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { SubmitHandler, useForm } from 'react-hook-form';
66
import useJoinBookGroup from '@/hooks/group/useJoinBookGroup';
77

88
import SSRSafeSuspense from '@/components/SSRSafeSuspense';
9+
import withAuthRequired from '@/hocs/withAuthRequired';
10+
911
import Loading from '@/v1/base/Loading';
1012
import Input from '@/v1/base/Input';
1113
import InputLength from '@/v1/base/InputLength';
@@ -36,6 +38,8 @@ const JoinBookGroupPage = ({
3638
);
3739
};
3840

41+
export default withAuthRequired(JoinBookGroupPage);
42+
3943
const BookGroupJoinForm = ({ groupId }: { groupId: number }) => {
4044
const router = useRouter();
4145
const { isMember, hasPassword, question, joinBookGroup } =
@@ -100,5 +104,3 @@ const BookGroupJoinForm = ({ groupId }: { groupId: number }) => {
100104
</form>
101105
);
102106
};
103-
104-
export default JoinBookGroupPage;

src/app/group/create/page.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
'use client';
2+
3+
import withAuthRequired from '@/hocs/withAuthRequired';
4+
15
import CreateBookGroupFunnel from '@/v1/bookGroup/create/CreateBookGroupFunnel';
26

37
const GroupCreateFunnelPage = () => {
48
return <CreateBookGroupFunnel />;
59
};
610

7-
export default GroupCreateFunnelPage;
11+
export default withAuthRequired(GroupCreateFunnelPage);

src/app/profile/me/add/page.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ import useAllJobQuery from '@/queries/job/useAllJobQuery';
44

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

7-
import AddJobProfile from '@/v1/profile/AddJobProfile';
87
import SSRSafeSuspense from '@/components/SSRSafeSuspense';
8+
import withAuthRequired from '@/hocs/withAuthRequired';
9+
10+
import AddJobProfile from '@/v1/profile/AddJobProfile';
911

1012
const AddJobProfilePage = () => {
1113
return (
@@ -15,6 +17,8 @@ const AddJobProfilePage = () => {
1517
);
1618
};
1719

20+
export default withAuthRequired(AddJobProfilePage);
21+
1822
const Contents = () => {
1923
const isAuthenticated = checkAuthentication();
2024
const allJobQuery = useAllJobQuery({ enabled: isAuthenticated });
@@ -23,5 +27,3 @@ const Contents = () => {
2327
<AddJobProfile jobCategories={allJobQuery.data.jobGroups} />
2428
) : null;
2529
};
26-
27-
export default AddJobProfilePage;

src/app/profile/me/edit/page.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,22 @@ import useMyProfileQuery from '@/queries/user/useMyProfileQuery';
55

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

8-
import EditProfile from '@/v1/profile/EditProfile';
98
import SSRSafeSuspense from '@/components/SSRSafeSuspense';
9+
import withAuthRequired from '@/hocs/withAuthRequired';
1010

11-
/**
12-
* @todo
13-
* Fallback UI 추가하기
14-
*/
11+
import EditProfile from '@/v1/profile/EditProfile';
12+
import Loading from '@/v1/base/Loading';
1513

1614
const EditProfilePage = () => {
1715
return (
18-
<SSRSafeSuspense fallback={null}>
16+
<SSRSafeSuspense fallback={<Loading fullpage />}>
1917
<Contents />
2018
</SSRSafeSuspense>
2119
);
2220
};
2321

22+
export default withAuthRequired(EditProfilePage);
23+
2424
const Contents = () => {
2525
const isAuthenticated = checkAuthentication();
2626
const allJobQuery = useAllJobQuery({ enabled: isAuthenticated });
@@ -30,5 +30,3 @@ const Contents = () => {
3030
<EditProfile profile={profileData} jobGroups={allJobQuery.data.jobGroups} />
3131
) : null;
3232
};
33-
34-
export default EditProfilePage;

src/app/profile/me/group/page.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import useMyGroupsQuery from '@/queries/group/useMyGroupQuery';
44
import { checkAuthentication } from '@/utils/helpers';
55

66
import SSRSafeSuspense from '@/components/SSRSafeSuspense';
7+
import withAuthRequired from '@/hocs/withAuthRequired';
8+
79
import BackButton from '@/v1/base/BackButton';
810
import TopNavigation from '@/v1/base/TopNavigation';
911
import DetailBookGroupCard from '@/v1/bookGroup/DetailBookGroupCard';
@@ -24,6 +26,8 @@ const UserGroupPage = () => {
2426
);
2527
};
2628

29+
export default withAuthRequired(UserGroupPage);
30+
2731
const UserGroupContent = () => {
2832
const isAuthenticated = checkAuthentication();
2933
const { data } = useMyGroupsQuery({ enabled: isAuthenticated });
@@ -65,8 +69,6 @@ const UserGroupContent = () => {
6569
);
6670
};
6771

68-
export default UserGroupPage;
69-
7072
const PageSkeleton = () => (
7173
<ul className="flex animate-pulse flex-col gap-[1rem] pt-[2rem]">
7274
{Array.from({ length: 4 }).map((_, index) => (

src/hocs/withAuthRequired.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use client';
2+
3+
import { useRouter } from 'next/navigation';
4+
import { useEffect, useState } from 'react';
5+
6+
import { checkAuthentication } from '@/utils/helpers';
7+
8+
const withAuthRequired = <P extends object>(
9+
WrappedComponent: React.ComponentType<P>
10+
) => {
11+
const Component = (props: P) => {
12+
const router = useRouter();
13+
14+
const [isAuthenticated, setIsAuthenticated] = useState(false);
15+
16+
useEffect(() => {
17+
const hasAccessToken = checkAuthentication();
18+
19+
if (!hasAccessToken) {
20+
router.push('/login');
21+
} else {
22+
setIsAuthenticated(hasAccessToken);
23+
}
24+
}, [router]);
25+
26+
if (!isAuthenticated) {
27+
return null;
28+
} else {
29+
return <WrappedComponent {...props} />;
30+
}
31+
};
32+
33+
return Component;
34+
};
35+
36+
export default withAuthRequired;

src/v1/profile/group/ProfileGroupContainer.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import useMyGroupsQuery from '@/queries/group/useMyGroupQuery';
22
import useMyProfileQuery from '@/queries/user/useMyProfileQuery';
3-
import { APIUser } from '@/types/user';
3+
import type { APIUser } from '@/types/user';
4+
5+
import { checkAuthentication } from '@/utils/helpers';
6+
47
import ProfileGroupPresenter from './ProfileGroupPresenter';
58

69
const ProfileGroupContainer = ({
710
userId,
811
}: {
912
userId: 'me' | APIUser['userId'];
1013
}) => {
11-
const { data } = useMyGroupsQuery();
14+
const isAuthenticated = checkAuthentication();
15+
16+
const { data } = useMyGroupsQuery({ enabled: isAuthenticated });
1217
const {
1318
data: { userId: myId },
1419
} = useMyProfileQuery({ enabled: userId === 'me' });

0 commit comments

Comments
 (0)