hackage-security-0.6.2.5: src/Hackage/Security/Key/Env.hs
module Hackage.Security.Key.Env (
KeyEnv -- opaque
, keyEnvMap
-- * Convenience constructors
, fromPublicKeys
, fromKeys
-- * The usual accessors
, empty
, null
, insert
, lookup
, union
) where
import Prelude hiding (lookup, null)
import Control.Monad
import Data.Map (Map)
import qualified Data.Map as Map
import Hackage.Security.Key
import Hackage.Security.Util.JSON
import Hackage.Security.Util.Some
{-------------------------------------------------------------------------------
Main datatype
-------------------------------------------------------------------------------}
-- | A key environment is a mapping from key IDs to the corresponding keys.
--
-- It should satisfy the invariant that these key IDs actually match the keys;
-- see 'checkKeyEnvInvariant'.
newtype KeyEnv = KeyEnv {
keyEnvMap :: Map KeyId (Some PublicKey)
}
deriving (Show)
-- | Verify that each key ID is mapped to a key with that ID
checkKeyEnvInvariant :: KeyEnv -> Bool
checkKeyEnvInvariant = all (uncurry go) . Map.toList . keyEnvMap
where
go :: KeyId -> Some PublicKey -> Bool
go kId key = kId == someKeyId key
{-------------------------------------------------------------------------------
Convenience constructors
-------------------------------------------------------------------------------}
fromPublicKeys :: [Some PublicKey] -> KeyEnv
fromPublicKeys = KeyEnv . Map.fromList . map aux
where
aux :: Some PublicKey -> (KeyId, Some PublicKey)
aux pub = (someKeyId pub, pub)
fromKeys :: [Some Key] -> KeyEnv
fromKeys = fromPublicKeys . map somePublicKey
{-------------------------------------------------------------------------------
The usual accessors
-------------------------------------------------------------------------------}
empty :: KeyEnv
empty = KeyEnv Map.empty
null :: KeyEnv -> Bool
null (KeyEnv env) = Map.null env
insert :: Some PublicKey -> KeyEnv -> KeyEnv
insert key (KeyEnv env) = KeyEnv $ Map.insert (someKeyId key) key env
lookup :: KeyId -> KeyEnv -> Maybe (Some PublicKey)
lookup kId (KeyEnv env) = Map.lookup kId env
union :: KeyEnv -> KeyEnv -> KeyEnv
union (KeyEnv env) (KeyEnv env') = KeyEnv (env `Map.union` env')
{-------------------------------------------------------------------------------
JSON
-------------------------------------------------------------------------------}
instance Monad m => ToJSON m KeyEnv where
toJSON (KeyEnv keyEnv) = toJSON keyEnv
instance ReportSchemaErrors m => FromJSON m KeyEnv where
fromJSON enc = do
keyEnv <- KeyEnv <$> fromJSON enc
-- We should really use 'validate', but that causes module import cycles.
-- Sigh.
unless (checkKeyEnvInvariant keyEnv) $
expected "valid key environment" Nothing
return keyEnv