diff options
author | Joey Hess <joey@kitenet.net> | 2012-09-02 17:32:24 -0400 |
---|---|---|
committer | Joey Hess <joey@kitenet.net> | 2012-09-02 17:32:24 -0400 |
commit | 014974a7daec4dad961ae48ad0aab6886651986f (patch) | |
tree | 7dc7e5187424fef0da37f5930a2c8a3f21772ed6 | |
parent | 5228ba931428f07a2df1549c913e723a1254a49e (diff) |
allow making encrypted rsync special remotes
wow, that was easy!
-rw-r--r-- | Assistant/WebApp/Configurators/Local.hs | 40 | ||||
-rw-r--r-- | Assistant/WebApp/Configurators/Ssh.hs | 101 | ||||
-rw-r--r-- | Assistant/WebApp/routes | 3 | ||||
-rw-r--r-- | templates/configurators/addssh.hamlet | 5 | ||||
-rw-r--r-- | templates/configurators/confirmssh.hamlet | 18 | ||||
-rw-r--r-- | templates/configurators/makessherror.hamlet | 2 |
6 files changed, 105 insertions, 64 deletions
diff --git a/Assistant/WebApp/Configurators/Local.hs b/Assistant/WebApp/Configurators/Local.hs index 64bb25b28..d68de5cd1 100644 --- a/Assistant/WebApp/Configurators/Local.hs +++ b/Assistant/WebApp/Configurators/Local.hs @@ -195,25 +195,37 @@ getAddDriveR = bootstrap (Just Config) $ do hostname <- maybe "host" id <$> liftIO getHostname hostlocation <- fromRepo Git.repoLocation liftIO $ inDir dir $ - void $ addRemote' hostname hostlocation - addRemote name dir + void $ makeGitRemote hostname hostlocation + addRemote $ makeGitRemote name dir -{- Adds a remote, if there is not already one with the same location. -} -addRemote :: String -> String -> Annex Remote -addRemote name location = do - name' <- addRemote' name location +{- Runs an action that returns a name of the remote, and finishes adding it. -} +addRemote :: Annex String -> Annex Remote +addRemote a = do + name <- a void $ remoteListRefresh - maybe (error "failed to add remote") return =<< Remote.byName (Just name') + maybe (error "failed to add remote") return =<< Remote.byName (Just name) -addRemote' :: String -> String -> Annex String -addRemote' name location = inRepo $ \r -> +{- Returns the name of the git remote it created. If there's already a + - remote at the location, returns its name. -} +makeGitRemote :: String -> String -> Annex String +makeGitRemote basename location = makeRemote basename location $ \name -> + void $ inRepo $ + Git.Command.runBool "remote" + [Param "add", Param name, Param location] + +{- If there's not already a remote at the location, adds it using the + - action, which is passed the name of the remote to make. + - + - Returns the name of the remote. -} +makeRemote :: String -> String -> (String -> Annex ()) -> Annex String +makeRemote basename location a = do + r <- fromRepo id if (null $ filter samelocation $ Git.remotes r) then do - let name' = uniqueRemoteName r name 0 - void $ Git.Command.runBool "remote" - [Param "add", Param name', Param location] r - return name' - else return name + let name = uniqueRemoteName r basename 0 + a name + return name + else return basename where samelocation x = Git.repoLocation x == location diff --git a/Assistant/WebApp/Configurators/Ssh.hs b/Assistant/WebApp/Configurators/Ssh.hs index 86ee937ee..b4dbe4e94 100644 --- a/Assistant/WebApp/Configurators/Ssh.hs +++ b/Assistant/WebApp/Configurators/Ssh.hs @@ -15,10 +15,16 @@ import Assistant.WebApp.Types import Assistant.WebApp.SideBar import Utility.Yesod import Assistant.WebApp.Configurators.Local +import qualified Types.Remote as R +import qualified Remote.Rsync as Rsync +import qualified Command.InitRemote +import Logs.UUID +import Logs.Remote import Yesod import Data.Text (Text) import qualified Data.Text as T +import qualified Data.Map as M import Network.BSD import System.Posix.User import System.Process (CreateProcess(..)) @@ -156,16 +162,6 @@ testServer sshserver = do report r = "echo " ++ token r sshopt k v = concat ["-o", k, "=", v] -{- ssh://user@host/path -} -genSshUrl :: SshData -> Text -genSshUrl s = T.concat ["ssh://", u, h, d, "/"] - where - u = maybe "" (\v -> T.concat [v, "@"]) $ sshUserName s - h = sshHostName s - d - | "/" `T.isPrefixOf` sshDirectory s = d - | otherwise = T.concat ["/~/", sshDirectory s] - {- user@host or host -} genSshHost :: Text -> Maybe Text -> String genSshHost host user = maybe "" (\v -> T.unpack v ++ "@") user ++ T.unpack host @@ -239,52 +235,75 @@ getConfirmSshR sshdata = sshConfigurator $ do let haspubkey = isJust $ pubKey sshdata $(widgetFile "configurators/confirmssh") -{- Creates the repository on the remote. Does any necessary ssh key setup. - - - - This is a one-sided remote setup; the remote server probably does not - - have a route to the client here. - -} -getMakeSshR :: SshData -> Handler RepHtml -getMakeSshR sshdata = do +getMakeSshGitR :: SshData -> Handler RepHtml +getMakeSshGitR = makeSsh False + +getMakeSshRsyncR :: SshData -> Handler RepHtml +getMakeSshRsyncR = makeSsh True + +makeSsh :: Bool -> SshData -> Handler RepHtml +makeSsh rsync sshdata = do (transcript, ok) <- liftIO $ sshTranscript [sshhost, remoteCommand] if ok then do - r <- runAnnex undefined $ - addRemote (sshRepoName sshdata) sshurl + r <- runAnnex undefined makerepo syncRemote r redirect RepositoriesR else showerr transcript where sshhost = genSshHost (sshHostName sshdata) (sshUserName sshdata) - authline = authorizedKeysLine sshdata remotedir = T.unpack $ sshDirectory sshdata - sshurl = T.unpack $ genSshUrl sshdata remoteCommand = join "&&" $ catMaybes [ Just $ "mkdir -p " ++ shellEscape remotedir , Just $ "cd " ++ shellEscape remotedir - , Just $ join "&&" makerepo - , if null authline - then Nothing - else Just $ join "&&" makeAuthorizedKeys - ] - makerepo - | rsyncOnly sshdata = [] - | otherwise = - [ "git init --bare --shared" - , "git annex init" - ] - makeAuthorizedKeys = - [ "mkdir -p ~/.ssh" - , "touch ~/.ssh/authorized_keys" - , "chmod 600 ~/.ssh/authorized_keys" - , unwords - [ "echo" - , shellEscape authline - , ">>~/.ssh/authorized_keys" - ] + , if rsync then Nothing else Just $ "git init --bare --shared" + , if rsync then Nothing else Just $ "git annex init" + , makeAuthorizedKeys sshdata ] showerr msg = sshConfigurator $ $(widgetFile "configurators/makessherror") + {- This is a one-sided remote setup; the remote server + - probably does not have a route to the client here. -} + makerepo = addRemote $ + (if rsync then makeRsyncRemote else makeGitRemote) + (sshRepoName sshdata) sshurl + sshurl = T.unpack $ T.concat $ if rsync + then [u, h, ":", sshDirectory sshdata, "/"] + else ["ssh://", u, h, d, "/"] + where + u = maybe "" (\v -> T.concat [v, "@"]) $ sshUserName sshdata + h = sshHostName sshdata + d + | "/" `T.isPrefixOf` sshDirectory sshdata = d + | otherwise = T.concat ["/~/", sshDirectory sshdata] + +{- Inits a rsync special remote, and returns the name of the remote. -} +makeRsyncRemote :: String -> String -> Annex String +makeRsyncRemote name location = makeRemote name location $ const $ do + (u, c) <- Command.InitRemote.findByName name + c' <- R.setup Rsync.remote u $ M.union config c + describeUUID u name + configSet u c' + where + config = M.fromList + [ ("encryption", "shared") + , ("rsyncurl", location) + , ("type", "rsync") + ] + +makeAuthorizedKeys :: SshData -> Maybe String +makeAuthorizedKeys sshdata + | pubKey sshdata == Nothing = Nothing + | otherwise = Just $ join "&&" $ + [ "mkdir -p ~/.ssh" + , "touch ~/.ssh/authorized_keys" + , "chmod 600 ~/.ssh/authorized_keys" + , unwords + [ "echo" + , shellEscape $ authorizedKeysLine sshdata + , ">>~/.ssh/authorized_keys" + ] + ] authorizedKeysLine :: SshData -> String authorizedKeysLine sshdata@(SshData { pubKey = Just pubkey }) diff --git a/Assistant/WebApp/routes b/Assistant/WebApp/routes index d22e689dd..5f8dfbbc4 100644 --- a/Assistant/WebApp/routes +++ b/Assistant/WebApp/routes @@ -8,7 +8,8 @@ /config/repository/add/drive AddDriveR GET /config/repository/add/ssh AddSshR GET /config/repository/add/ssh/confirm/#SshData ConfirmSshR GET -/config/repository/add/ssh/make/#SshData MakeSshR GET +/config/repository/add/ssh/make/git/#SshData MakeSshGitR GET +/config/repository/add/ssh/make/rsync/#SshData MakeSshRsyncR GET /config/repository/first FirstRepositoryR GET /transfers/#NotificationId TransfersR GET diff --git a/templates/configurators/addssh.hamlet b/templates/configurators/addssh.hamlet index 03a99fd96..c2336a169 100644 --- a/templates/configurators/addssh.hamlet +++ b/templates/configurators/addssh.hamlet @@ -2,11 +2,6 @@ <h2> Adding a remote server using ssh <p> - Clone this repository to a ssh server. Your data will be # - uploaded to the server. If you set up other devices to use the same # - server, they will all be kept in sync, using the server as a central # - hub. - <p> You can use nearly any server that has ssh and rsync. For example, you # could use a <a href="http://linode.com/">Linode</a> or another VPS, or # an account on a friend's server. diff --git a/templates/configurators/confirmssh.hamlet b/templates/configurators/confirmssh.hamlet index 0eb42a048..43d27d032 100644 --- a/templates/configurators/confirmssh.hamlet +++ b/templates/configurators/confirmssh.hamlet @@ -5,9 +5,23 @@ <div .span8> <p> The server has been verified to be usable. + $if not (rsyncOnly sshdata) + <p> + You have two options for how to use the server. + <p> + <a .btn .btn-primary href="@{MakeSshGitR sshdata}" onclick="$('#setupmodal').modal('show');"> + Use a git repository on the server + <br> + All your data will be uploaded to the server. If you set up other # + devices to use the same server, they will all be kept in sync, # + using the server as a central hub. # <p> - <a .btn .btn-primary href="@{MakeSshR sshdata}" onclick="$('#setupmodal').modal('show');"> - Clone this repository to the remote server + <a .btn .btn-primary href="@{MakeSshRsyncR sshdata}" onclick="$('#setupmodal').modal('show');"> + Use an encrypted rsync repository on the server + <br> + The contents of your files will be stored, fully encrypted, on the # + server. The server will not store other information about your # + git repository. <div .span4> $if haspubkey <div .alert .alert-info> diff --git a/templates/configurators/makessherror.hamlet b/templates/configurators/makessherror.hamlet index 6422431cc..05d2de412 100644 --- a/templates/configurators/makessherror.hamlet +++ b/templates/configurators/makessherror.hamlet @@ -6,5 +6,5 @@ <p> Transcript: #{msg} <p> - <a .btn .btn-primary href="@{MakeSshR sshdata}"> + <a .btn .btn-primary href="#"> Retry |