summaryrefslogtreecommitdiff
path: root/Assistant
diff options
context:
space:
mode:
authorGravatar Joey Hess <joey@kitenet.net>2012-08-31 18:59:57 -0400
committerGravatar Joey Hess <joey@kitenet.net>2012-08-31 18:59:57 -0400
commit54a492db5f86093349910cc0028ff1a56714775f (patch)
tree01a858ea5bb9d68dc8eed71efbd435f383269727 /Assistant
parent86fb1305dc623865ef672d499e1559a2608c5be6 (diff)
UI for adding a ssh or rsync remote
Diffstat (limited to 'Assistant')
-rw-r--r--Assistant/WebApp/Configurators.hs1
-rw-r--r--Assistant/WebApp/Configurators/Local.hs10
-rw-r--r--Assistant/WebApp/Configurators/Ssh.hs112
-rw-r--r--Assistant/WebApp/routes2
4 files changed, 93 insertions, 32 deletions
diff --git a/Assistant/WebApp/Configurators.hs b/Assistant/WebApp/Configurators.hs
index 94c84c03a..4d4d5c916 100644
--- a/Assistant/WebApp/Configurators.hs
+++ b/Assistant/WebApp/Configurators.hs
@@ -14,7 +14,6 @@ import Assistant.WebApp
import Assistant.WebApp.SideBar
import Assistant.DaemonStatus
import Assistant.WebApp.Configurators.Local
-import Assistant.WebApp.Configurators.Ssh
import Utility.Yesod
import qualified Remote
import qualified Types.Remote as Remote
diff --git a/Assistant/WebApp/Configurators/Local.hs b/Assistant/WebApp/Configurators/Local.hs
index 04345f731..beb41e1f1 100644
--- a/Assistant/WebApp/Configurators/Local.hs
+++ b/Assistant/WebApp/Configurators/Local.hs
@@ -12,13 +12,9 @@ module Assistant.WebApp.Configurators.Local where
import Assistant.Common
import Assistant.WebApp
import Assistant.WebApp.SideBar
-import Assistant.DaemonStatus
import Assistant.Threads.MountWatcher (handleMount)
import Utility.Yesod
-import qualified Remote
-import qualified Types.Remote as Remote
import Remote.List
-import Annex.UUID (getUUID)
import Init
import qualified Git
import qualified Git.Construct
@@ -102,7 +98,9 @@ defaultRepositoryPath firstrun = do
then do
desktop <- userDesktopDir
ifM (doesDirectoryExist desktop)
- (relHome (desktop </> "annex"), return "~/annex")
+ ( relHome $ desktop </> gitAnnexAssistantDefaultDir
+ , return $ "~" </> gitAnnexAssistantDefaultDir
+ )
else return cwd
localRepositoryForm :: Form RepositoryPath
@@ -178,7 +176,7 @@ getAddDriveR = bootstrap (Just Config) $ do
webapp <- getYesod
liftIO $ syncrepo dir webapp
where
- dir = mountpoint </> "annex"
+ dir = mountpoint </> gitAnnexAssistantDefaultDir
remotename = takeFileName mountpoint
{- The repo may already exist, when adding removable media
- that has already been used elsewhere. -}
diff --git a/Assistant/WebApp/Configurators/Ssh.hs b/Assistant/WebApp/Configurators/Ssh.hs
index 912bc7866..afd0e1a79 100644
--- a/Assistant/WebApp/Configurators/Ssh.hs
+++ b/Assistant/WebApp/Configurators/Ssh.hs
@@ -12,33 +12,97 @@ module Assistant.WebApp.Configurators.Ssh where
import Assistant.Common
import Assistant.WebApp
import Assistant.WebApp.SideBar
-import Assistant.DaemonStatus
-import Assistant.Threads.MountWatcher (handleMount)
import Utility.Yesod
-import qualified Remote
-import qualified Types.Remote as Remote
-import Remote.List
-import Annex.UUID (getUUID)
-import Init
-import qualified Git
-import qualified Git.Construct
-import qualified Git.Config
-import qualified Git.Command
-import qualified Annex
-import Locations.UserConfig
-import Utility.FreeDesktop
-import Utility.Mounts
-import Utility.DiskFree
-import Utility.DataUnits
-import Utility.Network
import Yesod
import Data.Text (Text)
import qualified Data.Text as T
-import Data.Char
-import System.Posix.Directory
-import qualified Control.Exception as E
+import Network.BSD
+import System.Posix.User
-getAddRemoteServerR :: Handler RepHtml
-getAddRemoteServerR = bootstrap (Just Config) $ do
- error "TODO"
+data SshServer = SshServer
+ { hostname :: Maybe Text
+ , username :: Maybe Text
+ , directory :: Maybe Text
+ }
+ deriving Show
+
+sshServerAForm :: Text -> AForm WebApp WebApp SshServer
+sshServerAForm localusername = SshServer
+ <$> aopt check_hostname "Host name" Nothing
+ <*> aopt check_username "User name" (Just $ Just localusername)
+ <*> aopt textField "Directory" (Just $ Just $ T.pack gitAnnexAssistantDefaultDir)
+ where
+ check_hostname = checkM (liftIO . checkdns) textField
+ checkdns t = do
+ let h = T.unpack t
+ r <- catchMaybeIO $ getHostByName h
+ return $ case r of
+ -- canonicalize input hostname if it had no dot
+ Just hostentry
+ | '.' `elem` h -> Right t
+ | otherwise -> Right $ T.pack $ hostName hostentry
+ Nothing -> Left bad_hostname
+
+ check_username = checkBool (all (`notElem` "/:@ \t") . T.unpack)
+ bad_username textField
+
+ bad_hostname = "cannot resolve host name" :: Text
+ bad_username = "bad user name" :: Text
+
+data ServerStatus
+ = UntestedServer
+ | UnusableServer Text -- reason why it's not usable
+ | UsableRsyncServer
+ | UsableSshServer
+
+{- Test if we can ssh into the server. If ssh doesn't work, fall back to
+ - trying rsync protocol.
+ -
+ - Before sshing in, if the user doesn't have a ssh key, a special one is
+ - generated just for this server, and configured to be used for this
+ - server. (If the user does have a ssh key, we assume they know what
+ - they're doing, and don't touch their ssh setup.)
+ -
+ - If we can ssh in, check that git-annex-shell is installed. If not, this
+ - will need to be a rsync special remote, rather than a git remote, so
+ - check that rsync is installed.
+ -
+ - When we ssh in, if we set up a ssh key, the server's authorized_keys
+ - is configured to let it run either git-annex-shell or rsync for that ssh
+ - key, and nothing else.
+ -
+ - Of course, ssh may ask for a passphrase, etc. We rely on ssh-askpass
+ - or an equivilant being used by ssh. Or, if the assistant is
+ - running in the foreground, the password will be asked there.
+ -}
+testServer :: SshServer -> IO ServerStatus
+testServer (SshServer { hostname = Nothing }) = return $
+ UnusableServer "Please enter a host name."
+testServer _sshserver = return UsableSshServer
+
+getAddSshR :: Handler RepHtml
+getAddSshR = bootstrap (Just Config) $ do
+ sideBarDisplay
+ setTitle "Add a remote server"
+ u <- liftIO $ T.pack . userName
+ <$> (getUserEntryForID =<< getEffectiveUserID)
+ ((result, form), enctype) <- lift $
+ runFormGet $ renderBootstrap $ sshServerAForm u
+ case result of
+ FormSuccess sshserver -> do
+ showform form enctype =<< liftIO (testServer sshserver)
+ _ -> showform form enctype UntestedServer
+ where
+ showform form enctype status = do
+ let authtoken = webAppFormAuthToken
+ $(widgetFile "configurators/addssh")
+
+ buttonText :: ServerStatus -> Text
+ buttonText UsableRsyncServer = "Make rsync repository"
+ buttonText UsableSshServer = "Clone repository to ssh server"
+ buttonText _ = "Check this server"
+
+ willTest UntestedServer = True
+ willTest (UnusableServer _) = True
+ willTest _ = False
diff --git a/Assistant/WebApp/routes b/Assistant/WebApp/routes
index 72b76c33d..eaa5ac7d1 100644
--- a/Assistant/WebApp/routes
+++ b/Assistant/WebApp/routes
@@ -6,7 +6,7 @@
/config ConfigR GET
/config/repository RepositoriesR GET
/config/repository/add/drive AddDriveR GET
-/config/repository/add/remoteserver AddRemoteServerR GET
+/config/repository/add/ssh AddSshR GET
/config/repository/first FirstRepositoryR GET
/transfers/#NotificationId TransfersR GET