module Hadolint.Rule.DL3066 (rule) where

import qualified Data.Char as Char
import qualified Data.Set as Set
import qualified Data.Text as Text
import Hadolint.Rule
import Language.Docker.Syntax


data Acc
  = Acc { Acc -> Set Text
args :: Set.Set Text.Text }
  | Empty
  deriving (Int -> Acc -> ShowS
[Acc] -> ShowS
Acc -> String
(Int -> Acc -> ShowS)
-> (Acc -> String) -> ([Acc] -> ShowS) -> Show Acc
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Acc -> ShowS
showsPrec :: Int -> Acc -> ShowS
$cshow :: Acc -> String
show :: Acc -> String
$cshowList :: [Acc] -> ShowS
showList :: [Acc] -> ShowS
Show)


rule :: Rule args
rule :: forall args. Rule args
rule = (Int -> State Acc -> Instruction args -> State Acc)
-> State Acc -> Rule args
forall a args.
(Int -> State a -> Instruction args -> State a)
-> State a -> Rule args
customRule Int -> State Acc -> Instruction args -> State Acc
forall {args}. Int -> State Acc -> Instruction args -> State Acc
check (Acc -> State Acc
forall a. a -> State a
emptyState Acc
Empty)
  where
    code :: RuleCode
code = RuleCode
"DL3066"
    severity :: DLSeverity
severity = DLSeverity
DLInfoC
    message :: Text
message = Text
"Non-numeric user-id may not be resolvable by host system"

    check :: Int -> State Acc -> Instruction args -> State Acc
check Int
line State Acc
st (User Text
u)
      | (Char -> Bool) -> Text -> Bool
Text.all Char -> Bool
Char.isDigit (Text -> Bool) -> Text -> Bool
forall a b. (a -> b) -> a -> b
$ Text -> Text
getUid Text
u = State Acc
st
      | Acc -> Text -> Bool
uidIsDefinedArg (State Acc -> Acc
forall a. State a -> a
state State Acc
st) Text
u = State Acc
st
      | Bool
otherwise = State Acc
st State Acc -> (State Acc -> State Acc) -> State Acc
forall a b. a -> (a -> b) -> b
|> CheckFailure -> State Acc -> State Acc
forall a. CheckFailure -> State a -> State a
addFail CheckFailure {Int
Text
RuleCode
DLSeverity
code :: RuleCode
severity :: DLSeverity
message :: Text
line :: Int
line :: Int
message :: Text
severity :: DLSeverity
code :: RuleCode
..}
    check Int
_ State Acc
st (Arg Text
arg Maybe Text
_) = State Acc
st State Acc -> (State Acc -> State Acc) -> State Acc
forall a b. a -> (a -> b) -> b
|> (Acc -> Acc) -> State Acc -> State Acc
forall a. (a -> a) -> State a -> State a
modify (Text -> Acc -> Acc
registerArg Text
arg)
    check Int
_ State Acc
st Instruction args
_ = State Acc
st
{-# INLINEABLE rule #-}

getUid :: Text.Text -> Text.Text
getUid :: Text -> Text
getUid Text
t
  | Text
":" Text -> Text -> Bool
`Text.isInfixOf` Text
t = [Text] -> Text
forall {a}. IsString a => [a] -> a
u ( HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
Text.splitOn Text
":" Text
t )
  | Bool
otherwise = Text
t
  where
    u :: [a] -> a
u [] = a
""
    u (a
h:[a]
_) = a
h

uidIsDefinedArg :: Acc -> Text.Text -> Bool
uidIsDefinedArg :: Acc -> Text -> Bool
uidIsDefinedArg Acc
Empty Text
_ = Bool
False
uidIsDefinedArg (Acc Set Text
args) Text
u = (Text -> Bool) -> Set Text -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Text -> Text -> Bool
`varInUid` Text
u) Set Text
args
  where
    varInUid :: Text.Text -> Text.Text -> Bool
    varInUid :: Text -> Text -> Bool
varInUid Text
var Text
uid =
      ( String -> Text
Text.pack String
"${" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
var Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack String
"}" ) Text -> Text -> Bool
`Text.isInfixOf` Text
uid
        Bool -> Bool -> Bool
|| ( String -> Text
Text.pack String
"$" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
var ) Text -> Text -> Bool
`Text.isInfixOf` Text
uid

registerArg :: Text.Text -> Acc -> Acc
registerArg :: Text -> Acc -> Acc
registerArg Text
arg Acc
Empty =
  Acc { args :: Set Text
args = Text -> Set Text
forall a. a -> Set a
Set.singleton Text
arg }
registerArg Text
arg (Acc Set Text
args) =
  Acc { args :: Set Text
args = Text -> Set Text -> Set Text
forall a. Ord a => a -> Set a -> Set a
Set.insert Text
arg Set Text
args }