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