Compare commits
10 Commits
7c5251fb99
...
670fb7e0a6
Author | SHA1 | Date | |
---|---|---|---|
![]() |
670fb7e0a6 | ||
![]() |
54a832f732 | ||
![]() |
02d3341b3d | ||
![]() |
7251fce43a | ||
![]() |
c6ad9a29bf | ||
![]() |
38ae7ca28e | ||
![]() |
6c51928b98 | ||
![]() |
d05aede7e7 | ||
![]() |
91f3088745 | ||
![]() |
1cff53640e |
0
app/.gitignore → .gitignore
vendored
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 544 B |
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 442 B |
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 721 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
0
app/ios/.gitignore → ios/.gitignore
vendored
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 295 B |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 406 B |
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 450 B |
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 282 B |
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 462 B |
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 704 B |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 406 B |
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 586 B |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 862 B |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 862 B |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 762 B |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 68 B |
@ -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: () {
|
0
app/linux/.gitignore → linux/.gitignore
vendored
0
app/macos/.gitignore → macos/.gitignore
vendored
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 520 B After Width: | Height: | Size: 520 B |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |