add readonly mode to serve P2P protocol

This will be used by git-annex-shell when configured to be readonly.

This commit was sponsored by Nick Daly on Patreon.
This commit is contained in:
Joey Hess 2018-03-07 13:15:55 -04:00
parent bd8c13e75b
commit 572a45ae00
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
2 changed files with 33 additions and 18 deletions

View file

@ -351,10 +351,13 @@ serveAuth myuuid = serverLoop handler
return ServerContinue return ServerContinue
handler _ = return ServerUnexpected handler _ = return ServerUnexpected
data ServerMode = ServeReadOnly | ServeReadWrite
-- | Serve the protocol, with a peer that has authenticated. -- | Serve the protocol, with a peer that has authenticated.
serveAuthed :: UUID -> Proto () serveAuthed :: ServerMode -> UUID -> Proto ()
serveAuthed myuuid = void $ serverLoop handler serveAuthed servermode myuuid = void $ serverLoop handler
where where
readonlyerror = net $ sendMessage (ERROR "this repository is read-only; write access denied")
handler (LOCKCONTENT key) = do handler (LOCKCONTENT key) = do
local $ tryLockContent key $ \locked -> do local $ tryLockContent key $ \locked -> do
sendSuccess locked sendSuccess locked
@ -367,27 +370,39 @@ serveAuthed myuuid = void $ serverLoop handler
handler (CHECKPRESENT key) = do handler (CHECKPRESENT key) = do
sendSuccess =<< local (checkContentPresent key) sendSuccess =<< local (checkContentPresent key)
return ServerContinue return ServerContinue
handler (REMOVE key) = do handler (REMOVE key) = case servermode of
sendSuccess =<< local (removeContent key) ServeReadWrite -> do
return ServerContinue sendSuccess =<< local (removeContent key)
handler (PUT af key) = do return ServerContinue
have <- local $ checkContentPresent key ServeReadOnly -> do
if have readonlyerror
then net $ sendMessage ALREADY_HAVE return ServerContinue
else do handler (PUT af key) = case servermode of
let sizer = tmpContentSize key ServeReadWrite -> do
let storer = storeContent key af have <- local $ checkContentPresent key
ok <- receiveContent nullMeterUpdate sizer storer PUT_FROM if have
when ok $ then net $ sendMessage ALREADY_HAVE
local $ setPresent key myuuid else do
return ServerContinue let sizer = tmpContentSize key
let storer = storeContent key af
ok <- receiveContent nullMeterUpdate sizer storer PUT_FROM
when ok $
local $ setPresent key myuuid
return ServerContinue
ServeReadOnly -> do
readonlyerror
return ServerContinue
handler (GET offset key af) = do handler (GET offset key af) = do
void $ sendContent af key offset nullMeterUpdate void $ sendContent af key offset nullMeterUpdate
-- setPresent not called because the peer may have -- setPresent not called because the peer may have
-- requested the data but not permanently stored it. -- requested the data but not permanently stored it.
return ServerContinue return ServerContinue
handler (CONNECT service) = do handler (CONNECT service) = do
net $ relayService service let goahead = net $ relayService service
case (servermode, service) of
(ServeReadWrite, _) -> goahead
(ServeReadOnly, UploadPack) -> goahead
(ServeReadOnly, ReceivePack) -> readonlyerror
-- After connecting to git, there may be unconsumed data -- After connecting to git, there may be unconsumed data
-- from the git processes hanging around (even if they -- from the git processes hanging around (even if they
-- exited successfully), so stop serving this connection. -- exited successfully), so stop serving this connection.

View file

@ -128,7 +128,7 @@ serveClient th u r q = bracket setup cleanup start
authed conn theiruuid = authed conn theiruuid =
bracket watchChangedRefs (liftIO . maybe noop stopWatchingChangedRefs) $ \crh -> do bracket watchChangedRefs (liftIO . maybe noop stopWatchingChangedRefs) $ \crh -> do
v' <- runFullProto (Serving theiruuid crh) conn $ v' <- runFullProto (Serving theiruuid crh) conn $
P2P.serveAuthed u P2P.serveAuthed P2P.ServeReadWrite u
case v' of case v' of
Right () -> return () Right () -> return ()
Left e -> liftIO $ debugM "remotedaemon" ("Tor connection error: " ++ e) Left e -> liftIO $ debugM "remotedaemon" ("Tor connection error: " ++ e)