1
0
forked from baron/baron-sso

로그인 전 계정조회

This commit is contained in:
2026-01-27 17:16:36 +09:00
parent c914fad405
commit 1a0dc74cb5
3 changed files with 113 additions and 87 deletions

View File

@@ -12,6 +12,7 @@ import '../../../core/services/audit_service.dart';
import '../../../core/services/web_auth_integration.dart';
import '../../../core/services/auth_proxy_service.dart';
import '../../../core/notifiers/auth_notifier.dart';
import '../../profile/domain/notifiers/profile_notifier.dart';
class LoginScreen extends ConsumerStatefulWidget {
final String? verificationToken;
@@ -272,19 +273,15 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
final jwt = res['sessionJwt'];
if (jwt != null && mounted) {
Navigator.of(context).pop(); // 로딩 닫기
final displayName = _getLoginIdFromJwt(jwt);
final dummyUser = DescopeUser(
'unknown', [], 0, displayName, null, '', false, '', false, {}, '', '', '', false, 'enabled', [], [], [],
);
final session = DescopeSession.fromJwt(jwt, jwt, dummyUser);
Descope.sessionManager.manageSession(session);
_onLoginSuccess(jwt);
}
} catch (e) {
if (mounted) Navigator.of(context).pop(); // 로딩 닫기
_showError("로그인 실패: ${e.toString().replaceFirst("Exception: ", "")}");
if (e.toString().contains("User not registered")) {
_showUnregisteredDialog();
} else {
_showError("로그인 실패: ${e.toString().replaceFirst("Exception: ", "")}");
}
}
}
@@ -303,7 +300,17 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
}
debugPrint("[Auth] Initiating Enchanted Link for: $loginId");
_startEnchantedFlow(loginId, isEmail: input.contains('@'));
// 링크 전송 전 사용자 존재 여부 체크 (백엔드에서 이미 처리하지만 에러 핸들링을 위해)
try {
await _startEnchantedFlow(loginId, isEmail: input.contains('@'));
} catch (e) {
if (e.toString().contains("User not registered")) {
_showUnregisteredDialog();
} else {
_showError("오류: $e");
}
}
}
Future<void> _startEnchantedFlow(String loginId, {required bool isEmail}) async {
@@ -316,7 +323,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
);
}
// 1. Init via Backend API (Now handles both SMS and SES Email)
// 1. Init via Backend API
final initResponse = await AuthProxyService.initEnchantedLink(loginId);
final pendingRef = initResponse['pendingRef'];
debugPrint("[Auth] Link Sent. PendingRef: $pendingRef");
@@ -356,7 +363,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
} catch (e) {
debugPrint("[Auth] Initialization failed: $e");
if (mounted && Navigator.canPop(context)) Navigator.of(context).pop();
_showError("전송 실패: $e");
if (e.toString().contains("User not registered")) {
_showUnregisteredDialog();
} else {
_showError("전송 실패: $e");
}
}
}
@@ -441,13 +452,34 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
}
}
void _onLoginSuccess(String token) {
void _onLoginSuccess(String token) async {
if (!mounted) return;
_logTokenDetails(token);
final userId = _getUserIdFromJwt(token);
// [New] 로그인 성공 직후 백엔드에서 전체 프로필 정보를 가져와 세션 업데이트
try {
// 임시 세션 생성 (API 호출을 위해)
final tempUser = DescopeUser(userId, [], 0, 'User', null, '', false, '', false, {}, '', '', '', false, 'enabled', [], [], []);
final tempSession = DescopeSession.fromJwt(token, token, tempUser);
Descope.sessionManager.manageSession(tempSession);
// 백엔드 GetMe 호출 (프로필 노티파이어 사용)
final profile = await ref.read(profileProvider.notifier).loadProfile();
if (profile != null) {
// 실제 정보로 세션 유저 정보 교체
final realUser = DescopeUser(
userId, [], 0, profile.name, null, profile.email, false, profile.phone, false, {}, '', '', '', false, 'enabled', [], [], [],
);
final realSession = DescopeSession.fromJwt(token, token, realUser);
Descope.sessionManager.manageSession(realSession);
}
} catch (e) {
debugPrint("[Auth] Failed to pre-fetch profile: $e");
}
// Record Audit Log
AuditService.logEvent(
userId: userId,
@@ -478,6 +510,30 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
}
}
// [New] 미등록 회원 안내 팝업
void _showUnregisteredDialog() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text("미등록 회원"),
content: const Text("가입되지 않은 정보입니다.\n회원가입 후 이용해 주세요."),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text("취소"),
),
FilledButton(
onPressed: () {
Navigator.pop(context);
context.push('/signup');
},
child: const Text("회원가입 하기"),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(