{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}

module OptEnvConf.Capability
  ( Capabilities (..),
    Capability (..),
    allCapabilities,
    enableCapability,
    disableCapability,
    missingCapabilities,

    -- * Predefined capabilities
    readSecretCapability,
  )
where

import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NE
import Data.Set (Set)
import qualified Data.Set as Set
import Data.String
import Data.Text (Text)
import Data.Validity
import Data.Validity.Containers ()
import Data.Validity.Text ()
import GHC.Generics (Generic)

-- Set of disabled capabilities
newtype Capabilities = Capabilities {Capabilities -> Set Capability
unCapabilities :: Set Capability}
  deriving (Int -> Capabilities -> ShowS
[Capabilities] -> ShowS
Capabilities -> String
(Int -> Capabilities -> ShowS)
-> (Capabilities -> String)
-> ([Capabilities] -> ShowS)
-> Show Capabilities
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Capabilities -> ShowS
showsPrec :: Int -> Capabilities -> ShowS
$cshow :: Capabilities -> String
show :: Capabilities -> String
$cshowList :: [Capabilities] -> ShowS
showList :: [Capabilities] -> ShowS
Show, (forall x. Capabilities -> Rep Capabilities x)
-> (forall x. Rep Capabilities x -> Capabilities)
-> Generic Capabilities
forall x. Rep Capabilities x -> Capabilities
forall x. Capabilities -> Rep Capabilities x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Capabilities -> Rep Capabilities x
from :: forall x. Capabilities -> Rep Capabilities x
$cto :: forall x. Rep Capabilities x -> Capabilities
to :: forall x. Rep Capabilities x -> Capabilities
Generic)

instance Validity Capabilities

allCapabilities :: Capabilities
allCapabilities :: Capabilities
allCapabilities = Capabilities {unCapabilities :: Set Capability
unCapabilities = Set Capability
forall a. Set a
Set.empty}

enableCapability :: Capability -> Capabilities -> Capabilities
enableCapability :: Capability -> Capabilities -> Capabilities
enableCapability Capability
cap (Capabilities Set Capability
caps) =
  Set Capability -> Capabilities
Capabilities (Capability -> Set Capability -> Set Capability
forall a. Ord a => a -> Set a -> Set a
Set.delete Capability
cap Set Capability
caps)

disableCapability :: Capability -> Capabilities -> Capabilities
disableCapability :: Capability -> Capabilities -> Capabilities
disableCapability Capability
cap (Capabilities Set Capability
caps) =
  Set Capability -> Capabilities
Capabilities (Capability -> Set Capability -> Set Capability
forall a. Ord a => a -> Set a -> Set a
Set.insert Capability
cap Set Capability
caps)

missingCapabilities :: Capabilities -> Set Capability -> Maybe (NonEmpty Capability)
missingCapabilities :: Capabilities -> Set Capability -> Maybe (NonEmpty Capability)
missingCapabilities (Capabilities Set Capability
caps) Set Capability
requiredCapabilities =
  [Capability] -> Maybe (NonEmpty Capability)
forall a. [a] -> Maybe (NonEmpty a)
NE.nonEmpty (Set Capability -> [Capability]
forall a. Set a -> [a]
Set.toList (Set Capability -> Set Capability -> Set Capability
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection Set Capability
requiredCapabilities Set Capability
caps))

newtype Capability = Capability {Capability -> Text
unCapability :: Text}
  deriving stock ((forall x. Capability -> Rep Capability x)
-> (forall x. Rep Capability x -> Capability) -> Generic Capability
forall x. Rep Capability x -> Capability
forall x. Capability -> Rep Capability x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Capability -> Rep Capability x
from :: forall x. Capability -> Rep Capability x
$cto :: forall x. Rep Capability x -> Capability
to :: forall x. Rep Capability x -> Capability
Generic)
  deriving newtype (Int -> Capability -> ShowS
[Capability] -> ShowS
Capability -> String
(Int -> Capability -> ShowS)
-> (Capability -> String)
-> ([Capability] -> ShowS)
-> Show Capability
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Capability -> ShowS
showsPrec :: Int -> Capability -> ShowS
$cshow :: Capability -> String
show :: Capability -> String
$cshowList :: [Capability] -> ShowS
showList :: [Capability] -> ShowS
Show, Capability -> Capability -> Bool
(Capability -> Capability -> Bool)
-> (Capability -> Capability -> Bool) -> Eq Capability
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Capability -> Capability -> Bool
== :: Capability -> Capability -> Bool
$c/= :: Capability -> Capability -> Bool
/= :: Capability -> Capability -> Bool
Eq, Eq Capability
Eq Capability =>
(Capability -> Capability -> Ordering)
-> (Capability -> Capability -> Bool)
-> (Capability -> Capability -> Bool)
-> (Capability -> Capability -> Bool)
-> (Capability -> Capability -> Bool)
-> (Capability -> Capability -> Capability)
-> (Capability -> Capability -> Capability)
-> Ord Capability
Capability -> Capability -> Bool
Capability -> Capability -> Ordering
Capability -> Capability -> Capability
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Capability -> Capability -> Ordering
compare :: Capability -> Capability -> Ordering
$c< :: Capability -> Capability -> Bool
< :: Capability -> Capability -> Bool
$c<= :: Capability -> Capability -> Bool
<= :: Capability -> Capability -> Bool
$c> :: Capability -> Capability -> Bool
> :: Capability -> Capability -> Bool
$c>= :: Capability -> Capability -> Bool
>= :: Capability -> Capability -> Bool
$cmax :: Capability -> Capability -> Capability
max :: Capability -> Capability -> Capability
$cmin :: Capability -> Capability -> Capability
min :: Capability -> Capability -> Capability
Ord, String -> Capability
(String -> Capability) -> IsString Capability
forall a. (String -> a) -> IsString a
$cfromString :: String -> Capability
fromString :: String -> Capability
IsString)

instance Validity Capability

-- | The annotation for any setting reading secrets.
--
-- We add these so that we can disable them in settings checks, to avoid
-- failing settings checks when secrets are read at runtime instead of
-- build-time.
readSecretCapability :: String
readSecretCapability :: String
readSecretCapability = String
"read-secret"