]> git.proxmox.com Git - flutter/proxmox_login_manager.git/blame - lib/proxmox_tfa_form.dart
login form: set TextInputAction.next for origin field
[flutter/proxmox_login_manager.git] / lib / proxmox_tfa_form.dart
CommitLineData
0e468546
TM
1import 'package:flutter/material.dart';
2import 'package:proxmox_dart_api_client/proxmox_dart_api_client.dart';
3import 'package:proxmox_login_manager/proxmox_login_form.dart';
4
5class ProxmoxTfaForm extends StatefulWidget {
a9d1ee22 6 final ProxmoxApiClient? apiClient;
0e468546 7
a9d1ee22 8 const ProxmoxTfaForm({Key? key, this.apiClient}) : super(key: key);
0e468546
TM
9
10 @override
11 _ProxmoxTfaFormState createState() => _ProxmoxTfaFormState();
12}
13
14class _ProxmoxTfaFormState extends State<ProxmoxTfaForm> {
15 final TextEditingController _codeController = TextEditingController();
16 bool _isLoading = false;
eb675700
TL
17 List<String> _tfa_kinds = [];
18 String _selected_tfa_kind = "";
19
20 @override
21 void initState() {
22 super.initState();
23 _tfa_kinds = widget.apiClient!.credentials.tfa!.kinds().toList();
24 _selected_tfa_kind = _tfa_kinds[0];
25 }
26
0e468546
TM
27 @override
28 Widget build(BuildContext context) {
29 return Theme(
291fc65f
DC
30 data: ThemeData.dark().copyWith(
31 colorScheme: ColorScheme.dark().copyWith(
32 secondary: ProxmoxColors.orange,
33 onSecondary: ProxmoxColors.supportGrey)),
79ed04db 34 child: Scaffold(
291fc65f 35 backgroundColor: ProxmoxColors.supportBlue,
79ed04db
TM
36 extendBodyBehindAppBar: true,
37 appBar: AppBar(
38 elevation: 0.0,
39 backgroundColor: Colors.transparent,
40 leading: IconButton(
41 icon: Icon(Icons.close),
42 onPressed: () => Navigator.of(context).pop(),
43 ),
44 ),
45 body: Stack(
0e468546
TM
46 alignment: Alignment.center,
47 children: [
48 SingleChildScrollView(
49 child: ConstrainedBox(
50 constraints: BoxConstraints.tightFor(
51 height: MediaQuery.of(context).size.height),
0de76be7
TL
52 child: SafeArea(
53 child: Padding(
54 padding: const EdgeInsets.all(8.0),
55 child: Column(
56 mainAxisAlignment: MainAxisAlignment.start,
57 crossAxisAlignment: CrossAxisAlignment.center,
58 children: <Widget>[
59 Padding(
60 padding: const EdgeInsets.fromLTRB(0, 100.0, 0, 30.0),
61 child: Icon(
62 Icons.lock,
63 size: 48,
64 ),
0e468546 65 ),
0de76be7
TL
66 Text(
67 'Verify',
68 style: TextStyle(
69 fontSize: 36,
70 color: Colors.white,
71 fontWeight: FontWeight.bold),
72 ),
73 Text(
74 'Check your second factor provider',
75 style: TextStyle(
76 color: Colors.white38,
77 fontWeight: FontWeight.bold),
78 ),
79 Padding(
80 padding: const EdgeInsets.fromLTRB(0, 50.0, 0, 8.0),
81 child: Container(
82 width: 175,
83 child: Column(
84 children: <Widget>[
85 DropdownButtonFormField(
eb675700 86 decoration: InputDecoration(
0de76be7
TL
87 labelText: 'Method',
88 icon: Icon(Icons.input)),
89 items: _tfa_kinds
90 .map((e) => DropdownMenuItem(
91 child: ListTile(title: Text(e)),
92 value: e,
93 ))
94 .toList(),
95 onChanged: (String? value) {
96 setState(() {
97 _selected_tfa_kind = value!;
98 });
99 },
100 selectedItemBuilder: (context) =>
101 _tfa_kinds.map((e) => Text(e)).toList(),
102 value: _selected_tfa_kind,
103 ),
104 TextField(
105 controller: _codeController,
106 textAlign: TextAlign.center,
107 decoration: InputDecoration(
108 labelText: 'Code',
109 icon: Icon(Icons.pin)),
110 autofocus: true,
111 onSubmitted: (value) => _submitTfaCode()),
112 ],
113 ),
eb675700 114 ),
0e468546 115 ),
0de76be7
TL
116 Expanded(
117 child: Align(
118 alignment: Alignment.bottomCenter,
119 child: Container(
120 width: MediaQuery.of(context).size.width,
121 child: TextButton(
122 style: TextButton.styleFrom(
123 foregroundColor: Colors.white,
124 backgroundColor: Color(0xFFE47225),
125 disabledBackgroundColor: Colors.grey,
126 ),
127 onPressed: () => _submitTfaCode(),
128 child: Text('Continue'),
fcdfb148 129 ),
0e468546
TM
130 ),
131 ),
132 ),
0de76be7
TL
133 ],
134 ),
0e468546
TM
135 ),
136 ),
137 ),
138 ),
139 if (_isLoading)
140 ProxmoxProgressOverlay(
aa8e7870 141 message: 'Verifying second-factor...',
0e468546
TM
142 )
143 ],
144 ),
145 ),
146 );
147 }
148
149 Future<void> _submitTfaCode() async {
150 setState(() {
151 _isLoading = true;
152 });
153 try {
eb675700
TL
154 final client = await widget.apiClient!
155 .finishTfaChallenge(_selected_tfa_kind, _codeController.text);
0e468546
TM
156 Navigator.of(context).pop(client);
157 } on ProxmoxApiException catch (e) {
158 showDialog(
159 context: context,
160 builder: (context) => ProxmoxApiErrorDialog(
161 exception: e,
162 ),
163 );
164 } catch (e, trace) {
165 print(e);
166 print(trace);
167 showDialog(
168 context: context,
90a3b765
DC
169 builder: (context) => ConnectionErrorDialog(
170 exception: e,
0e468546
TM
171 ),
172 );
173 }
174 setState(() {
175 _isLoading = false;
176 });
177 }
178}