class _ProxmoxTfaFormState extends State<ProxmoxTfaForm> {
final TextEditingController _codeController = TextEditingController();
bool _isLoading = false;
+ List<String> _tfa_kinds = [];
+ String _selected_tfa_kind = "";
+
+ @override
+ void initState() {
+ super.initState();
+ _tfa_kinds = widget.apiClient!.credentials.tfa!.kinds().toList();
+ _selected_tfa_kind = _tfa_kinds[0];
+ }
+
@override
Widget build(BuildContext context) {
return Theme(
data: ThemeData.dark().copyWith(
- colorScheme: ColorScheme.dark().copyWith(
+ colorScheme: const ColorScheme.dark().copyWith(
secondary: ProxmoxColors.orange,
onSecondary: ProxmoxColors.supportGrey)),
child: Scaffold(
elevation: 0.0,
backgroundColor: Colors.transparent,
leading: IconButton(
- icon: Icon(Icons.close),
+ icon: const Icon(Icons.close),
onPressed: () => Navigator.of(context).pop(),
),
),
child: ConstrainedBox(
constraints: BoxConstraints.tightFor(
height: MediaQuery.of(context).size.height),
- child: Padding(
- padding: const EdgeInsets.all(8.0),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.start,
- crossAxisAlignment: CrossAxisAlignment.center,
- children: <Widget>[
- Padding(
- padding: const EdgeInsets.fromLTRB(0, 100.0, 0, 30.0),
- child: Icon(
- Icons.lock,
- size: 48,
+ child: SafeArea(
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: <Widget>[
+ const Padding(
+ padding: EdgeInsets.fromLTRB(0, 100.0, 0, 30.0),
+ child: Icon(
+ Icons.lock,
+ size: 48,
+ ),
),
- ),
- Text(
- 'Verify',
- style: TextStyle(
- fontSize: 36,
- color: Colors.white,
- fontWeight: FontWeight.bold),
- ),
- Text(
- 'Check your second factor provider',
- style: TextStyle(
- color: Colors.white38, fontWeight: FontWeight.bold),
- ),
- Padding(
- padding: const EdgeInsets.fromLTRB(0, 50.0, 0, 8.0),
- child: Container(
- width: 150,
- child: TextField(
- controller: _codeController,
- textAlign: TextAlign.center,
- decoration: InputDecoration(labelText: 'Code'),
- autofocus: true,
- onSubmitted: (value) => _submitTfaCode()),
+ const Text(
+ 'Verify',
+ style: TextStyle(
+ fontSize: 36,
+ color: Colors.white,
+ fontWeight: FontWeight.bold),
),
- ),
- Expanded(
- child: Align(
- alignment: Alignment.bottomCenter,
+ const Text(
+ 'Check your second factor provider',
+ style: TextStyle(
+ color: Colors.white38,
+ fontWeight: FontWeight.bold),
+ ),
+ Padding(
+ padding: const EdgeInsets.fromLTRB(0, 50.0, 0, 8.0),
child: Container(
- width: MediaQuery.of(context).size.width,
- child: TextButton(
- style: TextButton.styleFrom(
- foregroundColor: Colors.white,
- backgroundColor: Color(0xFFE47225),
- disabledBackgroundColor: Colors.grey,
+ width: 175,
+ child: Column(
+ children: <Widget>[
+ DropdownButtonFormField(
+ decoration: const InputDecoration(
+ labelText: 'Method',
+ icon: Icon(Icons.input)),
+ items: _tfa_kinds
+ .map((e) => DropdownMenuItem(
+ value: e,
+ child: ListTile(title: Text(e)),
+ ))
+ .toList(),
+ onChanged: (String? value) {
+ setState(() {
+ _selected_tfa_kind = value!;
+ });
+ },
+ selectedItemBuilder: (context) =>
+ _tfa_kinds.map((e) => Text(e)).toList(),
+ value: _selected_tfa_kind,
+ ),
+ TextField(
+ controller: _codeController,
+ textAlign: TextAlign.center,
+ decoration: const InputDecoration(
+ labelText: 'Code',
+ icon: Icon(Icons.pin)),
+ keyboardType: _selected_tfa_kind == 'totp'
+ ? TextInputType.number
+ : TextInputType.visiblePassword,
+ autofocus: true,
+ onSubmitted: (value) => _submitTfaCode()),
+ ],
+ ),
+ ),
+ ),
+ Expanded(
+ child: Align(
+ alignment: Alignment.bottomCenter,
+ child: Container(
+ width: MediaQuery.of(context).size.width,
+ child: TextButton(
+ style: TextButton.styleFrom(
+ foregroundColor: Colors.white,
+ backgroundColor: const Color(0xFFE47225),
+ disabledBackgroundColor: Colors.grey,
+ ),
+ onPressed: () => _submitTfaCode(),
+ child: const Text('Continue'),
),
- onPressed: () => _submitTfaCode(),
- child: Text('Continue'),
),
),
),
- ),
- ],
+ ],
+ ),
),
),
),
),
if (_isLoading)
- ProxmoxProgressOverlay(
- message: 'Verify One-Time password...',
+ const ProxmoxProgressOverlay(
+ message: 'Verifying second-factor...',
)
],
),
_isLoading = true;
});
try {
- final client =
- await widget.apiClient!.finishTfaChallenge(_codeController.text);
+ final client = await widget.apiClient!
+ .finishTfaChallenge(_selected_tfa_kind, _codeController.text);
Navigator.of(context).pop(client);
} on ProxmoxApiException catch (e) {
showDialog(