Skip to content

Commit

Permalink
fix: 401 에러 관련 수정 (#140) (#141)
Browse files Browse the repository at this point in the history
* fix: 드롭다운 색상 수정

* fix: 인증 관련 오류 수정

* fix: 글로벌 에러바운더리 추가

* chore: 주석 코드 리버트
  • Loading branch information
alstn2468 authored Aug 4, 2024
1 parent 2698fd6 commit 24e602d
Show file tree
Hide file tree
Showing 14 changed files with 93 additions and 57 deletions.
2 changes: 2 additions & 0 deletions apps/admin/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import SitePolicyPage from './pages/SitePolicyPage/SitePolicyPage';
import GiftRegisterPage from './pages/GiftRegisterPage';
import GiftIntroPage from './pages/GiftIntroPage';
import { useAuthAtom } from './atoms/useAuthAtom';
import GlobalErrorBoundary from './components/ErrorBoundary/GlobalErrorBoundary';

setDefaultOptions({ locale: ko });

Expand Down Expand Up @@ -138,6 +139,7 @@ const routes: RouteObject[] = [
</BooltiUIProvider>
</QueryClientProvider>
),
errorElement: <GlobalErrorBoundary />,
children: [...publicRoutes, ...privateRoutes],
},
];
Expand Down
23 changes: 11 additions & 12 deletions apps/admin/src/atoms/useAuthAtom.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { LOCAL_STORAGE } from '@boolti/api';
import { useAtom } from 'jotai';
import { atomWithStorage, RESET } from 'jotai/utils';
import { atom, useAtom } from 'jotai';

const storageMethod = {
getItem: (key: string, initialValue: string | null) => {
Expand All @@ -13,29 +12,29 @@ const storageMethod = {
window.localStorage.removeItem(key);
},
};
const accessTokenAtom = atomWithStorage<string | null>(
LOCAL_STORAGE.ACCESS_TOKEN,
window.localStorage.getItem(LOCAL_STORAGE.ACCESS_TOKEN),
storageMethod,
const accessTokenAtom = atom<string | null>(
storageMethod.getItem(LOCAL_STORAGE.ACCESS_TOKEN, null),
);
const refreshTokenAtom = atomWithStorage<string | null>(
LOCAL_STORAGE.REFRESH_TOKEN,
window.localStorage.getItem(LOCAL_STORAGE.REFRESH_TOKEN),
storageMethod,
const refreshTokenAtom = atom<string | null>(
storageMethod.getItem(LOCAL_STORAGE.REFRESH_TOKEN, null),
);

export const useAuthAtom = () => {
const [accessToken, setAccessToken] = useAtom(accessTokenAtom);
const [refreshToken, setRefreshToken] = useAtom(refreshTokenAtom);

const setToken = (accessToken: string, refreshToken: string) => {
storageMethod.setItem(LOCAL_STORAGE.ACCESS_TOKEN, accessToken);
storageMethod.setItem(LOCAL_STORAGE.REFRESH_TOKEN, refreshToken);
setAccessToken(accessToken);
setRefreshToken(refreshToken);
};

const removeToken = () => {
setAccessToken(RESET);
setRefreshToken(RESET);
storageMethod.removeItem(LOCAL_STORAGE.ACCESS_TOKEN);
storageMethod.removeItem(LOCAL_STORAGE.REFRESH_TOKEN);
setAccessToken(null);
setRefreshToken(null);
};

const isLogin = () => !!accessToken && !!refreshToken;
Expand Down
15 changes: 8 additions & 7 deletions apps/admin/src/components/AccountDeleteForm/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Button } from '@boolti/ui';
import Styled from './AccountDeleteForm.styles';
import { useForm } from 'react-hook-form';
import { useDeleteMe, useLogout } from '@boolti/api';
import { queryKeys, useDeleteMe, useLogout, useQueryClient } from '@boolti/api';
import { useAuthAtom } from '~/atoms/useAuthAtom';
import { useNavigate } from 'react-router-dom';
import { PATH } from '~/constants/routes';
Expand All @@ -20,11 +20,8 @@ const AccountDeleteForm = ({ oauthType, onClose }: AccountDeleteFormProps) => {

const deleteMeMutation = useDeleteMe();
const { removeToken } = useAuthAtom();
const logoutMutation = useLogout({
onSuccess: () => {
removeToken();
},
});
const queryClient = useQueryClient();
const logoutMutation = useLogout();
const {
register,
handleSubmit,
Expand All @@ -41,12 +38,16 @@ const AccountDeleteForm = ({ oauthType, onClose }: AccountDeleteFormProps) => {
appleIdAuthorizationCode = appleAuthData?.authorization.code;
}

await deleteMeMutation.mutateAsync({
deleteMeMutation.mutate({
reason: data.reason,
appleIdAuthorizationCode,
});

await logoutMutation.mutateAsync();

removeToken();
queryClient.removeQueries({ ...queryKeys.user.summary });

onClose();
navigate(PATH.INDEX);
};
Expand Down
23 changes: 23 additions & 0 deletions apps/admin/src/components/ErrorBoundary/GlobalErrorBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { isBooltiHTTPError } from '@boolti/api/src/BooltiHTTPError';
import { useEffect } from 'react';
import { Navigate, useRouteError } from 'react-router-dom';
import { PATH } from '~/constants/routes';

const GlobalErrorBoundary = () => {
const error = useRouteError();

useEffect(() => {
if (error instanceof Error && isBooltiHTTPError(error)) {
const errorMessage = '[BooltiHTTPError] errorTraceId:' + error.errorTraceId + '\n';
'[BooltiHTTPError] type' + error.type + '\n';
'[BooltiHTTPError] detail' + error.detail;
console.error(errorMessage);
return;
}
console.error(error);
});

return <Navigate to={PATH.INDEX} replace />;
};

export default GlobalErrorBoundary;
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ const UserProfileImageWrapper = styled.div`
}
`;

const UserProfileIconWrapper = styled.div`
display: flex;
justify-content: center;
align-items: center;
`;

const UserProfileImage = styled.img`
border-radius: 50%;
width: 100%;
Expand Down Expand Up @@ -63,6 +69,7 @@ const DropdownMenuItemButton = styled.button`
`;

export default {
UserProfileIconWrapper,
DropdownContainer,
UserProfileImageWrapper,
UserProfileImage,
Expand Down
17 changes: 10 additions & 7 deletions apps/admin/src/components/ProfileDropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useLogout } from '@boolti/api';
import { queryKeys, useLogout, useQueryClient } from '@boolti/api';
import { ChevronDownIcon, ChevronUpIcon, LogoutIcon, SettingIcon } from '@boolti/icon';
import { useConfirm, useDialog, useDropdown } from '@boolti/ui/src/hooks';
import { useNavigate } from 'react-router-dom';
Expand Down Expand Up @@ -39,11 +39,8 @@ const ProfileSVG = () => (
const ProfileDropdown = ({ image, open, disabledDropdown, onClick }: ProfileDropdownProps) => {
const { isOpen, toggleDropdown } = useDropdown();
const { removeToken } = useAuthAtom();
const logoutMutation = useLogout({
onSuccess: () => {
removeToken();
},
});
const queryClient = useQueryClient();
const logoutMutation = useLogout();
const navigate = useNavigate();
const confirm = useConfirm();
const settingDialog = useDialog();
Expand All @@ -63,7 +60,9 @@ const ProfileDropdown = ({ image, open, disabledDropdown, onClick }: ProfileDrop
<Styled.UserProfileImageWrapper>
{image ? <Styled.UserProfileImage src={image} alt="유저 프로필 이미지" /> : <ProfileSVG />}
</Styled.UserProfileImageWrapper>
{dropdownOpen ? <ChevronUpIcon /> : <ChevronDownIcon />}
<Styled.UserProfileIconWrapper className="icon-wrapper">
{dropdownOpen ? <ChevronUpIcon /> : <ChevronDownIcon />}
</Styled.UserProfileIconWrapper>
{dropdownOpen && !disabledDropdown && (
<Styled.DropdownMenuWrapper>
<Styled.DropdownMenuItemButton
Expand All @@ -89,6 +88,10 @@ const ProfileDropdown = ({ image, open, disabledDropdown, onClick }: ProfileDrop
});
if (result) {
await logoutMutation.mutateAsync();

removeToken();
queryClient.removeQueries({ ...queryKeys.user.summary });

navigate(PATH.INDEX, { replace: true });
}
}}
Expand Down
20 changes: 14 additions & 6 deletions apps/admin/src/pages/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { useLogout, useSettlementBanners, useShowList, useUserSummary } from '@boolti/api';
import {
queryKeys,
useLogout,
useQueryClient,
useSettlementBanners,
useShowList,
useUserSummary,
} from '@boolti/api';
import { BooltiLogo, ChevronRightIcon, LogoutIcon, SettingIcon } from '@boolti/icon';
import { Footer, useConfirm, useDialog } from '@boolti/ui';

Expand All @@ -22,11 +29,8 @@ const bannerDescription = {

const HomePage = () => {
const { removeToken } = useAuthAtom();
const logoutMutation = useLogout({
onSuccess: () => {
removeToken();
},
});
const logoutMutation = useLogout();
const queryClient = useQueryClient();

const settingDialog = useDialog();
const confirm = useConfirm();
Expand Down Expand Up @@ -98,6 +102,10 @@ const HomePage = () => {
});
if (result) {
await logoutMutation.mutateAsync();

removeToken();
queryClient.removeQueries({ ...queryKeys.user.summary });

navigate(PATH.INDEX, { replace: true });
}
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const InternalLink = styled(Link)`
const DropDownContainer = styled.div`
margin-left: auto;
svg {
.icon-wrapper > svg {
color: ${({ theme }) => theme.palette.grey.w};
}
`;
Expand Down
15 changes: 8 additions & 7 deletions apps/admin/src/pages/Landing/components/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useLogout, useUserSummary } from '@boolti/api';
import { queryKeys, useLogout, useQueryClient, useUserSummary } from '@boolti/api';
import { BooltiDark, CloseIcon, MenuIcon } from '@boolti/icon';
import { useTheme } from '@emotion/react';
import { useAtomValue } from 'jotai';
Expand Down Expand Up @@ -26,20 +26,21 @@ const Header = () => {
const theme = useTheme();
const isMobile = deviceWidth < parseInt(theme.breakpoint.mobile, 10);

const logout = useLogout({
onSuccess: () => {
removeToken();
},
});
const logoutMutation = useLogout();
const navigate = useNavigate();
const queryClient = useQueryClient();

const [isExpanded, setIsExpanded] = useState(false);
const { data } = useUserSummary({ enabled: isLogin() });
const { imagePath } = data ?? {};

const onClickAuthButton = async () => {
if (isLogin()) {
await logout.mutateAsync();
await logoutMutation.mutateAsync();

removeToken();
queryClient.removeQueries({ ...queryKeys.user.summary });

return;
}

Expand Down
1 change: 1 addition & 0 deletions packages/api/src/QueryClientProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export function QueryClientProvider({ children }: React.PropsWithChildren) {
queries: {
refetchOnWindowFocus: false,
retry: false,
staleTime: 5000,
useErrorBoundary: (error) => {
// 인증 관련 에러일 때만 ErrorBoundary를 사용한다.
return (
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const instance = ky.create({
afterResponse: [
async (request, options, response) => {
// access token이 만료되었을 때, refresh token으로 새로운 access token을 발급받는다.
if (!response.ok && response.status === 401) {
if (!response.ok && response.status === 401 && !request.url.includes('logout')) {
try {
const { accessToken, refreshToken } = await postRefreshToken();

Expand Down
4 changes: 3 additions & 1 deletion packages/api/src/mutations/useKakaoToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const postKakaoToken = ({ code }: PostKakaoTokenRequest) => {
};

const useKakaoToken = () =>
useMutation(({ code }: PostKakaoTokenRequest) => postKakaoToken({ code }), { retry: false });
useMutation(({ code }: PostKakaoTokenRequest) => postKakaoToken({ code }), {
retry: false,
});

export default useKakaoToken;
17 changes: 3 additions & 14 deletions packages/api/src/mutations/useLogout.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
import type { UseMutationOptions } from '@tanstack/react-query';
import { useMutation } from '@tanstack/react-query';

import { LOCAL_STORAGE } from '../constants';
import { fetcher } from '../fetcher';

const postLogout = () => fetcher.post('web/v1/logout');

const useLogout = (options?: UseMutationOptions) =>
useMutation(postLogout, {
...options,
onSuccess: (data, variables, context) => {
if (options?.onSuccess) {
options.onSuccess(data, variables, context);
} else {
window.localStorage.removeItem(LOCAL_STORAGE.ACCESS_TOKEN);
window.localStorage.removeItem(LOCAL_STORAGE.REFRESH_TOKEN);
}
},
});
const useLogout = () => {
return useMutation({ mutationFn: postLogout });
};

export default useLogout;
2 changes: 1 addition & 1 deletion packages/api/src/queries/useUserSummary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import { useQuery } from '@tanstack/react-query';
import { queryKeys } from '../queryKey';

const useUserSummary = ({ enabled }: { enabled?: boolean } = {}) =>
useQuery({ enabled, ...queryKeys.user.summary });
useQuery({ ...queryKeys.user.summary, enabled });

export default useUserSummary;

0 comments on commit 24e602d

Please sign in to comment.