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(
|
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: () {
|
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 |