#if __GLASGOW_HASKELL__ >= 704
#endif
module Hails.Database.MongoDB.TCB.Access (
applyRawPolicyP
, applyRawPolicyTCB
, accessTCB
) where
import LIO
import LIO.TCB ( getTCB
, putTCB
, setLabelTCB
, lowerClrTCB
)
import LIO.MonadCatch
import Hails.Data.LBson.TCB
import Hails.Database.MongoDB.TCB.Types
import qualified Data.List as List
import Database.MongoDB.Connection
import qualified Database.MongoDB as M
import Control.Monad.Error hiding (liftIO)
import Control.Monad.Reader hiding (liftIO)
applyRawFieldPolicyP :: (LabelState l p s)
=> p
-> CollectionPolicy l
-> Document l
-> Key
-> LIO l p s (Field l)
applyRawFieldPolicyP p col doc k = do
let policies = rawFieldPolicies . colPolicy $ col
f <- maybe (throwIO NoFieldPolicy) return $ List.lookup k policies
when (isSearchableField f) $ throwIO InvalidPolicy
let (FieldPolicy fp) = f
plv <- getPolicyLabeledVal
lv <- case plv of
(PU v) -> labelP p (fp doc) v
(PL lv) -> do unless (labelOf lv == fp doc) $
throwIO PolicyViolation
return lv
return (k := (PolicyLabeledVal . PL $ lv))
where getPolicyLabeledVal = case look k doc of
(Just (PolicyLabeledVal x)) -> return x
_ -> throwIO InvalidPolicy
applyRawFieldPoliciesP :: (LabelState l p s)
=> p
-> CollectionPolicy l
-> Document l
-> LIO l p s (Document l)
applyRawFieldPoliciesP p col doc = forM doc $ \field@(k := v) ->
case v of
(PolicyLabeledVal _) -> applyRawFieldPolicyP p col doc k
_ -> case List.lookup k (rawFieldPolicies . colPolicy $ col) of
Just (FieldPolicy _) -> throwIO InvalidFieldPolicyType
_ -> return field
applyRawPolicyP :: (LabelState l p s)
=> p
-> CollectionPolicy l
-> Document l
-> LIO l p s (LabeledDocument l)
applyRawPolicyP p' col doc = withCombinedPrivs p' $ \p -> do
let docP = rawDocPolicy . colPolicy $ col
doc' <- applyRawFieldPoliciesP p col doc
labelP p (docP doc') doc'
applyRawPolicyTCB :: (LabelState l p s)
=> CollectionPolicy l
-> Document l
-> LIO l p s (LabeledDocument l)
applyRawPolicyTCB col doc = do
s0 <- getTCB
setLabelTCB lbot
lowerClrTCB ltop
ldoc <- applyRawPolicyP noPrivs col doc
putTCB s0
return ldoc
accessTCB :: LabelState l p s
=> Pipe
-> M.AccessMode
-> Database l
-> Action l p s a
-> LIO l p s (Either M.Failure a)
accessTCB pipe mode db (Action act) =
let lioAct = runReaderT act db
in unUnsafeLIO $ M.access pipe mode (dbIntern db) (unLIOAction lioAct)