forked from baron/baron-sso
내정보 페이지 사용성개선, adminFront user 정보 연동.
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import '../../../core/services/auth_proxy_service.dart';
|
||||
|
||||
class ForgotPasswordScreen extends StatefulWidget {
|
||||
@@ -91,7 +90,7 @@ class _ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
|
||||
children: [
|
||||
Text(
|
||||
"비밀번호를 잊으셨나요?",
|
||||
style: GoogleFonts.outfit(
|
||||
style: TextStyle(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:descope/descope.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
@@ -47,6 +46,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
int _linkExpireSeconds = 0;
|
||||
Timer? _linkExpireTimer;
|
||||
bool _verificationOnly = false;
|
||||
bool _verificationApproved = false;
|
||||
String _verificationMessage = '';
|
||||
bool _drySendEnabled = false;
|
||||
|
||||
@override
|
||||
@@ -352,15 +353,72 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
_onLoginSuccess(token, provider: provider);
|
||||
}
|
||||
|
||||
bool _hasLocalSession() {
|
||||
if (AuthTokenStore.getToken() != null) {
|
||||
return true;
|
||||
}
|
||||
return AuthTokenStore.usesCookie();
|
||||
}
|
||||
|
||||
void _markVerificationApproved(String message) {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_verificationApproved = true;
|
||||
_verificationMessage = message;
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildVerificationResultView() {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.check_circle_outline, color: Colors.green, size: 72),
|
||||
const SizedBox(height: 16),
|
||||
const Text(
|
||||
'승인 완료',
|
||||
style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Colors.green),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
_verificationMessage.isEmpty ? '로그인 승인에 성공했습니다.' : _verificationMessage,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(color: Colors.black54),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
FilledButton(
|
||||
onPressed: () => context.go('/'),
|
||||
child: const Text('확인'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _verifyToken(String token) async {
|
||||
debugPrint("[Auth] Starting verification for token: $token");
|
||||
try {
|
||||
// Use Backend to verify the token (Backend-Driven Flow)
|
||||
await AuthProxyService.verifyMagicLink(token);
|
||||
final res = await AuthProxyService.verifyMagicLink(token);
|
||||
debugPrint("[Auth] Verification successful for token: $token");
|
||||
final jwt = res['token'] ?? res['sessionJwt'];
|
||||
final provider = res['provider'] as String?;
|
||||
final hasLocalSession = _hasLocalSession();
|
||||
|
||||
if (jwt is String && jwt.isNotEmpty) {
|
||||
if (hasLocalSession) {
|
||||
_markVerificationApproved("승인되었습니다. 이미 로그인된 브라우저입니다.");
|
||||
return;
|
||||
}
|
||||
_completeLoginFromToken(jwt, provider: provider);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
_showInfo("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
_markVerificationApproved("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("[Auth] Verification FAILED for token: $token. Error: $e");
|
||||
@@ -382,23 +440,26 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
final jwt = res['sessionJwt'] ?? res['token'];
|
||||
final status = res['status']?.toString();
|
||||
debugPrint("[Auth] Code verification successful for loginId: $sanitizedLoginId");
|
||||
final hasLocalSession = _hasLocalSession();
|
||||
|
||||
if (jwt == null && status == 'approved') {
|
||||
if (mounted) {
|
||||
_showInfo("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_verificationOnly) {
|
||||
if (mounted) {
|
||||
_showInfo("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
_markVerificationApproved("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (jwt is String && jwt.isNotEmpty) {
|
||||
if (hasLocalSession) {
|
||||
_markVerificationApproved("승인되었습니다. 이미 로그인된 브라우저입니다.");
|
||||
return;
|
||||
}
|
||||
_completeLoginFromToken(jwt, provider: res['provider'] as String?);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_verificationOnly && mounted) {
|
||||
_markVerificationApproved("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("[Auth] Code verification FAILED for loginId: $sanitizedLoginId. Error: $e");
|
||||
@@ -417,23 +478,26 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
final jwt = res['sessionJwt'] ?? res['token'];
|
||||
final status = res['status']?.toString();
|
||||
debugPrint("[Auth] Short code verification successful");
|
||||
final hasLocalSession = _hasLocalSession();
|
||||
|
||||
if (jwt == null && status == 'approved') {
|
||||
if (mounted) {
|
||||
_showInfo("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_verificationOnly) {
|
||||
if (mounted) {
|
||||
_showInfo("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
_markVerificationApproved("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (jwt is String && jwt.isNotEmpty) {
|
||||
if (hasLocalSession) {
|
||||
_markVerificationApproved("승인되었습니다. 이미 로그인된 브라우저입니다.");
|
||||
return;
|
||||
}
|
||||
_completeLoginFromToken(jwt, provider: res['provider'] as String?);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_verificationOnly && mounted) {
|
||||
_markVerificationApproved("승인되었습니다. 로그인은 요청하신 창에서 완료됩니다.");
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint("[Auth] Short code verification FAILED. Error: $e");
|
||||
@@ -784,6 +848,19 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (_verificationOnly && _verificationApproved) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('로그인 승인'),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
onPressed: () => context.go('/'),
|
||||
),
|
||||
),
|
||||
body: _buildVerificationResultView(),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
body: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
@@ -800,7 +877,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen>
|
||||
children: [
|
||||
Text(
|
||||
"Baron 통합로그인",
|
||||
style: GoogleFonts.outfit(
|
||||
style: TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
|
||||
class LoginSuccessScreen extends StatelessWidget {
|
||||
const LoginSuccessScreen({super.key});
|
||||
@@ -18,7 +17,7 @@ class LoginSuccessScreen extends StatelessWidget {
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
"로그인 완료",
|
||||
style: GoogleFonts.outfit(
|
||||
style: TextStyle(
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
||||
@@ -206,7 +206,7 @@ class _QRScanScreenState extends State<QRScanScreen> {
|
||||
MobileScanner(
|
||||
controller: controller,
|
||||
onDetect: _onDetect,
|
||||
errorBuilder: (context, error, child) {
|
||||
errorBuilder: (context, error) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../../core/services/auth_proxy_service.dart';
|
||||
|
||||
@@ -150,7 +149,7 @@ class _ResetPasswordScreenState extends State<ResetPasswordScreen> {
|
||||
children: [
|
||||
Text(
|
||||
"새로운 비밀번호 설정",
|
||||
style: GoogleFonts.outfit(
|
||||
style: TextStyle(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import '../../../core/services/auth_proxy_service.dart';
|
||||
|
||||
@@ -332,7 +331,7 @@ class _SignupScreenState extends State<SignupScreen> {
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text('서비스 이용을 위해\n약관에 동의해주세요',
|
||||
style: GoogleFonts.outfit(
|
||||
style: TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold, height: 1.3)),
|
||||
const SizedBox(height: 24),
|
||||
// 모두 동의 버튼
|
||||
@@ -597,7 +596,7 @@ class _SignupScreenState extends State<SignupScreen> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text('본인 확인을 위해\n인증을 진행해주세요', style: GoogleFonts.outfit(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
Text('본인 확인을 위해\n인증을 진행해주세요', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
// 가족사 이메일 안내 문구
|
||||
Container(
|
||||
@@ -713,7 +712,7 @@ class _SignupScreenState extends State<SignupScreen> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text('회원님의\n소속 정보를 알려주세요', style: GoogleFonts.outfit(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
Text('회원님의\n소속 정보를 알려주세요', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 24),
|
||||
TextFormField(
|
||||
controller: _nameController,
|
||||
@@ -826,7 +825,7 @@ class _SignupScreenState extends State<SignupScreen> {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text('마지막으로\n비밀번호를 설정해주세요', style: GoogleFonts.outfit(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
Text('마지막으로\n비밀번호를 설정해주세요', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
|
||||
const SizedBox(height: 16),
|
||||
// 비밀번호 정책 안내 박스
|
||||
Container(
|
||||
@@ -918,7 +917,7 @@ class _SignupScreenState extends State<SignupScreen> {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
title: Text('회원가입', style: GoogleFonts.outfit(fontWeight: FontWeight.bold)),
|
||||
title: Text('회원가입', style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Colors.black,
|
||||
|
||||
Reference in New Issue
Block a user