Compare commits

...

2 Commits

Author SHA1 Message Date
lemoer
20358c8a34 exception if launchUrl fails 2025-07-07 21:52:24 +02:00
lemoer
171831994a Show dialog for ssh output 2025-07-07 21:27:50 +02:00

View File

@ -60,7 +60,7 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
title: 'LeineLab e.V. Key App',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.yellow),
),
@ -81,12 +81,23 @@ class MyHomePage extends StatefulWidget {
class _MyHomePageState extends State<MyHomePage> {
int navIndex = 0;
OpenSSHEd25519KeyPair? keyPair;
String _output = '';
String? _output;
SSHClient? client;
String key = '';
Future<void> doSSH(String user) async {
SSHSocket? socket;
if (client != null) {
// If we already have a client, close it
client!.close();
client = null;
}
setState(() {
_output = null;
});
try {
socket = await SSHSocket.connect(
'192.168.0.15',
@ -94,17 +105,48 @@ class _MyHomePageState extends State<MyHomePage> {
timeout: const Duration(seconds: 0, milliseconds: 500),
);
final client = SSHClient(
client = SSHClient(
socket,
username: user,
identities: List.of(keyPair != null ? [keyPair!] : []),
);
final uptime = await client.run('uptime');
setState(() {
_output = utf8.decode(uptime);
_output = 'Connecting to SSH server...\n\n';
});
if (client == null) {
return;
}
final shell = await client!.shell();
shell.stdout.listen((data) {
setState(() {
if (_output == null) {
return;
}
_output = _output! + utf8.decode(data);
});
});
if (client == null) {
return;
}
await shell.done;
if (client == null) {
return;
}
client!.close();
setState(() {
_output = null;
});
} on SSHAuthError catch (_) {
setState(() {
_output = null;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
@ -115,6 +157,9 @@ class _MyHomePageState extends State<MyHomePage> {
);
return;
} on SocketException catch (_) {
setState(() {
_output = null;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
@ -382,11 +427,7 @@ class _MyHomePageState extends State<MyHomePage> {
),
);
if (authentikApiState.isClosed()) {
return mainPage;
}
Widget title;
Widget? title;
var children = <Widget>[];
var actions = [
TextButton(onPressed: authentikApiState.exit, child: Text("Cancel")),
@ -394,7 +435,7 @@ class _MyHomePageState extends State<MyHomePage> {
switch (authentikApiState.status) {
case AuthentikUserSettingsChangeDialogStatus.closed:
return mainPage;
break;
case AuthentikUserSettingsChangeDialogStatus.waitingForOAuth:
title = Text("Waiting for OAuth");
children = [Text("Please complete the OAuth flow in your browser.")];
@ -429,6 +470,31 @@ class _MyHomePageState extends State<MyHomePage> {
children = [Text("Saving...")];
}
if (_output != null) {
title = Text("SSH Output");
children.add(Text(_output!, style: TextStyle(fontSize: 12)));
// TODO: fix action.
actions = [
TextButton(
onPressed: () {
setState(() {
_output = null;
if (client != null) {
client!.close();
client = null;
}
});
},
child: Text("Cancel"),
),
];
}
if (title == null) {
// If we have no title, just return the main page
return mainPage;
}
final dialog = AlertDialog(
title: title,
content: SingleChildScrollView(child: Column(children: children)),
@ -498,7 +564,12 @@ class AuthentikUserSettingsChangeDialogState extends ChangeNotifier {
server = await HttpServer.bind("127.0.0.1", 30165);
await launchUrl(authorizationUrl, mode: LaunchMode.externalApplication);
if (!await launchUrl(
authorizationUrl,
mode: LaunchMode.externalApplication,
)) {
throw Exception("Could not launch the authorization URL.");
}
if (server == null) {
// exit() might have been called before we arrived here.