module Security.Advisories.Queries
( listVersionAffectedBy
, listVersionRangeAffectedBy
, isVersionAffectedBy
, isVersionRangeAffectedBy
)
where
import Control.Monad.IO.Class (MonadIO)
import Data.Text (Text)
import Distribution.Types.Version (Version)
import Distribution.Types.VersionInterval (asVersionIntervals)
import Distribution.Types.VersionRange (VersionRange, anyVersion, earlierVersion, intersectVersionRanges, noVersion, orLaterVersion, unionVersionRanges, withinRange)
import Validation (Validation(..))
import Security.Advisories.Core.Advisory
import Security.Advisories.Filesystem
import Security.Advisories.Parse
isVersionAffectedBy :: Text -> Version -> Advisory -> Bool
isVersionAffectedBy :: Text -> Version -> Advisory -> Bool
isVersionAffectedBy = (Version -> VersionRange -> Bool)
-> Text -> Version -> Advisory -> Bool
forall a.
(a -> VersionRange -> Bool) -> Text -> a -> Advisory -> Bool
isAffectedByHelper Version -> VersionRange -> Bool
withinRange
isVersionRangeAffectedBy :: Text -> VersionRange -> Advisory -> Bool
isVersionRangeAffectedBy :: Text -> VersionRange -> Advisory -> Bool
isVersionRangeAffectedBy = (VersionRange -> VersionRange -> Bool)
-> Text -> VersionRange -> Advisory -> Bool
forall a.
(a -> VersionRange -> Bool) -> Text -> a -> Advisory -> Bool
isAffectedByHelper ((VersionRange -> VersionRange -> Bool)
-> Text -> VersionRange -> Advisory -> Bool)
-> (VersionRange -> VersionRange -> Bool)
-> Text
-> VersionRange
-> Advisory
-> Bool
forall a b. (a -> b) -> a -> b
$
\VersionRange
queryVersionRange VersionRange
affectedVersionRange ->
VersionRange -> Bool
isSomeVersion (VersionRange
affectedVersionRange VersionRange -> VersionRange -> VersionRange
`intersectVersionRanges` VersionRange
queryVersionRange)
where
isSomeVersion :: VersionRange -> Bool
isSomeVersion :: VersionRange -> Bool
isSomeVersion VersionRange
range
| [] <- VersionRange -> [VersionInterval]
asVersionIntervals VersionRange
range = Bool
False
| Bool
otherwise = Bool
True
isAffectedByHelper :: (a -> VersionRange -> Bool) -> Text -> a -> Advisory -> Bool
isAffectedByHelper :: forall a.
(a -> VersionRange -> Bool) -> Text -> a -> Advisory -> Bool
isAffectedByHelper a -> VersionRange -> Bool
checkWithRange Text
queryPackageName a
queryVersionish =
(Affected -> Bool) -> [Affected] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Affected -> Bool
checkAffected ([Affected] -> Bool)
-> (Advisory -> [Affected]) -> Advisory -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Advisory -> [Affected]
advisoryAffected
where
checkAffected :: Affected -> Bool
checkAffected :: Affected -> Bool
checkAffected Affected
affected =
Text
queryPackageName Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Affected -> Text
affectedPackage Affected
affected
Bool -> Bool -> Bool
&& a -> VersionRange -> Bool
checkWithRange a
queryVersionish (Affected -> VersionRange
fromAffected Affected
affected)
fromAffected :: Affected -> VersionRange
fromAffected :: Affected -> VersionRange
fromAffected = (AffectedVersionRange -> VersionRange -> VersionRange)
-> VersionRange -> [AffectedVersionRange] -> VersionRange
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (VersionRange -> VersionRange -> VersionRange
unionVersionRanges (VersionRange -> VersionRange -> VersionRange)
-> (AffectedVersionRange -> VersionRange)
-> AffectedVersionRange
-> VersionRange
-> VersionRange
forall b c a. (b -> c) -> (a -> b) -> a -> c
. AffectedVersionRange -> VersionRange
fromAffectedVersionRange) VersionRange
noVersion ([AffectedVersionRange] -> VersionRange)
-> (Affected -> [AffectedVersionRange]) -> Affected -> VersionRange
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Affected -> [AffectedVersionRange]
affectedVersions
fromAffectedVersionRange :: AffectedVersionRange -> VersionRange
fromAffectedVersionRange :: AffectedVersionRange -> VersionRange
fromAffectedVersionRange AffectedVersionRange
avr = VersionRange -> VersionRange -> VersionRange
intersectVersionRanges
(Version -> VersionRange
orLaterVersion (AffectedVersionRange -> Version
affectedVersionRangeIntroduced AffectedVersionRange
avr))
(VersionRange
-> (Version -> VersionRange) -> Maybe Version -> VersionRange
forall b a. b -> (a -> b) -> Maybe a -> b
maybe VersionRange
anyVersion Version -> VersionRange
earlierVersion (AffectedVersionRange -> Maybe Version
affectedVersionRangeFixed AffectedVersionRange
avr))
listVersionAffectedBy :: MonadIO m => FilePath -> Text -> Version -> m (Validation [ParseAdvisoryError] [Advisory])
listVersionAffectedBy :: forall (m :: * -> *).
MonadIO m =>
FilePath
-> Text
-> Version
-> m (Validation [ParseAdvisoryError] [Advisory])
listVersionAffectedBy = (Text -> Version -> Advisory -> Bool)
-> FilePath
-> Text
-> Version
-> m (Validation [ParseAdvisoryError] [Advisory])
forall (m :: * -> *) a.
MonadIO m =>
(Text -> a -> Advisory -> Bool)
-> FilePath
-> Text
-> a
-> m (Validation [ParseAdvisoryError] [Advisory])
listAffectedByHelper Text -> Version -> Advisory -> Bool
isVersionAffectedBy
listVersionRangeAffectedBy :: MonadIO m => FilePath -> Text -> VersionRange -> m (Validation [ParseAdvisoryError] [Advisory])
listVersionRangeAffectedBy :: forall (m :: * -> *).
MonadIO m =>
FilePath
-> Text
-> VersionRange
-> m (Validation [ParseAdvisoryError] [Advisory])
listVersionRangeAffectedBy = (Text -> VersionRange -> Advisory -> Bool)
-> FilePath
-> Text
-> VersionRange
-> m (Validation [ParseAdvisoryError] [Advisory])
forall (m :: * -> *) a.
MonadIO m =>
(Text -> a -> Advisory -> Bool)
-> FilePath
-> Text
-> a
-> m (Validation [ParseAdvisoryError] [Advisory])
listAffectedByHelper Text -> VersionRange -> Advisory -> Bool
isVersionRangeAffectedBy
listAffectedByHelper :: MonadIO m => (Text -> a -> Advisory -> Bool) -> FilePath -> Text -> a -> m (Validation [ParseAdvisoryError] [Advisory])
listAffectedByHelper :: forall (m :: * -> *) a.
MonadIO m =>
(Text -> a -> Advisory -> Bool)
-> FilePath
-> Text
-> a
-> m (Validation [ParseAdvisoryError] [Advisory])
listAffectedByHelper Text -> a -> Advisory -> Bool
checkAffectedBy FilePath
root Text
queryPackageName a
queryVersionish =
([Advisory] -> [Advisory])
-> Validation [ParseAdvisoryError] [Advisory]
-> Validation [ParseAdvisoryError] [Advisory]
forall a b.
(a -> b)
-> Validation [ParseAdvisoryError] a
-> Validation [ParseAdvisoryError] b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Advisory -> Bool) -> [Advisory] -> [Advisory]
forall a. (a -> Bool) -> [a] -> [a]
filter (Text -> a -> Advisory -> Bool
checkAffectedBy Text
queryPackageName a
queryVersionish)) (Validation [ParseAdvisoryError] [Advisory]
-> Validation [ParseAdvisoryError] [Advisory])
-> m (Validation [ParseAdvisoryError] [Advisory])
-> m (Validation [ParseAdvisoryError] [Advisory])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
FilePath -> m (Validation [ParseAdvisoryError] [Advisory])
forall (m :: * -> *).
MonadIO m =>
FilePath -> m (Validation [ParseAdvisoryError] [Advisory])
listAdvisories FilePath
root