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( return MaterialApp(
title: 'Flutter Demo', title: 'Flutter Demo',
theme: ThemeData( theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), colorScheme: ColorScheme.fromSeed(seedColor: Colors.yellow),
), ),
home: const MyHomePage(title: 'LeineLab e.V. Key App'), home: const MyHomePage(title: 'LeineLab e.V. Key App'),
); );
@ -100,30 +100,46 @@ class _MyHomePageState extends State<MyHomePage> {
String _output = ''; String _output = '';
String key = ''; String key = '';
Future<void> doSSH() async { Future<void> doSSH(String user) async {
SSHSocket? socket; SSHSocket? socket;
try { try {
socket = await SSHSocket.connect( socket = await SSHSocket.connect(
'192.168.2.123', '192.168.0.15',
22, 22,
timeout: const Duration(seconds: 0, milliseconds: 500), timeout: const Duration(seconds: 0, milliseconds: 500),
); );
final client = SSHClient( final client = SSHClient(
socket, socket,
username: 'test', username: user,
identities: List.of(keyPair != null ? [keyPair!] : []), identities: List.of(keyPair != null ? [keyPair!] : []),
); );
final uptime = await client.run('uptime'); final uptime = await client.run('uptime');
print(uptime);
setState(() { setState(() {
_output = utf8.decode(uptime); _output = utf8.decode(uptime);
}); });
} catch (e) { } on SSHAuthError catch (_) {
setState(() { ScaffoldMessenger.of(context).showSnackBar(
_output = "Error: $e"; 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; return;
} }
} }
@ -190,12 +206,96 @@ class _MyHomePageState extends State<MyHomePage> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
TextButton( Padding(
onPressed: () => authentikApiState.start(key), padding: EdgeInsets.all(20),
child: Text("Oauth2 Login"), 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,16 +303,47 @@ class _MyHomePageState extends State<MyHomePage> {
final bodyComponentInfo = Center( final bodyComponentInfo = Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, 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( final actionButtonInfo = FloatingActionButton(
onPressed: () => obtainKeyPair(regenerate: true), onPressed: () => obtainKeyPair(regenerate: true),
tooltip: 'Regenerate Key', tooltip: 'Regenerate Key',
@ -220,12 +351,12 @@ class _MyHomePageState extends State<MyHomePage> {
); );
var bodyComponent = bodyComponentMain; var bodyComponent = bodyComponentMain;
var actionButton = actionButtonMain; Widget? actionButton;
if (navIndex == 0) { if (navIndex == 0) {
// Main page // Main page
bodyComponent = bodyComponentMain; bodyComponent = bodyComponentMain;
actionButton = actionButtonMain; actionButton = null;
} else if (navIndex == 1) { } else if (navIndex == 1) {
// Info page // Info page
bodyComponent = bodyComponentInfo; bodyComponent = bodyComponentInfo;
@ -250,7 +381,7 @@ class _MyHomePageState extends State<MyHomePage> {
), ),
), ),
ListTile( ListTile(
title: const Text('Main Page'), title: const Text('Actions'),
onTap: () { onTap: () {
setState(() { setState(() {
navIndex = 0; navIndex = 0;
@ -259,7 +390,7 @@ class _MyHomePageState extends State<MyHomePage> {
}, },
), ),
ListTile( ListTile(
title: const Text('Info Page'), title: const Text('Key Management'),
onTap: () { onTap: () {
setState(() { setState(() {
navIndex = 1; navIndex = 1;
@ -546,36 +677,6 @@ class AuthentikUserSettingsChangeDialogState extends ChangeNotifier {
_keysToKeep.clear(); _keysToKeep.clear();
notifyListeners(); 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 { class KeepOrDeleteKey extends StatelessWidget {
@ -638,8 +739,9 @@ class KeepOrDeleteKey extends StatelessWidget {
Widget titleWidget = Text(title, style: TextStyle(fontSize: 25)); Widget titleWidget = Text(title, style: TextStyle(fontSize: 25));
if (isOurKey) { if (isOurKey) {
titleWidget = Row( titleWidget = Wrap(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, spacing: 8.0, // horizontaler Abstand zwischen den Elementen
runSpacing: 4.0, // vertikaler Abstand zwischen den Zeilen
children: [ children: [
titleWidget, titleWidget,
Container( Container(
@ -668,8 +770,9 @@ class KeepOrDeleteKey extends StatelessWidget {
), ),
Padding( Padding(
padding: EdgeInsets.fromLTRB(20, 0, 20, 20), padding: EdgeInsets.fromLTRB(20, 0, 20, 20),
child: Row( child: Wrap(
mainAxisAlignment: MainAxisAlignment.spaceAround, spacing: 8.0, // horizontaler Abstand zwischen den Elementen
runSpacing: 4.0, // vertikaler Abstand zwischen den Zeilen
children: [ children: [
TextButton( TextButton(
onPressed: () { 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