diff --git a/src/App/Page/Zone.purs b/src/App/Page/Zone.purs index 2070814..ee6fd36 100644 --- a/src/App/Page/Zone.purs +++ b/src/App/Page/Zone.purs @@ -149,8 +149,8 @@ data Action -- | Add a new resource record to the zone. | AddRR AcceptedRRTypes ResourceRecord - -- | Reset the different values of SPF modal (mechanisms, modifiers, etc.). - | ResetSPF + -- | Reset the different temporary values, such as SPF mechanisms or DMARC mail entry. + | ResetTemporaryValues -- | Save the changes done in an already existing resource record. | SaveRR ResourceRecord @@ -182,6 +182,18 @@ data Action -- | Add a SPF modifier to the currently modified (SPF) entry (see `_currentRR`). | SPF_Modifier_Add + -- | Add a new mail address to the DMARC rua list. + | DMARC_rua_Add + + -- | Add a new mail address to the DMARC ruf list. + | DMARC_ruf_Add + + -- | Remove a mail address of the DMARC rua list. + | DMARC_remove_rua Int + + -- | Remove a mail address of the DMARC ruf list. + | DMARC_remove_ruf Int + | DMARC_policy Int | DMARC_sp_policy Int | DMARC_adkim Int @@ -241,6 +253,9 @@ type State = , spf_modifier_t :: String , spf_modifier_v :: String + , dmarc_mail :: String + , dmarc_mail_limit :: Maybe Int + , dkim :: DKIM.DKIM , dmarc :: DMARC.DMARC @@ -294,9 +309,13 @@ initialState domain = , spf_mechanism_v: "" , spf_modifier_t: "redirect" , spf_modifier_v: "" + , dkim: DKIM.emptyDKIMRR , dmarc: DMARC.emptyDMARCRR + , dmarc_mail: "" + , dmarc_mail_limit: Nothing + , current_tab: Zone } @@ -554,7 +573,7 @@ handleAction = case _ of CancelModal -> do H.modify_ _ { rr_modal = NoModal } H.modify_ _ { _currentRR_errors = [] } - handleAction $ ResetSPF + handleAction $ ResetTemporaryValues -- | Create the RR modal. DeleteRRModal rr_id -> do @@ -686,12 +705,14 @@ handleAction = case _ of H.modify_ _ { _currentRR_errors = [] } handleAction $ SaveRR rr - ResetSPF -> do + ResetTemporaryValues -> do H.modify_ _ { spf_mechanism_q = "pass" , spf_mechanism_t = "a" , spf_mechanism_v = "" , spf_modifier_t = "redirect" , spf_modifier_v = "" + , dmarc_mail = "" + , dmarc_mail_limit = Nothing } SaveRR rr -> do @@ -702,7 +723,7 @@ handleAction = case _ of $ DNSManager.serialize $ DNSManager.MkUpdateRR { domain: state._domain, rr: rr } H.raise $ MessageToSend message - handleAction $ ResetSPF + handleAction $ ResetTemporaryValues RemoveRR rr_id -> do { _domain } <- H.get @@ -763,7 +784,7 @@ handleAction = case _ of [] -> Nothing v -> Just v H.modify_ _ { _currentRR { mechanisms = new_value }} - handleAction $ ResetSPF + handleAction $ ResetTemporaryValues SPF_Modifier_Add -> do state <- H.get @@ -775,7 +796,61 @@ handleAction = case _ of [] -> Nothing v -> Just v H.modify_ _ { _currentRR { modifiers = new_value }} - handleAction $ ResetSPF + handleAction $ ResetTemporaryValues + + DMARC_rua_Add -> do + state <- H.get + let current_ruas = case state._currentRR.dmarc of + Nothing -> [] + Just dmarc -> fromMaybe [] dmarc.rua + dmarc_mail = state.dmarc_mail + dmarc_mail_limit = state.dmarc_mail_limit + new_list = current_ruas <> [ {mail: dmarc_mail, limit: dmarc_mail_limit} ] + new_dmarc = case state._currentRR.dmarc of + Nothing -> DMARC.emptyDMARCRR { rua = Just new_list } + Just dmarc -> dmarc { rua = Just new_list } + H.modify_ _ { _currentRR { dmarc = Just new_dmarc } } + handleAction $ ResetTemporaryValues + + DMARC_ruf_Add -> do + state <- H.get + let current_rufs = case state._currentRR.dmarc of + Nothing -> [] + Just dmarc -> fromMaybe [] dmarc.ruf + dmarc_mail = state.dmarc_mail + dmarc_mail_limit = state.dmarc_mail_limit + new_list = current_rufs <> [ {mail: dmarc_mail, limit: dmarc_mail_limit} ] + new_dmarc = case state._currentRR.dmarc of + Nothing -> DMARC.emptyDMARCRR { ruf = Just new_list } + Just dmarc -> dmarc { ruf = Just new_list } + H.modify_ _ { _currentRR { dmarc = Just new_dmarc } } + handleAction $ ResetTemporaryValues + + DMARC_remove_rua i -> do + state <- H.get + let current_ruas = case state._currentRR.dmarc of + Nothing -> [] + Just dmarc -> fromMaybe [] dmarc.rua + new_value = case (remove_id i $ attach_id 0 current_ruas) of + [] -> Nothing + v -> Just v + new_dmarc = case state._currentRR.dmarc of + Nothing -> DMARC.emptyDMARCRR { rua = new_value } + Just dmarc -> dmarc { rua = new_value } + H.modify_ \s -> s { _currentRR { dmarc = Just new_dmarc } } + + DMARC_remove_ruf i -> do + state <- H.get + let current_rufs = case state._currentRR.dmarc of + Nothing -> [] + Just dmarc -> fromMaybe [] dmarc.ruf + new_value = case (remove_id i $ attach_id 0 current_rufs) of + [] -> Nothing + v -> Just v + new_dmarc = case state._currentRR.dmarc of + Nothing -> DMARC.emptyDMARCRR { ruf = new_value } + Just dmarc -> dmarc { ruf = new_value } + H.modify_ \s -> s { _currentRR { dmarc = Just new_dmarc } } DMARC_policy v -> H.modify_ _ { dmarc { p = fromMaybe DMARC.None $ DMARC.policies A.!! v } } DMARC_sp_policy v -> H.modify_ _ { dmarc { sp = DMARC.policies A.!! (v - 1) } } diff --git a/src/App/Type/ResourceRecord.purs b/src/App/Type/ResourceRecord.purs index e5a7953..0ae8978 100644 --- a/src/App/Type/ResourceRecord.purs +++ b/src/App/Type/ResourceRecord.purs @@ -9,6 +9,7 @@ import Data.Codec.Argonaut as CA import Data.Codec.Argonaut.Record as CAR import App.Type.DKIM as DKIM +import App.Type.DMARC as DMARC type ResourceRecord = { rrtype :: String @@ -44,6 +45,7 @@ type ResourceRecord , q :: Maybe Qualifier -- Qualifier for default mechanism (`all`). , dkim :: Maybe DKIM.DKIM + , dmarc :: Maybe DMARC.DMARC -- TODO: DMARC specific entries. } @@ -84,6 +86,7 @@ codec = CA.object "ResourceRecord" , q: CAR.optional codecQualifier , dkim: CAR.optional DKIM.codec + , dmarc: CAR.optional DMARC.codec }) type Mechanism @@ -225,6 +228,7 @@ emptyRR , q: Nothing , dkim: Nothing + , dmarc: Nothing } data Qualifier = Pass | Neutral | SoftFail | HardFail