{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE UnicodeSyntax #-}
module Configuration.Utils.Validation
( ConfigValidation
, validateHttpOrHttpsUrl
, validateHttpUrl
, validateHttpsUrl
, validateUri
, validateAbsoluteUri
, validateAbsoluteUriFragment
, validateIPv4
, validateIPv6
, validatePort
, validateNonEmpty
, validateLength
, validateMinLength
, validateMaxLength
, validateMinMaxLength
, validateFilePath
, validateFile
, validateFileReadable
, validateFileWritable
, validateExecutable
, validateDirectory
, validateConfigFile
, validateFalse
, validateTrue
, validateBool
, validateNonNegative
, validatePositive
, validateNonPositive
, validateNegative
, validateNonNull
, validateLess
, validateLessEq
, validateGreater
, validateGreaterEq
, validateRange
) where
import Configuration.Utils.Internal
import Control.Monad.Error.Class
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Writer.Class
import qualified Data.Foldable as F
import Data.Monoid.Unicode
import qualified Data.Text as T
import Network.URI
import Prelude.Unicode
import System.Directory
type ConfigValidation a f = ∀ m . (MonadIO m, Functor m, Applicative m, MonadError T.Text m, MonadWriter (f T.Text) m) ⇒ a → m ()
validateHttpOrHttpsUrl
∷ MonadError T.Text m
⇒ T.Text
→ String
→ m ()
validateHttpOrHttpsUrl :: forall (m :: * -> *). MonadError Text m => Text -> String -> m ()
validateHttpOrHttpsUrl Text
configName String
uri =
case String -> Maybe URI
parseURI String
uri of
Maybe URI
Nothing → forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
uri forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not a valid URI"
Just URI
u → forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (URI -> String
uriScheme URI
u forall α. Eq α => α -> α -> Bool
≡ String
"http:" Bool -> Bool -> Bool
|| URI -> String
uriScheme URI
u forall α. Eq α => α -> α -> Bool
≡ String
"https:") forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
uri forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not an HTTP or HTTPS URL"
validateHttpUrl
∷ MonadError T.Text m
⇒ T.Text
→ String
→ m ()
validateHttpUrl :: forall (m :: * -> *). MonadError Text m => Text -> String -> m ()
validateHttpUrl Text
configName String
uri =
case String -> Maybe URI
parseURI String
uri of
Maybe URI
Nothing → forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
uri forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not a valid URI"
Just URI
u → forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (URI -> String
uriScheme URI
u forall α. Eq α => α -> α -> Bool
≡ String
"http:") forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
uri forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not an HTTP URL"
validateHttpsUrl
∷ MonadError T.Text m
⇒ T.Text
→ String
→ m ()
validateHttpsUrl :: forall (m :: * -> *). MonadError Text m => Text -> String -> m ()
validateHttpsUrl Text
configName String
uri =
case String -> Maybe URI
parseURI String
uri of
Maybe URI
Nothing → forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
uri forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not a valid URI"
Just URI
u → forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (URI -> String
uriScheme URI
u forall α. Eq α => α -> α -> Bool
≡ String
"https:") forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
uri forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not an HTTPS URL"
validateUri
∷ MonadError T.Text m
⇒ T.Text
→ String
→ m ()
validateUri :: forall (m :: * -> *). MonadError Text m => Text -> String -> m ()
validateUri Text
configName String
uri =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Bool
isURIReference String
uri) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"The value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
uri forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not a valid URI"
validateAbsoluteUri
∷ MonadError T.Text m
⇒ T.Text
→ String
→ m ()
validateAbsoluteUri :: forall (m :: * -> *). MonadError Text m => Text -> String -> m ()
validateAbsoluteUri Text
configName String
uri =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Bool
isAbsoluteURI String
uri) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"The value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
uri forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not a valid URI"
validateAbsoluteUriFragment
∷ MonadError T.Text m
⇒ T.Text
→ String
→ m ()
validateAbsoluteUriFragment :: forall (m :: * -> *). MonadError Text m => Text -> String -> m ()
validateAbsoluteUriFragment Text
configName String
uri =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Bool
isURI String
uri) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"The value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
uri forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not a valid URI"
validateIPv4
∷ MonadError T.Text m
⇒ T.Text
→ String
→ m ()
validateIPv4 :: forall (m :: * -> *). MonadError Text m => Text -> String -> m ()
validateIPv4 Text
configName String
ipv4 =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Bool
isIPv4address String
ipv4) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"The value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
ipv4 forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not a valid IPv4 address"
validateIPv6
∷ MonadError T.Text m
⇒ T.Text
→ String
→ m ()
validateIPv6 :: forall (m :: * -> *). MonadError Text m => Text -> String -> m ()
validateIPv6 Text
configName String
ipv6 =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (String -> Bool
isIPv6address String
ipv6) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"The value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
ipv6 forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not a valid IPv6 address"
validatePort
∷ (MonadError T.Text m, Integral n, Show n)
⇒ T.Text
→ n
→ m ()
validatePort :: forall (m :: * -> *) n.
(MonadError Text m, Integral n, Show n) =>
Text -> n -> m ()
validatePort Text
configName n
p =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (n
p forall a. Ord a => a -> a -> Bool
> n
1 Bool -> Bool -> Bool
&& n
p forall a. Ord a => a -> a -> Bool
< n
65535) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"port value " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack (forall a. Show a => a -> String
show n
p) forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not valid port number"
validateNonEmpty
∷ (MonadError T.Text m, Eq a, Monoid a)
⇒ T.Text
→ a
→ m ()
validateNonEmpty :: forall (m :: * -> *) a.
(MonadError Text m, Eq a, Monoid a) =>
Text -> a -> m ()
validateNonEmpty Text
configName a
x =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (a
x forall α. Eq α => α -> α -> Bool
≡ forall a. Monoid a => a
mempty) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must not be empty"
validateLength
∷ (MonadError T.Text m, F.Foldable f)
⇒ T.Text
→ Int
→ f a
→ m ()
validateLength :: forall (m :: * -> *) (f :: * -> *) a.
(MonadError Text m, Foldable f) =>
Text -> Int -> f a -> m ()
validateLength Text
configName Int
len f a
x =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList f a
x) forall α. Eq α => α -> α -> Bool
≡ Int
len) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be of length exactly " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow Int
len
validateMaxLength
∷ (MonadError T.Text m, F.Foldable f)
⇒ T.Text
→ Int
→ f a
→ m ()
validateMaxLength :: forall (m :: * -> *) (f :: * -> *) a.
(MonadError Text m, Foldable f) =>
Text -> Int -> f a -> m ()
validateMaxLength Text
configName Int
u f a
x =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList f a
x) forall a. Ord a => a -> a -> Bool
≤ Int
u) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be of length at most " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow Int
u
validateMinLength
∷ (MonadError T.Text m, F.Foldable f)
⇒ T.Text
→ Int
→ f a
→ m ()
validateMinLength :: forall (m :: * -> *) (f :: * -> *) a.
(MonadError Text m, Foldable f) =>
Text -> Int -> f a -> m ()
validateMinLength Text
configName Int
l f a
x =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> Int
length (forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList f a
x) forall a. Ord a => a -> a -> Bool
≥ Int
l) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be of length at least " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow Int
l
validateMinMaxLength
∷ (MonadError T.Text m, F.Foldable f)
⇒ T.Text
→ Int
→ Int
→ f a
→ m ()
validateMinMaxLength :: forall (m :: * -> *) (f :: * -> *) a.
(MonadError Text m, Foldable f) =>
Text -> Int -> Int -> f a -> m ()
validateMinMaxLength Text
configName Int
l Int
u f a
x =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Int
len forall a. Ord a => a -> a -> Bool
≥ Int
l Bool -> Bool -> Bool
&& Int
len forall a. Ord a => a -> a -> Bool
≤ Int
u) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the length of the value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕
Text
" must be at least " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow Int
l forall α. Monoid α => α -> α -> α
⊕ Text
" and at most " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow Int
u
where
len :: Int
len = forall (t :: * -> *) a. Foldable t => t a -> Int
length forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => t a -> [a]
F.toList f a
x
validateFilePath
∷ MonadError T.Text m
⇒ T.Text
→ FilePath
→ m ()
validateFilePath :: forall (m :: * -> *). MonadError Text m => Text -> String -> m ()
validateFilePath Text
configName String
file =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
file) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"file path for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must not be empty"
validateFile
∷ (MonadError T.Text m, MonadIO m)
⇒ T.Text
→ FilePath
→ m ()
validateFile :: forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFile Text
configName String
file = do
Bool
exists ← forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ String -> IO Bool
doesFileExist String
file
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
exists forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the file " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
file forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" does not exist"
validateFileReadable
∷ (MonadError T.Text m, MonadIO m)
⇒ T.Text
→ FilePath
→ m ()
validateFileReadable :: forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFileReadable Text
configName String
file = do
forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFile Text
configName String
file
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO Permissions
getPermissions String
file) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Permissions
x → forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Permissions -> Bool
readable Permissions
x) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the file " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
file forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not readable"
validateFileWritable
∷ (MonadError T.Text m, MonadIO m)
⇒ T.Text
→ FilePath
→ m ()
validateFileWritable :: forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFileWritable Text
configName String
file = do
forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFile Text
configName String
file
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO Permissions
getPermissions String
file) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Permissions
x → forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Permissions -> Bool
writable Permissions
x) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the file " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
file forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not writable"
validateFileExecutable
∷ (MonadError T.Text m, MonadIO m)
⇒ T.Text
→ FilePath
→ m ()
validateFileExecutable :: forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFileExecutable Text
configName String
file = do
forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFile Text
configName String
file
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO Permissions
getPermissions String
file) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Permissions
x → forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Permissions -> Bool
executable Permissions
x) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the file " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
file forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" is not excutable"
validateDirectory
∷ (MonadError T.Text m, MonadIO m)
⇒ T.Text
→ FilePath
→ m ()
validateDirectory :: forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateDirectory Text
configName String
dir = do
Bool
exists ← forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ String -> IO Bool
doesDirectoryExist String
dir
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
exists forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the directory " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
dir forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" does not exist"
validateExecutable
∷ (Functor m, MonadError T.Text m, MonadIO m)
⇒ T.Text
→ FilePath
→ m ()
validateExecutable :: forall (m :: * -> *).
(Functor m, MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateExecutable Text
configName String
file = do
String
execFile ← (String
file forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFile Text
configName String
file) forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
`catchError` \Text
_ ->
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO (Maybe String)
findExecutable String
file) forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
Maybe String
Nothing → forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"the executable " forall α. Monoid α => α -> α -> α
⊕ String -> Text
T.pack String
file forall α. Monoid α => α -> α -> α
⊕ Text
" for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" could not be found in the system;"
forall α. Monoid α => α -> α -> α
⊕ Text
" you may check your SearchPath and PATH variable settings"
Just String
f → forall (m :: * -> *) a. Monad m => a -> m a
return String
f
forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFileExecutable Text
configName String
execFile
validateConfigFile
∷ (MonadIO m, MonadError T.Text m)
⇒ String
→ m ()
validateConfigFile :: forall (m :: * -> *).
(MonadIO m, MonadError Text m) =>
String -> m ()
validateConfigFile String
filepath =
forall (m :: * -> *).
(MonadError Text m, MonadIO m) =>
Text -> String -> m ()
validateFileReadable Text
"config-file" String
filepath
#ifdef REMOTE_CONFIGS
`catchError` \_ ->
validateHttpOrHttpsUrl "config-file" filepath
#endif
validateFalse
∷ (MonadError T.Text m)
⇒ T.Text
→ Bool
→ m ()
validateFalse :: forall (m :: * -> *). MonadError Text m => Text -> Bool -> m ()
validateFalse Text
configName = forall (m :: * -> *).
MonadError Text m =>
Text -> Bool -> Bool -> m ()
validateBool Text
configName Bool
False
validateTrue
∷ (MonadError T.Text m)
⇒ T.Text
→ Bool
→ m ()
validateTrue :: forall (m :: * -> *). MonadError Text m => Text -> Bool -> m ()
validateTrue Text
configName = forall (m :: * -> *).
MonadError Text m =>
Text -> Bool -> Bool -> m ()
validateBool Text
configName Bool
True
validateBool
∷ (MonadError T.Text m)
⇒ T.Text
→ Bool
→ Bool
→ m ()
validateBool :: forall (m :: * -> *).
MonadError Text m =>
Text -> Bool -> Bool -> m ()
validateBool Text
configName Bool
expected Bool
x = forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Bool
x forall α. Eq α => α -> α -> Bool
≡ Bool
expected) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"expected " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" to be " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow Bool
expected forall α. Monoid α => α -> α -> α
⊕ Text
", but was " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow Bool
x
validateNonNegative
∷ (MonadError T.Text m, Ord a, Num a)
⇒ T.Text
→ a
→ m ()
validateNonNegative :: forall (m :: * -> *) a.
(MonadError Text m, Ord a, Num a) =>
Text -> a -> m ()
validateNonNegative Text
configName a
x =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (a
x forall a. Ord a => a -> a -> Bool
< a
0) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must not be negative"
validatePositive
∷ (MonadError T.Text m, Ord a, Num a)
⇒ T.Text
→ a
→ m ()
validatePositive :: forall (m :: * -> *) a.
(MonadError Text m, Ord a, Num a) =>
Text -> a -> m ()
validatePositive Text
configName a
x =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (a
x forall a. Ord a => a -> a -> Bool
≤ a
0) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be positive"
validateNonPositive
∷ (MonadError T.Text m, Ord a, Num a)
⇒ T.Text
→ a
→ m ()
validateNonPositive :: forall (m :: * -> *) a.
(MonadError Text m, Ord a, Num a) =>
Text -> a -> m ()
validateNonPositive Text
configName a
x =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (a
x forall a. Ord a => a -> a -> Bool
> a
0) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must not be positive"
validateNegative
∷ (MonadError T.Text m, Ord a, Num a)
⇒ T.Text
→ a
→ m ()
validateNegative :: forall (m :: * -> *) a.
(MonadError Text m, Ord a, Num a) =>
Text -> a -> m ()
validateNegative Text
configName a
x =
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (a
x forall a. Ord a => a -> a -> Bool
≥ a
0) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be negative"
validateNonNull
∷ (MonadError T.Text m, Eq a, Num a)
⇒ T.Text
→ a
→ m ()
validateNonNull :: forall (m :: * -> *) a.
(MonadError Text m, Eq a, Num a) =>
Text -> a -> m ()
validateNonNull Text
configName a
x = forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (a
x forall α. Eq α => α -> α -> Bool
≡ a
0) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must not be zero"
validateLess
∷ (MonadError T.Text m, Ord a, Show a)
⇒ T.Text
→ a
→ a
→ m ()
validateLess :: forall (m :: * -> *) a.
(MonadError Text m, Ord a, Show a) =>
Text -> a -> a -> m ()
validateLess Text
configName a
upper a
x = forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (a
x forall a. Ord a => a -> a -> Bool
< a
upper) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be strictly less than " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
upper forall α. Monoid α => α -> α -> α
⊕ Text
", but was " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
x
validateLessEq
∷ (MonadError T.Text m, Ord a, Show a)
⇒ T.Text
→ a
→ a
→ m ()
validateLessEq :: forall (m :: * -> *) a.
(MonadError Text m, Ord a, Show a) =>
Text -> a -> a -> m ()
validateLessEq Text
configName a
upper a
x = forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (a
x forall a. Ord a => a -> a -> Bool
≤ a
upper) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be less or equal than " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
upper forall α. Monoid α => α -> α -> α
⊕ Text
", but was " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
x
validateGreater
∷ (MonadError T.Text m, Ord a, Show a)
⇒ T.Text
→ a
→ a
→ m ()
validateGreater :: forall (m :: * -> *) a.
(MonadError Text m, Ord a, Show a) =>
Text -> a -> a -> m ()
validateGreater Text
configName a
lower a
x = forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (a
x forall a. Ord a => a -> a -> Bool
> a
lower) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be strictly greater than " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
lower forall α. Monoid α => α -> α -> α
⊕ Text
", but was " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
x
validateGreaterEq
∷ (MonadError T.Text m, Ord a, Show a)
⇒ T.Text
→ a
→ a
→ m ()
validateGreaterEq :: forall (m :: * -> *) a.
(MonadError Text m, Ord a, Show a) =>
Text -> a -> a -> m ()
validateGreaterEq Text
configName a
lower a
x = forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (a
x forall a. Ord a => a -> a -> Bool
≥ a
lower) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be greater or equal than " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
lower forall α. Monoid α => α -> α -> α
⊕ Text
", but was " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
x
validateRange
∷ (MonadError T.Text m, Ord a, Show a)
⇒ T.Text
→ (a, a)
→ a
→ m ()
validateRange :: forall (m :: * -> *) a.
(MonadError Text m, Ord a, Show a) =>
Text -> (a, a) -> a -> m ()
validateRange Text
configName (a
lower,a
upper) a
x = forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (a
x forall a. Ord a => a -> a -> Bool
≥ a
lower Bool -> Bool -> Bool
∧ a
x forall a. Ord a => a -> a -> Bool
≤ a
upper) forall β γ α. (β -> γ) -> (α -> β) -> α -> γ
∘ forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text
"value for " forall α. Monoid α => α -> α -> α
⊕ Text
configName forall α. Monoid α => α -> α -> α
⊕ Text
" must be within the range of (" forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
lower forall α. Monoid α => α -> α -> α
⊕ Text
", " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
upper forall α. Monoid α => α -> α -> α
⊕ Text
"), but was " forall α. Monoid α => α -> α -> α
⊕ forall a s. (Show a, IsString s) => a -> s
sshow a
x