diff --git a/frontend/lib/core/services/auth_proxy_service.dart b/frontend/lib/core/services/auth_proxy_service.dart index e44fa099..470a4255 100644 --- a/frontend/lib/core/services/auth_proxy_service.dart +++ b/frontend/lib/core/services/auth_proxy_service.dart @@ -58,6 +58,22 @@ class AuthProxyService { } } + static Future sendSms(String phoneNumber) async { + final url = Uri.parse('$_baseUrl/api/v1/auth/sms'); + + final response = await http.post( + url, + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'phoneNumber': phoneNumber, + }), + ); + + if (response.statusCode != 200) { + throw Exception('Failed to send SMS: ${response.body}'); + } + } + static Future logError(String message) async { final url = Uri.parse('$_baseUrl/api/v1/client-log'); try { diff --git a/frontend/lib/features/auth/presentation/login_screen.dart b/frontend/lib/features/auth/presentation/login_screen.dart index 1de59201..cf718054 100644 --- a/frontend/lib/features/auth/presentation/login_screen.dart +++ b/frontend/lib/features/auth/presentation/login_screen.dart @@ -21,6 +21,8 @@ class _LoginScreenState extends ConsumerState final TextEditingController _emailController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); final TextEditingController _phoneController = TextEditingController(); + final TextEditingController _smsCodeController = TextEditingController(); + bool _smsSent = false; @override void initState() { @@ -74,6 +76,7 @@ class _LoginScreenState extends ConsumerState _emailController.dispose(); _passwordController.dispose(); _phoneController.dispose(); + _smsCodeController.dispose(); super.dispose(); } @@ -233,66 +236,20 @@ class _LoginScreenState extends ConsumerState if (phone.isEmpty) return; try { - // 1. Init via Proxy - final initData = await AuthProxyService.initEnchantedLink(phone); - final pendingRef = initData['pendingRef']; - - if (mounted) { - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => AlertDialog( - title: const Text("Check your Messages"), - content: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Text("We sent a message to $phone"), - const SizedBox(height: 16), - const LinearProgressIndicator(), - const SizedBox(height: 16), - ], - ), - ), - ); - - // 2. Poll via Proxy - final pollData = await AuthProxyService.pollEnchantedLink(pendingRef); - - String sessionToken = ""; - if (pollData['sessionToken'] is Map) { - sessionToken = pollData['sessionToken']['jwt'] ?? ""; - } else if (pollData['sessionToken'] is String) { - sessionToken = pollData['sessionToken']; - } - - if (sessionToken.isEmpty) { - throw Exception("Invalid session token received"); - } - - await AuditService.logEvent( - userId: phone, - eventType: 'login_success', - status: 'success', - details: 'Method: SMS/EnchantedLink/Proxy', - ); - - if (mounted) { - Navigator.of(context).pop(); // Close Dialog - - if (WebAuthIntegration.isPopup()) { - WebAuthIntegration.sendLoginSuccess(sessionToken); - _showError("Login Successful! You can close this window."); - } else { - _showError("Login Successful (Standalone)"); - } - } - } + await AuthProxyService.sendSms(phone); + setState(() { + _smsSent = true; + }); } catch (e) { - if (mounted && Navigator.canPop(context)) Navigator.of(context).pop(); - _showError("SMS Enchanted Link Failed (Proxy): $e"); + _showError("Failed to send SMS: $e"); } } + Future _handleSmsVerification() async { + // For now, just show a success message + _showSuccessDialog(); + } + void _showError(String message) { if (!mounted) return; @@ -388,23 +345,42 @@ class _LoginScreenState extends ConsumerState // Phone/SMS Form Column( children: [ - TextField( - controller: _phoneController, - decoration: const InputDecoration( - labelText: "Phone Number", - hintText: "+82 10-1234-5678", - border: OutlineInputBorder(), - prefixIcon: Icon(Icons.phone_android), + if (!_smsSent) ...[ + TextField( + controller: _phoneController, + decoration: const InputDecoration( + labelText: "Phone Number", + hintText: "+82 10-1234-5678", + border: OutlineInputBorder(), + prefixIcon: Icon(Icons.phone_android), + ), ), - ), - const SizedBox(height: 24), - FilledButton( - onPressed: _handleSmsLogin, - style: FilledButton.styleFrom( - minimumSize: const Size.fromHeight(50), + const SizedBox(height: 24), + FilledButton( + onPressed: _handleSmsLogin, + style: FilledButton.styleFrom( + minimumSize: const Size.fromHeight(50), + ), + child: const Text("Send Verification Code"), ), - child: const Text("Send Login Link"), - ), + ] else ...[ + TextField( + controller: _smsCodeController, + decoration: const InputDecoration( + labelText: "Verification Code", + border: OutlineInputBorder(), + prefixIcon: Icon(Icons.password), + ), + ), + const SizedBox(height: 24), + FilledButton( + onPressed: _handleSmsVerification, + style: FilledButton.styleFrom( + minimumSize: const Size.fromHeight(50), + ), + child: const Text("Verify Code"), + ), + ], ], ), ],