root
safe-access is a small Haskell library to control accesses through a simple capability-based interface.
Concepts
Access descriptor
You will have to define a type describing the different kind of accesses that your program will be performing.
Capability
A capability describes some accesses that are granted or denied for a certain part of your program or another subsystem. It simply is a function from an access descriptor to an access decision explained thereafter.
Access decision
Every capability can return a decision. AccessGranted and AccessDenied are pretty obvious while AccessDeniedSoft would deny the access should no other capability overwrite this decision.
SafeAccessT
SafeAccessT is a monad transformer in which you can run some piece of code and check for accesses. It also instantiates Applicative, Functor and MonadIO with the appropriate conditions.
Example
import Control.Applicative
import Control.SafeAccess
data Descr = AccessA | AccessB | OtherDescr String deriving (Show, Eq)
instance AccessDescriptor Descr where
descrMsg = OtherDescr -- this is for the function fail in Monad
normalUserCapability :: Capability Descr
normalUserCapability = MkCapability $ \descr -> case descr of
AccessA -> AccessGranted
AccessB -> AccessDenied
_ -> AccessDeniedSoft
getA :: SafeAccessT Descr IO String
getA = do
ensureAccess AccessA
return "A"
getB :: SafeAccessT Descr IO String
getB = do
ensureAccess AccessB
return "B"
getData :: SafeAccessT Descr IO (String, String)
getData = (,) <$> getA <*> getB
main :: IO ()
main = do
eRes <- runSafeAccessT getData [normalUserCapability]
print eRes -- will print Left AccessB