Skip to content

Commit

Permalink
[SKP-143-apple-login-reissue] 애플로그인 수정 및 탈퇴 (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
imeureka authored Aug 21, 2024
2 parents 345c757 + 3ec0bd2 commit a6610b4
Show file tree
Hide file tree
Showing 44 changed files with 908 additions and 51 deletions.
10 changes: 10 additions & 0 deletions ios/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
PODS:
- BEMCheckBox (1.4.1)
- boost (1.83.0)
- DoubleConversion (1.1.6)
- FBLazyVector (0.74.3)
Expand Down Expand Up @@ -1193,6 +1194,9 @@ PODS:
- React-Core
- RNCAsyncStorage (1.24.0):
- React-Core
- RNCCheckbox (0.5.17):
- BEMCheckBox (~> 1.4)
- React-Core
- RNGestureHandler (2.17.1):
- DoubleConversion
- glog
Expand Down Expand Up @@ -1325,6 +1329,7 @@ DEPENDENCIES:
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- "RNAppleAuthentication (from `../node_modules/@invertase/react-native-apple-authentication`)"
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- "RNCCheckbox (from `../node_modules/@react-native-community/checkbox`)"
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNReanimated (from `../node_modules/react-native-reanimated`)
- RNScreens (from `../node_modules/react-native-screens`)
Expand All @@ -1334,6 +1339,7 @@ DEPENDENCIES:

SPEC REPOS:
trunk:
- BEMCheckBox
- SocketRocket

EXTERNAL SOURCES:
Expand Down Expand Up @@ -1454,6 +1460,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/@invertase/react-native-apple-authentication"
RNCAsyncStorage:
:path: "../node_modules/@react-native-async-storage/async-storage"
RNCCheckbox:
:path: "../node_modules/@react-native-community/checkbox"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNReanimated:
Expand All @@ -1468,6 +1476,7 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"

SPEC CHECKSUMS:
BEMCheckBox: 5ba6e37ade3d3657b36caecc35c8b75c6c2b1a4e
boost: d3f49c53809116a5d38da093a8aa78bf551aed09
DoubleConversion: 76ab83afb40bddeeee456813d9c04f67f78771b5
FBLazyVector: 7e977dd099937dc5458851233141583abba49ff2
Expand Down Expand Up @@ -1526,6 +1535,7 @@ SPEC CHECKSUMS:
ReactCommon: f00e436b3925a7ae44dfa294b43ef360fbd8ccc4
RNAppleAuthentication: e99eaf3c4c01ad8ecb6125dd6f0cfd98871685b5
RNCAsyncStorage: ec53e44dc3e75b44aa2a9f37618a49c3bc080a7a
RNCCheckbox: a3ca9978cb0846b981d28da4e9914bd437403d77
RNGestureHandler: 8dbcccada4a7e702e7dec9338c251b1cf393c960
RNReanimated: f4ff116e33e0afc3d127f70efe928847c7c66355
RNScreens: 5aeecbb09aa7285379b6e9f3c8a3c859bb16401c
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@gorhom/bottom-sheet": "^4",
"@invertase/react-native-apple-authentication": "^2.3.0",
"@react-native-async-storage/async-storage": "^1.24.0",
"@react-native-community/checkbox": "^0.5.17",
"@react-navigation/bottom-tabs": "^6.6.0",
"@react-navigation/native": "^6.1.17",
"@react-navigation/native-stack": "^6.10.0",
Expand Down
24 changes: 18 additions & 6 deletions src/apis/authApi.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {axiosApi} from './client';
import {AuthResponseDto} from '../types/dtos/auth';
import {AuthResponseDto, DeleteAccountResponseDto} from '../types/dtos/auth';

export const authApi = {
postLoginUser: async (body: {
Expand All @@ -12,14 +12,26 @@ export const authApi = {
};
}): Promise<AuthResponseDto> => {
const response = await axiosApi.post(`/api/auth/apple/login`, body);
console.log(response.data.result);

return response.data.result;
},

deleteAccount: async () => {
const response = await axiosApi.post('/api/user/withdrawal');
return response.data.result;
},

postLogoutUser: async (body: {refreshToken: string}) => {
const response = await axiosApi.post('/api/auth/logoutt', {
refreshToken: body.refreshToken,
});
deleteAppleId: async (body: {
state: null;
code: string | null;
id_token: string;
user: {
email: string | null;
name: {firstName: string | null; lastName: string | null};
};
}): Promise<DeleteAccountResponseDto> => {
const response = await axiosApi.post(`/api/auth/apple/revoke`, body);

return response.data.result;
},
};
81 changes: 62 additions & 19 deletions src/apis/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const axiosApi = axios.create({
axiosApi.interceptors.request.use(
async config => {
const accessToken: string = await localStorage.get(TokenKeys.AccessToken);
console.log(accessToken);
console.log('어쎄스 토큰 : ', accessToken);

if (accessToken) {
config.headers.Authorization = `Bearer ${accessToken}`;
Expand All @@ -38,30 +38,73 @@ const onFulfilled = (res: AxiosResponse) => {
return res;
};

const onRejected = async (error: AxiosError) => {
const originalConfig = error.config;
let isRefreshing = false;
let failedQueue: any[] = [];

const refreshToken = (await localStorage.get(
TokenKeys.RefreshToken,
)) as string;
const processQueue = (error: any, token: string | null = null) => {
failedQueue.forEach(prom => {
if (error) {
prom.reject(error);
} else {
prom.resolve(token);
}
});

const statusArray = [4100, 4101, 4102, 4103, 4104];
failedQueue = [];
};

if (originalConfig && statusArray.includes(error.response?.status || 0)) {
try {
const response = await axiosApi.post('/api/auth/jwt/reissue', {
refreshToken,
});
const {result} = response.data.result;

localStorage.set(TokenKeys.AccessToken, result.accessToken);
localStorage.set(TokenKeys.RefreshToken, result.refreshToken);

originalConfig.headers.Authorization = `Bearer ${result.accessToken}`;
const onRejected = async (error: AxiosError) => {
const originalConfig = error.config;
if (error.response?.status === 500) {
return Promise.reject(error);
}

return axiosApi(originalConfig);
} catch (e) {
return Promise.reject(e);
if (originalConfig && error.response?.status === 401) {
if (!isRefreshing) {
isRefreshing = true;

try {
const refreshToken = await localStorage.get(TokenKeys.RefreshToken);
console.log('만료됐슴당~~ 내가 보내는 리프레쉬 토큰', refreshToken);

const response = await axiosApi.post('/api/auth/jwt/reissue', {
refreshToken,
});

const result = response.data.result;
console.log('이건 새로운 어쎄스 토큰', result.accessToken);

await localStorage.set(TokenKeys.AccessToken, result.accessToken);
const acc: string = await localStorage.get(TokenKeys.AccessToken);
console.log('이건 새롭게 저장된 어쎼스 토큰', acc);

//리프레쉬 토큰조차 만료되면 로그인 화면으로 ->

axiosApi.defaults.headers.common['Authorization'] = `Bearer ${acc}`;
originalConfig.headers.Authorization = `Bearer ${acc}`;

processQueue(null, result.accessToken);

return axiosApi(originalConfig);
} catch (err) {
processQueue(err, null);
return Promise.reject(err);
} finally {
isRefreshing = false;
}
} else {
return new Promise(function (resolve, reject) {
failedQueue.push({resolve, reject});
})
.then(token => {
originalConfig.headers.Authorization = 'Bearer ' + token;
return axiosApi(originalConfig);
})
.catch(err => {
return Promise.reject(err);
});
}
}

Expand Down
11 changes: 11 additions & 0 deletions src/assets/icon/ic_apple.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/icon/ic_profile.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icon/ic_right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/icon/ic_warning.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/icon/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,8 @@ export {default as IcCardHistory} from './ic_card_history.svg';
export {default as IcCardNature} from './ic_card_nature.svg';
export {default as IcCardRest} from './ic_card_rest.svg';
export {default as IcCardShopping} from './ic_card_shopping.svg';

export {default as IcRight} from './ic_right.svg';
export {default as IcProfile} from './ic_profile.svg';
export {default as IcApple} from './ic_apple.svg';
export {default as IcWarning} from './ic_warning.svg';
15 changes: 14 additions & 1 deletion src/components/Login/AppleLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import {userInfoState} from '../../libs/recoil/states/userInfo';
import {authState} from '../../libs/recoil/states/auth';
import styles from './AppleLogin.style';
import {View} from 'react-native';
import {userAppleInfoState} from '../../libs/recoil/states/userAppleInfo';

function AppleLogin() {
const {setAuthData} = useAuthStorage();
const setUserInfo = useSetRecoilState(userInfoState);
const setAuth = useSetRecoilState(authState);
const {authMutation} = useSocialLoginMutation();
const setUserAppleInfo = useSetRecoilState(userAppleInfoState);

const handlePressAppleLoginButton = async () => {
try {
Expand Down Expand Up @@ -51,8 +53,19 @@ function AppleLogin() {
onSuccess: async ({accessToken, refreshToken}) => {
setAuthData({accessToken, refreshToken});
setUserInfo({username});

setAuth({isAuthenticated: true});

setUserAppleInfo({
email: email || '',
user: user || '',
fullName: {
firstName: fullName?.givenName || '',
lastName: fullName?.familyName || '',
},
identityToken: idToken,
authorizationCode: code || '',
});
console.log(idToken);
},
},
);
Expand Down
38 changes: 38 additions & 0 deletions src/components/Settings/Profile.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {StyleSheet} from 'react-native';
import {theme} from '../../styles';
import {flexBox} from '../../styles/common';

const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 100,
backgroundColor: theme.palette.white,
},
loadingContainer: {},
profileSection: {
...flexBox('row', 'flex-start'),
paddingLeft: 20,
paddingBottom: 20,
},
profileTextContainer: {
marginLeft: 15,
gap: 5,
},
name: {
fontSize: 18,
fontWeight: 'bold',
},
emailContainer: {
...flexBox('row', 'center'),
},
email: {
fontSize: 14,
color: theme.palette.gray5,
marginRight: 5,
},
appleIcon: {
marginLeft: 5,
},
});

export default styles;
29 changes: 29 additions & 0 deletions src/components/Settings/Profile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import {View, Text} from 'react-native';
import {IcApple, IcProfile} from '../../assets/icon';
import styles from './Profile.style';

type ProfileProps = {
userInfo: {
name: string;
email: string;
provider: string;
};
};

export default function Profile({userInfo}: ProfileProps) {
return (
<View style={styles.profileSection}>
<IcProfile width={60} height={60} />
<View style={styles.profileTextContainer}>
<Text style={styles.name}>{userInfo.name}</Text>
<View style={styles.emailContainer}>
<Text style={styles.email}>{userInfo.email}</Text>
{userInfo.provider === 'APPLE' && (
<IcApple width={18} height={18} style={styles.appleIcon} />
)}
</View>
</View>
</View>
);
}
Loading

0 comments on commit a6610b4

Please sign in to comment.