module Hackage.Security.TUF.Header (
HasHeader(..)
, FileVersion(..)
, FileExpires(..)
, Header(..)
, expiresInDays
, expiresNever
, isExpired
, versionInitial
, versionIncrement
) where
import Data.Time
import Data.Typeable (Typeable)
import Hackage.Security.JSON
import Hackage.Security.Util.Lens
class HasHeader a where
fileExpires :: Lens' a FileExpires
fileVersion :: Lens' a FileVersion
newtype FileVersion = FileVersion Int54
deriving (Eq, Ord, Typeable)
instance Show FileVersion where
show (FileVersion v) = show v
instance Read FileVersion where
readsPrec p = map (\(v, xs) -> (FileVersion v, xs)) . readsPrec p
newtype FileExpires = FileExpires (Maybe UTCTime)
deriving (Eq, Ord, Show, Typeable)
data Header = Header {
headerExpires :: FileExpires
, headerVersion :: FileVersion
}
instance HasHeader Header where
fileExpires f x = (\y -> x { headerExpires = y }) <$> f (headerExpires x)
fileVersion f x = (\y -> x { headerVersion = y }) <$> f (headerVersion x)
expiresNever :: FileExpires
expiresNever = FileExpires Nothing
expiresInDays :: UTCTime -> Integer -> FileExpires
expiresInDays now n =
FileExpires . Just $ addUTCTime (fromInteger n * oneDay) now
isExpired :: UTCTime -> FileExpires -> Bool
isExpired _ (FileExpires Nothing) = False
isExpired now (FileExpires (Just e)) = e < now
versionInitial :: FileVersion
versionInitial = FileVersion 1
versionIncrement :: FileVersion -> FileVersion
versionIncrement (FileVersion i) = FileVersion (i + 1)
instance Monad m => ToJSON m FileVersion where
toJSON (FileVersion i) = toJSON i
instance Monad m => ToJSON m FileExpires where
toJSON (FileExpires (Just e)) = toJSON e
toJSON (FileExpires Nothing) = return JSNull
instance ReportSchemaErrors m => FromJSON m FileVersion where
fromJSON enc = FileVersion <$> fromJSON enc
instance ReportSchemaErrors m => FromJSON m FileExpires where
fromJSON JSNull = return $ FileExpires Nothing
fromJSON enc = FileExpires . Just <$> fromJSON enc
instance ReportSchemaErrors m => FromJSON m Header where
fromJSON enc = do
headerExpires <- fromJSField enc "expires"
headerVersion <- fromJSField enc "version"
return Header{..}
oneDay :: NominalDiffTime
oneDay = 24 * 60 * 60