diff --git a/pkg/id/id.go b/pkg/id/id.go index cfb8b6390ac48e50ed5fb899db11316b3f1df31c..2f3a9adda1b3ad0cccd15db8f14881d22533fb24 100644 --- a/pkg/id/id.go +++ b/pkg/id/id.go @@ -1,7 +1,52 @@ package id -import "github.com/rs/xid" +import ( + "regexp" + "strings" + + "git.perx.ru/perxis/perxis-go/pkg/errors" + "github.com/rs/xid" +) + +const ( + MaxLengthID = 64 + MaxLengthName = 256 +) + +var ( + ErrEmptyID = errors.New("empty id") + ErrNotValidID = errors.New("id contains invalid characters") + ErrLongID = errors.Errorf("id too long (max %d symbols)", MaxLengthID) + ErrEmptyName = errors.New("empty name") + ErrLongName = errors.Errorf("name too long (max %d symbols)", MaxLengthName) + isValidID = regexp.MustCompile(`^[A-Za-z][A-Za-z0-9-_]*$`).MatchString +) func GenerateNewID() string { return xid.New().String() } + +func ValidateID(id string) (string, error) { + trimmedID := strings.TrimSpace(id) + if trimmedID == "" { + return trimmedID, ErrEmptyID + } + if len(trimmedID) > MaxLengthID { + return trimmedID, ErrLongID + } + if !isValidID(trimmedID) { + return trimmedID, errors.WithDetail(ErrNotValidID, "must begin with latin letters and contain latin letters, numbers or '-', '_'") + } + return trimmedID, nil +} + +func ValidateName(name string) (string, error) { + trimmedName := strings.TrimSpace(name) + if trimmedName == "" { + return trimmedName, ErrEmptyName + } + if len(trimmedName) > MaxLengthName { + return trimmedName, ErrLongName + } + return trimmedName, nil +} diff --git a/pkg/id/id_test.go b/pkg/id/id_test.go new file mode 100644 index 0000000000000000000000000000000000000000..f778e3a9d70b1711d05e983fcc2ac0c43bfd61ff --- /dev/null +++ b/pkg/id/id_test.go @@ -0,0 +1,135 @@ +package id + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestValidateID(t *testing.T) { + tests := []struct { + name string + id string + result string + wantErr bool + }{ + { + "Correct ID #1", + "test", + "test", + false, + }, + { + "Correct ID #2", + "test_1", + "test_1", + false, + }, + { + "Correct ID #3", + "test_1-2", + "test_1-2", + false, + }, + { + "Trimmed ID #1", + " test_1-2 ", + "test_1-2", + false, + }, + { + "Trimmed ID #2", + "test_1-2 ", + "test_1-2", + false, + }, + { + "Fail, ID starts with number", + "1test", + "1test", + true, + }, + { + "Fail, ID to long", + "9QoulAlFbIcnQYLSudMistN1IczCWrXUTtN5EgNQJd516DN9UjXYJxieJ1RcsNcs1", + "9QoulAlFbIcnQYLSudMistN1IczCWrXUTtN5EgNQJd516DN9UjXYJxieJ1RcsNcs1", + true, + }, + { + "Fail, ID with symbols", + "test!_)(&&", + "test!_)(&&", + true, + }, + { + "Fail, ID is empty", + " ", + "", + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := ValidateID(tt.id) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateID() error = %v, wantErr %v", err, tt.wantErr) + } + require.Equal(t, tt.result, res) + }) + } +} + +func TestValidateName(t *testing.T) { + tests := []struct { + nameTest string + name string + result string + wantErr bool + }{ + { + "Correct name #1", + "test", + "test", + false, + }, + { + "Correct name #2", + "test_1", + "test_1", + false, + }, + { + "Correct name #3", + "test_1-2", + "test_1-2", + false, + }, + { + "Trimmed name #1", + " test_1-3 ", + "test_1-3", + false, + }, + { + "Trimmed name #2", + "test_1234 ", + "test_1234", + false, + }, + { + "Fail, name to long", + "ChKRLdvWi0wYYPazuBXrIRtNFy96qGrhBDkuKQNd6N2DPV86IGdXVkeTjWj7qezKreIFUp9IUn03A8WJTTORHkgXAvkPuDVM8tVMcnHbR2hznooJ3gGUsXpn4uXo2QhsviHPyUKmE10GnkCOv9FgAMILNoFVHnIiSHI3cjWlGJglpS9YAMXFB1phOIRF5yol3jmPE7EeU1uZPUw9C2PChuksGsOuJQov07Zom0b13r6wOJv8PZVa4IKmjDDLGKlq1", + "ChKRLdvWi0wYYPazuBXrIRtNFy96qGrhBDkuKQNd6N2DPV86IGdXVkeTjWj7qezKreIFUp9IUn03A8WJTTORHkgXAvkPuDVM8tVMcnHbR2hznooJ3gGUsXpn4uXo2QhsviHPyUKmE10GnkCOv9FgAMILNoFVHnIiSHI3cjWlGJglpS9YAMXFB1phOIRF5yol3jmPE7EeU1uZPUw9C2PChuksGsOuJQov07Zom0b13r6wOJv8PZVa4IKmjDDLGKlq1", + true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + res, err := ValidateName(tt.name) + if (err != nil) != tt.wantErr { + t.Errorf("ValidateName() error = %v, wantErr %v", err, tt.wantErr) + } + require.Equal(t, tt.result, res) + }) + } +}