mirror of
https://github.com/rustdesk/rustdesk.git
synced 2025-06-07 18:02:48 +08:00
Refact/verification code input check (#6924)
* Refact, login verification code, input check Signed-off-by: fufesou <shuanglongchen@yeah.net> * Refact, settings, enable 2fa, dialog input Signed-off-by: fufesou <shuanglongchen@yeah.net> * Refact. Connect, 2fa code, input check Signed-off-by: fufesou <shuanglongchen@yeah.net> * refact, 2Fa text field, input formatter, only digits Signed-off-by: fufesou <shuanglongchen@yeah.net> * refact, error message Signed-off-by: fufesou <shuanglongchen@yeah.net> --------- Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
d39129887b
commit
06b3894249
@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@ -362,6 +363,7 @@ class DialogTextField extends StatelessWidget {
|
|||||||
final Widget? suffixIcon;
|
final Widget? suffixIcon;
|
||||||
final TextEditingController controller;
|
final TextEditingController controller;
|
||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
|
final List<TextInputFormatter>? inputFormatters;
|
||||||
|
|
||||||
static const kUsernameTitle = 'Username';
|
static const kUsernameTitle = 'Username';
|
||||||
static const kUsernameIcon = Icon(Icons.account_circle_outlined);
|
static const kUsernameIcon = Icon(Icons.account_circle_outlined);
|
||||||
@ -377,6 +379,7 @@ class DialogTextField extends StatelessWidget {
|
|||||||
this.prefixIcon,
|
this.prefixIcon,
|
||||||
this.suffixIcon,
|
this.suffixIcon,
|
||||||
this.hintText,
|
this.hintText,
|
||||||
|
this.inputFormatters,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.controller})
|
required this.controller})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
@ -401,6 +404,7 @@ class DialogTextField extends StatelessWidget {
|
|||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
obscureText: obscureText,
|
obscureText: obscureText,
|
||||||
|
inputFormatters: inputFormatters,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -408,6 +412,241 @@ class DialogTextField extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class ValidationField extends StatelessWidget {
|
||||||
|
ValidationField({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
String? validate();
|
||||||
|
bool get isReady;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dialog2FaField extends ValidationField {
|
||||||
|
Dialog2FaField({
|
||||||
|
Key? key,
|
||||||
|
required this.controller,
|
||||||
|
this.autoFocus = true,
|
||||||
|
this.reRequestFocus = false,
|
||||||
|
this.title,
|
||||||
|
this.helperText,
|
||||||
|
this.hintText,
|
||||||
|
this.errorText,
|
||||||
|
this.readyCallback,
|
||||||
|
this.onChanged,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final TextEditingController controller;
|
||||||
|
final bool autoFocus;
|
||||||
|
final bool reRequestFocus;
|
||||||
|
final String? title;
|
||||||
|
final String? helperText;
|
||||||
|
final String? hintText;
|
||||||
|
final String? errorText;
|
||||||
|
final VoidCallback? readyCallback;
|
||||||
|
final VoidCallback? onChanged;
|
||||||
|
final errMsg = translate('2FA code must be 6 digits.');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DialogVerificationCodeField(
|
||||||
|
title: title ?? translate('2FA code'),
|
||||||
|
controller: controller,
|
||||||
|
errorText: errorText,
|
||||||
|
autoFocus: autoFocus,
|
||||||
|
reRequestFocus: reRequestFocus,
|
||||||
|
hintText: hintText,
|
||||||
|
readyCallback: readyCallback,
|
||||||
|
helperText: helperText ?? translate('2fa_tip'),
|
||||||
|
onChanged: _onChanged,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.allow(RegExp(r'[0-9]')),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get text => controller.text;
|
||||||
|
bool get isAllDigits => text.codeUnits.every((e) => e >= 48 && e <= 57);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isReady => text.length == 6 && isAllDigits;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? validate() => isReady ? null : errMsg;
|
||||||
|
|
||||||
|
_onChanged(StateSetter setState, SimpleWrapper<String?> errText) {
|
||||||
|
onChanged?.call();
|
||||||
|
|
||||||
|
if (text.length > 6) {
|
||||||
|
setState(() => errText.value = errMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isAllDigits) {
|
||||||
|
setState(() => errText.value = errMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReady) {
|
||||||
|
readyCallback?.call();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errText.value != null) {
|
||||||
|
setState(() => errText.value = null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DialogEmailCodeField extends ValidationField {
|
||||||
|
DialogEmailCodeField({
|
||||||
|
Key? key,
|
||||||
|
required this.controller,
|
||||||
|
this.autoFocus = true,
|
||||||
|
this.reRequestFocus = false,
|
||||||
|
this.hintText,
|
||||||
|
this.errorText,
|
||||||
|
this.readyCallback,
|
||||||
|
this.onChanged,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final TextEditingController controller;
|
||||||
|
final bool autoFocus;
|
||||||
|
final bool reRequestFocus;
|
||||||
|
final String? hintText;
|
||||||
|
final String? errorText;
|
||||||
|
final VoidCallback? readyCallback;
|
||||||
|
final VoidCallback? onChanged;
|
||||||
|
final errMsg = translate('Email verification code must be 6 characters.');
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DialogVerificationCodeField(
|
||||||
|
title: translate('Verification code'),
|
||||||
|
controller: controller,
|
||||||
|
errorText: errorText,
|
||||||
|
autoFocus: autoFocus,
|
||||||
|
reRequestFocus: reRequestFocus,
|
||||||
|
hintText: hintText,
|
||||||
|
readyCallback: readyCallback,
|
||||||
|
helperText: translate('verification_tip'),
|
||||||
|
onChanged: _onChanged,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get text => controller.text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool get isReady => text.length == 6;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? validate() => isReady ? null : errMsg;
|
||||||
|
|
||||||
|
_onChanged(StateSetter setState, SimpleWrapper<String?> errText) {
|
||||||
|
onChanged?.call();
|
||||||
|
|
||||||
|
if (text.length > 6) {
|
||||||
|
setState(() => errText.value = errMsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReady) {
|
||||||
|
readyCallback?.call();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errText.value != null) {
|
||||||
|
setState(() => errText.value = null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DialogVerificationCodeField extends StatefulWidget {
|
||||||
|
DialogVerificationCodeField({
|
||||||
|
Key? key,
|
||||||
|
required this.controller,
|
||||||
|
required this.title,
|
||||||
|
this.autoFocus = true,
|
||||||
|
this.reRequestFocus = false,
|
||||||
|
this.helperText,
|
||||||
|
this.hintText,
|
||||||
|
this.errorText,
|
||||||
|
this.textLength,
|
||||||
|
this.readyCallback,
|
||||||
|
this.onChanged,
|
||||||
|
this.inputFormatters,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
final TextEditingController controller;
|
||||||
|
final bool autoFocus;
|
||||||
|
final bool reRequestFocus;
|
||||||
|
final String title;
|
||||||
|
final String? helperText;
|
||||||
|
final String? hintText;
|
||||||
|
final String? errorText;
|
||||||
|
final int? textLength;
|
||||||
|
final VoidCallback? readyCallback;
|
||||||
|
final Function(StateSetter setState, SimpleWrapper<String?> errText)?
|
||||||
|
onChanged;
|
||||||
|
final List<TextInputFormatter>? inputFormatters;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DialogVerificationCodeField> createState() =>
|
||||||
|
_DialogVerificationCodeField();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DialogVerificationCodeField extends State<DialogVerificationCodeField> {
|
||||||
|
final _focusNode = FocusNode();
|
||||||
|
Timer? _timer;
|
||||||
|
Timer? _timerReRequestFocus;
|
||||||
|
SimpleWrapper<String?> errorText = SimpleWrapper(null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.autoFocus) {
|
||||||
|
_timer =
|
||||||
|
Timer(Duration(milliseconds: 50), () => _focusNode.requestFocus());
|
||||||
|
|
||||||
|
if (widget.onChanged != null) {
|
||||||
|
widget.controller.addListener(() {
|
||||||
|
widget.onChanged!(setState, errorText);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// software secure keyboard will take the focus since flutter 3.13
|
||||||
|
// request focus again when android account password obtain focus
|
||||||
|
if (Platform.isAndroid && widget.reRequestFocus) {
|
||||||
|
_focusNode.addListener(() {
|
||||||
|
if (_focusNode.hasFocus) {
|
||||||
|
_timerReRequestFocus?.cancel();
|
||||||
|
_timerReRequestFocus = Timer(
|
||||||
|
Duration(milliseconds: 100), () => _focusNode.requestFocus());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_timer?.cancel();
|
||||||
|
_timerReRequestFocus?.cancel();
|
||||||
|
_focusNode.unfocus();
|
||||||
|
_focusNode.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return DialogTextField(
|
||||||
|
title: widget.title,
|
||||||
|
controller: widget.controller,
|
||||||
|
errorText: widget.errorText ?? errorText.value,
|
||||||
|
focusNode: _focusNode,
|
||||||
|
helperText: widget.helperText,
|
||||||
|
inputFormatters: widget.inputFormatters,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PasswordWidget extends StatefulWidget {
|
class PasswordWidget extends StatefulWidget {
|
||||||
PasswordWidget({
|
PasswordWidget({
|
||||||
Key? key,
|
Key? key,
|
||||||
@ -1512,9 +1751,31 @@ void change2fa({Function()? callback}) async {
|
|||||||
var new2fa = (await bind.mainGenerate2Fa());
|
var new2fa = (await bind.mainGenerate2Fa());
|
||||||
final secretRegex = RegExp(r'secret=([^&]+)');
|
final secretRegex = RegExp(r'secret=([^&]+)');
|
||||||
final secret = secretRegex.firstMatch(new2fa)?.group(1);
|
final secret = secretRegex.firstMatch(new2fa)?.group(1);
|
||||||
var msg = ''.obs;
|
String? errorText;
|
||||||
final RxString code = "".obs;
|
final controller = TextEditingController();
|
||||||
gFFI.dialogManager.show((setState, close, context) {
|
gFFI.dialogManager.show((setState, close, context) {
|
||||||
|
onVerify() async {
|
||||||
|
if (await bind.mainVerify2Fa(code: controller.text.trim())) {
|
||||||
|
callback?.call();
|
||||||
|
close();
|
||||||
|
} else {
|
||||||
|
errorText = translate('wrong-2fa-code');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final codeField = Dialog2FaField(
|
||||||
|
controller: controller,
|
||||||
|
errorText: errorText,
|
||||||
|
onChanged: () => setState(() => errorText = null),
|
||||||
|
title: translate('Verification code'),
|
||||||
|
readyCallback: () {
|
||||||
|
onVerify();
|
||||||
|
setState(() {});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
getOnSubmit() => codeField.isReady ? onVerify : null;
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("enable-2fa-title")),
|
title: Text(translate("enable-2fa-title")),
|
||||||
content: Column(
|
content: Column(
|
||||||
@ -1535,36 +1796,12 @@ void change2fa({Function()? callback}) async {
|
|||||||
)).marginOnly(bottom: 6),
|
)).marginOnly(bottom: 6),
|
||||||
SelectableText(secret ?? '', style: TextStyle(fontSize: 12))
|
SelectableText(secret ?? '', style: TextStyle(fontSize: 12))
|
||||||
.marginOnly(bottom: 12),
|
.marginOnly(bottom: 12),
|
||||||
Row(children: [
|
Row(children: [Expanded(child: codeField)]),
|
||||||
Expanded(
|
|
||||||
child: Obx(() => TextField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
errorText:
|
|
||||||
msg.value.isEmpty ? null : translate(msg.value),
|
|
||||||
hintText: translate("Verification code")),
|
|
||||||
onChanged: (value) {
|
|
||||||
code.value = value;
|
|
||||||
msg.value = '';
|
|
||||||
},
|
|
||||||
autofocus: true)))
|
|
||||||
]),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton("Cancel", onPressed: close, isOutline: true),
|
dialogButton("Cancel", onPressed: close, isOutline: true),
|
||||||
Obx(() => dialogButton(
|
dialogButton("OK", onPressed: getOnSubmit()),
|
||||||
"OK",
|
|
||||||
onPressed: code.value.trim().length == 6
|
|
||||||
? () async {
|
|
||||||
if (await bind.mainVerify2Fa(code: code.value.trim())) {
|
|
||||||
callback?.call();
|
|
||||||
close();
|
|
||||||
} else {
|
|
||||||
msg.value = translate('wrong-2fa-code');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
)),
|
|
||||||
],
|
],
|
||||||
onCancel: close,
|
onCancel: close,
|
||||||
);
|
);
|
||||||
@ -1573,7 +1810,9 @@ void change2fa({Function()? callback}) async {
|
|||||||
|
|
||||||
void enter2FaDialog(
|
void enter2FaDialog(
|
||||||
SessionID sessionId, OverlayDialogManager dialogManager) async {
|
SessionID sessionId, OverlayDialogManager dialogManager) async {
|
||||||
final RxString code = "".obs;
|
final controller = TextEditingController();
|
||||||
|
final RxBool submitReady = false.obs;
|
||||||
|
|
||||||
dialogManager.dismissAll();
|
dialogManager.dismissAll();
|
||||||
dialogManager.show((setState, close, context) {
|
dialogManager.show((setState, close, context) {
|
||||||
cancel() {
|
cancel() {
|
||||||
@ -1582,34 +1821,23 @@ void enter2FaDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
if (code.value.trim().length != 6) {
|
gFFI.send2FA(sessionId, controller.text.trim());
|
||||||
return;
|
|
||||||
}
|
|
||||||
gFFI.send2FA(sessionId, code.value.trim());
|
|
||||||
close();
|
close();
|
||||||
dialogManager.showLoading(translate('Logging in...'),
|
dialogManager.showLoading(translate('Logging in...'),
|
||||||
onCancel: closeConnection);
|
onCancel: closeConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
late Dialog2FaField codeField;
|
||||||
|
|
||||||
|
codeField = Dialog2FaField(
|
||||||
|
controller: controller,
|
||||||
|
title: translate('Verification code'),
|
||||||
|
onChanged: () => submitReady.value = codeField.isReady,
|
||||||
|
);
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("enter-2fa-title")),
|
title: Text(translate('enter-2fa-title')),
|
||||||
content: Column(
|
content: codeField,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(children: [
|
|
||||||
Expanded(
|
|
||||||
child: TextField(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: translate("Verification code")),
|
|
||||||
onChanged: (value) {
|
|
||||||
code.value = value;
|
|
||||||
},
|
|
||||||
autofocus: true))
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onSubmit: submit,
|
|
||||||
onCancel: cancel,
|
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton(
|
dialogButton(
|
||||||
'Cancel',
|
'Cancel',
|
||||||
@ -1618,7 +1846,7 @@ void enter2FaDialog(
|
|||||||
),
|
),
|
||||||
Obx(() => dialogButton(
|
Obx(() => dialogButton(
|
||||||
'OK',
|
'OK',
|
||||||
onPressed: code.value.trim().length == 6 ? submit : null,
|
onPressed: submitReady.isTrue ? submit : null,
|
||||||
)),
|
)),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -615,23 +615,11 @@ Future<bool?> verificationCodeDialog(
|
|||||||
var autoLogin = true;
|
var autoLogin = true;
|
||||||
var isInProgress = false;
|
var isInProgress = false;
|
||||||
String? errorText;
|
String? errorText;
|
||||||
String preCode = '';
|
|
||||||
|
|
||||||
final code = TextEditingController();
|
final code = TextEditingController();
|
||||||
final focusNode = FocusNode()..requestFocus();
|
|
||||||
Timer(Duration(milliseconds: 100), () => focusNode..requestFocus());
|
|
||||||
|
|
||||||
final res = await gFFI.dialogManager.show<bool>((setState, close, context) {
|
final res = await gFFI.dialogManager.show<bool>((setState, close, context) {
|
||||||
bool validate() {
|
|
||||||
return code.text.length >= 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
void onVerify() async {
|
void onVerify() async {
|
||||||
if (!validate()) {
|
|
||||||
setState(
|
|
||||||
() => errorText = translate('Too short, at least 6 characters.'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setState(() => isInProgress = true);
|
setState(() => isInProgress = true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -666,18 +654,21 @@ Future<bool?> verificationCodeDialog(
|
|||||||
setState(() => isInProgress = false);
|
setState(() => isInProgress = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
code.addListener(() {
|
final codeField = isEmailVerification
|
||||||
if (errorText != null) {
|
? DialogEmailCodeField(
|
||||||
setState(() => errorText = null);
|
controller: code,
|
||||||
}
|
errorText: errorText,
|
||||||
if (preCode.length != 6 && code.text.length == 6) {
|
readyCallback: onVerify,
|
||||||
onVerify();
|
onChanged: () => errorText = null,
|
||||||
}
|
)
|
||||||
if (!isEmailVerification && preCode.length != 10 && code.text.length == 10) {
|
: Dialog2FaField(
|
||||||
onVerify();
|
controller: code,
|
||||||
}
|
errorText: errorText,
|
||||||
preCode = code.text;
|
readyCallback: onVerify,
|
||||||
});
|
onChanged: () => errorText = null,
|
||||||
|
);
|
||||||
|
|
||||||
|
getOnSubmit() => codeField.isReady ? onVerify : null;
|
||||||
|
|
||||||
return CustomAlertDialog(
|
return CustomAlertDialog(
|
||||||
title: Text(translate("Verification code")),
|
title: Text(translate("Verification code")),
|
||||||
@ -693,15 +684,7 @@ Future<bool?> verificationCodeDialog(
|
|||||||
controller: TextEditingController(text: user?.email),
|
controller: TextEditingController(text: user?.email),
|
||||||
)),
|
)),
|
||||||
isEmailVerification ? const SizedBox(height: 8) : const Offstage(),
|
isEmailVerification ? const SizedBox(height: 8) : const Offstage(),
|
||||||
DialogTextField(
|
codeField,
|
||||||
title:
|
|
||||||
'${translate(isEmailVerification ? "Verification code" : "2FA code")}:',
|
|
||||||
controller: code,
|
|
||||||
errorText: errorText,
|
|
||||||
focusNode: focusNode,
|
|
||||||
helperText: translate(
|
|
||||||
isEmailVerification ? 'verification_tip' : '2fa_tip'),
|
|
||||||
),
|
|
||||||
/*
|
/*
|
||||||
CheckboxListTile(
|
CheckboxListTile(
|
||||||
contentPadding: const EdgeInsets.all(0),
|
contentPadding: const EdgeInsets.all(0),
|
||||||
@ -722,10 +705,10 @@ Future<bool?> verificationCodeDialog(
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
onCancel: close,
|
onCancel: close,
|
||||||
onSubmit: onVerify,
|
onSubmit: getOnSubmit(),
|
||||||
actions: [
|
actions: [
|
||||||
dialogButton("Cancel", onPressed: close, isOutline: true),
|
dialogButton("Cancel", onPressed: close, isOutline: true),
|
||||||
dialogButton("Verify", onPressed: onVerify),
|
dialogButton("Verify", onPressed: getOnSubmit()),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", "Email 验证码必须是 6 个字符。"),
|
||||||
|
("2FA code must be 6 digits.", "2FA 码必须是6位数字。"),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", "Bitte richten Sie jetzt Ihren Authentifikator ein. Sie können eine Authentifizierungs-App wie Authy, Microsoft oder Google Authenticator auf Ihrem Telefon oder Desktop verwenden.\n\nScannen Sie den QR-Code mit Ihrer App und geben Sie den Code ein, den Ihre App anzeigt, um die Zwei-Faktor-Authentifizierung zu aktivieren."),
|
("enable-2fa-desc", "Bitte richten Sie jetzt Ihren Authentifikator ein. Sie können eine Authentifizierungs-App wie Authy, Microsoft oder Google Authenticator auf Ihrem Telefon oder Desktop verwenden.\n\nScannen Sie den QR-Code mit Ihrer App und geben Sie den Code ein, den Ihre App anzeigt, um die Zwei-Faktor-Authentifizierung zu aktivieren."),
|
||||||
("wrong-2fa-code", "Der Code kann nicht verifiziert werden. Prüfen Sie, ob der Code und die lokalen Zeiteinstellungen korrekt sind."),
|
("wrong-2fa-code", "Der Code kann nicht verifiziert werden. Prüfen Sie, ob der Code und die lokalen Zeiteinstellungen korrekt sind."),
|
||||||
("enter-2fa-title", "Zwei-Faktor-Authentifizierung"),
|
("enter-2fa-title", "Zwei-Faktor-Authentifizierung"),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
@ -585,5 +585,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
|||||||
("enable-2fa-desc", ""),
|
("enable-2fa-desc", ""),
|
||||||
("wrong-2fa-code", ""),
|
("wrong-2fa-code", ""),
|
||||||
("enter-2fa-title", ""),
|
("enter-2fa-title", ""),
|
||||||
|
("Email verification code must be 6 characters.", ""),
|
||||||
|
("2FA code must be 6 digits.", ""),
|
||||||
].iter().cloned().collect();
|
].iter().cloned().collect();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user