From 7046bec40a32b044a700d3cce57621ffe5decdf5 Mon Sep 17 00:00:00 2001 From: Onur Cinar Date: Sat, 17 Jun 2023 00:51:06 -0700 Subject: [PATCH] MAC and CIDR checkers are added. (#53) * CIDR checker is added. Fixes #42 * Update README.md. * MAC checker is added. Fixes #25 * Remove file. --- README.md | 2 ++ checker.go | 2 ++ cidr.go | 36 ++++++++++++++++++++++++++++ cidr_test.go | 57 ++++++++++++++++++++++++++++++++++++++++++++ doc/checkers/cidr.md | 28 ++++++++++++++++++++++ doc/checkers/mac.md | 28 ++++++++++++++++++++++ mac.go | 36 ++++++++++++++++++++++++++++ mac_test.go | 57 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 246 insertions(+) create mode 100644 cidr.go create mode 100644 cidr_test.go create mode 100644 doc/checkers/cidr.md create mode 100644 doc/checkers/mac.md create mode 100644 mac.go create mode 100644 mac_test.go diff --git a/README.md b/README.md index c8e9005..915061f 100644 --- a/README.md +++ b/README.md @@ -72,10 +72,12 @@ This package currently provides the following checkers: - [alphanumeric](doc/checkers/alphanumeric.md) checks if the given string consists of only alphanumeric characters. - [ascii](doc/checkers/ascii.md) checks if the given string consists of only ASCII characters. +- [cidr](doc/checkers/cidr.md) checker checks if the value is a valid CIDR notation IP address and prefix length. - [digits](doc/checkers/digits.md) checks if the given string consists of only digit characters. - [ip](doc/checkers/ip.md) checks if the given value is an IP address. - [ipv4](doc/checkers/ipv4.md) checks if the given value is an IPv4 address. - [ipv6](doc/checkers/ipv6.md) checks if the given value is an IPv6 address. +- [mac](doc/checkers/mac.md) checks if the given value is a valid an IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet IP over InfiniBand link-layer address. - [max](doc/checkers/max.md) checks if the given value is less than the given maximum. - [max-length](doc/checkers/maxlength.md) checks if the length of the given value is less than the given maximum length. - [min](doc/checkers/min.md) checks if the given value is greather than the given minimum. diff --git a/checker.go b/checker.go index ca4bcd9..d64be8a 100644 --- a/checker.go +++ b/checker.go @@ -33,10 +33,12 @@ const ResultValid Result = "VALID" var makers = map[string]MakeFunc{ CheckerAlphanumeric: makeAlphanumeric, CheckerAscii: makeAscii, + CheckerCidr: makeCidr, CheckerDigits: makeDigits, CheckerIp: makeIp, CheckerIpV4: makeIpV4, CheckerIpV6: makeIpV6, + CheckerMac: makeMac, CheckerMax: makeMax, CheckerMaxLength: makeMaxLength, CheckerMin: makeMin, diff --git a/cidr.go b/cidr.go new file mode 100644 index 0000000..8490dc9 --- /dev/null +++ b/cidr.go @@ -0,0 +1,36 @@ +package checker + +import ( + "net" + "reflect" +) + +// CheckerCidr is the name of the checker. +const CheckerCidr = "cidr" + +// ResultNotCidr indicates that the given value is not a valid CIDR. +const ResultNotCidr = "NOT_CIDR" + +// IsCidr checker checks if the value is a valid CIDR notation IP address and prefix length. +func IsCidr(value string) Result { + _, _, err := net.ParseCIDR(value) + if err != nil { + return ResultNotCidr + } + + return ResultValid +} + +// makeCidr makes a checker function for the ip checker. +func makeCidr(_ string) CheckFunc { + return checkCidr +} + +// checkCidr checker checks if the value is a valid CIDR notation IP address and prefix length. +func checkCidr(value, _ reflect.Value) Result { + if value.Kind() != reflect.String { + panic("string expected") + } + + return IsCidr(value.String()) +} diff --git a/cidr_test.go b/cidr_test.go new file mode 100644 index 0000000..6e77832 --- /dev/null +++ b/cidr_test.go @@ -0,0 +1,57 @@ +package checker + +import "testing" + +func TestIsCidrInvalid(t *testing.T) { + if IsCidr("900.800.200.100//24") == ResultValid { + t.Fail() + } +} + +func TestIsCidrValid(t *testing.T) { + if IsCidr("2001:db8::/32") != ResultValid { + t.Fail() + } +} + +func TestCheckCidrNonString(t *testing.T) { + defer FailIfNoPanic(t) + + type Network struct { + Subnet int `checkers:"cidr"` + } + + network := &Network{} + + Check(network) +} + +func TestCheckCidrInvalid(t *testing.T) { + type Network struct { + Subnet string `checkers:"cidr"` + } + + network := &Network{ + Subnet: "900.800.200.100//24", + } + + _, valid := Check(network) + if valid { + t.Fail() + } +} + +func TestCheckCidrValid(t *testing.T) { + type Network struct { + Subnet string `checkers:"cidr"` + } + + network := &Network{ + Subnet: "192.0.2.0/24", + } + + _, valid := Check(network) + if !valid { + t.Fail() + } +} diff --git a/doc/checkers/cidr.md b/doc/checkers/cidr.md new file mode 100644 index 0000000..8e4f4ae --- /dev/null +++ b/doc/checkers/cidr.md @@ -0,0 +1,28 @@ +# CIDR Checker + +The ```cidr``` checker checks if the value is a valid CIDR notation IP address and prefix length, like "192.0.2.0/24" or "2001:db8::/32", as defined in [RFC 4632](https://rfc-editor.org/rfc/rfc4632.html) and [RFC 4291](https://rfc-editor.org/rfc/rfc4291.html). If the value is not a valid CIDR notation, the checker will return the ```NOT_CIDR``` result. Here is an example: + +```golang +type Network struct { + Subnet string `checkers:"cidr"` +} + +network := &Network{ + Subnet: "192.0.2.0/24", +} + +_, valid := Check(network) +if !valid { + // Send the mistakes back to the user +} +``` + +In your custom checkers, you can call the ```cidr``` checker function ```IsCidr``` to validate the user input. Here is an example: + +```golang +result := IsCidr("2001:db8::/32") + +if result != ResultValid { + // Send the mistakes back to the user +} +``` diff --git a/doc/checkers/mac.md b/doc/checkers/mac.md new file mode 100644 index 0000000..dfa8c11 --- /dev/null +++ b/doc/checkers/mac.md @@ -0,0 +1,28 @@ +# MAC Checker + +The ```mac``` checker checks if the value is a valid an IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet IP over InfiniBand link-layer address. If the value is not a valid MAC address, the checker will return the ```NOT_MAC``` result. Here is an example: + +```golang +type Network struct { + HardwareAddress string `checkers:"mac"` +} + +network := &Network{ + HardwareAddress: "00:00:5e:00:53:01", +} + +_, valid := Check(network) +if !valid { + // Send the mistakes back to the user +} +``` + +In your custom checkers, you can call the ```mac``` checker function ```IsMAc``` to validate the user input. Here is an example: + +```golang +result := IsMac("00:00:5e:00:53:01") + +if result != ResultValid { + // Send the mistakes back to the user +} +``` diff --git a/mac.go b/mac.go new file mode 100644 index 0000000..56a20c2 --- /dev/null +++ b/mac.go @@ -0,0 +1,36 @@ +package checker + +import ( + "net" + "reflect" +) + +// CheckerMac is the name of the checker. +const CheckerMac = "mac" + +// ResultNotMac indicates that the given value is not an MAC address. +const ResultNotMac = "NOT_MAC" + +// IsMac checks if the given value is a valid an IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet IP over InfiniBand link-layer address. +func IsMac(value string) Result { + _, err := net.ParseMAC(value) + if err != nil { + return ResultNotMac + } + + return ResultValid +} + +// makeMac makes a checker function for the ip checker. +func makeMac(_ string) CheckFunc { + return checkMac +} + +// checkMac checks if the given value is a valid an IEEE 802 MAC-48, EUI-48, EUI-64, or a 20-octet IP over InfiniBand link-layer address. +func checkMac(value, _ reflect.Value) Result { + if value.Kind() != reflect.String { + panic("string expected") + } + + return IsMac(value.String()) +} diff --git a/mac_test.go b/mac_test.go new file mode 100644 index 0000000..b636567 --- /dev/null +++ b/mac_test.go @@ -0,0 +1,57 @@ +package checker + +import "testing" + +func TestIsMacInvalid(t *testing.T) { + if IsMac("1234") == ResultValid { + t.Fail() + } +} + +func TestIsMacValid(t *testing.T) { + if IsMac("00:00:5e:00:53:01") != ResultValid { + t.Fail() + } +} + +func TestCheckMacNonString(t *testing.T) { + defer FailIfNoPanic(t) + + type Network struct { + HardwareAddress int `checkers:"mac"` + } + + network := &Network{} + + Check(network) +} + +func TestCheckMacInvalid(t *testing.T) { + type Network struct { + HardwareAddress string `checkers:"mac"` + } + + network := &Network{ + HardwareAddress: "1234", + } + + _, valid := Check(network) + if valid { + t.Fail() + } +} + +func TestCheckMacValid(t *testing.T) { + type Network struct { + HardwareAddress string `checkers:"mac"` + } + + network := &Network{ + HardwareAddress: "00:00:5e:00:53:01", + } + + _, valid := Check(network) + if !valid { + t.Fail() + } +}