From 69fbd20040d65ccb1c17118cddeeef1d81e2f00d Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Mon, 17 Feb 2020 18:02:57 +0100 Subject: [PATCH] HostSetup: Allow custom keys to be provided Fixes #26 --- lib/setup/screens.dart | 111 ++++++++++++++++++++++++++++++++------- lib/setup/sshkey.dart | 115 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+), 19 deletions(-) diff --git a/lib/setup/screens.dart b/lib/setup/screens.dart index 0509dc3a..3dc65913 100644 --- a/lib/setup/screens.dart +++ b/lib/setup/screens.dart @@ -36,6 +36,7 @@ class GitHostSetupScreen extends StatefulWidget { enum PageChoice0 { Unknown, KnownProvider, CustomProvider } enum PageChoice1 { Unknown, Manual, Auto } +enum KeyGenerationChoice { Unknown, AutoGenerated, UserProvided } class GitHostSetupScreenState extends State { var _pageCount = 1; @@ -44,6 +45,7 @@ class GitHostSetupScreenState extends State { PageChoice0.Unknown, PageChoice1.Unknown, ]; + var _keyGenerationChoice = KeyGenerationChoice.Unknown; var _gitHostType = GitHostType.Unknown; var _gitCloneUrl = ""; @@ -87,7 +89,6 @@ class GitHostSetupScreenState extends State { _pageCount = pos + 2; _nextPage(); - _generateSshKey(context); }); }, initialValue: _gitCloneUrl, @@ -115,16 +116,23 @@ class GitHostSetupScreenState extends State { if (pos == 2) { if (_pageChoice[0] == PageChoice0.CustomProvider) { - return GitHostSetupSshKeyUnknownProvider( - doneFunction: () { + return GitHostSetupKeyChoice( + onGenerateKeys: () { setState(() { + _keyGenerationChoice = KeyGenerationChoice.AutoGenerated; + _pageCount = pos + 2; + + _nextPage(); + _generateSshKey(context); + }); + }, + onUserProvidedKeys: () { + setState(() { + _keyGenerationChoice = KeyGenerationChoice.UserProvided; _pageCount = pos + 2; _nextPage(); - _startGitClone(context); }); }, - publicKey: publicKey, - copyKeyFunction: _copyKeyToClipboard, ); } @@ -138,7 +146,6 @@ class GitHostSetupScreenState extends State { _gitCloneUrl = sshUrl; _nextPage(); - _generateSshKey(context); }); }, launchCreateUrlPage: _launchCreateRepoPage, @@ -163,29 +170,52 @@ class GitHostSetupScreenState extends State { if (pos == 3) { if (_pageChoice[0] == PageChoice0.CustomProvider) { - return GitHostSetupGitClone(errorMessage: gitCloneErrorMessage); + assert(_keyGenerationChoice != KeyGenerationChoice.Unknown); + if (_keyGenerationChoice == KeyGenerationChoice.AutoGenerated) { + return GitHostSetupSshKeyUnknownProvider( + doneFunction: () { + setState(() { + _pageCount = pos + 2; + _nextPage(); + _startGitClone(context); + }); + }, + publicKey: publicKey, + copyKeyFunction: _copyKeyToClipboard, + ); + } else if (_keyGenerationChoice == KeyGenerationChoice.UserProvided) { + return GitHostUserProvidedKeys( + doneFunction: (String publicKey, String privateKey) async { + await setSshKeys(publicKey: publicKey, privateKey: privateKey); + setState(() { + this.publicKey = publicKey; + _pageCount = pos + 2; + _nextPage(); + _startGitClone(context); + }); + }, + ); + } } if (_pageChoice[1] == PageChoice1.Manual) { - // FIXME: Create a new page with better instructions - return GitHostSetupSshKeyKnownProvider( - doneFunction: () { + return GitHostSetupKeyChoice( + onGenerateKeys: () { setState(() { - _pageCount = 6; + _keyGenerationChoice = KeyGenerationChoice.AutoGenerated; + _pageCount = pos + 2; _nextPage(); - _startGitClone(context); + _generateSshKey(context); }); }, - regenerateFunction: () { + onUserProvidedKeys: () { setState(() { - publicKey = ""; + _keyGenerationChoice = KeyGenerationChoice.UserProvided; + _pageCount = pos + 2; + _nextPage(); }); - _generateSshKey(context); }, - publicKey: publicKey, - copyKeyFunction: _copyKeyToClipboard, - openDeployKeyPage: _launchDeployKeyPage, ); } else if (_pageChoice[1] == PageChoice1.Auto) { return GitHostSetupGitClone(errorMessage: gitCloneErrorMessage); @@ -195,6 +225,49 @@ class GitHostSetupScreenState extends State { } if (pos == 4) { + if (_pageChoice[0] == PageChoice0.CustomProvider) { + return GitHostSetupGitClone(errorMessage: gitCloneErrorMessage); + } + + if (_pageChoice[1] == PageChoice1.Manual) { + assert(_keyGenerationChoice != KeyGenerationChoice.Unknown); + if (_keyGenerationChoice == KeyGenerationChoice.AutoGenerated) { + return GitHostSetupSshKeyKnownProvider( + doneFunction: () { + setState(() { + _pageCount = 6; + + _nextPage(); + _startGitClone(context); + }); + }, + regenerateFunction: () { + setState(() { + publicKey = ""; + }); + _generateSshKey(context); + }, + publicKey: publicKey, + copyKeyFunction: _copyKeyToClipboard, + openDeployKeyPage: _launchDeployKeyPage, + ); + } else if (_keyGenerationChoice == KeyGenerationChoice.UserProvided) { + return GitHostUserProvidedKeys( + doneFunction: (String publicKey, String privateKey) async { + await setSshKeys(publicKey: publicKey, privateKey: privateKey); + setState(() { + this.publicKey = publicKey; + _pageCount = pos + 2; + _nextPage(); + _startGitClone(context); + }); + }, + ); + } + } + } + + if (pos == 5) { if (_pageChoice[1] == PageChoice1.Manual) { return GitHostSetupGitClone(errorMessage: gitCloneErrorMessage); } diff --git a/lib/setup/sshkey.dart b/lib/setup/sshkey.dart index 355f9ef6..7efdf134 100644 --- a/lib/setup/sshkey.dart +++ b/lib/setup/sshkey.dart @@ -157,6 +157,121 @@ class GitHostSetupSshKeyUnknownProvider extends StatelessWidget { } } +class GitHostSetupKeyChoice extends StatelessWidget { + final Func0 onGenerateKeys; + final Func0 onUserProvidedKeys; + + GitHostSetupKeyChoice({ + @required this.onGenerateKeys, + @required this.onUserProvidedKeys, + }); + + @override + Widget build(BuildContext context) { + return Container( + child: Column( + children: [ + Text( + "We need SSH keys to authenticate -", + style: Theme.of(context).textTheme.headline, + ), + const SizedBox(height: 16.0), + GitHostSetupButton( + text: "Generate new keys", + onPressed: onGenerateKeys, + ), + const SizedBox(height: 8.0), + GitHostSetupButton( + text: "Provide Custom SSH Keys", + onPressed: onUserProvidedKeys, + ), + ], + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + ), + ); + } +} + +class GitHostUserProvidedKeys extends StatefulWidget { + final Func2 doneFunction; + + GitHostUserProvidedKeys({ + @required this.doneFunction, + }); + + @override + _GitHostUserProvidedKeysState createState() => + _GitHostUserProvidedKeysState(); +} + +class _GitHostUserProvidedKeysState extends State { + final _publicKeyController = TextEditingController(); + final _privateKeyController = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Container( + child: Column( + children: [ + Text( + "Public Key -", + style: Theme.of(context).textTheme.headline, + ), + const SizedBox(height: 8.0), + KeyEditor(_publicKeyController), + const SizedBox(height: 8.0), + Text( + "Private Key -", + style: Theme.of(context).textTheme.headline, + ), + KeyEditor(_privateKeyController), + const SizedBox(height: 16.0), + GitHostSetupButton( + text: "Next", + onPressed: () { + var publicKey = _publicKeyController.text.trim(); + var privateKey = _privateKeyController.text.trim(); + widget.doneFunction(publicKey, privateKey); + }, + ), + ], + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + ), + ); + } +} + +// FIXME: vHanda: Add validation +class KeyEditor extends StatelessWidget { + final TextEditingController controller; + + KeyEditor(this.controller); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + height: 80.0, + child: Container( + color: Theme.of(context).buttonColor, + child: SingleChildScrollView( + child: Container( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: controller, + textAlign: TextAlign.left, + maxLines: null, + style: Theme.of(context).textTheme.body1, + ), + ), + ), + ), + ); + } +} + class PublicKeyWidget extends StatelessWidget { final String publicKey;