module Avers.Server.Authorization
( Authorizations(..), Authz, AuthzR(..)
, defaultAuthorizations
, runAuthorization
, trace
, sufficient
, requisite
, sessionCreatedObject
, sessionIsObject
) where
import Control.Monad.IO.Class
import Control.Monad.Except
import Data.Text (Text)
import Avers
import Avers.API
import Servant.Server
data Authorizations = Authorizations
{ createObjectAuthz :: Credentials -> Text -> Authz
, lookupObjectAuthz :: Credentials -> ObjId -> Authz
, patchObjectAuthz :: Credentials -> ObjId -> [Operation] -> Authz
, deleteObjectAuthz :: Credentials -> ObjId -> Authz
, uploadBlobAuthz :: Credentials -> Text -> Authz
, lookupBlobAuthz :: Credentials -> BlobId -> Authz
, lookupBlobContentAuthz :: Credentials -> BlobId -> Authz
}
defaultAuthorizations :: Authorizations
defaultAuthorizations = Authorizations
{ createObjectAuthz = \_ _ -> [pure AllowR]
, lookupObjectAuthz = \cred objId ->
[ sufficient $ do
session <- case cred of
CredAnonymous -> throwError NotAuthorized
CredSessionId sId -> lookupSession sId
sessionCreatedObject session objId
]
, patchObjectAuthz = \cred objId _ ->
[ sufficient $ do
session <- case cred of
CredAnonymous -> throwError NotAuthorized
CredSessionId sId -> lookupSession sId
sessionCreatedObject session objId
]
, deleteObjectAuthz = \cred objId ->
[ sufficient $ do
session <- case cred of
CredAnonymous -> throwError NotAuthorized
CredSessionId sId -> lookupSession sId
sessionCreatedObject session objId
]
, uploadBlobAuthz = \_ _ -> [pure AllowR]
, lookupBlobAuthz = \_ _ -> [pure AllowR]
, lookupBlobContentAuthz = \_ _ -> [pure AllowR]
}
type Authz = [Avers AuthzR]
data AuthzR = ContinueR | AllowR | RejectR
runAuthorization :: Handle -> Authz -> Handler ()
runAuthorization _ [] = pure ()
runAuthorization aversH (x:xs) = do
res <- liftIO $ evalAvers aversH x
case res of
Left _ -> throwError err500
Right r -> case r of
ContinueR -> runAuthorization aversH xs
AllowR -> pure ()
RejectR -> throwError err401
trace :: Avers () -> Avers AuthzR
trace m = m >> pure ContinueR
sufficient :: Avers Bool -> Avers AuthzR
sufficient m = do
res <- m
pure $ if res then AllowR else ContinueR
requisite :: Avers Bool -> Avers AuthzR
requisite m = do
res <- m
pure $ if res then ContinueR else RejectR
sessionCreatedObject :: Session -> ObjId -> Avers Bool
sessionCreatedObject session objId = do
obj <- Avers.lookupObject objId
return $ objectCreatedBy obj == sessionObjId session
sessionIsObject :: Session -> ObjId -> Avers Bool
sessionIsObject session objId = do
return $ sessionObjId session == objId