Refactor auth utils for Cloud

Simplify signUpUtils.ts and signInUtils.ts by removing unnecessary code related to CORS proxies, optimizing for Supabase Cloud environment.
This commit is contained in:
gpt-engineer-app[bot]
2025-03-18 06:15:28 +00:00
parent 30730c5cd0
commit 613f6a49d7
6 changed files with 225 additions and 646 deletions

View File

@@ -1,208 +1,53 @@
import { supabase } from '@/lib/supabase';
import { parseResponse, showAuthToast, handleNetworkError } from '@/utils/auth';
import { getProxyType, isCorsProxyEnabled, getSupabaseUrl, getOriginalSupabaseUrl } from '@/lib/supabase/config';
import { showAuthToast } from '@/utils/auth';
/**
* 직접 API 호출을 통한 로그인 시도 (대체 방법)
* 로그인 기능 - Supabase Cloud 환경에 최적화
*/
export const signInWithDirectApi = async (email: string, password: string) => {
console.log('직접 API 호출로 로그인 시도');
console.log('Supabase Cloud 로그인 시도');
try {
// API 호출 URL 및 헤더 설정
const supabaseUrl = getOriginalSupabaseUrl(); // 원본 URL 사용
const proxyUrl = getSupabaseUrl(); // 프록시 적용된 URL
const supabaseKey = localStorage.getItem('supabase_key') || supabase.supabaseKey;
// 프록시 정보 로그
const usingProxy = isCorsProxyEnabled();
const proxyType = getProxyType();
console.log(`CORS 프록시 사용: ${usingProxy ? '예' : '아니오'}, 타입: ${proxyType}, 프록시 URL: ${proxyUrl}`);
// 실제 요청에 사용할 URL 결정 (항상 프록시 URL 사용)
const useUrl = usingProxy ? proxyUrl : supabaseUrl;
// URL에 auth/v1이 이미 포함되어있는지 확인
const baseUrl = useUrl.includes('/auth/v1') ? useUrl : `${useUrl}/auth/v1`;
// 토큰 엔드포인트 경로
const tokenUrl = `${baseUrl}/token?grant_type=password`;
console.log('로그인 API 요청 URL:', tokenUrl);
// 로그인 요청 보내기
const response = await fetch(tokenUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': supabaseKey
},
body: JSON.stringify({ email, password })
// Supabase Cloud를 통한 로그인 요청
const { data, error } = await supabase.auth.signInWithPassword({
email,
password
});
// 응답 상태 확인 및 로깅
console.log('로그인 응답 상태:', response.status);
// HTTP 상태 코드 확인
if (response.status === 401) {
console.log('로그인 실패: 인증 오류');
showAuthToast('로그인 실패', '이메일 또는 비밀번호가 올바르지 않습니다.', 'destructive');
return {
error: { message: '인증 실패: 이메일 또는 비밀번호가 올바르지 않습니다.' },
user: null
};
}
if (response.status === 404) {
console.warn('API 경로를 찾을 수 없음 (404). 새 엔드포인트 시도 중...');
// 오류 응답 처리
if (error) {
console.error('로그인 오류:', error);
// 대체 엔드포인트 시도 (/token 대신 /signin)
const signinUrl = `${baseUrl}/signin`;
// 오류 메시지 포맷팅
let errorMessage = error.message;
try {
const signinResponse = await fetch(signinUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'apikey': supabaseKey
},
body: JSON.stringify({ email, password })
});
console.log('대체 로그인 경로 응답 상태:', signinResponse.status);
if (signinResponse.status === 404) {
showAuthToast('로그인 실패', '서버 설정을 확인하세요: 인증 API 경로를 찾을 수 없습니다.', 'destructive');
return {
error: { message: '서버 설정 문제: 인증 API 경로를 찾을 수 없습니다. Supabase URL을 확인하세요.' },
user: null
};
}
// 대체 응답 처리
const signinData = await parseResponse(signinResponse);
if (signinData.error) {
showAuthToast('로그인 실패', signinData.error, 'destructive');
return { error: { message: signinData.error }, user: null };
}
if (signinData.access_token) {
await supabase.auth.setSession({
access_token: signinData.access_token,
refresh_token: signinData.refresh_token || ''
});
const { data: userData } = await supabase.auth.getUser();
showAuthToast('로그인 성공', '환영합니다!');
return { error: null, user: userData.user };
}
} catch (altError) {
console.error('대체 로그인 엔드포인트 오류:', altError);
if (error.message.includes('Invalid login credentials')) {
errorMessage = '이메일 또는 비밀번호가 올바르지 않습니다.';
} else if (error.message.includes('Email not confirmed')) {
errorMessage = '이메일 인증이 완료되지 않았습니다. 이메일을 확인해주세요.';
}
showAuthToast('로그인 실패', '서버 설정을 확인하세요: 인증 API 경로를 찾을 수 없습니다.', 'destructive');
return {
error: { message: '서버 경로를 찾을 수 없습니다. Supabase URL을 확인하세요.' },
user: null
};
}
// 응답 처리
const responseText = await response.text();
console.log('로그인 응답 내용:', responseText);
let responseData;
try {
// 응답이 비어있지 않은 경우에만 JSON 파싱 시도
responseData = responseText ? JSON.parse(responseText) : {};
} catch (e) {
console.warn('JSON 파싱 실패:', e, '원본 응답:', responseText);
if (response.status >= 200 && response.status < 300) {
// 성공 응답이지만 JSON이 아닌 경우 (빈 응답 등)
responseData = { success: true };
} else {
responseData = { error: '서버 응답을 처리할 수 없습니다' };
}
}
// 오류 응답 확인
if (responseData?.error) {
const errorMessage = responseData.error_description || responseData.error;
showAuthToast('로그인 실패', errorMessage, 'destructive');
return { error: { message: errorMessage }, user: null };
}
// 로그인 성공 응답 처리
if (response.ok && responseData?.access_token) {
try {
// 로그인 성공 시 Supabase 세션 설정
await supabase.auth.setSession({
access_token: responseData.access_token,
refresh_token: responseData.refresh_token || ''
});
// 사용자 정보 가져오기
const { data: userData } = await supabase.auth.getUser();
console.log('로그인 성공:', userData);
showAuthToast('로그인 성공', '환영합니다!');
return { error: null, user: userData.user };
} catch (sessionError) {
console.error('세션 설정 오류:', sessionError);
showAuthToast('로그인 후처리 오류', '로그인에 성공했지만 세션 설정에 실패했습니다.', 'destructive');
return { error: { message: '세션 설정 오류' }, user: null };
}
} else if (response.ok) {
// 응답 내용 없이 성공 상태인 경우
try {
// 사용자 세션 확인 시도
const { data: userData } = await supabase.auth.getUser();
if (userData.user) {
showAuthToast('로그인 성공', '환영합니다!');
return { error: null, user: userData.user };
} else {
// 세션은 있지만 사용자 정보가 없는 경우
showAuthToast('로그인 부분 성공', '로그인은 성공했지만 사용자 정보를 가져오지 못했습니다.', 'default');
return { error: { message: '사용자 정보 조회 실패' }, user: null };
}
} catch (userError) {
console.error('사용자 정보 조회 오류:', userError);
showAuthToast('로그인 후처리 오류', '로그인은 성공했지만 사용자 정보를 가져오지 못했습니다.', 'destructive');
return { error: { message: '사용자 정보 조회 실패' }, user: null };
}
// 로그인 성공 처리
if (data && data.user) {
console.log('로그인 성공:', data.user);
showAuthToast('로그인 성공', '환영합니다!');
return { error: null, user: data.user };
} else {
// 오류 응답이나 예상치 못한 응답 형식 처리
console.error('로그인 오류 응답:', responseData);
const errorMessage = responseData?.error_description ||
responseData?.error ||
responseData?.message ||
'로그인에 실패했습니다. 이메일과 비밀번호를 확인하세요.';
showAuthToast('로그인 실패', errorMessage, 'destructive');
return { error: { message: errorMessage }, user: null };
// 사용자 정보가 없는 경우 (드문 경우)
console.warn('로그인 성공했지만 사용자 정보가 없습니다');
showAuthToast('로그인 부분 성공', '로그인은 성공했지만 사용자 정보를 가져오지 못했습니다.', 'default');
return { error: { message: '사용자 정보 조회 실패' }, user: null };
}
} catch (fetchError) {
console.error('로그인 요청 중 fetch 오류:', fetchError);
} catch (error: any) {
console.error('로그인 요청 중 예외:', error);
const errorMessage = error.message || '로그인 중 오류가 발생했습니다.';
// 오류 발생 시 프록시 설정 확인 정보 출력
const usingProxy = isCorsProxyEnabled();
const proxyType = getProxyType();
console.log(`오류 발생 시 CORS 설정 - 프록시 사용: ${usingProxy ? '예' : '아니오'}, 타입: ${proxyType}`);
// Cloudflare 프록시 추천 메시지 추가
const errorMessage = handleNetworkError(fetchError);
let enhancedMessage = errorMessage;
if (!usingProxy || proxyType !== 'cloudflare') {
enhancedMessage = `${errorMessage} (설정에서 Cloudflare CORS 프록시 사용을 권장합니다)`;
}
showAuthToast('로그인 요청 실패', enhancedMessage, 'destructive');
return { error: { message: enhancedMessage }, user: null };
showAuthToast('로그인 요청 실패', errorMessage, 'destructive');
return { error: { message: errorMessage }, user: null };
}
};