module ConfCrypt.Validation (
runAllRules,
parameterTypesMatchSchema,
logMissingSchemas,
logMissingParameters
) where
import ConfCrypt.Types
import ConfCrypt.Encryption (decryptValue, MonadDecrypt)
import Control.Monad.Except (runExcept, catchError)
import Control.Monad.Reader (MonadReader, ask)
import Data.Char (isDigit)
import Data.Maybe (isNothing)
import qualified Data.Text as T
import qualified Data.Map as M
runAllRules :: (Monad m,
MonadDecrypt m key,
MonadReader (ConfCryptFile, key) m) =>
m [T.Text]
runAllRules = do
(ccf, privateKey) <- ask
a <- parameterTypesMatchSchema privateKey ccf
b <- logMissingSchemas ccf
c <- logMissingParameters ccf
pure $ filter (not . T.null) $ a <> b <> c
parameterTypesMatchSchema :: (Monad m, MonadDecrypt m key) =>
key
-> ConfCryptFile
-> m [T.Text]
parameterTypesMatchSchema key ConfCryptFile {parameters} =
traverse decryptAndCompare parameters
where
decryptAndCompare Parameter {paramName, paramValue, paramType} =
catchError (runRule paramType paramName =<< decryptValue key paramValue)
(const $ pure ("Error: Could not decrypt " <> paramName))
runRule paramType paramName val =
case paramType of
Nothing -> pure ""
Just CInt | all isDigit $ T.unpack val -> pure ""
Just CBoolean | T.toLower val == "true" || T.toLower val == "false" -> pure ""
Just CString | not (T.null val) -> pure ""
Just CString | T.null val -> pure $ "Warning: "<> paramName <> " is empty"
Just pt -> pure $ "Error: "<> paramName <> " does not match the schema type " <> typeToOutputString pt
logMissingSchemas :: Monad m =>
ConfCryptFile
-> m [T.Text]
logMissingSchemas ConfCryptFile {parameters} =
traverse logMissingSchema parameters
where
logMissingSchema Parameter {paramName, paramType}
| isNothing paramType = pure $ "Error: " <> paramName <> " does not have a schema"
| otherwise = pure ""
logMissingParameters :: Monad m =>
ConfCryptFile
-> m [T.Text]
logMissingParameters ConfCryptFile {fileContents} =
traverse logMissingParameter . M.toList $ M.filterWithKey (\k _ -> isSchema k) fileContents
where
isSchema (SchemaLine _) = True
isSchema _ = False
paramForName name (ParameterLine ParamLine {pName}) = name == pName
paramForName name _ = False
logMissingParameter (SchemaLine Schema {sName}, _)
| M.null $ M.filterWithKey (\k _ -> paramForName sName k) fileContents = pure $ "Error: no matching parameter for schema "<> sName
| otherwise = pure ""
logMissingParameter _ = pure ""