implement serveRemove and send WWW-Authenticate header on auth failure

This commit is contained in:
Joey Hess 2024-07-10 09:13:01 -04:00
parent 97d0fc9b65
commit 48f76cb3e8
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
4 changed files with 37 additions and 11 deletions

View file

@ -67,7 +67,12 @@ optParser _ = Options
) )
seek :: Options -> CommandSeek seek :: Options -> CommandSeek
seek o = startConcurrency commandStages $ seek o = startConcurrency commandStages $ do
-- XXX remove this
when (isNothing (portOption o)) $ do
liftIO $ putStrLn "test begins"
testCheckPresent
giveup "TEST DONE"
withLocalP2PConnections $ \acquireconn -> liftIO $ do withLocalP2PConnections $ \acquireconn -> liftIO $ do
authenv <- getAuthEnv authenv <- getAuthEnv
st <- mkP2PHttpServerState acquireconn $ st <- mkP2PHttpServerState acquireconn $

View file

@ -21,7 +21,7 @@ module P2P.Http (
import Annex.Common import Annex.Common
import P2P.Http.Types import P2P.Http.Types
import P2P.Http.State import P2P.Http.State
import P2P.Protocol hiding (Offset, Bypass) import P2P.Protocol hiding (Offset, Bypass, auth)
import P2P.IO import P2P.IO
import Servant import Servant
@ -181,9 +181,8 @@ serveCheckPresent st apiver (B64Key k) cu su bypass sec auth = do
$ \runst conn -> $ \runst conn ->
liftIO $ runNetProto runst conn $ checkPresent k liftIO $ runNetProto runst conn $ checkPresent k
case res of case res of
Right (Right b) -> return (CheckPresentResult b) Right b -> return (CheckPresentResult b)
Right (Left err) -> throwError $ err500 { errBody = encodeBL err } Left err -> throwError $ err500 { errBody = encodeBL err }
Left err -> throwError $ err500 { errBody = encodeBL (describeProtoFailure err) }
clientCheckPresent clientCheckPresent
:: ClientEnv :: ClientEnv
@ -214,6 +213,7 @@ type RemoveAPI result
:> ClientUUID Required :> ClientUUID Required
:> ServerUUID Required :> ServerUUID Required
:> BypassUUIDs :> BypassUUIDs
:> IsSecure
:> AuthHeader :> AuthHeader
:> Post '[JSON] result :> Post '[JSON] result
@ -226,9 +226,18 @@ serveRemove
-> B64UUID ClientSide -> B64UUID ClientSide
-> B64UUID ServerSide -> B64UUID ServerSide
-> [B64UUID Bypass] -> [B64UUID Bypass]
-> IsSecure
-> Maybe Auth -> Maybe Auth
-> Handler t -> Handler t
serveRemove = undefined serveRemove st resultmangle apiver (B64Key k) cu su bypass sec auth = do
res <- withP2PConnection apiver st cu su bypass sec auth RemoveAction
$ \runst conn ->
liftIO $ runNetProto runst conn $ remove Nothing k
case res of
(Right b, plus) -> return $ resultmangle $
RemoveResultPlus b (map B64UUID (fromMaybe [] plus))
(Left err, _) -> throwError $
err500 { errBody = encodeBL err }
clientRemove clientRemove
:: ProtocolVersion :: ProtocolVersion
@ -248,7 +257,7 @@ clientRemove (ProtocolVersion ver) k cu su bypass auth = case ver of
_ :<|> _ :<|> _ :<|> _ :<|> _ :<|> _ :<|> _ :<|> _ :<|>
_ :<|> _ :<|> _ :<|> _ :<|> _ :<|> _ :<|> _ :<|> _ :<|>
v3 :<|> v2 :<|> v1 :<|> v0 :<|> _ = client p2pHttpAPI v3 :<|> v2 :<|> v1 :<|> v0 :<|> _ = client p2pHttpAPI
type RemoveBeforeAPI type RemoveBeforeAPI
= KeyParam = KeyParam
:> ClientUUID Required :> ClientUUID Required

View file

@ -8,6 +8,7 @@
-} -}
{-# LANGUAGE BangPatterns #-} {-# LANGUAGE BangPatterns #-}
{-# LANGUAGE OverloadedStrings #-}
module P2P.Http.State where module P2P.Http.State where
@ -49,7 +50,7 @@ withP2PConnection
-> IsSecure -> IsSecure
-> Maybe Auth -> Maybe Auth
-> ActionClass -> ActionClass
-> (RunState -> P2PConnection -> Handler a) -> (RunState -> P2PConnection -> Handler (Either ProtoFailure a))
-> Handler a -> Handler a
withP2PConnection apiver st cu su bypass sec auth actionclass connaction = withP2PConnection apiver st cu su bypass sec auth actionclass connaction =
case (getServerMode st sec auth, actionclass) of case (getServerMode st sec auth, actionclass) of
@ -58,7 +59,7 @@ withP2PConnection apiver st cu su bypass sec auth actionclass connaction =
(Just P2P.ServeAppendOnly, _) -> go P2P.ServeAppendOnly (Just P2P.ServeAppendOnly, _) -> go P2P.ServeAppendOnly
(Just P2P.ServeReadOnly, ReadAction) -> go P2P.ServeReadOnly (Just P2P.ServeReadOnly, ReadAction) -> go P2P.ServeReadOnly
(Just P2P.ServeReadOnly, _) -> throwError err403 (Just P2P.ServeReadOnly, _) -> throwError err403
(Nothing, _) -> throwError err401 (Nothing, _) -> throwError basicAuthRequired
where where
go servermode = liftIO (acquireP2PConnection st cp) >>= \case go servermode = liftIO (acquireP2PConnection st cp) >>= \case
Left (ConnectionFailed err) -> Left (ConnectionFailed err) ->
@ -66,7 +67,7 @@ withP2PConnection apiver st cu su bypass sec auth actionclass connaction =
Left TooManyConnections -> Left TooManyConnections ->
throwError err503 throwError err503
Right (runst, conn, releaseconn) -> Right (runst, conn, releaseconn) ->
connaction runst conn connaction' runst conn
`finally` liftIO releaseconn `finally` liftIO releaseconn
where where
cp = ConnectionParams cp = ConnectionParams
@ -76,6 +77,17 @@ withP2PConnection apiver st cu su bypass sec auth actionclass connaction =
, connectionBypass = map fromB64UUID bypass , connectionBypass = map fromB64UUID bypass
, connectionServerMode = servermode , connectionServerMode = servermode
} }
connaction' runst conn = connaction runst conn >>= \case
Right r -> return r
Left err -> throwError $
err500 { errBody = encodeBL (describeProtoFailure err) }
basicAuthRequired :: ServerError
basicAuthRequired = err401 { errHeaders = [(h, v)] }
where
h = "WWW-Authenticate"
v = "Basic realm=\"git-annex\", charset=\"UTF-8\""
-- Nothing when the server is not allowed to serve any requests. -- Nothing when the server is not allowed to serve any requests.
type GetServerMode = IsSecure -> Maybe Auth -> Maybe P2P.ServerMode type GetServerMode = IsSecure -> Maybe Auth -> Maybe P2P.ServerMode

View file

@ -24,7 +24,7 @@ configuration of the HTTP server. When a request needs authentication,
it will fail with 401 Unauthorized. it will fail with 401 Unauthorized.
Authentication is done using HTTP basic auth. The realm to use when Authentication is done using HTTP basic auth. The realm to use when
authenticating is "git-annex". authenticating is "git-annex". The charset is UTF-8.
When authentication is successful but does not allow a request to be When authentication is successful but does not allow a request to be
performed, it will fail with 403 Forbidden. performed, it will fail with 403 Forbidden.