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.Writer (MonadWriter, tell)
import Control.Monad.Reader (MonadReader, ask)
import Data.Char (isDigit)
import Data.Foldable (traverse_)
import Data.Maybe (isNothing)
import qualified Data.Text as T
import qualified Data.Map as M
runAllRules :: (MonadDecrypt m key,
Monad m,
MonadWriter [T.Text] m,
MonadReader (ConfCryptFile, key) m) =>
m ()
runAllRules = do
(ccf, privateKey) <- ask
parameterTypesMatchSchema privateKey ccf
logMissingSchemas ccf
logMissingParameters ccf
parameterTypesMatchSchema :: (Monad m, MonadWriter [T.Text] m, MonadDecrypt m key) =>
key
-> ConfCryptFile
-> m ()
parameterTypesMatchSchema key ConfCryptFile {parameters} =
traverse_ decryptAndCompare parameters
where
decryptAndCompare Parameter {paramName, paramValue, paramType} =
catchError (runRule paramType paramName =<< decryptValue key paramValue)
(const $ tell ["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 -> tell ["Warning: "<> paramName <> " is empty"]
Just pt -> tell ["Error: "<> paramName <> " does not match the schema type " <> typeToOutputString pt]
logMissingSchemas :: (Monad m, MonadWriter [T.Text] m) =>
ConfCryptFile
-> m ()
logMissingSchemas ConfCryptFile {parameters} =
traverse_ logMissingSchema parameters
where
logMissingSchema Parameter {paramName, paramType}
| isNothing paramType = tell ["Error: " <> paramName <> " does not have a scheam"]
| otherwise = pure ()
logMissingParameters :: (Monad m, MonadWriter [T.Text] m) =>
ConfCryptFile
-> m ()
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 = tell ["Error: no matching parameter for schema "<> sName]
| otherwise = pure ()
logMissingParameter _ = pure ()