Skip to content

Commit

Permalink
Reverse default behavior regarding keep
Browse files Browse the repository at this point in the history
Replaces the keep modifier with a clear modifier. The functionality is
the same, but now the env clearing is opt-in instead of opt-out.

Fixes supki#9
  • Loading branch information
pbrisbin committed Mar 28, 2018
1 parent 97306bc commit 434a90b
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 39 deletions.
4 changes: 2 additions & 2 deletions src/Env.hs
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ module Env
, Flag
, HasHelp
, help
, HasKeep
, keep
, HasClear
, clear
, Help.helpDoc
, Error(..)
, Error.AsUnset(..)
Expand Down
60 changes: 32 additions & 28 deletions src/Env/Internal/Parser.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ module Env.Internal.Parser
, Flag
, HasHelp
, help
, HasKeep
, keep
, HasClear
, clear
) where

import Control.Applicative
Expand Down Expand Up @@ -55,7 +55,7 @@ parsePure (Parser p) (Map.fromList -> env) =

eachUnsetVar :: Applicative m => Parser e a -> (String -> m b) -> m ()
eachUnsetVar Parser {unParser} =
for_ (foldAlt (\VarF {varfKeep, varfName} -> if varfKeep then Set.empty else Set.singleton varfName) unParser)
for_ (foldAlt (\VarF {varfClear, varfName} -> if varfClear then Set.singleton varfName else Set.empty) unParser)

readVar :: VarF e a -> Map String String -> Either [(String, e)] a
readVar VarF {varfName, varfReader} =
Expand Down Expand Up @@ -90,7 +90,7 @@ data VarF e a = VarF
, varfHelp :: Maybe String
, varfDef :: Maybe a
, varfHelpDef :: Maybe String
, varfKeep :: Bool
, varfClear :: Bool
} deriving (Functor)

liftVarF :: VarF e a -> Parser e a
Expand All @@ -117,10 +117,10 @@ var r n (Mod f) =
, varfHelp = varHelp
, varfDef = varDef
, varfHelpDef = varHelpDef <*> varDef
, varfKeep = varKeep
, varfClear = varClear
}
where
Var {varHelp, varDef, varHelpDef, varKeep} = f defaultVar
Var {varHelp, varDef, varHelpDef, varClear} = f defaultVar

-- | A flag that takes the active value if the environment variable
-- is set and non-empty and the default value otherwise
Expand All @@ -140,10 +140,10 @@ flag f t n (Mod g) =
, varfHelp = flagHelp
, varfDef = Just f
, varfHelpDef = Nothing
, varfKeep = flagKeep
, varfClear = flagClear
}
where
Flag {flagHelp, flagKeep} = g defaultFlag
Flag {flagHelp, flagClear} = g defaultFlag

-- | A simple boolean 'flag'
--
Expand Down Expand Up @@ -195,19 +195,19 @@ data Var a = Var
{ varHelp :: Maybe String
, varHelpDef :: Maybe (a -> String)
, varDef :: Maybe a
, varKeep :: Bool
, varClear :: Bool
}

defaultVar :: Var a
defaultVar = Var
{ varHelp = Nothing
, varDef = Nothing
, varHelpDef = Nothing
, varKeep = defaultKeep
, varClear = defaultClear
}

defaultKeep :: Bool
defaultKeep = False
defaultClear :: Bool
defaultClear = False

-- | The default value of the variable
--
Expand All @@ -218,14 +218,14 @@ def d =

-- | Flag metadata
data Flag a = Flag
{ flagHelp :: Maybe String
, flagKeep :: Bool
{ flagHelp :: Maybe String
, flagClear :: Bool
}

defaultFlag :: Flag a
defaultFlag = Flag
{ flagHelp = Nothing
, flagKeep = defaultKeep
{ flagHelp = Nothing
, flagClear = defaultClear
}

-- | Show the default value of the variable in help.
Expand Down Expand Up @@ -254,18 +254,22 @@ help :: HasHelp t => String -> Mod t a
help =
Mod . setHelp

-- | A class of things that can be still kept in an environment when the
-- parsing has been completed.
class HasKeep t where
setKeep :: t a -> t a
-- | A class of things that can be cleared from an environment when the parsing
-- has been completed.
class HasClear t where
setClear :: t a -> t a

instance HasKeep Var where
setKeep v = v {varKeep=True}
instance HasClear Var where
setClear v = v {varClear=True}

instance HasKeep Flag where
setKeep v = v {flagKeep=True}
instance HasClear Flag where
setClear v = v {flagClear=True}

-- | Keep a variable.
keep :: HasKeep t => Mod t a
keep =
Mod setKeep
-- | Clear a variable after reading it
--
-- This can make your application more secure by not passing parsed variables
-- onto any sub-processes.
--
clear :: HasClear t => Mod t a
clear =
Mod setClear
18 changes: 9 additions & 9 deletions test/EnvSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -87,26 +87,26 @@ spec =
Just "zygohistomorphic"

#if __GLASGOW_HASKELL__ >= 708
it "unsets parsed variables" $ do
it "does not unset parsed variables" $ do
setEnv "FOO" "4"
setEnv "BAR" "7"
parse (header "hi") (liftA2 (+) (var auto "FOO" (help "a")) (var auto "BAR" (help "b"))) `shouldReturn` (11 :: Int)
lookupEnv "FOO" `shouldReturn` Nothing
lookupEnv "BAR" `shouldReturn` Nothing
lookupEnv "FOO" `shouldReturn` Just "4"
lookupEnv "BAR" `shouldReturn` Just "7"

context "some variables are marked as kept" $
it "does not unset them" $ do
context "some variables are marked as clear" $
it "does unset them" $ do
setEnv "FOO" "4"
setEnv "BAR" "7"
parse (header "hi") (liftA2 (+) (var auto "FOO" (help "a" <> keep)) (var auto "BAR" (help "b"))) `shouldReturn` (11 :: Int)
lookupEnv "FOO" `shouldReturn` Just "4"
lookupEnv "BAR" `shouldReturn` Nothing
parse (header "hi") (liftA2 (+) (var auto "FOO" (help "a" <> clear)) (var auto "BAR" (help "b"))) `shouldReturn` (11 :: Int)
lookupEnv "FOO" `shouldReturn` Nothing
lookupEnv "BAR" `shouldReturn` Just "7"

context "parsing fails" $
it "does not unset any variables" $ do
setEnv "FOO" "4"
setEnv "BAR" "bar"
parse (header "hi") (liftA2 (+) (var auto "FOO" (help "a" <> keep)) (var auto "BAR" (help "b"))) `shouldThrow` anyException
parse (header "hi") (liftA2 (+) (var auto "FOO" (help "a" <> clear)) (var auto "BAR" (help "b"))) `shouldThrow` anyException
lookupEnv "FOO" `shouldReturn` Just "4"
lookupEnv "BAR" `shouldReturn` Just "bar"
#endif
Expand Down

0 comments on commit 434a90b

Please sign in to comment.