Massive code removal!
parent
e63bfdca3c
commit
32fe44e34c
|
@ -1,31 +1,19 @@
|
||||||
module App.Validation where
|
module App.Validation where
|
||||||
|
|
||||||
import Prelude (class Eq, apply, map, otherwise, pure, show, between, bind
|
import Prelude (apply, between, bind, map, pure, ($), (-), (<))
|
||||||
, ($), (&&), (<), (<<<), (<=), (<>), (>=), (-))
|
|
||||||
|
|
||||||
import Data.Validation.Semigroup (V, andThen, invalid, toEither)
|
|
||||||
import Data.Array as A
|
|
||||||
import Parsing (runParser)
|
|
||||||
import Data.Maybe (Maybe(..), maybe)
|
|
||||||
import Data.Either (Either(..))
|
|
||||||
import Data.Tuple (Tuple(..))
|
|
||||||
import Data.String.Regex as R
|
|
||||||
import Data.String.Regex.Flags as RF
|
|
||||||
import Data.String as S
|
|
||||||
import Data.String.CodeUnits as CU
|
|
||||||
import Data.Int (fromString)
|
|
||||||
import URI.Host.IPv4Address as IPv4
|
|
||||||
import URI.Host.IPv6Address as IPv6
|
|
||||||
|
|
||||||
import Control.Alt ((<|>))
|
import Control.Alt ((<|>))
|
||||||
|
import Data.Array as A
|
||||||
|
import Data.Either (Either(..))
|
||||||
|
import Data.Maybe (Maybe(..), maybe)
|
||||||
|
import Data.String.CodeUnits as CU
|
||||||
|
import Data.Validation.Semigroup (V, invalid, toEither)
|
||||||
|
|
||||||
import App.RR
|
|
||||||
import App.AcceptedRRTypes (AcceptedRRTypes(..))
|
|
||||||
import App.ResourceRecord (ResourceRecord)
|
import App.ResourceRecord (ResourceRecord)
|
||||||
import GenericParser.SomeParsers as SomeParsers
|
import GenericParser.SomeParsers as SomeParsers
|
||||||
import GenericParser.Parser as G
|
import GenericParser.Parser as G
|
||||||
import GenericParser.DomainParser.Common as DomainParser
|
import GenericParser.DomainParser.Common (DomainError) as DomainParser
|
||||||
import GenericParser.DomainParser as DomainParser
|
import GenericParser.DomainParser (sub_eof) as DomainParser
|
||||||
import GenericParser.IPAddress as IPAddress
|
import GenericParser.IPAddress as IPAddress
|
||||||
import GenericParser.RFC5234 as RFC5234
|
import GenericParser.RFC5234 as RFC5234
|
||||||
|
|
||||||
|
@ -44,26 +32,6 @@ import GenericParser.RFC5234 as RFC5234
|
||||||
-- |
|
-- |
|
||||||
-- | Maybe the code will change again in the future, but for now it will be enough.
|
-- | Maybe the code will change again in the future, but for now it will be enough.
|
||||||
|
|
||||||
--andThenDrop :: forall errors a b. V errors a -> V errors b -> V errors b
|
|
||||||
-- andThenDrop f1 f2 = f1 !> (\ _ -> f2)
|
|
||||||
|
|
||||||
infixl 8 andThen as !>
|
|
||||||
-- infixl 8 andThenDrop as !<
|
|
||||||
|
|
||||||
data Attribute
|
|
||||||
= Name
|
|
||||||
| TTL
|
|
||||||
| RRType
|
|
||||||
| Id
|
|
||||||
| Target
|
|
||||||
| Priority
|
|
||||||
| Protocol
|
|
||||||
| Weight
|
|
||||||
| Port
|
|
||||||
| NotAnAttribute
|
|
||||||
|
|
||||||
derive instance eqAttribute :: Eq Attribute
|
|
||||||
|
|
||||||
data ValidationError
|
data ValidationError
|
||||||
= UNKNOWN
|
= UNKNOWN
|
||||||
| VEIPv4 (G.Error IPAddress.IPv4Error)
|
| VEIPv4 (G.Error IPAddress.IPv4Error)
|
||||||
|
@ -82,10 +50,7 @@ data ValidationError
|
||||||
|
|
||||||
type AVErrors = Array ValidationError
|
type AVErrors = Array ValidationError
|
||||||
|
|
||||||
type Errors = Array (Tuple Attribute String)
|
-- | Current default values.
|
||||||
|
|
||||||
-- | Totally garbage values at the moment. Please fix. **TODO**
|
|
||||||
|
|
||||||
min_ttl :: Int
|
min_ttl :: Int
|
||||||
min_ttl = 30
|
min_ttl = 30
|
||||||
max_ttl :: Int
|
max_ttl :: Int
|
||||||
|
@ -104,270 +69,6 @@ min_weight :: Int
|
||||||
min_weight = 0
|
min_weight = 0
|
||||||
max_weight :: Int
|
max_weight :: Int
|
||||||
max_weight = 65535
|
max_weight = 65535
|
||||||
name_min_len :: Int
|
|
||||||
name_min_len = 1
|
|
||||||
name_max_len :: Int
|
|
||||||
name_max_len = 50
|
|
||||||
target_min_len :: Int
|
|
||||||
target_min_len = 1
|
|
||||||
target_max_len :: Int
|
|
||||||
target_max_len = 50
|
|
||||||
target_TXT_max_len :: Int
|
|
||||||
target_TXT_max_len = 500
|
|
||||||
protocol_min_len :: Int
|
|
||||||
protocol_min_len = 1
|
|
||||||
protocol_max_len :: Int
|
|
||||||
protocol_max_len = 10
|
|
||||||
name_format :: String
|
|
||||||
name_format = "[a-zA-Z]+"
|
|
||||||
hostname_format :: String
|
|
||||||
hostname_format = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])[.]?$"
|
|
||||||
protocol_format :: String
|
|
||||||
protocol_format = "^(tcp|udp|sctp)$"
|
|
||||||
|
|
||||||
-- Basic tools for validation.
|
|
||||||
|
|
||||||
lengthIsBetween :: Attribute -> Int -> Int -> String -> V Errors String
|
|
||||||
lengthIsBetween field minlen maxlen value
|
|
||||||
= if valid_condition
|
|
||||||
then pure value
|
|
||||||
else invalid [ Tuple field error_message ]
|
|
||||||
where
|
|
||||||
actual_len = S.length value
|
|
||||||
valid_condition = actual_len >= minlen && actual_len <= maxlen
|
|
||||||
error_message = "acceptable length [" <> show minlen <> "-" <> show maxlen <> "]"
|
|
||||||
|
|
||||||
-- | `matches` is a simple format verification based on regex parsing.
|
|
||||||
-- | `verify_regex` is a handler to use `matches` with a string regex format.
|
|
||||||
-- |
|
|
||||||
-- | ```
|
|
||||||
-- | verify_regex Name name_format name
|
|
||||||
-- | ```
|
|
||||||
matches :: Attribute -> String -> R.Regex -> V Errors String
|
|
||||||
matches field value regex
|
|
||||||
| R.test regex value = pure value
|
|
||||||
| otherwise = invalid [Tuple field "unacceptable format"]
|
|
||||||
|
|
||||||
intBetween :: Attribute -> Int -> Int -> Int -> V Errors Int
|
|
||||||
intBetween field min max value
|
|
||||||
| min <= value && value <= max = pure value
|
|
||||||
| otherwise = invalid [Tuple field error_message]
|
|
||||||
where
|
|
||||||
error_message = "acceptable value [" <> show min <> "-" <> show max <> "]"
|
|
||||||
|
|
||||||
validate_integer :: Attribute -> String -> V Errors Int
|
|
||||||
validate_integer field string
|
|
||||||
= case fromString string of
|
|
||||||
Nothing -> invalid [Tuple field "not an integer"]
|
|
||||||
Just i -> pure i
|
|
||||||
|
|
||||||
-- | `verify_domain` provides a SIMPLISTIC verification for hostname format.
|
|
||||||
|
|
||||||
verify_domain :: Attribute -> String -> V Errors String
|
|
||||||
verify_domain field value = verify_regex field hostname_format value
|
|
||||||
|
|
||||||
-- | `verify_regex` provides a reasonable way to verify a value based on a regex.
|
|
||||||
-- | The regex is a simple string.
|
|
||||||
-- | An example:
|
|
||||||
-- |
|
|
||||||
-- | ```
|
|
||||||
-- | verify_length name
|
|
||||||
-- | !> verify_regex Name name_format
|
|
||||||
-- | ```
|
|
||||||
|
|
||||||
verify_regex :: Attribute -> String -> String -> V Errors String
|
|
||||||
verify_regex field restr value
|
|
||||||
= case R.regex restr RF.unicode of
|
|
||||||
Left error_string -> invalid [Tuple field $ "error in regex: " <> error_string]
|
|
||||||
Right regex -> matches field value regex
|
|
||||||
|
|
||||||
verify_ipv4 :: Attribute -> String -> V Errors String
|
|
||||||
verify_ipv4 field str = case runParser str IPv4.parser of
|
|
||||||
Left _ -> invalid [Tuple field "cannot parse this IPv4"]
|
|
||||||
Right _ -> pure str
|
|
||||||
|
|
||||||
verify_ipv6 :: Attribute -> String -> V Errors String
|
|
||||||
verify_ipv6 field str = case runParser str IPv6.parser of
|
|
||||||
Left _ -> invalid [Tuple field "cannot parse this IPv6"]
|
|
||||||
Right _ -> pure str
|
|
||||||
|
|
||||||
-- Field-related validations.
|
|
||||||
|
|
||||||
validate_name :: String -> V Errors String
|
|
||||||
validate_name name
|
|
||||||
= verify_length name !> verify_regex Name name_format
|
|
||||||
where
|
|
||||||
verify_length = lengthIsBetween Name name_min_len name_max_len
|
|
||||||
|
|
||||||
validate_ttl :: String -> V Errors Int
|
|
||||||
validate_ttl str_ttl
|
|
||||||
= is_int str_ttl !> right_range
|
|
||||||
where
|
|
||||||
is_int = validate_integer TTL
|
|
||||||
right_range = intBetween TTL min_ttl max_ttl
|
|
||||||
|
|
||||||
validate_priority :: String -> V Errors Int
|
|
||||||
validate_priority str_priority
|
|
||||||
= is_int str_priority !> right_range
|
|
||||||
where
|
|
||||||
is_int = validate_integer Priority
|
|
||||||
right_range = intBetween Priority min_priority max_priority
|
|
||||||
|
|
||||||
validate_protocol :: String -> V Errors String
|
|
||||||
validate_protocol protocol
|
|
||||||
= verify_length protocol !> verify_regex Protocol protocol_format
|
|
||||||
where
|
|
||||||
verify_length = lengthIsBetween Protocol protocol_min_len protocol_max_len
|
|
||||||
|
|
||||||
validate_weight :: String -> V Errors Int
|
|
||||||
validate_weight str_weight
|
|
||||||
= is_int str_weight !> right_range
|
|
||||||
where
|
|
||||||
is_int = validate_integer Weight
|
|
||||||
right_range = intBetween Weight min_weight max_weight
|
|
||||||
|
|
||||||
validate_port :: String -> V Errors Int
|
|
||||||
validate_port str_port
|
|
||||||
= is_int str_port !> right_range
|
|
||||||
where
|
|
||||||
is_int = validate_integer Port
|
|
||||||
right_range = intBetween Port min_port max_port
|
|
||||||
|
|
||||||
validate_target_A :: String -> V Errors String
|
|
||||||
validate_target_A target
|
|
||||||
= verify_length target !> verify_format
|
|
||||||
where
|
|
||||||
verify_length = lengthIsBetween Target target_min_len target_max_len
|
|
||||||
verify_format = verify_ipv4 Target
|
|
||||||
|
|
||||||
validate_target_AAAA :: String -> V Errors String
|
|
||||||
validate_target_AAAA target
|
|
||||||
= verify_length target !> verify_format
|
|
||||||
where
|
|
||||||
verify_length = lengthIsBetween Target target_min_len target_max_len
|
|
||||||
verify_format = verify_ipv6 Target
|
|
||||||
|
|
||||||
validate_target_TXT :: String -> V Errors String
|
|
||||||
validate_target_TXT target
|
|
||||||
= verify_length target
|
|
||||||
where
|
|
||||||
verify_length = lengthIsBetween Target target_min_len target_TXT_max_len
|
|
||||||
|
|
||||||
validate_target_CNAME :: String -> V Errors String
|
|
||||||
validate_target_CNAME target
|
|
||||||
= verify_length target
|
|
||||||
where
|
|
||||||
verify_length = lengthIsBetween Target target_min_len target_max_len
|
|
||||||
|
|
||||||
validate_target_NS :: String -> V Errors String
|
|
||||||
validate_target_NS target
|
|
||||||
= verify_length target !> verify_domain Target
|
|
||||||
where
|
|
||||||
verify_length = lengthIsBetween Target target_min_len target_max_len
|
|
||||||
|
|
||||||
validate_target_MX :: String -> V Errors String
|
|
||||||
validate_target_MX target
|
|
||||||
= verify_length target !> verify_domain Target
|
|
||||||
where
|
|
||||||
verify_length = lengthIsBetween Target target_min_len target_max_len
|
|
||||||
|
|
||||||
validate_target_SRV :: String -> V Errors String
|
|
||||||
validate_target_SRV target
|
|
||||||
= verify_length target !> verify_domain Target
|
|
||||||
where
|
|
||||||
verify_length = lengthIsBetween Target target_min_len target_max_len
|
|
||||||
|
|
||||||
-- Resource-related validations.
|
|
||||||
|
|
||||||
validateA :: forall l. SimpleRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateA form = ado
|
|
||||||
name <- validate_name form.name
|
|
||||||
ttl <- validate_ttl form.ttl
|
|
||||||
target <- validate_target_A form.target
|
|
||||||
in toRR_basic form.rrid form.readonly "A" name ttl target
|
|
||||||
|
|
||||||
validateAAAA :: forall l. SimpleRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateAAAA form = ado
|
|
||||||
name <- validate_name form.name
|
|
||||||
ttl <- validate_ttl form.ttl
|
|
||||||
target <- validate_target_AAAA form.target
|
|
||||||
in toRR_basic form.rrid form.readonly "AAAA" name ttl target
|
|
||||||
|
|
||||||
validateTXT :: forall l. SimpleRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateTXT form = ado
|
|
||||||
name <- validate_name form.name
|
|
||||||
ttl <- validate_ttl form.ttl
|
|
||||||
target <- validate_target_TXT form.target
|
|
||||||
in toRR_basic form.rrid form.readonly "TXT" name ttl target
|
|
||||||
|
|
||||||
validateCNAME :: forall l. SimpleRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateCNAME form = ado
|
|
||||||
name <- validate_name form.name
|
|
||||||
ttl <- validate_ttl form.ttl
|
|
||||||
target <- validate_target_CNAME form.target
|
|
||||||
in toRR_basic form.rrid form.readonly "CNAME" name ttl target
|
|
||||||
|
|
||||||
validateNS :: forall l. SimpleRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateNS form = ado
|
|
||||||
name <- validate_name form.name
|
|
||||||
ttl <- validate_ttl form.ttl
|
|
||||||
target <- validate_target_NS form.target
|
|
||||||
in toRR_basic form.rrid form.readonly "NS" name ttl target
|
|
||||||
|
|
||||||
validateSRR_ :: forall l. SimpleRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateSRR_ form = case form.rrtype of
|
|
||||||
"A" -> validateA form
|
|
||||||
"AAAA" -> validateAAAA form
|
|
||||||
"TXT" -> validateTXT form
|
|
||||||
"CNAME" -> validateCNAME form
|
|
||||||
"NS" -> validateNS form
|
|
||||||
_ -> invalid [Tuple NotAnAttribute $ "invalid type: " <> form.rrtype]
|
|
||||||
|
|
||||||
validateMX :: forall l. MXRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateMX form = ado
|
|
||||||
name <- validate_name form.name
|
|
||||||
ttl <- validate_ttl form.ttl
|
|
||||||
target <- validate_target_MX form.target
|
|
||||||
priority <- validate_priority form.priority
|
|
||||||
in toRR_mx form.rrid form.readonly "MX" name ttl target priority
|
|
||||||
|
|
||||||
validateMXRR_ :: forall l. MXRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateMXRR_ form = case form.rrtype of
|
|
||||||
"MX" -> validateMX form
|
|
||||||
_ -> invalid [Tuple NotAnAttribute $ "invalid type (expected: MX): " <> form.rrtype]
|
|
||||||
|
|
||||||
validateSRV :: forall l. SRVRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateSRV form = ado
|
|
||||||
name <- validate_name form.name
|
|
||||||
ttl <- validate_ttl form.ttl
|
|
||||||
target <- validate_target_SRV form.target
|
|
||||||
priority <- validate_priority form.priority
|
|
||||||
protocol <- validate_protocol form.protocol
|
|
||||||
weight <- validate_weight form.weight
|
|
||||||
port <- validate_port form.port
|
|
||||||
in toRR_srv form.rrid form.readonly "SRV" name ttl target priority port protocol weight
|
|
||||||
|
|
||||||
validateSRVRR_ :: forall l. SRVRR (|l) -> V Errors ResourceRecord
|
|
||||||
validateSRVRR_ form = case form.rrtype of
|
|
||||||
"SRV" -> validateSRV form
|
|
||||||
_ -> invalid [Tuple NotAnAttribute $ "invalid type (expected: SRV): " <> form.rrtype]
|
|
||||||
|
|
||||||
validateSRR :: forall l. SimpleRR (|l) -> Either Errors ResourceRecord
|
|
||||||
validateSRR = toEither <<< validateSRR_
|
|
||||||
|
|
||||||
validateMXRR :: forall l. MXRR (|l) -> Either Errors ResourceRecord
|
|
||||||
validateMXRR = toEither <<< validateMXRR_
|
|
||||||
|
|
||||||
validateSRVRR :: forall l. SRVRR (|l) -> Either Errors ResourceRecord
|
|
||||||
validateSRVRR = toEither <<< validateSRVRR_
|
|
||||||
|
|
||||||
|
|
||||||
-- Full zone validations.
|
|
||||||
|
|
||||||
-- type ZoneErrors = Array (Tuple Errors RRId)
|
|
||||||
-- type Zone l = String -> Array (SimpleRR (|l)) -> Array (MXRR (|l)) -> Array (SRVRR (|l))
|
|
||||||
|
|
||||||
-- validateZone :: forall l. Zone l -> Either Errors
|
|
||||||
|
|
||||||
-- Functions handling network-related structures (ResourceRecord).
|
-- Functions handling network-related structures (ResourceRecord).
|
||||||
|
|
||||||
|
@ -441,16 +142,6 @@ toRR_srv rrid readonly rrtype rrname ttl target priority port protocol weight
|
||||||
= toRR rrid readonly rrtype rrname ttl target (Just priority) (Just port) (Just protocol) (Just weight)
|
= toRR rrid readonly rrtype rrname ttl target (Just priority) (Just port) (Just protocol) (Just weight)
|
||||||
Nothing Nothing Nothing Nothing Nothing Nothing Nothing
|
Nothing Nothing Nothing Nothing Nothing Nothing Nothing
|
||||||
|
|
||||||
data TTLError
|
|
||||||
= TTLNotInt
|
|
||||||
| TTLNotBetween Int Int Int -- min max value
|
|
||||||
ttl_parser :: G.Parser TTLError Int
|
|
||||||
ttl_parser = do pos <- G.current_position
|
|
||||||
n <- SomeParsers.nat <|> G.Parser \_ -> G.failureError pos (Just TTLNotInt)
|
|
||||||
if between min_ttl max_ttl n
|
|
||||||
then pure n
|
|
||||||
else G.Parser \_ -> G.failureError pos (Just $ TTLNotBetween min_ttl max_ttl n)
|
|
||||||
|
|
||||||
data TXTError
|
data TXTError
|
||||||
= TXTInvalidCharacter
|
= TXTInvalidCharacter
|
||||||
| TXTTooLong Int Int -- max current
|
| TXTTooLong Int Int -- max current
|
||||||
|
@ -511,18 +202,6 @@ validationNS form = ado
|
||||||
target <- parse DomainParser.sub_eof form.target VENS
|
target <- parse DomainParser.sub_eof form.target VENS
|
||||||
in toRR_basic form.rrid form.readonly "NS" name ttl target
|
in toRR_basic form.rrid form.readonly "NS" name ttl target
|
||||||
|
|
||||||
data PriorityError
|
|
||||||
= PriorityNotInt
|
|
||||||
| PriorityNotBetween Int Int Int -- min max value
|
|
||||||
|
|
||||||
priority_parser :: G.Parser PriorityError Int
|
|
||||||
priority_parser = do
|
|
||||||
pos <- G.current_position
|
|
||||||
n <- SomeParsers.nat <|> G.Parser \_ -> G.failureError pos (Just PriorityNotInt)
|
|
||||||
if between min_priority max_priority n
|
|
||||||
then pure n
|
|
||||||
else G.Parser \_ -> G.failureError pos (Just $ PriorityNotBetween min_priority max_priority n)
|
|
||||||
|
|
||||||
data ProtocolError
|
data ProtocolError
|
||||||
= InvalidProtocol
|
= InvalidProtocol
|
||||||
|
|
||||||
|
@ -531,35 +210,11 @@ protocol_parser = do
|
||||||
pos <- G.current_position
|
pos <- G.current_position
|
||||||
G.string "tcp" <|> G.string "udp" <|> G.Parser \_ -> G.failureError pos (Just InvalidProtocol)
|
G.string "tcp" <|> G.string "udp" <|> G.Parser \_ -> G.failureError pos (Just InvalidProtocol)
|
||||||
|
|
||||||
data PortError
|
|
||||||
= PortNotInt
|
|
||||||
| PortNotBetween Int Int Int -- min max value
|
|
||||||
|
|
||||||
port_parser :: G.Parser PortError Int
|
|
||||||
port_parser = do
|
|
||||||
pos <- G.current_position
|
|
||||||
n <- SomeParsers.nat <|> G.Parser \_ -> G.failureError pos (Just PortNotInt)
|
|
||||||
if between min_port max_port n
|
|
||||||
then pure n
|
|
||||||
else G.Parser \_ -> G.failureError pos (Just $ PortNotBetween min_port max_port n)
|
|
||||||
|
|
||||||
data WeightError
|
|
||||||
= WeightNotInt
|
|
||||||
| WeightNotBetween Int Int Int -- min max value
|
|
||||||
|
|
||||||
is_between :: Int -> Int -> Int -> (Int -> Int -> Int -> ValidationError) -> V AVErrors Int
|
is_between :: Int -> Int -> Int -> (Int -> Int -> Int -> ValidationError) -> V AVErrors Int
|
||||||
is_between min max n ve = if between min max n
|
is_between min max n ve = if between min max n
|
||||||
then pure n
|
then pure n
|
||||||
else invalid [ve min max n]
|
else invalid [ve min max n]
|
||||||
|
|
||||||
weight_parser :: G.Parser WeightError Int
|
|
||||||
weight_parser = do
|
|
||||||
pos <- G.current_position
|
|
||||||
n <- SomeParsers.nat <|> G.Parser \_ -> G.failureError pos (Just WeightNotInt)
|
|
||||||
if between min_weight max_weight n
|
|
||||||
then pure n
|
|
||||||
else G.Parser \_ -> G.failureError pos (Just $ WeightNotBetween min_weight max_weight n)
|
|
||||||
|
|
||||||
validationMX :: ResourceRecord -> V AVErrors ResourceRecord
|
validationMX :: ResourceRecord -> V AVErrors ResourceRecord
|
||||||
validationMX form = ado
|
validationMX form = ado
|
||||||
name <- parse DomainParser.sub_eof form.name VEName
|
name <- parse DomainParser.sub_eof form.name VEName
|
||||||
|
|
|
@ -23,22 +23,17 @@ module App.ZoneInterface where
|
||||||
|
|
||||||
import Prelude (Unit, unit, void
|
import Prelude (Unit, unit, void
|
||||||
, bind, pure
|
, bind, pure
|
||||||
, comparing, discard, map, max, otherwise, show
|
, comparing, discard, map, show
|
||||||
, ($), (+), (/=), (<<<), (<>), (==), (>))
|
, ($), (/=), (<<<), (<>), (==), (>))
|
||||||
|
|
||||||
import Data.HashMap as Hash
|
--import Data.HashMap as Hash
|
||||||
import Data.Array as A
|
import Data.Array as A
|
||||||
import Data.Int (fromString)
|
import Data.Int (fromString)
|
||||||
import Data.Tuple (Tuple(..))
|
|
||||||
import Data.ArrayBuffer.Types (ArrayBuffer)
|
import Data.ArrayBuffer.Types (ArrayBuffer)
|
||||||
import Data.Array.NonEmpty as NonEmpty
|
import Data.Array.NonEmpty as NonEmpty
|
||||||
import Data.Either (Either(..))
|
import Data.Either (Either(..))
|
||||||
import Data.Foldable as Foldable
|
import Data.Foldable as Foldable
|
||||||
import Data.Maybe (Maybe(..), fromMaybe, maybe)
|
import Data.Maybe (Maybe(..), fromMaybe, maybe)
|
||||||
import Data.String as S
|
|
||||||
import Data.String.Regex as Regex
|
|
||||||
import Data.String.Regex.Flags as RegexFlags
|
|
||||||
import Data.String.Regex.Unsafe as RegexUnsafe
|
|
||||||
import Effect.Aff.Class (class MonadAff)
|
import Effect.Aff.Class (class MonadAff)
|
||||||
import Halogen as H
|
import Halogen as H
|
||||||
import Halogen.HTML as HH
|
import Halogen.HTML as HH
|
||||||
|
@ -49,8 +44,6 @@ import Bulma as Bulma
|
||||||
import CSSClasses as C
|
import CSSClasses as C
|
||||||
|
|
||||||
import App.AcceptedRRTypes (AcceptedRRTypes(..))
|
import App.AcceptedRRTypes (AcceptedRRTypes(..))
|
||||||
import App.RR (MXRR, Port, Priority, Protocol, RRId, RecordName, RecordTarget, SOARR, SRVRR, SimpleRR, TTL, Weight
|
|
||||||
, defaultResourceA, defaultResourceMX, defaultResourceSRV)
|
|
||||||
import App.ResourceRecord (ResourceRecord)
|
import App.ResourceRecord (ResourceRecord)
|
||||||
|
|
||||||
import App.LogMessage (LogMessage(..))
|
import App.LogMessage (LogMessage(..))
|
||||||
|
@ -60,6 +53,7 @@ import GenericParser.DomainParser.Common (DomainError(..)) as DomainParser
|
||||||
-- import GenericParser.DomainParser as DomainParser
|
-- import GenericParser.DomainParser as DomainParser
|
||||||
import GenericParser.IPAddress as IPAddress
|
import GenericParser.IPAddress as IPAddress
|
||||||
|
|
||||||
|
type RRId = Int
|
||||||
|
|
||||||
id :: forall a. a -> a
|
id :: forall a. a -> a
|
||||||
id x = x
|
id x = x
|
||||||
|
@ -90,38 +84,13 @@ type Slot = H.Slot Query Output
|
||||||
type Input = String
|
type Input = String
|
||||||
|
|
||||||
data Field
|
data Field
|
||||||
= Field_Domain RecordName
|
= Field_Domain String
|
||||||
| Field_TTL TTL
|
| Field_TTL String
|
||||||
| Field_Target RecordTarget
|
| Field_Target String
|
||||||
| Field_Priority Priority
|
| Field_Priority String
|
||||||
| Field_Protocol Protocol
|
| Field_Protocol String
|
||||||
| Field_Weight Weight
|
| Field_Weight String
|
||||||
| Field_Port Port
|
| Field_Port String
|
||||||
|
|
||||||
data Update_SRR_Form
|
|
||||||
= Update_SRR_Domain RecordName
|
|
||||||
| Update_SRR_TTL TTL
|
|
||||||
| Update_SRR_Target RecordTarget
|
|
||||||
|
|
||||||
data Update_MX_Form
|
|
||||||
= Update_MX_Domain RecordName
|
|
||||||
| Update_MX_TTL TTL
|
|
||||||
| Update_MX_Target RecordTarget
|
|
||||||
| Update_MX_Priority Priority
|
|
||||||
|
|
||||||
data Update_SRV_Form
|
|
||||||
= Update_SRV_Domain RecordName
|
|
||||||
| Update_SRV_TTL TTL
|
|
||||||
| Update_SRV_Target RecordTarget
|
|
||||||
| Update_SRV_Priority Priority
|
|
||||||
| Update_SRV_Protocol Protocol
|
|
||||||
| Update_SRV_Weight Weight
|
|
||||||
| Update_SRV_Port Port
|
|
||||||
|
|
||||||
data Update_Local_Form
|
|
||||||
= Update_Local_Form_SRR Update_SRR_Form
|
|
||||||
| Update_Local_Form_MXRR Update_MX_Form
|
|
||||||
| Update_Local_Form_SRVRR Update_SRV_Form
|
|
||||||
|
|
||||||
-- | Steps to create a new RR:
|
-- | Steps to create a new RR:
|
||||||
-- | 1. `CreateNewRRModal AcceptedRRTypes`: create a modal with default values based on selected accepted type.
|
-- | 1. `CreateNewRRModal AcceptedRRTypes`: create a modal with default values based on selected accepted type.
|
||||||
|
@ -140,8 +109,8 @@ data Update_Local_Form
|
||||||
-- | In both cases, once the add (or update) is performed, the resource should be added (updated) in `_resources`.
|
-- | In both cases, once the add (or update) is performed, the resource should be added (updated) in `_resources`.
|
||||||
|
|
||||||
data Action
|
data Action
|
||||||
-- | Create a modal to ask confirmation before deleting a resource record.
|
-- | Initiate the component. This means asking the content of the zone to `dnsmanagerd`.
|
||||||
= DeleteRRModal RRId
|
= Initialize
|
||||||
|
|
||||||
-- | Cancel the current displayed modal.
|
-- | Cancel the current displayed modal.
|
||||||
| CancelModal
|
| CancelModal
|
||||||
|
@ -152,11 +121,11 @@ data Action
|
||||||
-- | Create modal (a form) for a resource record to update.
|
-- | Create modal (a form) for a resource record to update.
|
||||||
| CreateUpdateRRModal RRId
|
| CreateUpdateRRModal RRId
|
||||||
|
|
||||||
-- | Initiate the component. This means asking the content of the zone to `dnsmanagerd`.
|
-- | Create a modal to ask confirmation before deleting a resource record.
|
||||||
| Initialize
|
| DeleteRRModal RRId
|
||||||
|
|
||||||
-- | Add a new resource record to the zone.
|
-- | Update new entry form (in the `rr_modal` modal).
|
||||||
| AddRR AcceptedRRTypes ResourceRecord
|
| UpdateCurrentRR Field
|
||||||
|
|
||||||
-- | Validate a new resource record before adding it.
|
-- | Validate a new resource record before adding it.
|
||||||
| ValidateRR AcceptedRRTypes
|
| ValidateRR AcceptedRRTypes
|
||||||
|
@ -165,26 +134,18 @@ data Action
|
||||||
-- | Automatically calls for `SaveRR` once record is verified.
|
-- | Automatically calls for `SaveRR` once record is verified.
|
||||||
| ValidateLocal
|
| ValidateLocal
|
||||||
|
|
||||||
|
-- | Add a new resource record to the zone.
|
||||||
|
| AddRR AcceptedRRTypes ResourceRecord
|
||||||
|
|
||||||
-- | Save the changes done in an already existing resource record.
|
-- | Save the changes done in an already existing resource record.
|
||||||
| SaveRR ResourceRecord
|
| SaveRR ResourceRecord
|
||||||
|
|
||||||
-- | Update new entry form (in the `rr_modal` modal).
|
-- | Send a message to remove a resource record.
|
||||||
| UpdateCurrentRR Field
|
-- | Automatically closes the modal.
|
||||||
|
|
||||||
-- | TODO: OLD: Update an already active entry.
|
|
||||||
| UpdateLocalRR RRId Update_Local_Form
|
|
||||||
|
|
||||||
-- TODO: OLD: Update an already existing resource record (update _resources).
|
|
||||||
| SaveSRR RRId
|
|
||||||
| SaveMXRR RRId
|
|
||||||
| SaveSRVRR RRId
|
|
||||||
|
|
||||||
| RemoveRR RRId
|
| RemoveRR RRId
|
||||||
|
|
||||||
| TellSomethingWentWrong RRId String
|
| TellSomethingWentWrong RRId String
|
||||||
|
|
||||||
-- |
|
|
||||||
|
|
||||||
data RRModal
|
data RRModal
|
||||||
= NoModal
|
= NoModal
|
||||||
| NewRRModal AcceptedRRTypes
|
| NewRRModal AcceptedRRTypes
|
||||||
|
@ -213,35 +174,19 @@ string_to_acceptedtype str = case str of
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
type State =
|
type State =
|
||||||
{ _domain :: RecordName
|
{ _domain :: String
|
||||||
, wsUp :: Boolean
|
, wsUp :: Boolean
|
||||||
|
|
||||||
-- A modal to present a form for adding a new RR.
|
-- A modal to present a form for adding a new RR.
|
||||||
, rr_modal :: RRModal
|
, rr_modal :: RRModal
|
||||||
|
|
||||||
-- TODO: get all the resources in a single entry.
|
-- | All resource records.
|
||||||
-- Better that way: simpler code.
|
|
||||||
, _resources :: Array ResourceRecord
|
, _resources :: Array ResourceRecord
|
||||||
, _local_errors :: Hash.HashMap RRId (Array Validation.ValidationError)
|
--, _local_errors :: Hash.HashMap RRId (Array Validation.ValidationError)
|
||||||
|
|
||||||
-- current entries
|
|
||||||
, _soa :: Maybe (SOARR ())
|
|
||||||
, _srr :: Array (SimpleRR ())
|
|
||||||
, _mxrr :: Array (MXRR ())
|
|
||||||
, _srvrr :: Array (SRVRR ())
|
|
||||||
, _errors :: Hash.HashMap RRId Validation.Errors
|
|
||||||
|
|
||||||
-- Unique RR form.
|
-- Unique RR form.
|
||||||
, _currentRR :: ResourceRecord
|
, _currentRR :: ResourceRecord
|
||||||
, _currentRR_errors :: Array Validation.ValidationError
|
, _currentRR_errors :: Array Validation.ValidationError
|
||||||
|
|
||||||
-- potential future entries
|
|
||||||
, _newSRR :: (SimpleRR ())
|
|
||||||
, _newMXRR :: (MXRR ())
|
|
||||||
, _newSRVRR :: (SRVRR ())
|
|
||||||
, _newSRR_errors :: Hash.HashMap RRId Validation.Errors
|
|
||||||
, _newMXRR_errors :: Hash.HashMap RRId Validation.Errors
|
|
||||||
, _newSRVRR_errors :: Hash.HashMap RRId Validation.Errors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
component :: forall m. MonadAff m => H.Component Query Input Output m
|
component :: forall m. MonadAff m => H.Component Query Input Output m
|
||||||
|
@ -296,25 +241,12 @@ initialState domain =
|
||||||
, _domain: domain
|
, _domain: domain
|
||||||
|
|
||||||
, _resources: []
|
, _resources: []
|
||||||
, _local_errors: Hash.empty
|
--, _local_errors: Hash.empty
|
||||||
|
|
||||||
, _soa: Nothing
|
|
||||||
, _srr: []
|
|
||||||
, _mxrr: []
|
|
||||||
, _srvrr: []
|
|
||||||
, _errors: Hash.empty
|
|
||||||
|
|
||||||
-- This is the state for the new RR modal.
|
-- This is the state for the new RR modal.
|
||||||
, _currentRR: default_empty_rr
|
, _currentRR: default_empty_rr
|
||||||
-- List of errors within the form in new RR modal.
|
-- List of errors within the form in new RR modal.
|
||||||
, _currentRR_errors: []
|
, _currentRR_errors: []
|
||||||
|
|
||||||
, _newSRR: defaultResourceA
|
|
||||||
, _newMXRR: defaultResourceMX
|
|
||||||
, _newSRVRR: defaultResourceSRV
|
|
||||||
, _newSRR_errors: Hash.empty
|
|
||||||
, _newMXRR_errors: Hash.empty
|
|
||||||
, _newSRVRR_errors: Hash.empty
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type SortableRecord l = Record (rrtype :: String, rrid :: Int | l)
|
type SortableRecord l = Record (rrtype :: String, rrid :: Int | l)
|
||||||
|
@ -330,12 +262,8 @@ render state
|
||||||
true, NoModal -> HH.div_
|
true, NoModal -> HH.div_
|
||||||
[ Bulma.h1 state._domain
|
[ Bulma.h1 state._domain
|
||||||
, Bulma.hr
|
, Bulma.hr
|
||||||
, render_resources state._local_errors $ sorted state._resources
|
, render_resources $ sorted state._resources
|
||||||
, Bulma.hr
|
, Bulma.hr
|
||||||
, render_soa state._soa
|
|
||||||
, render_records state._errors $ sorted state._srr
|
|
||||||
, render_mx_records state._errors $ sorted state._mxrr
|
|
||||||
, render_srv_records state._errors $ sorted state._srvrr
|
|
||||||
, render_new_records state
|
, render_new_records state
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
@ -679,86 +607,6 @@ handleAction = case _ of
|
||||||
let newRR = update_field state._currentRR field
|
let newRR = update_field state._currentRR field
|
||||||
H.modify_ _ { _currentRR = newRR }
|
H.modify_ _ { _currentRR = newRR }
|
||||||
|
|
||||||
-- TODO: this code can be used to replace the old RR with the updated one, once received by `dnsmanagerd`.
|
|
||||||
-- Update_Current_RR rr_id field -> do
|
|
||||||
-- state <- H.get
|
|
||||||
-- H.raise $ Log $ SimpleLog $ "Let's try to update entry number " <> show rr_id
|
|
||||||
-- let replaceRR rr1 rr2 | rr1.rrid == rr2.rrid = rr1
|
|
||||||
-- | otherwise = rr2
|
|
||||||
-- maybeentry = first (\rr -> rr.rrid == rr_id) state._resources
|
|
||||||
-- case maybeentry of
|
|
||||||
-- Nothing -> H.raise $ Log $ SimpleLog ("Local Update Failed (RR " <> show rr_id <> ")")
|
|
||||||
-- Just entry -> do
|
|
||||||
-- let new_entry = update_field entry field
|
|
||||||
-- H.modify_ _ { _resources = (map (replaceRR entry) state._resources) }
|
|
||||||
|
|
||||||
UpdateLocalRR rr_id form -> case form of
|
|
||||||
Update_Local_Form_SRR rr_update -> case rr_update of
|
|
||||||
Update_SRR_Domain val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local RR " <> show rr_id <> " name: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srr = (update_domain rr_id val state._srr) }
|
|
||||||
Update_SRR_TTL val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local RR " <> show rr_id <> " TTL: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srr = (update_ttl rr_id val state._srr) }
|
|
||||||
Update_SRR_Target val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local RR " <> show rr_id <> " target: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srr = (update_target rr_id val state._srr) }
|
|
||||||
|
|
||||||
Update_Local_Form_MXRR rr_update -> case rr_update of
|
|
||||||
-- TODO: FIXME: test all inputs
|
|
||||||
Update_MX_Domain val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local MX RR " <> show rr_id <> " name: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _mxrr = (update_domain rr_id val state._mxrr) }
|
|
||||||
-- TODO: FIXME: test all inputs
|
|
||||||
Update_MX_TTL val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local MX " <> show rr_id <> " entry ttl: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _mxrr = (update_ttl rr_id val state._mxrr) }
|
|
||||||
-- TODO: FIXME: test all inputs
|
|
||||||
Update_MX_Target val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local MX " <> show rr_id <> " entry target: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _mxrr = (update_target rr_id val state._mxrr) }
|
|
||||||
Update_MX_Priority val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local MX " <> show rr_id <> " entry priority: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _mxrr = (update_priority rr_id val state._mxrr) }
|
|
||||||
|
|
||||||
Update_Local_Form_SRVRR rr_update -> case rr_update of
|
|
||||||
Update_SRV_Domain val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local SRV " <> show rr_id <> " entry name: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srvrr = (update_domain rr_id val state._srvrr) }
|
|
||||||
Update_SRV_Target val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local SRV " <> show rr_id <> " entry target: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srvrr = (update_target rr_id val state._srvrr) }
|
|
||||||
-- TODO: FIXME: test all inputs
|
|
||||||
Update_SRV_TTL val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local SRV " <> show rr_id <> " entry ttl: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srvrr = (update_ttl rr_id val state._srvrr) }
|
|
||||||
Update_SRV_Priority val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local SRV " <> show rr_id <> " entry priority: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srvrr = (update_priority rr_id val state._srvrr) }
|
|
||||||
Update_SRV_Protocol val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update new SRV entry protocol: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srvrr = (update_protocol rr_id val state._srvrr) }
|
|
||||||
Update_SRV_Weight val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local SRV " <> show rr_id <> " entry weight: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srvrr = (update_weight rr_id val state._srvrr) }
|
|
||||||
Update_SRV_Port val -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog ("Update local SRV " <> show rr_id <> " entry port: " <> val)
|
|
||||||
state <- H.get
|
|
||||||
H.modify_ _ { _srvrr = (update_port rr_id val state._srvrr) }
|
|
||||||
|
|
||||||
-- | Validate any local RR with the new `_resources` and `_local_errors`.
|
-- | Validate any local RR with the new `_resources` and `_local_errors`.
|
||||||
ValidateLocal -> do
|
ValidateLocal -> do
|
||||||
state <- H.get
|
state <- H.get
|
||||||
|
@ -779,21 +627,6 @@ handleAction = case _ of
|
||||||
$ DNSManager.MkUpdateRR { domain: state._domain, rr: rr }
|
$ DNSManager.MkUpdateRR { domain: state._domain, rr: rr }
|
||||||
H.raise $ MessageToSend message
|
H.raise $ MessageToSend message
|
||||||
|
|
||||||
SaveSRR local_rr_id -> do
|
|
||||||
state <- H.get
|
|
||||||
let maybe_local_rr = first (\rr -> rr.rrid == local_rr_id) state._srr
|
|
||||||
try_update_entry state._domain Validation.validateSRR maybe_local_rr "simple"
|
|
||||||
|
|
||||||
SaveMXRR local_rr_id -> do
|
|
||||||
state <- H.get
|
|
||||||
let maybe_local_rr = first (\rr -> rr.rrid == local_rr_id) state._mxrr
|
|
||||||
try_update_entry state._domain Validation.validateMXRR maybe_local_rr "MX"
|
|
||||||
|
|
||||||
SaveSRVRR local_rr_id -> do
|
|
||||||
state <- H.get
|
|
||||||
let maybe_local_rr = first (\rr -> rr.rrid == local_rr_id) state._srvrr
|
|
||||||
try_update_entry state._domain Validation.validateSRVRR maybe_local_rr "SRV"
|
|
||||||
|
|
||||||
RemoveRR rr_id -> do
|
RemoveRR rr_id -> do
|
||||||
{ _domain } <- H.get
|
{ _domain } <- H.get
|
||||||
H.raise $ Log $ SimpleLog $ "Ask to remove rr (rrid: " <> show rr_id <> ")"
|
H.raise $ Log $ SimpleLog $ "Ask to remove rr (rrid: " <> show rr_id <> ")"
|
||||||
|
@ -811,33 +644,6 @@ handleAction = case _ of
|
||||||
-- H.raise $ Log $ SimpleLog (show rr)
|
-- H.raise $ Log $ SimpleLog (show rr)
|
||||||
H.raise $ Log $ SimpleLog (" => " <> val)
|
H.raise $ Log $ SimpleLog (" => " <> val)
|
||||||
|
|
||||||
where
|
|
||||||
try_update_entry :: forall r
|
|
||||||
. String
|
|
||||||
-> (AtLeastRRID r -> Either Validation.Errors ResourceRecord)
|
|
||||||
-> Maybe (AtLeastRRID r)
|
|
||||||
-> String
|
|
||||||
-> H.HalogenM State Action () Output m Unit
|
|
||||||
try_update_entry d validation v t = case v of
|
|
||||||
Nothing -> H.raise $ Log $ SimpleLog $ "Cannot find " <> t <> " RR with this rrid"
|
|
||||||
Just local_rr -> do
|
|
||||||
state <- H.get
|
|
||||||
case validation local_rr of
|
|
||||||
Left validation_errors -> do
|
|
||||||
let new_error_hash = Hash.insert local_rr.rrid validation_errors state._errors
|
|
||||||
H.modify_ _ { _errors = new_error_hash }
|
|
||||||
H.raise $ Log $ SimpleLog $ "[😈] Errors in "
|
|
||||||
<> t
|
|
||||||
<> " RR! Please fix them before update."
|
|
||||||
Right rr -> do
|
|
||||||
-- H.raise $ Log $ SimpleLog $ "Save " <> t <> " RR"
|
|
||||||
let new_error_hash = Hash.delete local_rr.rrid state._errors
|
|
||||||
H.modify_ _ { _errors = new_error_hash }
|
|
||||||
message <- H.liftEffect
|
|
||||||
$ DNSManager.serialize
|
|
||||||
$ DNSManager.MkUpdateRR { domain: d, rr: rr }
|
|
||||||
H.raise $ MessageToSend message
|
|
||||||
|
|
||||||
type AtLeastRRID r = { rrid :: Int | r }
|
type AtLeastRRID r = { rrid :: Int | r }
|
||||||
|
|
||||||
handleQuery :: forall a m. MonadAff m => Query a -> H.HalogenM State Action () Output m (Maybe a)
|
handleQuery :: forall a m. MonadAff m => Query a -> H.HalogenM State Action () Output m (Maybe a)
|
||||||
|
@ -852,23 +658,11 @@ handleQuery = case _ of
|
||||||
H.modify_ _ { rr_modal = NoModal }
|
H.modify_ _ { rr_modal = NoModal }
|
||||||
(DNSManager.MkRRAdded response) -> do
|
(DNSManager.MkRRAdded response) -> do
|
||||||
state <- H.get
|
state <- H.get
|
||||||
let new_rr = response.rr
|
H.put $ add_RR state response.rr
|
||||||
case add_entry state new_rr of
|
|
||||||
Left error_message -> H.raise $ Log $ SimpleLog $ "Error while adding new entry: " <> error_message
|
|
||||||
Right new_state -> H.put new_state
|
|
||||||
nstate <- H.get
|
|
||||||
H.put $ add_RR nstate new_rr
|
|
||||||
(DNSManager.MkRRDeleted response) -> do
|
(DNSManager.MkRRDeleted response) -> do
|
||||||
-- Remove the resource record.
|
-- Remove the resource record.
|
||||||
state <- H.get
|
state <- H.get
|
||||||
H.modify_ _ { _srr = A.filter (\rr -> rr.rrid /= response.rrid) state._srr
|
H.modify_ _ { _resources = A.filter (\rr -> rr.rrid /= response.rrid) state._resources }
|
||||||
, _mxrr = A.filter (\rr -> rr.rrid /= response.rrid) state._mxrr
|
|
||||||
, _srvrr = A.filter (\rr -> rr.rrid /= response.rrid) state._srvrr
|
|
||||||
, _resources = A.filter (\rr -> rr.rrid /= response.rrid) state._resources
|
|
||||||
}
|
|
||||||
-- Remove its possible errors.
|
|
||||||
let new_error_hash = Hash.delete response.rrid state._errors
|
|
||||||
H.modify_ _ { _errors = new_error_hash }
|
|
||||||
(DNSManager.MkZone response) -> do
|
(DNSManager.MkZone response) -> do
|
||||||
add_entries response.zone.resources
|
add_entries response.zone.resources
|
||||||
|
|
||||||
|
@ -884,54 +678,34 @@ handleQuery = case _ of
|
||||||
pure (Just a)
|
pure (Just a)
|
||||||
|
|
||||||
where
|
where
|
||||||
-- replace_entry :: RRId
|
-- replace_entry :: ResourceRecord
|
||||||
replace_entry new_rr = do
|
replace_entry new_rr = do
|
||||||
state <- H.get
|
state <- H.get
|
||||||
H.modify_ _ { _srr = A.filter (\rr -> rr.rrid /= new_rr.rrid) state._srr
|
H.modify_ _ { _resources = A.filter (\rr -> rr.rrid /= new_rr.rrid) state._resources }
|
||||||
, _mxrr = A.filter (\rr -> rr.rrid /= new_rr.rrid) state._mxrr
|
|
||||||
, _srvrr = A.filter (\rr -> rr.rrid /= new_rr.rrid) state._srvrr
|
|
||||||
, _resources = A.filter (\rr -> rr.rrid /= new_rr.rrid) state._resources
|
|
||||||
}
|
|
||||||
|
|
||||||
new_state <- H.get
|
new_state <- H.get
|
||||||
case add_entry new_state new_rr of
|
H.put $ add_RR new_state new_rr
|
||||||
Left errmsg -> H.raise $ Log $ SimpleLog $ "Error while replacing a resource record: " <> errmsg
|
|
||||||
Right s -> H.put s
|
|
||||||
new_state2 <- H.get
|
|
||||||
H.put $ add_RR new_state2 new_rr
|
|
||||||
H.raise $ Log $ SimpleLog $ "Replacing a resource record! Should be visible everywhere!"
|
H.raise $ Log $ SimpleLog $ "Replacing a resource record! Should be visible everywhere!"
|
||||||
|
|
||||||
add_entries [] = H.raise $ Log $ SimpleLog "[🎉] Zone fully loaded!"
|
add_entries [] = H.raise $ Log $ SimpleLog "[🎉] Zone fully loaded!"
|
||||||
add_entries arr = do
|
add_entries arr = do
|
||||||
state <- H.get
|
|
||||||
case A.head arr, A.tail arr of
|
case A.head arr, A.tail arr of
|
||||||
Nothing, _ -> H.raise $ Log $ SimpleLog "Done adding entries (but why this didn't performed pattern matching??)"
|
Nothing, _ -> H.raise $ Log $ SimpleLog "Done adding entries (but why this didn't performed pattern matching??)"
|
||||||
Just new_rr, tail -> case add_entry state new_rr of
|
Just new_rr, tail -> do
|
||||||
Left error_message -> do
|
state <- H.get
|
||||||
H.raise $ Log $ SimpleLog $ "Error while adding new entry: " <> error_message
|
H.put $ add_RR state new_rr
|
||||||
add_entries $ fromMaybe [] tail
|
|
||||||
Right new_state -> do
|
|
||||||
H.put $ add_RR new_state new_rr -- TODO: add to `_resources`
|
|
||||||
add_entries $ fromMaybe [] tail
|
add_entries $ fromMaybe [] tail
|
||||||
|
|
||||||
add_RR :: State -> ResourceRecord -> State
|
add_RR :: State -> ResourceRecord -> State
|
||||||
add_RR state new_rr = state { _resources = (state._resources <> [ new_rr ]) }
|
add_RR state new_rr = state { _resources = (state._resources <> [ new_rr ]) }
|
||||||
|
|
||||||
add_entry :: State -> ResourceRecord -> Either String State
|
|
||||||
add_entry state new_rr = do
|
|
||||||
case new_rr.rrtype, (A.elem new_rr.rrtype baseRecords) of
|
|
||||||
_, true -> Right $ add_new_entry state $ fromResourceRecordToLocalRepresentationSimpleRR new_rr
|
|
||||||
"MX", _ -> Right $ add_new_mx state $ fromResourceRecordToLocalRepresentationMXRR new_rr
|
|
||||||
"SRV", _ -> Right $ add_new_srv state $ fromResourceRecordToLocalRepresentationSRVRR new_rr
|
|
||||||
"SOA", _ -> Right $ new_soa state $ fromResourceRecordToLocalRepresentationSOARR new_rr
|
|
||||||
_, _ -> Left $ "TODO: cannot add '" <> new_rr.rrtype <> "' resource records at the moment."
|
|
||||||
|
|
||||||
-- Rendering
|
-- Rendering
|
||||||
render_soa2 :: forall (w :: Type). Maybe ResourceRecord -> HH.HTML w Action
|
render_soa :: forall (w :: Type). Maybe ResourceRecord -> HH.HTML w Action
|
||||||
render_soa2 Nothing = Bulma.box [ HH.text "SOA not loaded, yet" ]
|
render_soa Nothing = Bulma.box [ HH.text "SOA not loaded, yet" ]
|
||||||
render_soa2 (Just soa) = Bulma.box [ Bulma.zone_rr_title "Start Of Authority (SOA)"
|
render_soa (Just soa) = Bulma.box [ Bulma.zone_rr_title "Start Of Authority (SOA)"
|
||||||
, table_rr
|
, table_rr
|
||||||
]
|
]
|
||||||
where table_rr = Bulma.table [] [ simple_SOA_table_header, table_content ]
|
where table_rr = Bulma.table [] [ simple_SOA_table_header, table_content ]
|
||||||
simple_SOA_table_header
|
simple_SOA_table_header
|
||||||
= HH.thead_ [ HH.tr_ [ HH.th_ [ HH.text "name"]
|
= HH.thead_ [ HH.tr_ [ HH.th_ [ HH.text "name"]
|
||||||
|
@ -963,54 +737,18 @@ render_soa2 (Just soa) = Bulma.box [ Bulma.zone_rr_title "Start Of Authority (SO
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
render_soa :: forall (w :: Type). Maybe (SOARR ()) -> HH.HTML w Action
|
|
||||||
render_soa Nothing = Bulma.box [ HH.text "SOA not loaded, yet" ]
|
|
||||||
render_soa (Just soa) = Bulma.box [ Bulma.zone_rr_title "Start Of Authority (SOA)"
|
|
||||||
, table_rr
|
|
||||||
]
|
|
||||||
where table_rr = Bulma.table [] [ simple_SOA_table_header, table_content ]
|
|
||||||
simple_SOA_table_header
|
|
||||||
= HH.thead_ [ HH.tr_ [ HH.th_ [ HH.text "name"]
|
|
||||||
, HH.th_ [ HH.text "ttl"]
|
|
||||||
, HH.th_ [ HH.text "target"]
|
|
||||||
, HH.th_ [ HH.text "mname"]
|
|
||||||
, HH.th_ [ HH.text "rname"]
|
|
||||||
, HH.th_ [ HH.text "serial"]
|
|
||||||
, HH.th_ [ HH.text "refresh"]
|
|
||||||
, HH.th_ [ HH.text "retry"]
|
|
||||||
, HH.th_ [ HH.text "expire"]
|
|
||||||
, HH.th_ [ HH.text "minttl"]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
table_content
|
|
||||||
= HH.tbody_ $ [ HH.tr_ $ [
|
|
||||||
--, Bulma.p $ "rrtype: " <> soa.rrtype
|
|
||||||
--, Bulma.p $ "rrid: " <> show soa.rrid
|
|
||||||
HH.td_ [ HH.text soa.name ]
|
|
||||||
, HH.td_ [ HH.text soa.ttl ]
|
|
||||||
, HH.td_ [ HH.text soa.target ]
|
|
||||||
, HH.td_ [ HH.text soa.mname ]
|
|
||||||
, HH.td_ [ HH.text soa.rname ]
|
|
||||||
, HH.td_ [ HH.text soa.serial ]
|
|
||||||
, HH.td_ [ HH.text soa.refresh ]
|
|
||||||
, HH.td_ [ HH.text soa.retry ]
|
|
||||||
, HH.td_ [ HH.text soa.expire ]
|
|
||||||
, HH.td_ [ HH.text soa.minttl ]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
-- | Render all Resource Records.
|
-- | Render all Resource Records.
|
||||||
render_resources :: forall w
|
render_resources :: forall w
|
||||||
. Hash.HashMap RRId (Array Validation.ValidationError)
|
-- . Hash.HashMap RRId (Array Validation.ValidationError)
|
||||||
-> Array (ResourceRecord)
|
. Array (ResourceRecord)
|
||||||
-> HH.HTML w Action
|
-> HH.HTML w Action
|
||||||
render_resources _ []
|
render_resources []
|
||||||
= Bulma.box [ Bulma.zone_rr_title "All records (TEST)"
|
= Bulma.box [ Bulma.zone_rr_title "All records (TEST)"
|
||||||
, Bulma.subtitle "No records for now"
|
, Bulma.subtitle "No records for now"
|
||||||
]
|
]
|
||||||
render_resources errors records
|
render_resources records
|
||||||
= Bulma.box [ Bulma.zone_rr_title "All records (TEST)"
|
= Bulma.box [ Bulma.zone_rr_title "All records (TEST)"
|
||||||
, render_soa2 $ A.head $ A.filter (\rr -> rr.rrtype == "SOA") records
|
, render_soa $ A.head $ A.filter (\rr -> rr.rrtype == "SOA") records
|
||||||
, table_rr
|
, table_rr
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
|
@ -1018,18 +756,6 @@ render_resources errors records
|
||||||
table_content = HH.tbody_ $ A.concat $ map rows $ A.filter (\rr -> rr.rrtype /= "SOA") records
|
table_content = HH.tbody_ $ A.concat $ map rows $ A.filter (\rr -> rr.rrtype /= "SOA") records
|
||||||
rows rr = [ HH.tr_ $ render_row rr ] -- <> error_row rr
|
rows rr = [ HH.tr_ $ render_row rr ] -- <> error_row rr
|
||||||
|
|
||||||
-- error_row rr = case Hash.lookup rr.rrid errors of
|
|
||||||
-- Nothing -> []
|
|
||||||
-- Just error_array -> [ HH.tr_ $
|
|
||||||
-- [ Bulma.txt_name ""
|
|
||||||
-- , HH.td_ $ from_error_array_to_td error_array Validation.Name
|
|
||||||
-- , HH.td_ $ from_error_array_to_td error_array Validation.TTL
|
|
||||||
-- , HH.td_ $ from_error_array_to_td error_array Validation.Target
|
|
||||||
-- , HH.td_ []
|
|
||||||
-- , HH.td_ []
|
|
||||||
-- ]
|
|
||||||
-- ]
|
|
||||||
|
|
||||||
render_row :: ResourceRecord -> Array (HH.HTML w Action)
|
render_row :: ResourceRecord -> Array (HH.HTML w Action)
|
||||||
render_row rr =
|
render_row rr =
|
||||||
case rr.rrtype of
|
case rr.rrtype of
|
||||||
|
@ -1063,137 +789,6 @@ render_resources errors records
|
||||||
, HH.td_ [ Bulma.btn_delete (\_ -> DeleteRRModal rr.rrid) ]
|
, HH.td_ [ Bulma.btn_delete (\_ -> DeleteRRModal rr.rrid) ]
|
||||||
]
|
]
|
||||||
|
|
||||||
render_records :: forall (w :: Type). Hash.HashMap RRId Validation.Errors -> Array (SimpleRR ()) -> HH.HTML w Action
|
|
||||||
render_records _ []
|
|
||||||
= Bulma.box [ Bulma.zone_rr_title $ S.joinWith ", " baseRecords
|
|
||||||
, Bulma.subtitle "No records for now"
|
|
||||||
]
|
|
||||||
render_records errors records
|
|
||||||
= Bulma.box [ Bulma.zone_rr_title $ S.joinWith ", " baseRecords
|
|
||||||
, table_rr
|
|
||||||
]
|
|
||||||
where
|
|
||||||
-- subtitle_txt = "Each line is a resource record from your DNS zone."
|
|
||||||
-- <> " You can edit them, then click on the \"fix\" button to synchronize with the server."
|
|
||||||
table_rr = Bulma.table [] [ Bulma.simple_table_header, table_content ]
|
|
||||||
table_content = HH.tbody_ $ A.concat $ map rows records
|
|
||||||
|
|
||||||
rows rr
|
|
||||||
= [ HH.tr_ $
|
|
||||||
[ Bulma.txt_name rr.rrtype
|
|
||||||
, HH.td_ [ Bulma.input_domain (update_simple rr.rrid Update_SRR_Domain) rr.name rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_ttl (update_simple rr.rrid Update_SRR_TTL ) rr.ttl rr.valid ]
|
|
||||||
, HH.td_ [ case rr.rrtype of
|
|
||||||
"TXT" -> Bulma.textarea (update_simple rr.rrid Update_SRR_Target) rr.target rr.valid
|
|
||||||
_ -> Bulma.input_target (update_simple rr.rrid Update_SRR_Target) rr.target rr.valid
|
|
||||||
]
|
|
||||||
, HH.td_ [ Bulma.btn_change (SaveSRR rr.rrid) (TellSomethingWentWrong rr.rrid "cannot update") rr.modified rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.btn_delete (\_ -> DeleteRRModal rr.rrid) ]
|
|
||||||
]
|
|
||||||
] <> error_row rr
|
|
||||||
update_simple rrid v = (UpdateLocalRR rrid) <<< Update_Local_Form_SRR <<< v
|
|
||||||
error_row rr = case Hash.lookup rr.rrid errors of
|
|
||||||
Nothing -> []
|
|
||||||
Just error_array -> [ HH.tr_ $
|
|
||||||
[ Bulma.txt_name ""
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.Name
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.TTL
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.Target
|
|
||||||
, HH.td_ []
|
|
||||||
, HH.td_ []
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
from_error_array_to_td :: forall w i. Validation.Errors -> Validation.Attribute -> Array (HH.HTML w i)
|
|
||||||
from_error_array_to_td [] _ = []
|
|
||||||
from_error_array_to_td errors attribute = case A.uncons errors of
|
|
||||||
Just { head: (Tuple attr err), tail: xs } -> if attr == attribute
|
|
||||||
then [Bulma.p_ (C.help <> C.is_danger) err]
|
|
||||||
else from_error_array_to_td xs attribute
|
|
||||||
Nothing -> []
|
|
||||||
|
|
||||||
|
|
||||||
render_mx_records :: forall (w :: Type) (l :: Row Type)
|
|
||||||
. Hash.HashMap RRId Validation.Errors -> Array (MXRR l) -> HH.HTML w Action
|
|
||||||
render_mx_records _ []
|
|
||||||
= Bulma.box [ Bulma.zone_rr_title "MX records"
|
|
||||||
, Bulma.subtitle "No records for now"
|
|
||||||
]
|
|
||||||
render_mx_records errors records
|
|
||||||
= Bulma.box [ Bulma.zone_rr_title "MX records"
|
|
||||||
, table_rr
|
|
||||||
]
|
|
||||||
where
|
|
||||||
table_rr = Bulma.table [] [ Bulma.mx_table_header, table_content ]
|
|
||||||
table_content = HH.tbody_ $ A.concat $ map rows records
|
|
||||||
|
|
||||||
rows rr = [ HH.tr_ $
|
|
||||||
[ HH.td_ [ Bulma.input_domain (update_mx rr.rrid Update_MX_Domain) rr.name rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_ttl (update_mx rr.rrid Update_MX_TTL) rr.ttl rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_priority (update_mx rr.rrid Update_MX_Priority) rr.priority rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_target (update_mx rr.rrid Update_MX_Target) rr.target rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.btn_change (SaveMXRR rr.rrid) (TellSomethingWentWrong rr.rrid "cannot update") rr.modified rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.btn_delete (\_ -> DeleteRRModal rr.rrid) ]
|
|
||||||
]
|
|
||||||
] <> error_row rr
|
|
||||||
update_mx rrid v = (UpdateLocalRR rrid) <<< Update_Local_Form_MXRR <<< v
|
|
||||||
error_row rr = case Hash.lookup rr.rrid errors of
|
|
||||||
Nothing -> []
|
|
||||||
Just error_array ->
|
|
||||||
[ HH.tr_ $
|
|
||||||
[ HH.td_ $ from_error_array_to_td error_array Validation.Name
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.TTL
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.Priority
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.Target
|
|
||||||
, HH.td_ []
|
|
||||||
, HH.td_ []
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
render_srv_records :: forall (w :: Type) (l :: Row Type)
|
|
||||||
. Hash.HashMap RRId Validation.Errors -> Array (SRVRR l) -> HH.HTML w Action
|
|
||||||
render_srv_records _ []
|
|
||||||
= Bulma.box [ Bulma.zone_rr_title "SRV records"
|
|
||||||
, Bulma.subtitle "No records for now"
|
|
||||||
]
|
|
||||||
render_srv_records errors records
|
|
||||||
= Bulma.box [ Bulma.zone_rr_title "SRV records"
|
|
||||||
, table_rr
|
|
||||||
]
|
|
||||||
where
|
|
||||||
table_rr = Bulma.table [] [ Bulma.srv_table_header, table_content ]
|
|
||||||
table_content = HH.tbody_ $ A.concat $ map rows records
|
|
||||||
|
|
||||||
rows rr
|
|
||||||
= [ HH.tr_ $
|
|
||||||
[ HH.td_ [ Bulma.input_domain (update_srv rr.rrid Update_SRV_Domain ) rr.name rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_ttl (update_srv rr.rrid Update_SRV_TTL ) rr.ttl rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_priority (update_srv rr.rrid Update_SRV_Priority) rr.priority rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_protocol (update_srv rr.rrid Update_SRV_Protocol) rr.protocol rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_weight (update_srv rr.rrid Update_SRV_Weight ) rr.weight rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_port (update_srv rr.rrid Update_SRV_Port ) rr.port rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.input_target (update_srv rr.rrid Update_SRV_Target ) rr.target rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.btn_change (SaveSRVRR rr.rrid) (TellSomethingWentWrong rr.rrid "cannot update") rr.modified rr.valid ]
|
|
||||||
, HH.td_ [ Bulma.btn_delete (\_ -> DeleteRRModal rr.rrid) ]
|
|
||||||
]
|
|
||||||
] <> error_row rr
|
|
||||||
update_srv rrid v = (UpdateLocalRR rrid) <<< Update_Local_Form_SRVRR <<< v
|
|
||||||
error_row rr = case Hash.lookup rr.rrid errors of
|
|
||||||
Nothing -> []
|
|
||||||
Just error_array ->
|
|
||||||
[ HH.tr_ $
|
|
||||||
[ HH.td_ $ from_error_array_to_td error_array Validation.Name
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.TTL
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.Priority
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.Protocol
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.Weight
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.Port
|
|
||||||
, HH.td_ $ from_error_array_to_td error_array Validation.Target
|
|
||||||
, HH.td_ []
|
|
||||||
, HH.td_ []
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
baseRecords :: Array String
|
baseRecords :: Array String
|
||||||
baseRecords = [ "A", "AAAA", "CNAME", "TXT", "NS" ]
|
baseRecords = [ "A", "AAAA", "CNAME", "TXT", "NS" ]
|
||||||
|
|
||||||
|
@ -1218,140 +813,6 @@ render_new_records _
|
||||||
|
|
||||||
-- ACTIONS
|
-- ACTIONS
|
||||||
|
|
||||||
-- add a new record and get a new placeholter
|
|
||||||
add_new_entry :: State -> Maybe (SimpleRR ()) -> State
|
|
||||||
add_new_entry state = case _ of
|
|
||||||
Nothing -> state
|
|
||||||
Just rr -> state { _srr = (state._srr <> [ rr ]), _newSRR = defaultResourceA }
|
|
||||||
|
|
||||||
-- add a new record and get a new placeholter
|
|
||||||
add_new_mx :: State -> Maybe (MXRR ()) -> State
|
|
||||||
add_new_mx state = case _ of
|
|
||||||
Nothing -> state
|
|
||||||
Just rr -> state { _mxrr = (state._mxrr <> [ rr ]), _newMXRR = defaultResourceMX }
|
|
||||||
|
|
||||||
-- add a new record and get a new placeholter
|
|
||||||
add_new_srv :: State -> Maybe (SRVRR ()) -> State
|
|
||||||
add_new_srv state = case _ of
|
|
||||||
Nothing -> state
|
|
||||||
Just rr -> state { _srvrr = (state._srvrr <> [ rr ]), _newSRVRR = defaultResourceSRV }
|
|
||||||
|
|
||||||
new_soa :: State -> Maybe (SOARR ()) -> State
|
|
||||||
new_soa state = case _ of
|
|
||||||
Nothing -> state
|
|
||||||
Just rr -> state { _soa = Just rr }
|
|
||||||
|
|
||||||
update_domain :: forall (l :: Row Type). Int -> String -> Array (SimpleRR l) -> Array (SimpleRR l)
|
|
||||||
update_domain rr_id val = update (\rr -> rr { modified = true, name = val }) rr_id
|
|
||||||
|
|
||||||
update_target :: forall (l :: Row Type). Int -> String -> Array (SimpleRR l) -> Array (SimpleRR l)
|
|
||||||
update_target rr_id val = update (\rr -> rr { modified = true, target = val }) rr_id
|
|
||||||
|
|
||||||
update_ttl :: forall (l :: Row Type). Int -> String -> Array (SimpleRR l) -> Array (SimpleRR l)
|
|
||||||
update_ttl rr_id val = update (\rr -> rr { modified = true, ttl = val, valid = isInteger val }) rr_id
|
|
||||||
|
|
||||||
update_priority :: forall (l :: Row Type). Int -> Priority -> Array (MXRR l) -> Array (MXRR l)
|
|
||||||
update_priority rr_id val = update (\rr -> rr { modified = true, priority = val}) rr_id
|
|
||||||
|
|
||||||
update_protocol :: forall (l :: Row Type). Int -> Protocol -> Array (SRVRR l) -> Array (SRVRR l)
|
|
||||||
update_protocol rr_id val = update (\rr -> rr { modified = true, protocol = val}) rr_id
|
|
||||||
|
|
||||||
update_weight :: forall (l :: Row Type). Int -> Priority -> Array (SRVRR l) -> Array (SRVRR l)
|
|
||||||
update_weight rr_id val = update (\rr -> rr { modified = true, weight = val}) rr_id
|
|
||||||
|
|
||||||
update_port :: Int -> Priority -> Array (SRVRR ()) -> Array (SRVRR ())
|
|
||||||
update_port rr_id val = update (\rr -> rr { modified = true, port = val}) rr_id
|
|
||||||
|
|
||||||
isIntRegex :: Regex.Regex
|
|
||||||
isIntRegex = RegexUnsafe.unsafeRegex "^[0-9]*$" RegexFlags.noFlags
|
|
||||||
|
|
||||||
isInteger :: String -> Boolean
|
|
||||||
isInteger = Regex.test isIntRegex
|
|
||||||
|
|
||||||
update :: forall (l :: Row Type).
|
|
||||||
(SimpleRR l -> SimpleRR l) -> Int -> Array (SimpleRR l) -> Array (SimpleRR l)
|
|
||||||
update f rr_id records = map doSmth records
|
|
||||||
where
|
|
||||||
doSmth rr
|
|
||||||
| rr_id == rr.rrid = f rr
|
|
||||||
| otherwise = rr
|
|
||||||
|
|
||||||
fromResourceRecordToLocalRepresentationSimpleRR :: ResourceRecord -> Maybe (SimpleRR ())
|
|
||||||
fromResourceRecordToLocalRepresentationSimpleRR new_rr =
|
|
||||||
Just { rrtype: new_rr.rrtype
|
|
||||||
, rrid: new_rr.rrid
|
|
||||||
, modified: false
|
|
||||||
, valid: true
|
|
||||||
, readonly: new_rr.readonly
|
|
||||||
, ttl: show new_rr.ttl
|
|
||||||
, name: new_rr.name
|
|
||||||
, target: new_rr.target
|
|
||||||
}
|
|
||||||
|
|
||||||
fromResourceRecordToLocalRepresentationMXRR :: ResourceRecord -> Maybe (MXRR ())
|
|
||||||
fromResourceRecordToLocalRepresentationMXRR new_rr = do
|
|
||||||
priority <- new_rr.priority
|
|
||||||
Just { rrtype: new_rr.rrtype
|
|
||||||
, rrid: new_rr.rrid
|
|
||||||
, modified: false
|
|
||||||
, valid: true
|
|
||||||
, readonly: new_rr.readonly
|
|
||||||
, ttl: show new_rr.ttl
|
|
||||||
, name: new_rr.name
|
|
||||||
, target: new_rr.target
|
|
||||||
, priority: show priority
|
|
||||||
}
|
|
||||||
-- TODO: would be nice to have a simpler implementation, something like this:
|
|
||||||
--fromResourceRecordToLocalRepresentationMXRR new_rr
|
|
||||||
-- = let simple_rr = fromResourceRecordToLocalRepresentationSimpleRR new_rr
|
|
||||||
-- simple_rr { priority = show new_rr.priority }
|
|
||||||
|
|
||||||
fromResourceRecordToLocalRepresentationSRVRR :: ResourceRecord -> Maybe (SRVRR ())
|
|
||||||
fromResourceRecordToLocalRepresentationSRVRR new_rr = do
|
|
||||||
port <- new_rr.port
|
|
||||||
weight <- new_rr.weight
|
|
||||||
priority <- new_rr.priority
|
|
||||||
protocol <- new_rr.protocol
|
|
||||||
Just { rrtype: new_rr.rrtype
|
|
||||||
, rrid: new_rr.rrid
|
|
||||||
, modified: false
|
|
||||||
, valid: true
|
|
||||||
, readonly: new_rr.readonly
|
|
||||||
, ttl: show new_rr.ttl
|
|
||||||
, name: new_rr.name
|
|
||||||
, target: new_rr.target
|
|
||||||
, priority: show priority
|
|
||||||
, port: show port
|
|
||||||
, weight: show weight
|
|
||||||
, protocol: protocol
|
|
||||||
}
|
|
||||||
|
|
||||||
fromResourceRecordToLocalRepresentationSOARR :: ResourceRecord -> Maybe (SOARR ())
|
|
||||||
fromResourceRecordToLocalRepresentationSOARR new_rr = do
|
|
||||||
mname <- new_rr.mname -- :: Maybe String
|
|
||||||
rname <- new_rr.rname -- :: Maybe String
|
|
||||||
serial <- new_rr.serial -- :: Maybe Int
|
|
||||||
refresh <- new_rr.refresh -- :: Maybe Int
|
|
||||||
retry <- new_rr.retry -- :: Maybe Int
|
|
||||||
expire <- new_rr.expire -- :: Maybe Int
|
|
||||||
minttl <- new_rr.minttl -- :: Maybe Int
|
|
||||||
Just { rrtype: new_rr.rrtype
|
|
||||||
, rrid: new_rr.rrid
|
|
||||||
, modified: false
|
|
||||||
, valid: true
|
|
||||||
, readonly: new_rr.readonly
|
|
||||||
, ttl: show new_rr.ttl
|
|
||||||
, name: new_rr.name
|
|
||||||
, target: new_rr.target
|
|
||||||
, mname: mname -- :: RR (Maybe String) Local (String)
|
|
||||||
, rname: rname -- :: RR (Maybe String) Local (String)
|
|
||||||
, serial: show serial -- :: RR (Maybe Int) Local (String)
|
|
||||||
, refresh: show refresh -- :: RR (Maybe Int) Local (String)
|
|
||||||
, retry: show retry -- :: RR (Maybe Int) Local (String)
|
|
||||||
, expire: show expire -- :: RR (Maybe Int) Local (String)
|
|
||||||
, minttl: show minttl -- :: RR (Maybe Int) Local (String)
|
|
||||||
}
|
|
||||||
|
|
||||||
first :: forall a. (a -> Boolean) -> Array a -> Maybe a
|
first :: forall a. (a -> Boolean) -> Array a -> Maybe a
|
||||||
first condition = A.head <<< (A.filter condition)
|
first condition = A.head <<< (A.filter condition)
|
||||||
|
|
||||||
|
@ -1366,18 +827,6 @@ loopE f a = case (A.head a) of
|
||||||
Nothing -> pure unit
|
Nothing -> pure unit
|
||||||
Just xs -> loopE f xs
|
Just xs -> loopE f xs
|
||||||
|
|
||||||
getNewID :: State -> Int
|
|
||||||
getNewID state = (_ + 1)
|
|
||||||
$ Foldable.foldl max 0 [ maxIDrr
|
|
||||||
, maxIDmxrr
|
|
||||||
, maxIDsrvrr
|
|
||||||
]
|
|
||||||
|
|
||||||
where
|
|
||||||
maxIDrr = Foldable.foldl max 0 $ map _.rrid state._srr
|
|
||||||
maxIDmxrr = Foldable.foldl max 0 $ map _.rrid state._mxrr
|
|
||||||
maxIDsrvrr = Foldable.foldl max 0 $ map _.rrid state._srvrr
|
|
||||||
|
|
||||||
error_to_paragraph :: forall w. Validation.ValidationError -> HH.HTML w Action
|
error_to_paragraph :: forall w. Validation.ValidationError -> HH.HTML w Action
|
||||||
error_to_paragraph v = Bulma.error_message (Bulma.p $ show_error_title v)
|
error_to_paragraph v = Bulma.error_message (Bulma.p $ show_error_title v)
|
||||||
(case v of
|
(case v of
|
||||||
|
|
Loading…
Reference in New Issue