{-# LANGUAGE OverloadedStrings #-}
module Network.Cloudflare.DNS.DNSSEC where

import           Control.Lens             hiding ((.=))
import           Data.Aeson
import           Data.Maybe
import           Data.Text                (Text)
import qualified Data.Text                as Text
import qualified Data.Text.Encoding       as Text
import           Data.Time
import           Data.Word
import           Network.Cloudflare.Types
import           Network.Wreq

-- https://developers.cloudflare.com/dns/dnssec/multi-signer-dnssec/setup/


-- | Get the DNSSEC settings for a zone
getDNSSEC :: CloudflareAuth -> Text -> IO (Either String (ResultResponse DNSECDetails))
getDNSSEC :: CloudflareAuth
-> Text -> IO (Either String (ResultResponse DNSECDetails))
getDNSSEC CloudflareAuth
authInfo Text
zone = do
  let opts :: Options
opts = Options
defaults forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"Authorization" forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
"Bearer " forall a. Semigroup a => a -> a -> a
<> Text -> ByteString
Text.encodeUtf8 (CloudflareAuth -> Text
cloudflareAuthToken CloudflareAuth
authInfo)]
      url :: String
url = String
"https://api.cloudflare.com/client/v4/zones/" forall a. Semigroup a => a -> a -> a
<> Text -> String
Text.unpack Text
zone forall a. Semigroup a => a -> a -> a
<> String
"/dnssec"
  Response ByteString
r <- Options -> String -> IO (Response ByteString)
getWith Options
opts String
url
  forall a. Show a => a -> IO ()
print Response ByteString
r
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Response ByteString
r forall s a. s -> Getting a s a -> a
^. forall body0 body1.
Lens (Response body0) (Response body1) body0 body1
responseBody forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. FromJSON a => ByteString -> Either String a
eitherDecode

-- | Edit DNSSEC settings for a zone
editDNSSEC :: CloudflareAuth -> Text -> EditDNSSECStatus -> IO (Either String (ResultResponse DNSSEC))
editDNSSEC :: CloudflareAuth
-> Text
-> EditDNSSECStatus
-> IO (Either String (ResultResponse DNSSEC))
editDNSSEC CloudflareAuth
authInfo Text
zone EditDNSSECStatus
edit = do
  let opts :: Options
opts = Options
defaults forall a b. a -> (a -> b) -> b
& HeaderName -> Lens' Options [ByteString]
header HeaderName
"Authorization" forall s t a b. ASetter s t a b -> b -> s -> t
.~ [ByteString
"Bearer " forall a. Semigroup a => a -> a -> a
<> Text -> ByteString
Text.encodeUtf8 (CloudflareAuth -> Text
cloudflareAuthToken CloudflareAuth
authInfo)]
      url :: String
url = String
"https://api.cloudflare.com/client/v4/zones/" forall a. Semigroup a => a -> a -> a
<> Text -> String
Text.unpack Text
zone forall a. Semigroup a => a -> a -> a
<> String
"/dnssec"
  Response ByteString
r <- forall a.
Patchable a =>
Options -> String -> a -> IO (Response ByteString)
patchWith Options
opts String
url forall a b. (a -> b) -> a -> b
$ forall a. ToJSON a => a -> Value
toJSON EditDNSSECStatus
edit
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Response ByteString
r forall s a. s -> Getting a s a -> a
^. forall body0 body1.
Lens (Response body0) (Response body1) body0 body1
responseBody forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to forall a. FromJSON a => ByteString -> Either String a
eitherDecode

-- | Edit DNSSEC settings for a zone, fields set to Nothing will not be changed
data EditDNSSECStatus = EditDNSSECStatus {
  EditDNSSECStatus -> Maybe Bool
editDNSSECMultiSigner :: Maybe Bool -- ^ Enable or disable multi-signer DNSSEC
, EditDNSSECStatus -> Maybe Bool
editDNSSECPresigned :: Maybe Bool -- ^ Enable or disable presigned DNSSEC
, EditDNSSECStatus -> Maybe DNSSECStatus
editDNSSECStatus :: Maybe DNSSECStatus -- ^ Enable or disable DNSSEC
} deriving (EditDNSSECStatus -> EditDNSSECStatus -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
$c/= :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
== :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
$c== :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
Eq, Eq EditDNSSECStatus
EditDNSSECStatus -> EditDNSSECStatus -> Bool
EditDNSSECStatus -> EditDNSSECStatus -> Ordering
EditDNSSECStatus -> EditDNSSECStatus -> EditDNSSECStatus
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
min :: EditDNSSECStatus -> EditDNSSECStatus -> EditDNSSECStatus
$cmin :: EditDNSSECStatus -> EditDNSSECStatus -> EditDNSSECStatus
max :: EditDNSSECStatus -> EditDNSSECStatus -> EditDNSSECStatus
$cmax :: EditDNSSECStatus -> EditDNSSECStatus -> EditDNSSECStatus
>= :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
$c>= :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
> :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
$c> :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
<= :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
$c<= :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
< :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
$c< :: EditDNSSECStatus -> EditDNSSECStatus -> Bool
compare :: EditDNSSECStatus -> EditDNSSECStatus -> Ordering
$ccompare :: EditDNSSECStatus -> EditDNSSECStatus -> Ordering
Ord, Int -> EditDNSSECStatus -> ShowS
[EditDNSSECStatus] -> ShowS
EditDNSSECStatus -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [EditDNSSECStatus] -> ShowS
$cshowList :: [EditDNSSECStatus] -> ShowS
show :: EditDNSSECStatus -> String
$cshow :: EditDNSSECStatus -> String
showsPrec :: Int -> EditDNSSECStatus -> ShowS
$cshowsPrec :: Int -> EditDNSSECStatus -> ShowS
Show)

instance ToJSON EditDNSSECStatus where
  toJSON :: EditDNSSECStatus -> Value
toJSON (EditDNSSECStatus Maybe Bool
multiSigner Maybe Bool
presigned Maybe DNSSECStatus
status) = [Pair] -> Value
object forall a b. (a -> b) -> a -> b
$ forall a. [Maybe a] -> [a]
catMaybes [
      (Key
"multi_signer" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.=) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Bool
multiSigner
    , (Key
"presigned" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.=) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Bool
presigned
    , (Key
"status" forall e kv v. (KeyValue e kv, ToJSON v) => Key -> v -> kv
.=) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe DNSSECStatus
status
    ]

-- | Status of DNSSec for a zone
data DNSSECStatus =
    DNSSECActive
  | DNSSECDisabled deriving (DNSSECStatus -> DNSSECStatus -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DNSSECStatus -> DNSSECStatus -> Bool
$c/= :: DNSSECStatus -> DNSSECStatus -> Bool
== :: DNSSECStatus -> DNSSECStatus -> Bool
$c== :: DNSSECStatus -> DNSSECStatus -> Bool
Eq, Eq DNSSECStatus
DNSSECStatus -> DNSSECStatus -> Bool
DNSSECStatus -> DNSSECStatus -> Ordering
DNSSECStatus -> DNSSECStatus -> DNSSECStatus
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
min :: DNSSECStatus -> DNSSECStatus -> DNSSECStatus
$cmin :: DNSSECStatus -> DNSSECStatus -> DNSSECStatus
max :: DNSSECStatus -> DNSSECStatus -> DNSSECStatus
$cmax :: DNSSECStatus -> DNSSECStatus -> DNSSECStatus
>= :: DNSSECStatus -> DNSSECStatus -> Bool
$c>= :: DNSSECStatus -> DNSSECStatus -> Bool
> :: DNSSECStatus -> DNSSECStatus -> Bool
$c> :: DNSSECStatus -> DNSSECStatus -> Bool
<= :: DNSSECStatus -> DNSSECStatus -> Bool
$c<= :: DNSSECStatus -> DNSSECStatus -> Bool
< :: DNSSECStatus -> DNSSECStatus -> Bool
$c< :: DNSSECStatus -> DNSSECStatus -> Bool
compare :: DNSSECStatus -> DNSSECStatus -> Ordering
$ccompare :: DNSSECStatus -> DNSSECStatus -> Ordering
Ord, Int -> DNSSECStatus -> ShowS
[DNSSECStatus] -> ShowS
DNSSECStatus -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DNSSECStatus] -> ShowS
$cshowList :: [DNSSECStatus] -> ShowS
show :: DNSSECStatus -> String
$cshow :: DNSSECStatus -> String
showsPrec :: Int -> DNSSECStatus -> ShowS
$cshowsPrec :: Int -> DNSSECStatus -> ShowS
Show)

instance ToJSON DNSSECStatus where
  toJSON :: DNSSECStatus -> Value
toJSON = Text -> Value
String forall b c a. (b -> c) -> (a -> b) -> a -> c
. DNSSECStatus -> Text
dnssecStatusToText


-- | Text representation of DNSSECStatus
dnssecStatusToText :: DNSSECStatus -> Text
dnssecStatusToText :: DNSSECStatus -> Text
dnssecStatusToText DNSSECStatus
DNSSECActive = Text
"active"
dnssecStatusToText DNSSECStatus
DNSSECDisabled = Text
"disabled"

--
data DNSECDetails =
    DNSSecActive DNSSEC
  | DNSSecDisabled
  | DNSSecPending DNSSEC
  deriving (DNSECDetails -> DNSECDetails -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DNSECDetails -> DNSECDetails -> Bool
$c/= :: DNSECDetails -> DNSECDetails -> Bool
== :: DNSECDetails -> DNSECDetails -> Bool
$c== :: DNSECDetails -> DNSECDetails -> Bool
Eq, Eq DNSECDetails
DNSECDetails -> DNSECDetails -> Bool
DNSECDetails -> DNSECDetails -> Ordering
DNSECDetails -> DNSECDetails -> DNSECDetails
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
min :: DNSECDetails -> DNSECDetails -> DNSECDetails
$cmin :: DNSECDetails -> DNSECDetails -> DNSECDetails
max :: DNSECDetails -> DNSECDetails -> DNSECDetails
$cmax :: DNSECDetails -> DNSECDetails -> DNSECDetails
>= :: DNSECDetails -> DNSECDetails -> Bool
$c>= :: DNSECDetails -> DNSECDetails -> Bool
> :: DNSECDetails -> DNSECDetails -> Bool
$c> :: DNSECDetails -> DNSECDetails -> Bool
<= :: DNSECDetails -> DNSECDetails -> Bool
$c<= :: DNSECDetails -> DNSECDetails -> Bool
< :: DNSECDetails -> DNSECDetails -> Bool
$c< :: DNSECDetails -> DNSECDetails -> Bool
compare :: DNSECDetails -> DNSECDetails -> Ordering
$ccompare :: DNSECDetails -> DNSECDetails -> Ordering
Ord, Int -> DNSECDetails -> ShowS
[DNSECDetails] -> ShowS
DNSECDetails -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DNSECDetails] -> ShowS
$cshowList :: [DNSECDetails] -> ShowS
show :: DNSECDetails -> String
$cshow :: DNSECDetails -> String
showsPrec :: Int -> DNSECDetails -> ShowS
$cshowsPrec :: Int -> DNSECDetails -> ShowS
Show)

instance FromJSON DNSECDetails where
  parseJSON :: Value -> Parser DNSECDetails
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"DNSECDetails" forall a b. (a -> b) -> a -> b
$ \Object
o -> do
    String
status <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"status"
    case String
status of
      String
"active" -> DNSSEC -> DNSECDetails
DNSSecActive forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      String
"disabled" -> forall (f :: * -> *) a. Applicative f => a -> f a
pure DNSECDetails
DNSSecDisabled
      String
"pending" -> DNSSEC -> DNSECDetails
DNSSecPending forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. FromJSON a => Value -> Parser a
parseJSON (Object -> Value
Object Object
o)
      String
_ -> forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Unknown DNSSEC status: " forall a. Semigroup a => a -> a -> a
<> String
status

data DNSSEC = DNSSEC {
  DNSSEC -> Maybe Text
dnssecAlgorithm :: Maybe Text
, DNSSEC -> Maybe Text
dnssecDigest ::  Maybe Text
, DNSSEC -> Maybe Text
dnssecDigestType :: Maybe Text
, DNSSEC -> Maybe Bool
dnssecMultiSigner :: Maybe Bool
, DNSSEC -> Maybe Bool
dnssecPresigned :: Maybe Bool
, DNSSEC -> Text
dnssecDS :: Text
, DNSSEC -> Word8
dnssecFlags :: Word8
, DNSSEC -> Word16
dnssecKeyTag :: Word16
, DNSSEC -> Text
dnssecKeyType :: Text
, DNSSEC -> UTCTime
dnssecModifiedOn :: UTCTime
, DNSSEC -> Text
dnssecPublicKey :: Text
, DNSSEC -> Text
dnssecStatus :: Text -- TODO this could be an enum with the status values but it's different from the existing DNSSECStatus
} deriving (DNSSEC -> DNSSEC -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DNSSEC -> DNSSEC -> Bool
$c/= :: DNSSEC -> DNSSEC -> Bool
== :: DNSSEC -> DNSSEC -> Bool
$c== :: DNSSEC -> DNSSEC -> Bool
Eq, Eq DNSSEC
DNSSEC -> DNSSEC -> Bool
DNSSEC -> DNSSEC -> Ordering
DNSSEC -> DNSSEC -> DNSSEC
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
min :: DNSSEC -> DNSSEC -> DNSSEC
$cmin :: DNSSEC -> DNSSEC -> DNSSEC
max :: DNSSEC -> DNSSEC -> DNSSEC
$cmax :: DNSSEC -> DNSSEC -> DNSSEC
>= :: DNSSEC -> DNSSEC -> Bool
$c>= :: DNSSEC -> DNSSEC -> Bool
> :: DNSSEC -> DNSSEC -> Bool
$c> :: DNSSEC -> DNSSEC -> Bool
<= :: DNSSEC -> DNSSEC -> Bool
$c<= :: DNSSEC -> DNSSEC -> Bool
< :: DNSSEC -> DNSSEC -> Bool
$c< :: DNSSEC -> DNSSEC -> Bool
compare :: DNSSEC -> DNSSEC -> Ordering
$ccompare :: DNSSEC -> DNSSEC -> Ordering
Ord, Int -> DNSSEC -> ShowS
[DNSSEC] -> ShowS
DNSSEC -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DNSSEC] -> ShowS
$cshowList :: [DNSSEC] -> ShowS
show :: DNSSEC -> String
$cshow :: DNSSEC -> String
showsPrec :: Int -> DNSSEC -> ShowS
$cshowsPrec :: Int -> DNSSEC -> ShowS
Show)

instance FromJSON DNSSEC where
  parseJSON :: Value -> Parser DNSSEC
parseJSON = forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"EditDNSSEC" forall a b. (a -> b) -> a -> b
$ \Object
o -> do
    Maybe Text
algorithm <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"algorithm"
    Maybe Text
digest <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"digest"
    Maybe Text
digestType <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"digest_type"
    Maybe Bool
multiSigner <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"multi_signer"
    Maybe Bool
presigned <- Object
o forall a. FromJSON a => Object -> Key -> Parser (Maybe a)
.:? Key
"presigned"
    Text
ds <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"ds"
    Word8
flags <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"flags"
    Word16
keyTag <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"key_tag"
    Text
keyType <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"key_type"
    UTCTime
modifiedOn <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"modified_on"
    Text
pubKey <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"public_key"
    Text
status <- Object
o forall a. FromJSON a => Object -> Key -> Parser a
.: Key
"status"
    forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Maybe Text
-> Maybe Text
-> Maybe Text
-> Maybe Bool
-> Maybe Bool
-> Text
-> Word8
-> Word16
-> Text
-> UTCTime
-> Text
-> Text
-> DNSSEC
DNSSEC Maybe Text
algorithm Maybe Text
digest Maybe Text
digestType Maybe Bool
multiSigner Maybe Bool
presigned Text
ds Word8
flags Word16
keyTag Text
keyType UTCTime
modifiedOn Text
pubKey Text
status