Compare commits

...

10 Commits

Author SHA1 Message Date
lemoer
670fb7e0a6 Move everything to main dir 2025-07-06 14:36:20 +02:00
lemoer
54a832f732 Nicer error message 2025-07-06 01:44:36 +02:00
lemoer
02d3341b3d Show SSH exceptions as useful error messages in SnackBars 2025-07-06 01:01:11 +02:00
lemoer
7251fce43a Change theme to be yellow 2025-07-06 00:49:18 +02:00
lemoer
c6ad9a29bf Remove commented out code 2025-07-06 00:45:55 +02:00
lemoer
38ae7ca28e More beauty icons 2025-07-06 00:36:35 +02:00
lemoer
6c51928b98 Add real ssh actions and host 2025-07-06 00:26:45 +02:00
lemoer
d05aede7e7 Fix padding in "Manage Keys Registered To Locks" 2025-07-05 23:57:44 +02:00
lemoer
91f3088745 Use Wrap in Favor Of Row in KeepOrDeleteKey-Widget 2025-07-05 23:54:23 +02:00
lemoer
1cff53640e Make Key Management Page nicer 2025-07-05 23:23:19 +02:00
130 changed files with 161 additions and 58 deletions

View File

View File

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 544 B

View File

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 442 B

View File

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 721 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 68 B

View File

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 68 B

View File

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 68 B

View File

@ -78,7 +78,7 @@ class MyApp extends StatelessWidget {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
colorScheme: ColorScheme.fromSeed(seedColor: Colors.yellow),
),
home: const MyHomePage(title: 'LeineLab e.V. Key App'),
);
@ -100,30 +100,46 @@ class _MyHomePageState extends State<MyHomePage> {
String _output = '';
String key = '';
Future<void> doSSH() async {
Future<void> doSSH(String user) async {
SSHSocket? socket;
try {
socket = await SSHSocket.connect(
'192.168.2.123',
'192.168.0.15',
22,
timeout: const Duration(seconds: 0, milliseconds: 500),
);
final client = SSHClient(
socket,
username: 'test',
username: user,
identities: List.of(keyPair != null ? [keyPair!] : []),
);
final uptime = await client.run('uptime');
print(uptime);
setState(() {
_output = utf8.decode(uptime);
});
} catch (e) {
setState(() {
_output = "Error: $e";
});
} on SSHAuthError catch (_) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
"Error! Server rejected your key. Maybe you need to register it first? Or you do not have access to this lock?",
),
duration: const Duration(seconds: 3),
),
);
return;
} on SocketException catch (_) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
"Error! Could not connect to SSH server. Maybe you are not in the right wifi network?",
),
duration: const Duration(seconds: 3),
),
);
return;
}
}
@ -190,12 +206,96 @@ class _MyHomePageState extends State<MyHomePage> {
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
onPressed: () => authentikApiState.start(key),
child: Text("Oauth2 Login"),
Padding(
padding: EdgeInsets.all(20),
child: Card(
child: Column(
children: [
Padding(
padding: EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(right: 15),
child: Icon(Icons.diversity_1, size: 25),
),
Text(
"Hauptraum (oben)",
style: TextStyle(fontSize: 25),
),
],
),
),
Padding(
padding: EdgeInsets.fromLTRB(20, 0, 20, 20),
child: Wrap(
spacing:
8.0, // horizontaler Abstand zwischen den Elementen
runSpacing: 4.0, // vertikaler Abstand zwischen den Zeilen
children: [
TextButton(
onPressed: () => doSSH("innentuer-open"),
child: const Text('Open Inside Door'),
),
TextButton(
onPressed: () => doSSH("aussentuer-open"),
child: const Text('Open Outdoor'),
),
TextButton(
onPressed: () => doSSH("lab-close"),
child: const Text('Close All Doors'),
),
],
),
),
],
),
),
),
Padding(
padding: EdgeInsets.all(20),
child: Card(
child: Column(
children: [
Padding(
padding: EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(right: 15),
child: Icon(Icons.construction, size: 25),
),
Text(
"Werkstatt (oben)",
style: TextStyle(fontSize: 25),
),
],
),
),
Padding(
padding: EdgeInsets.fromLTRB(20, 0, 20, 20),
child: Wrap(
spacing:
8.0, // horizontaler Abstand zwischen den Elementen
runSpacing: 4.0, // vertikaler Abstand zwischen den Zeilen
children: [
TextButton(
onPressed: () => doSSH("werkstatt-open"),
child: const Text('Open'),
),
TextButton(
onPressed: () => doSSH("werkstatt-close"),
child: const Text('Close'),
),
],
),
),
],
),
),
),
Text('Current output:'),
Text(outputText, style: Theme.of(context).textTheme.headlineMedium),
],
),
);
@ -203,14 +303,45 @@ class _MyHomePageState extends State<MyHomePage> {
final bodyComponentInfo = Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Center(child: Text('Info\n\n$key'))],
children: <Widget>[
Padding(
padding: EdgeInsets.all(20),
child: Card(
child: Column(
children: [
Padding(
padding: EdgeInsets.all(20),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(right: 15),
child: Icon(Icons.key, size: 25),
),
Text(
"Your Current Key",
style: TextStyle(fontSize: 25),
),
],
),
),
Padding(
padding: EdgeInsets.fromLTRB(20, 0, 20, 20),
child: Text(key, style: TextStyle(fontSize: 15)),
),
Padding(
padding: EdgeInsets.fromLTRB(20, 0, 20, 20),
child: TextButton(
onPressed: () => authentikApiState.start(key),
child: Text("Manage Keys Registered To Locks"),
),
),
],
),
),
),
],
),
);
final actionButtonMain = FloatingActionButton(
onPressed: doSSH,
tooltip: 'Do SSH',
child: const Icon(Icons.computer),
);
final actionButtonInfo = FloatingActionButton(
@ -220,12 +351,12 @@ class _MyHomePageState extends State<MyHomePage> {
);
var bodyComponent = bodyComponentMain;
var actionButton = actionButtonMain;
Widget? actionButton;
if (navIndex == 0) {
// Main page
bodyComponent = bodyComponentMain;
actionButton = actionButtonMain;
actionButton = null;
} else if (navIndex == 1) {
// Info page
bodyComponent = bodyComponentInfo;
@ -250,7 +381,7 @@ class _MyHomePageState extends State<MyHomePage> {
),
),
ListTile(
title: const Text('Main Page'),
title: const Text('Actions'),
onTap: () {
setState(() {
navIndex = 0;
@ -259,7 +390,7 @@ class _MyHomePageState extends State<MyHomePage> {
},
),
ListTile(
title: const Text('Info Page'),
title: const Text('Key Management'),
onTap: () {
setState(() {
navIndex = 1;
@ -546,36 +677,6 @@ class AuthentikUserSettingsChangeDialogState extends ChangeNotifier {
_keysToKeep.clear();
notifyListeners();
}
// Future<void> doOAuth1() async {
// final client = await getOAuth2Client();
// // TODO: Handle errors better
// try {
// final jsonMe = await client.read(
// Uri.parse('https://auth.leinelab.org/api/v3/core/users/me/'),
// );
// final me = jsonDecode(jsonMe);
// final user = me['user'];
// final transformed = {
// "username": user['username'],
// "name": user['name'],
// "email": user['email'],
// "attributes.settings.locale": user['settings']['locale'],
// "attributes.sshPublicKeys":
// "foooooooobar :O :O!", // fix oder aus anderer Quelle
// "component": "ak-stage-prompt",
// };
// print(user);
// print(transformed);
// } catch (e) {
// print(e.toString());
// }
// ;
// }
}
class KeepOrDeleteKey extends StatelessWidget {
@ -638,8 +739,9 @@ class KeepOrDeleteKey extends StatelessWidget {
Widget titleWidget = Text(title, style: TextStyle(fontSize: 25));
if (isOurKey) {
titleWidget = Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
titleWidget = Wrap(
spacing: 8.0, // horizontaler Abstand zwischen den Elementen
runSpacing: 4.0, // vertikaler Abstand zwischen den Zeilen
children: [
titleWidget,
Container(
@ -668,8 +770,9 @@ class KeepOrDeleteKey extends StatelessWidget {
),
Padding(
padding: EdgeInsets.fromLTRB(20, 0, 20, 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
child: Wrap(
spacing: 8.0, // horizontaler Abstand zwischen den Elementen
runSpacing: 4.0, // vertikaler Abstand zwischen den Zeilen
children: [
TextButton(
onPressed: () {

View File

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 520 B

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Some files were not shown because too many files have changed in this diff Show More