forked from baron/baron-sso
i18n 대대적 변경
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
|
||||
@@ -33,12 +34,14 @@ class AuditService {
|
||||
);
|
||||
|
||||
if (response.statusCode >= 200 && response.statusCode < 300) {
|
||||
print("Audit log sent successfully");
|
||||
debugPrint('Audit log sent successfully');
|
||||
} else {
|
||||
print("Failed to send audit log: ${response.statusCode} ${response.body}");
|
||||
debugPrint(
|
||||
'Failed to send audit log: ${response.statusCode} ${response.body}',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error sending audit log: $e");
|
||||
debugPrint('Error sending audit log: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:userfront/i18n.dart';
|
||||
import 'http_client.dart';
|
||||
import 'web_window.dart';
|
||||
import 'auth_token_store.dart';
|
||||
@@ -30,13 +31,26 @@ class AuthProxyService {
|
||||
return drySend == true;
|
||||
}
|
||||
|
||||
static Exception _error(String key, String fallback, {String? detail}) {
|
||||
return Exception(
|
||||
tr(
|
||||
key,
|
||||
fallback: fallback,
|
||||
params: detail != null ? {'error': detail} : null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> fetchPasswordPolicy() async {
|
||||
final url = Uri.parse('$_baseUrl/api/v1/auth/password/policy');
|
||||
final response = await http.get(url);
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
throw Exception('Failed to fetch password policy');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.password_policy_fetch',
|
||||
'비밀번호 정책을 불러오지 못했습니다.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +66,11 @@ class AuthProxyService {
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
}
|
||||
throw Exception('Failed to load profile: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.profile_load',
|
||||
'프로필을 불러오지 못했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
@@ -107,7 +125,11 @@ class AuthProxyService {
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
throw Exception('Failed to init login: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.login_init',
|
||||
'로그인 초기화에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +150,11 @@ class AuthProxyService {
|
||||
if (response.statusCode == 400) {
|
||||
return jsonDecode(response.body);
|
||||
}
|
||||
throw Exception('Polling failed: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.login_poll',
|
||||
'로그인 상태 확인에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> verifyMagicLink(String token, {bool verifyOnly = false}) async {
|
||||
@@ -146,7 +172,11 @@ class AuthProxyService {
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
throw Exception('Verification failed: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.verify_failed',
|
||||
'검증에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +206,11 @@ class AuthProxyService {
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
throw Exception('Verification failed: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.verify_failed',
|
||||
'검증에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +232,11 @@ class AuthProxyService {
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
throw Exception('Verification failed: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.verify_failed',
|
||||
'검증에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,7 +263,13 @@ class AuthProxyService {
|
||||
return data;
|
||||
} else {
|
||||
final errorBody = jsonDecode(response.body);
|
||||
throw Exception(errorBody['error'] ?? 'Failed to login');
|
||||
throw Exception(
|
||||
errorBody['error'] ??
|
||||
tr(
|
||||
'err.userfront.auth_proxy.login_failed',
|
||||
fallback: '로그인에 실패했습니다.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
static Future<Map<String, dynamic>> getConsentInfo(String consentChallenge) async {
|
||||
@@ -239,7 +283,13 @@ class AuthProxyService {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
final errorBody = jsonDecode(response.body);
|
||||
throw Exception(errorBody['error'] ?? 'Failed to get consent info');
|
||||
throw Exception(
|
||||
errorBody['error'] ??
|
||||
tr(
|
||||
'err.userfront.auth_proxy.consent_fetch',
|
||||
fallback: '동의 정보를 가져오지 못했습니다.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +312,13 @@ class AuthProxyService {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
final errorBody = jsonDecode(response.body);
|
||||
throw Exception(errorBody['error'] ?? 'Failed to accept consent');
|
||||
throw Exception(
|
||||
errorBody['error'] ??
|
||||
tr(
|
||||
'err.userfront.auth_proxy.consent_accept',
|
||||
fallback: '동의 처리에 실패했습니다.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +338,13 @@ class AuthProxyService {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
final errorBody = jsonDecode(response.body);
|
||||
throw Exception(errorBody['error'] ?? 'Failed to reject consent');
|
||||
throw Exception(
|
||||
errorBody['error'] ??
|
||||
tr(
|
||||
'err.userfront.auth_proxy.consent_reject',
|
||||
fallback: '동의 거부에 실패했습니다.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +373,13 @@ class AuthProxyService {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
final errorBody = jsonDecode(response.body);
|
||||
throw Exception(errorBody['error'] ?? 'Failed to accept OIDC login');
|
||||
throw Exception(
|
||||
errorBody['error'] ??
|
||||
tr(
|
||||
'err.userfront.auth_proxy.oidc_accept',
|
||||
fallback: 'OIDC 로그인 승인에 실패했습니다.',
|
||||
),
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
client.close();
|
||||
@@ -334,7 +402,13 @@ class AuthProxyService {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
final errorBody = jsonDecode(response.body);
|
||||
throw Exception(errorBody['error'] ?? 'Failed to initiate password reset');
|
||||
throw Exception(
|
||||
errorBody['error'] ??
|
||||
tr(
|
||||
'err.userfront.auth_proxy.password_reset_init',
|
||||
fallback: '비밀번호 재설정을 시작하지 못했습니다.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +435,13 @@ class AuthProxyService {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
final errorBody = jsonDecode(response.body);
|
||||
throw Exception(errorBody['error'] ?? 'Failed to complete password reset');
|
||||
throw Exception(
|
||||
errorBody['error'] ??
|
||||
tr(
|
||||
'err.userfront.auth_proxy.password_reset_complete',
|
||||
fallback: '비밀번호 재설정에 실패했습니다.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +457,11 @@ class AuthProxyService {
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to send SMS: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.sms_send',
|
||||
'SMS 전송에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,7 +480,11 @@ class AuthProxyService {
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
throw Exception('Failed to verify code: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.code_verify',
|
||||
'인증 코드 확인에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +498,11 @@ class AuthProxyService {
|
||||
if (response.statusCode == 200) {
|
||||
return jsonDecode(response.body);
|
||||
} else {
|
||||
throw Exception('Failed to init QR login: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.qr_init',
|
||||
'QR 로그인을 시작하지 못했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,7 +520,11 @@ class AuthProxyService {
|
||||
if (response.statusCode == 400) {
|
||||
return jsonDecode(response.body);
|
||||
}
|
||||
throw Exception('QR Polling failed: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.qr_poll',
|
||||
'QR 상태 확인에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
|
||||
static Future<void> approveQrLogin(
|
||||
@@ -462,7 +558,11 @@ class AuthProxyService {
|
||||
));
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('QR Approval failed: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.qr_approve',
|
||||
'QR 승인에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
client?.close();
|
||||
@@ -509,7 +609,11 @@ class AuthProxyService {
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to create user: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.user_create',
|
||||
'사용자 생성에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,7 +635,11 @@ class AuthProxyService {
|
||||
final data = jsonDecode(response.body);
|
||||
return data['users'] ?? [];
|
||||
} else {
|
||||
throw Exception('Failed to list users: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.user_list',
|
||||
'사용자 목록 조회에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,7 +656,11 @@ class AuthProxyService {
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to delete user: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.user_delete',
|
||||
'사용자 삭제에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,7 +678,11 @@ class AuthProxyService {
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to update status: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.user_status_update',
|
||||
'상태 업데이트에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,7 +711,11 @@ class AuthProxyService {
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to update user: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.user_update',
|
||||
'사용자 수정에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,7 +742,10 @@ class AuthProxyService {
|
||||
final data = jsonDecode(response.body);
|
||||
return data['items'] ?? [];
|
||||
} else {
|
||||
throw Exception('연동된 앱 목록을 불러오지 못했습니다.');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.linked_apps_load',
|
||||
'연동된 앱 목록을 불러오지 못했습니다.',
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
client.close();
|
||||
@@ -650,7 +773,13 @@ class AuthProxyService {
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
final errorBody = jsonDecode(response.body);
|
||||
throw Exception(errorBody['error'] ?? '연동 해지에 실패했습니다.');
|
||||
throw Exception(
|
||||
errorBody['error'] ??
|
||||
tr(
|
||||
'err.userfront.auth_proxy.linked_app_revoke',
|
||||
fallback: '연동 해지에 실패했습니다.',
|
||||
),
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
client.close();
|
||||
@@ -688,7 +817,6 @@ class AuthProxyService {
|
||||
}
|
||||
|
||||
static int _clientLogFailureCount = 0;
|
||||
static DateTime? _clientLogLastFailureAt;
|
||||
static DateTime? _clientLogOpenUntil;
|
||||
|
||||
static bool _canSendClientLog() {
|
||||
@@ -702,7 +830,6 @@ class AuthProxyService {
|
||||
|
||||
static void _recordClientLogFailure() {
|
||||
_clientLogFailureCount += 1;
|
||||
_clientLogLastFailureAt = DateTime.now();
|
||||
if (_clientLogFailureCount >= 3) {
|
||||
_clientLogOpenUntil = DateTime.now().add(const Duration(minutes: 1));
|
||||
_clientLogFailureCount = 0;
|
||||
@@ -711,7 +838,6 @@ class AuthProxyService {
|
||||
|
||||
static void _recordClientLogSuccess() {
|
||||
_clientLogFailureCount = 0;
|
||||
_clientLogLastFailureAt = null;
|
||||
_clientLogOpenUntil = null;
|
||||
}
|
||||
|
||||
@@ -743,7 +869,11 @@ class AuthProxyService {
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to send code: ${response.body}');
|
||||
throw _error(
|
||||
'err.userfront.auth_proxy.phone_code_send',
|
||||
'인증 코드 전송에 실패했습니다: {{error}}',
|
||||
detail: response.body,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter, deprecated_member_use
|
||||
|
||||
import 'dart:html' as html;
|
||||
|
||||
class AuthTokenStore {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
void implSendLoginSuccess(String token) {
|
||||
// No-op on non-web platforms
|
||||
print("Not on web: Login Success with token: $token");
|
||||
debugPrint('Not on web: Login Success with token: $token');
|
||||
}
|
||||
|
||||
bool implIsPopup() {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import 'dart:html' as html;
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter, deprecated_member_use
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:html' as html;
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
void implSendLoginSuccess(String token) {
|
||||
final message = {'type': 'LOGIN_SUCCESS', 'token': token};
|
||||
@@ -7,9 +10,9 @@ void implSendLoginSuccess(String token) {
|
||||
if (html.window.opener != null) {
|
||||
try {
|
||||
html.window.opener!.postMessage(message, '*');
|
||||
print("Sent login success message to opener");
|
||||
debugPrint('Sent login success message to opener');
|
||||
} catch (e) {
|
||||
print("Failed to postMessage: $e");
|
||||
debugPrint('Failed to postMessage: $e');
|
||||
}
|
||||
|
||||
// Close the popup after a short delay to ensure message sending
|
||||
@@ -18,7 +21,7 @@ void implSendLoginSuccess(String token) {
|
||||
});
|
||||
} else {
|
||||
// Should not happen given isPopup check, but as fallback:
|
||||
print("No opener found during popup flow.");
|
||||
debugPrint('No opener found during popup flow.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// ignore_for_file: avoid_web_libraries_in_flutter, deprecated_member_use
|
||||
|
||||
import 'dart:html' as html;
|
||||
|
||||
class WebWindow {
|
||||
|
||||
Reference in New Issue
Block a user