diff --git a/datatrails-common-api/assets/v2/assets/listevents.proto b/datatrails-common-api/assets/v2/assets/listevents.proto index c6847d9..1240175 100644 --- a/datatrails-common-api/assets/v2/assets/listevents.proto +++ b/datatrails-common-api/assets/v2/assets/listevents.proto @@ -142,6 +142,13 @@ message ListEventsRequest { // filter events by mmr index optional int64 mmr_index = 24 [(validate.rules).int64.gte = 0]; + + // filter from wallet address + optional string from = 25 [ + (validate.rules).string = { + pattern: "^0x[[:xdigit:]]+$" + } + ]; } message ListEventsResponse { diff --git a/datatrails-common-api/marshalers/query/attributeparser.go b/datatrails-common-api/marshalers/query/attributeparser.go index 7b3e62e..a1f73b7 100644 --- a/datatrails-common-api/marshalers/query/attributeparser.go +++ b/datatrails-common-api/marshalers/query/attributeparser.go @@ -264,15 +264,15 @@ func getFilterParts(spec string) ([]string, error) { filters := []string{} // greedy match for stuff surrounded by single quotes - matchQuote := `'((?:[^']|.)*)'` + matchQuote := `'((?:[^'\\]|\\.)*)'` q, err := regexp.Compile(matchQuote) if err != nil { return filters, err } // match fiter-ish thing - some attribute equals to a value in quotes with spaces - // or continues string - matchTerm := `(\S+?)=(('.+')|(\S+?))(\s|$)` + // or continous string + matchTerm := `(\S+?)=(('((?:[^'\\]|\\.)*)')|(\S+?))(\s|$)` r, err := regexp.Compile(matchTerm) if err != nil { return filters, err @@ -285,8 +285,9 @@ func getFilterParts(spec string) ([]string, error) { term := r.FindStringSubmatch(filterSpec) // trim excessive unquoted spaces and trim the part we're processing filterSpec = strings.TrimSpace(strings.TrimPrefix(filterSpec, term[0])) - // trim outer quotes if they are present + // trim outer quotes if they are present and replace the escape sequences t := q.ReplaceAllString(term[2], "$1") + t = strings.ReplaceAll(t, "\\'", "'") // append our new term to filters list filters = append(filters, fmt.Sprintf("%s=%s", strings.TrimSpace(term[1]), t)) // check if we have anything left @@ -294,7 +295,7 @@ func getFilterParts(spec string) ([]string, error) { // if we have an or we remove it, otherwise we fail // as we have some additonal unexpected text if !strings.HasPrefix(strings.ToLower(filterSpec), "or ") { - return filters, fmt.Errorf("malformd filter") + return filters, fmt.Errorf("malformed filter") } filterSpec = filterSpec[3:] } diff --git a/datatrails-common-api/marshalers/query/attributeparser_test.go b/datatrails-common-api/marshalers/query/attributeparser_test.go index 184202e..832c4f5 100644 --- a/datatrails-common-api/marshalers/query/attributeparser_test.go +++ b/datatrails-common-api/marshalers/query/attributeparser_test.go @@ -32,9 +32,9 @@ func TestFilterParsing(t *testing.T) { { name: "test multiple or", message: &assets.ListAssetsRequest{}, - values: map[string][]string{"filters": {"attributes.foo=2 OR attributes.bar=2", "attributes.foo=dd OR attributes.bar=77"}}, + values: map[string][]string{"filters": {"attributes.foo='2' OR attributes.bar=2", "attributes.foo='dd xx' OR attributes.bar='77'"}}, parser: &runtime.DefaultQueryParser{}, - expectedResult: [][]string{{"attributes.foo=2", "attributes.bar=2"}, {"attributes.foo=dd", "attributes.bar=77"}}, + expectedResult: [][]string{{"attributes.foo=2", "attributes.bar=2"}, {"attributes.foo=dd xx", "attributes.bar=77"}}, }, { name: "test or *", @@ -118,12 +118,12 @@ func TestGetFilterParts(t *testing.T) { }, { name: "test different cases", - filterSpec: "attributes.foo=2 OR attributes.bar=' stuff or 245677 some 'other' stuff' oR foo.bar=single or bar.baz=popmo Or pop=push_1", + filterSpec: `attributes.foo=2 OR attributes.bar=' stuff or 245677 some \'other\' stuff' oR foo.bar=single or bar.baz=popmo Or pop=push_1`, expectedResult: []string{"attributes.foo=2", "attributes.bar= stuff or 245677 some 'other' stuff", "foo.bar=single", "bar.baz=popmo", "pop=push_1"}, }, { name: "test quoted", - filterSpec: "attributes.foo=2 or attributes.bar=''something' or = 'else''", + filterSpec: "attributes.foo=2 or attributes.bar='\\'something\\' or = \\'else\\''", expectedResult: []string{"attributes.foo=2", "attributes.bar='something' or = 'else'"}, }, {