From ce4f3f42621852f00227b5c1804f466c82229734 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Thu, 15 Feb 2024 10:06:12 +0400 Subject: [PATCH] cli/util: Refactor eACL parser New ops are coming, with this it'll be easier to change the code. Also add unit tests. Refs #2730. Signed-off-by: Leonard Lyubich --- cmd/neofs-cli/modules/util/acl.go | 41 +++++++++------ cmd/neofs-cli/modules/util/acl_test.go | 70 ++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 16 deletions(-) create mode 100644 cmd/neofs-cli/modules/util/acl_test.go diff --git a/cmd/neofs-cli/modules/util/acl.go b/cmd/neofs-cli/modules/util/acl.go index 12949042b3e..94bb76270ea 100644 --- a/cmd/neofs-cli/modules/util/acl.go +++ b/cmd/neofs-cli/modules/util/acl.go @@ -235,24 +235,11 @@ func parseEACLRecord(args []string) (*eacl.Record, error) { return nil, fmt.Errorf("invalid filter or target: %s", args[i]) } - i := strings.Index(ss[1], "=") - if i < 0 { - return nil, fmt.Errorf("invalid filter key-value pair: %s", ss[1]) + key, value, op, err := parseKVWithOp(ss[1]) + if err != nil { + return nil, fmt.Errorf("invalid filter key-value pair %s: %w", ss[1], err) } - var key, value string - var op eacl.Match - - if 0 < i && ss[1][i-1] == '!' { - key = ss[1][:i-1] - op = eacl.MatchStringNotEqual - } else { - key = ss[1][:i] - op = eacl.MatchStringEqual - } - - value = ss[1][i+1:] - typ := eacl.HeaderFromRequest if ss[0] == "obj" { typ = eacl.HeaderFromObject @@ -288,6 +275,28 @@ func parseEACLRecord(args []string) (*eacl.Record, error) { return r, nil } +func parseKVWithOp(s string) (string, string, eacl.Match, error) { + i := strings.Index(s, "=") + if i < 0 { + return "", "", 0, errors.New("missing op") + } + + var key, value string + var op eacl.Match + + if 0 < i && s[i-1] == '!' { + key = s[:i-1] + op = eacl.MatchStringNotEqual + } else { + key = s[:i] + op = eacl.MatchStringEqual + } + + value = s[i+1:] + + return key, value, op, nil +} + // eaclRoleFromString parses eacl.Role from string. func eaclRoleFromString(s string) (eacl.Role, error) { var r eacl.Role diff --git a/cmd/neofs-cli/modules/util/acl_test.go b/cmd/neofs-cli/modules/util/acl_test.go new file mode 100644 index 00000000000..92bdcefa6ff --- /dev/null +++ b/cmd/neofs-cli/modules/util/acl_test.go @@ -0,0 +1,70 @@ +package util + +import ( + "testing" + + "github.com/nspcc-dev/neofs-sdk-go/eacl" + "github.com/stretchr/testify/require" +) + +func TestParseKVWithOp(t *testing.T) { + for _, tc := range []struct { + s string + k string + op eacl.Match + v string + }{ + {"=", "", eacl.MatchStringEqual, ""}, + {"!=", "", eacl.MatchStringNotEqual, ""}, + {">=", ">", eacl.MatchStringEqual, ""}, + {"=>", "", eacl.MatchStringEqual, ">"}, + {"<=", "<", eacl.MatchStringEqual, ""}, + {"=<", "", eacl.MatchStringEqual, "<"}, + {"key=", "key", eacl.MatchStringEqual, ""}, + {"key>=", "key>", eacl.MatchStringEqual, ""}, + {"key<=", "key<", eacl.MatchStringEqual, ""}, + {"=value", "", eacl.MatchStringEqual, "value"}, + {"!=value", "", eacl.MatchStringNotEqual, "value"}, + {"key=value", "key", eacl.MatchStringEqual, "value"}, + {"key==value", "key", eacl.MatchStringEqual, "=value"}, + {"key=>value", "key", eacl.MatchStringEqual, ">value"}, + {"key>=value", "key>", eacl.MatchStringEqual, "value"}, + {"key<=value", "key<", eacl.MatchStringEqual, "value"}, + {"key=", "missing op"}, + {"<", "missing op"}, + {"k", "missing op"}, + {"k!", "missing op"}, + {"k>", "missing op"}, + {"k<", "missing op"}, + {"k!v", "missing op"}, + {"kv", "missing op"}, + } { + _, _, _, err := parseKVWithOp(tc.s) + require.ErrorContains(t, err, tc.e, tc) + } +}