From 811378207d1e8c39989f1935a21862ef713be585 Mon Sep 17 00:00:00 2001 From: Robin Huang Date: Mon, 3 Jun 2024 11:17:59 -0700 Subject: [PATCH] Improve node id validation error message. --- mapper/node.go | 19 ++++++++++++++----- mapper/node_test.go | 30 +++++++++++++----------------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/mapper/node.go b/mapper/node.go index 118151d..5d6a5ee 100644 --- a/mapper/node.go +++ b/mapper/node.go @@ -72,23 +72,32 @@ func ValidateNode(node *drip.Node) error { if len(*node.Id) > 100 { return fmt.Errorf("node id is too long") } - if !IsValidNodeID(*node.Id) { - return fmt.Errorf("invalid node id") + isValid, err := IsValidNodeID(*node.Id) + if !isValid { + return fmt.Errorf(err) } } return nil } -func IsValidNodeID(nodeID string) bool { +func IsValidNodeID(nodeID string) (bool, string) { if len(nodeID) == 0 || len(nodeID) > 50 { - return false + return false, "node id must be between 1 and 50 characters" + } + // Check if there are capital letters in the string + if strings.ToLower(nodeID) != nodeID { + return false, "Node ID can only contain lowercase letters" } // Regular expression pattern for Node ID validation (lowercase letters only) pattern := `^[a-z][a-z0-9-_]+(\.[a-z0-9-_]+)*$` // Compile the regular expression pattern regex := regexp.MustCompile(pattern) // Check if the string matches the pattern - return regex.MatchString(nodeID) + matches := regex.MatchString(nodeID) + if !matches { + return false, "Node ID can only contain lowercase letters, numbers, hyphens, underscores, and dots. Dots cannot be consecutive or be at the start or end of the id." + } + return true, "" } func DbNodeToApiNode(node *ent.Node) *drip.Node { diff --git a/mapper/node_test.go b/mapper/node_test.go index 1bcb0fd..29da250 100644 --- a/mapper/node_test.go +++ b/mapper/node_test.go @@ -8,6 +8,7 @@ import ( // TestIsValidNodeID tests the isValidNodeID function with various inputs. func TestIsValidNodeID(t *testing.T) { + regexErrorMessage := "Node ID can only contain lowercase letters, numbers, hyphens, underscores, and dots. Dots cannot be consecutive or be at the start or end of the id." testCases := []struct { name string node *drip.Node @@ -26,7 +27,7 @@ func TestIsValidNodeID(t *testing.T) { { name: "Invalid Node ID", node: &drip.Node{Id: stringPtr("123")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, { @@ -42,38 +43,33 @@ func TestIsValidNodeID(t *testing.T) { { name: "Invalid with uppercase", node: &drip.Node{Id: stringPtr("Node")}, - expectedError: "invalid node id", + expectedError: "Node ID can only contain lowercase letters", }, { name: "Invalid with special characters", node: &drip.Node{Id: stringPtr("node_@")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, { name: "Invalid start with number", node: &drip.Node{Id: stringPtr("1node")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, { name: "Invalid start with dash", node: &drip.Node{Id: stringPtr("-node")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, { name: "Empty input", node: &drip.Node{Id: stringPtr("")}, - expectedError: "invalid node id", + expectedError: "node id must be between 1 and 50 characters", }, { name: "Valid all lowercase letters", node: &drip.Node{Id: stringPtr("abcdefghijklmnopqrstuvwxyz")}, expectedError: "", }, - { - name: "Valid all uppercase letters", - node: &drip.Node{Id: stringPtr("ABCD")}, - expectedError: "invalid node id", - }, { name: "Valid containing underscore", node: &drip.Node{Id: stringPtr("comfy_ui")}, @@ -97,17 +93,17 @@ func TestIsValidNodeID(t *testing.T) { { name: "Invalid ID with number first", node: &drip.Node{Id: stringPtr("1invalidnodeid")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, { name: "Invalid ID with consecutive dots", node: &drip.Node{Id: stringPtr("invalid..nodeid")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, { name: "Invalid ID with special character first", node: &drip.Node{Id: stringPtr("-invalidnodeid")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, { name: "Valid complex ID", @@ -117,17 +113,17 @@ func TestIsValidNodeID(t *testing.T) { { name: "Invalid ID with special characters only", node: &drip.Node{Id: stringPtr("$$$$")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, { name: "Invalid ID with leading dot", node: &drip.Node{Id: stringPtr(".invalidnodeid")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, { name: "Invalid ID with ending dot", node: &drip.Node{Id: stringPtr("invalidnodeid.")}, - expectedError: "invalid node id", + expectedError: regexErrorMessage, }, }