From 0c1ccf1f041cc0d5e94e81bd20784c200cc9e20f Mon Sep 17 00:00:00 2001 From: Felix Gateru Date: Wed, 25 Feb 2026 11:59:43 +0300 Subject: [PATCH] MG-408 - Fix client authentication in readers (#409) Signed-off-by: Felix Gateru --- readers/api/http/endpoint_test.go | 892 ++++++++++++++---------------- readers/api/http/transport.go | 4 +- 2 files changed, 421 insertions(+), 475 deletions(-) diff --git a/readers/api/http/endpoint_test.go b/readers/api/http/endpoint_test.go index 5c4992229..37abc0774 100644 --- a/readers/api/http/endpoint_test.go +++ b/readers/api/http/endpoint_test.go @@ -138,23 +138,23 @@ func TestReadAll(t *testing.T) { defer ts.Close() cases := []struct { - desc string - req string - url string - token string - key string - authResponse bool - status int - res pageRes - authnErr error - err error + desc string + req string + url string + token string + key string + status int + res pageRes + authnErr error + authzRes *grpcChannelsV1.AuthzRes + authzErr error + err error }{ { - desc: "read page with valid offset and limit", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with valid offset and limit", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -162,11 +162,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with valid offset and limit as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with valid offset and limit as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -174,76 +173,66 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with negative offset as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=-1&limit=10", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with negative offset as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=-1&limit=10", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with negative limit as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=-10", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with negative limit as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=-10", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with zero limit as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=0", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with zero limit as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=0", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with non-integer offset as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=abc&limit=10", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-integer offset as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=abc&limit=10", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with non-integer limit as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=abc", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-integer limit as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=abc", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with invalid channel id as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, ""), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with invalid channel id as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, ""), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with multiple offset as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&offset=1&limit=10", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with multiple offset as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&offset=1&limit=10", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with multiple limit as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=20&limit=10", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with multiple limit as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=20&limit=10", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with empty token as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), - token: "", - authResponse: false, - authnErr: svcerr.ErrAuthentication, - status: http.StatusUnauthorized, - err: svcerr.ErrAuthentication, + desc: "read page with empty token as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), + token: "", + authnErr: svcerr.ErrAuthentication, + status: http.StatusUnauthorized, + err: svcerr.ErrAuthentication, }, { - desc: "read page with default offset as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?limit=10", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with default offset as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?limit=10", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -251,11 +240,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with default limit as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with default limit as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -263,11 +251,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with senml format as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?format=messages", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with senml format as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?format=messages", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -275,11 +262,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with subtopic as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, domainID, chanID, subtopic, httpProt), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with subtopic as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, domainID, chanID, subtopic, httpProt), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Subtopic: subtopic, Format: "messages", Protocol: httpProt, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -287,11 +273,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with subtopic and protocol as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, domainID, chanID, subtopic, httpProt), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with subtopic and protocol as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, domainID, chanID, subtopic, httpProt), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Subtopic: subtopic, Format: "messages", Protocol: httpProt, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -299,11 +284,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with publisher as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?publisher=%s", ts.URL, domainID, chanID, pubID2), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with publisher as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?publisher=%s", ts.URL, domainID, chanID, pubID2), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Publisher: pubID2, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -311,11 +295,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with protocol as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?protocol=http", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with protocol as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?protocol=http", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Protocol: httpProt, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -323,11 +306,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with name as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?name=%s", ts.URL, domainID, chanID, msgName), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with name as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?name=%s", ts.URL, domainID, chanID, msgName), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Name: msgName, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -335,11 +317,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f", ts.URL, domainID, chanID, v), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f", ts.URL, domainID, chanID, v), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -347,11 +328,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and equal comparator as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v, readers.EqualKey), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value and equal comparator as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v, readers.EqualKey), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v, Comparator: readers.EqualKey, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -359,11 +339,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and lower-than comparator as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v+1, readers.LowerThanKey), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value and lower-than comparator as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v+1, readers.LowerThanKey), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v + 1, Comparator: readers.LowerThanKey, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -371,11 +350,11 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and lower-than-or-equal comparator as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v+1, readers.LowerThanEqualKey), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value and lower-than-or-equal comparator as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v+1, readers.LowerThanEqualKey), + key: clientToken, + + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v + 1, Comparator: readers.LowerThanEqualKey, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -383,11 +362,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and greater-than comparator as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v-1, readers.GreaterThanKey), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value and greater-than comparator as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v-1, readers.GreaterThanKey), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v - 1, Comparator: readers.GreaterThanKey, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -395,11 +373,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and greater-than-or-equal comparator as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v-1, readers.GreaterThanEqualKey), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value and greater-than-or-equal comparator as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v-1, readers.GreaterThanEqualKey), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v - 1, Comparator: readers.GreaterThanEqualKey, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -407,25 +384,22 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with non-float value as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=ab01", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-float value as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=ab01", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with value and wrong comparator as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=wrong", ts.URL, domainID, chanID, v-1), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with value and wrong comparator as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=wrong", ts.URL, domainID, chanID, v-1), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with boolean value as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=true", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with boolean value as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=true", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", BoolValue: true, Order: "time", Dir: "desc"}, Total: uint64(len(boolMsgs)), @@ -433,18 +407,16 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with non-boolean value as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=yes", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-boolean value as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=yes", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with string value as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?vs=%s", ts.URL, domainID, chanID, vs), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with string value as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?vs=%s", ts.URL, domainID, chanID, vs), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", StringValue: vs, Order: "time", Dir: "desc"}, Total: uint64(len(stringMsgs)), @@ -452,11 +424,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with data value as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?vd=%s", ts.URL, domainID, chanID, vd), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with data value as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?vd=%s", ts.URL, domainID, chanID, vd), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", DataValue: vd, Order: "time", Dir: "desc"}, Total: uint64(len(dataMsgs)), @@ -464,25 +435,22 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with non-float from as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?from=ABCD", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-float from as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?from=ABCD", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with non-float to as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?to=ABCD", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-float to as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?to=ABCD", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with from/to as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with from/to as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", From: messages[19].Time, To: messages[4].Time, Order: "time", Dir: "desc"}, Total: uint64(len(messages[5:20])), @@ -490,18 +458,16 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with aggregation as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with interval as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?interval=10h", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with interval as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?interval=10h", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -509,67 +475,57 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with aggregation and interval as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h", ts.URL, domainID, chanID), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation and interval as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h", ts.URL, domainID, chanID), + key: clientToken, + status: http.StatusBadRequest, }, - { - desc: "read page with aggregation, interval, to and from as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), - key: clientToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with aggregation, interval, to and from as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), + key: clientToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Aggregation: "MAX", Interval: "10h", From: messages[19].Time, To: messages[4].Time, Order: "time", Dir: "desc"}, Total: uint64(len(messages[5:20])), Messages: messages[5:15], }, }, - { - desc: "read page with invalid aggregation and valid interval, to and from as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=invalid&interval=10h&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with invalid aggregation and valid interval, to and from as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=invalid&interval=10h&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with invalid interval and valid aggregation, to and from as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10hrs&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with invalid interval and valid aggregation, to and from as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10hrs&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with aggregation, interval and to with missing from as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=%f", ts.URL, domainID, chanID, messages[4].Time), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation, interval and to with missing from as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=%f", ts.URL, domainID, chanID, messages[4].Time), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with aggregation, interval and to with invalid from as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=ABCD&from=%f", ts.URL, domainID, chanID, messages[4].Time), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation, interval and to with invalid from as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=ABCD&from=%f", ts.URL, domainID, chanID, messages[4].Time), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with aggregation, interval and to with invalid to as client", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=ABCD", ts.URL, domainID, chanID, messages[4].Time), - key: clientToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation, interval and to with invalid to as client", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=ABCD", ts.URL, domainID, chanID, messages[4].Time), + key: clientToken, + status: http.StatusBadRequest, }, { - desc: "read page with valid offset and limit as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with valid offset and limit as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -577,83 +533,99 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with negative offset as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=-1&limit=10", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with invalid client key", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), + key: "invalid", + authnErr: svcerr.ErrAuthentication, + status: http.StatusUnauthorized, + err: svcerr.ErrAuthentication, }, { - desc: "read page with negative limit as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=-10", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with unauthorized client key", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), + key: clientToken, + authnErr: nil, + authzRes: &grpcChannelsV1.AuthzRes{Authorized: false}, + status: http.StatusForbidden, + err: svcerr.ErrAuthorization, }, { - desc: "read page with zero limit as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=0", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with negative offset as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=-1&limit=10", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with non-integer offset as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=abc&limit=10", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with negative limit as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=-10", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with non-integer limit as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=abc", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with zero limit as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=0", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with invalid channel id as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, ""), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-integer offset as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=abc&limit=10", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with invalid token as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), - token: invalidToken, - authResponse: false, - status: http.StatusForbidden, - err: svcerr.ErrAuthorization, + desc: "read page with non-integer limit as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=abc", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with multiple offset as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&offset=1&limit=10", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with invalid channel id as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, ""), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with multiple limit as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=20&limit=10", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with invalid token as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), + token: invalidToken, + authnErr: svcerr.ErrAuthentication, + status: http.StatusUnauthorized, + err: svcerr.ErrAuthorization, }, { - desc: "read page with empty token as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), - token: "", - authResponse: false, - status: http.StatusUnauthorized, - err: svcerr.ErrAuthorization, + desc: "read page with unauthorized as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), + token: userToken, + authzRes: &grpcChannelsV1.AuthzRes{Authorized: false}, + status: http.StatusForbidden, + err: svcerr.ErrAuthorization, }, { - desc: "read page with default offset as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?limit=10", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with multiple offset as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&offset=1&limit=10", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, + }, + { + desc: "read page with multiple limit as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=20&limit=10", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, + }, + { + desc: "read page with empty token as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID), + token: "", + authnErr: svcerr.ErrAuthentication, + status: http.StatusUnauthorized, + err: svcerr.ErrAuthorization, + }, + { + desc: "read page with default offset as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?limit=10", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -661,11 +633,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with default limit as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with default limit as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -673,11 +644,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with senml format as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?format=messages", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with senml format as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?format=messages", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -685,11 +655,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with subtopic as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, domainID, chanID, subtopic, httpProt), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with subtopic as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, domainID, chanID, subtopic, httpProt), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Subtopic: subtopic, Protocol: httpProt, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -697,11 +666,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with subtopic and protocol as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, domainID, chanID, subtopic, httpProt), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with subtopic and protocol as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, domainID, chanID, subtopic, httpProt), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Subtopic: subtopic, Protocol: httpProt, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -709,11 +677,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with publisher as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?publisher=%s", ts.URL, domainID, chanID, pubID2), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with publisher as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?publisher=%s", ts.URL, domainID, chanID, pubID2), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Publisher: pubID2, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -721,11 +688,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with protocol as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?protocol=http", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with protocol as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?protocol=http", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Protocol: httpProt, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -733,11 +699,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with name as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?name=%s", ts.URL, domainID, chanID, msgName), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with name as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?name=%s", ts.URL, domainID, chanID, msgName), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Name: msgName, Order: "time", Dir: "desc"}, Total: uint64(len(queryMsgs)), @@ -745,11 +710,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f", ts.URL, domainID, chanID, v), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f", ts.URL, domainID, chanID, v), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -757,11 +721,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and equal comparator as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v, readers.EqualKey), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value and equal comparator as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v, readers.EqualKey), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v, Comparator: readers.EqualKey, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -769,11 +732,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and lower-than comparator as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v+1, readers.LowerThanKey), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value and lower-than comparator as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v+1, readers.LowerThanKey), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v + 1, Comparator: readers.LowerThanKey, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -781,11 +743,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and lower-than-or-equal comparator as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v+1, readers.LowerThanEqualKey), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value and lower-than-or-equal comparator as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v+1, readers.LowerThanEqualKey), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Value: v + 1, Comparator: readers.LowerThanEqualKey, Order: "time", Dir: "desc"}, Total: uint64(len(valueMsgs)), @@ -793,11 +754,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and greater-than comparator as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v-1, readers.GreaterThanKey), - token: userToken, - status: http.StatusOK, - authResponse: true, + desc: "read page with value and greater-than comparator as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v-1, readers.GreaterThanKey), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Order: "time", Dir: "desc", Format: "messages", Value: v - 1, Comparator: readers.GreaterThanKey}, Total: uint64(len(valueMsgs)), @@ -805,11 +765,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with value and greater-than-or-equal comparator as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v-1, readers.GreaterThanEqualKey), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with value and greater-than-or-equal comparator as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, domainID, chanID, v-1, readers.GreaterThanEqualKey), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Order: "time", Dir: "desc", Limit: 10, Format: "messages", Value: v - 1, Comparator: readers.GreaterThanEqualKey}, Total: uint64(len(valueMsgs)), @@ -817,25 +776,22 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with non-float value as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=ab01", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-float value as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=ab01", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with value and wrong comparator as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=wrong", ts.URL, domainID, chanID, v-1), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with value and wrong comparator as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=wrong", ts.URL, domainID, chanID, v-1), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with boolean value as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=true", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with boolean value as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=true", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", BoolValue: true, Order: "time", Dir: "desc"}, Total: uint64(len(boolMsgs)), @@ -843,18 +799,16 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with non-boolean value as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=yes", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-boolean value as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=yes", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with string value as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?vs=%s", ts.URL, domainID, chanID, vs), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with string value as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?vs=%s", ts.URL, domainID, chanID, vs), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", StringValue: vs, Order: "time", Dir: "desc"}, Total: uint64(len(stringMsgs)), @@ -862,11 +816,10 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with data value as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?vd=%s", ts.URL, domainID, chanID, vd), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with data value as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?vd=%s", ts.URL, domainID, chanID, vd), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", DataValue: vd, Order: "time", Dir: "desc"}, Total: uint64(len(dataMsgs)), @@ -874,25 +827,22 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with non-float from as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?from=ABCD", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-float from as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?from=ABCD", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with non-float to as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?to=ABCD", ts.URL, domainID, chanID), - token: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with non-float to as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?to=ABCD", ts.URL, domainID, chanID), + token: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with from/to as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), - token: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with from/to as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), + token: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", From: messages[19].Time, To: messages[4].Time, Order: "time", Dir: "desc"}, Total: uint64(len(messages[5:20])), @@ -900,18 +850,16 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with aggregation as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX", ts.URL, domainID, chanID), - key: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX", ts.URL, domainID, chanID), + key: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with interval as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?interval=10h", ts.URL, domainID, chanID), - key: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with interval as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?interval=10h", ts.URL, domainID, chanID), + key: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Order: "time", Dir: "desc"}, Total: uint64(len(messages)), @@ -919,18 +867,16 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with aggregation and interval as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h", ts.URL, domainID, chanID), - key: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation and interval as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h", ts.URL, domainID, chanID), + key: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with aggregation, interval, to and from as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), - key: userToken, - authResponse: true, - status: http.StatusOK, + desc: "read page with aggregation, interval, to and from as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), + key: userToken, + status: http.StatusOK, res: pageRes{ PageMetadata: readers.PageMetadata{Limit: 10, Format: "messages", Aggregation: "MAX", Interval: "10h", From: messages[19].Time, To: messages[4].Time, Order: "time", Dir: "desc"}, Total: uint64(len(messages[5:20])), @@ -938,71 +884,71 @@ func TestReadAll(t *testing.T) { }, }, { - desc: "read page with invalid aggregation and valid interval, to and from as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=invalid&interval=10h&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), - key: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with invalid aggregation and valid interval, to and from as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=invalid&interval=10h&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), + key: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with invalid interval and valid aggregation, to and from as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10hrs&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), - key: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with invalid interval and valid aggregation, to and from as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10hrs&from=%f&to=%f", ts.URL, domainID, chanID, messages[19].Time, messages[4].Time), + key: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with aggregation, interval and to with missing from as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=%f", ts.URL, domainID, chanID, messages[4].Time), - key: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation, interval and to with missing from as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=%f", ts.URL, domainID, chanID, messages[4].Time), + key: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with aggregation, interval and to with invalid from as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=ABCD&from=%f", ts.URL, domainID, chanID, messages[4].Time), - key: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation, interval and to with invalid from as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=ABCD&from=%f", ts.URL, domainID, chanID, messages[4].Time), + key: userToken, + status: http.StatusBadRequest, }, { - desc: "read page with aggregation, interval and to with invalid to as user", - url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=ABCD", ts.URL, domainID, chanID, messages[4].Time), - key: userToken, - authResponse: true, - status: http.StatusBadRequest, + desc: "read page with aggregation, interval and to with invalid to as user", + url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=ABCD", ts.URL, domainID, chanID, messages[4].Time), + key: userToken, + status: http.StatusBadRequest, }, } for _, tc := range cases { - authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(validSession, tc.authnErr) - if tc.key != "" { - authnCall = clients.On("Authenticate", mock.Anything, &grpcClientsV1.AuthnReq{ - Token: smqauthn.AuthPack(smqauthn.DomainAuth, chanID, tc.key), - }).Return(&grpcClientsV1.AuthnRes{Id: testsutil.GenerateUUID(t), Authenticated: true}, tc.authnErr) - } - authzCall := channels.On("Authorize", mock.Anything, mock.Anything).Return(&grpcChannelsV1.AuthzRes{Authorized: true}, tc.err) - repoCall := repo.On("ReadAll", chanID, tc.res.PageMetadata).Return(readers.MessagesPage{Total: tc.res.Total, Messages: fromSenml(tc.res.Messages)}, nil) - req := testRequest{ - client: ts.Client(), - method: http.MethodGet, - url: tc.url, - token: tc.token, - key: tc.key, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + t.Run(tc.desc, func(t *testing.T) { + authnCall := authn.On("Authenticate", mock.Anything, tc.token).Return(validSession, tc.authnErr) + if tc.key != "" { + authnCall = clients.On("Authenticate", mock.Anything, &grpcClientsV1.AuthnReq{ + Token: smqauthn.AuthPack(smqauthn.DomainAuth, domainID, tc.key), + }).Return(&grpcClientsV1.AuthnRes{Id: testsutil.GenerateUUID(t), Authenticated: true}, tc.authnErr) + } + if tc.authzRes == nil { + tc.authzRes = &grpcChannelsV1.AuthzRes{Authorized: true} + } + authzCall := channels.On("Authorize", mock.Anything, mock.Anything).Return(tc.authzRes, tc.authzErr) + repoCall := repo.On("ReadAll", chanID, tc.res.PageMetadata).Return(readers.MessagesPage{Total: tc.res.Total, Messages: fromSenml(tc.res.Messages)}, nil) + req := testRequest{ + client: ts.Client(), + method: http.MethodGet, + url: tc.url, + token: tc.token, + key: tc.key, + } + res, err := req.make() + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - var page pageRes - err = json.NewDecoder(res.Body).Decode(&page) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected %d got %d", tc.desc, tc.status, res.StatusCode)) - assert.Equal(t, tc.res.Total, page.Total, fmt.Sprintf("%s: expected %d got %d", tc.desc, tc.res.Total, page.Total)) - assert.ElementsMatch(t, tc.res.Messages, page.Messages, fmt.Sprintf("%s: got incorrect body from response", tc.desc)) - authzCall.Unset() - authnCall.Unset() - repoCall.Unset() + var page pageRes + err = json.NewDecoder(res.Body).Decode(&page) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) + assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) + assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected %d got %d", tc.desc, tc.status, res.StatusCode)) + assert.Equal(t, tc.res.Total, page.Total, fmt.Sprintf("%s: expected %d got %d", tc.desc, tc.res.Total, page.Total)) + assert.ElementsMatch(t, tc.res.Messages, page.Messages, fmt.Sprintf("%s: got incorrect body from response", tc.desc)) + authzCall.Unset() + authnCall.Unset() + repoCall.Unset() + }) } } diff --git a/readers/api/http/transport.go b/readers/api/http/transport.go index 8c7620e0f..9b7964044 100644 --- a/readers/api/http/transport.go +++ b/readers/api/http/transport.go @@ -212,7 +212,7 @@ func encodeResponse(_ context.Context, w http.ResponseWriter, response any) erro func authnAuthz(ctx context.Context, req listMessagesReq, authn smqauthn.Authentication, clients grpcClientsV1.ClientsServiceClient, channels grpcChannelsV1.ChannelsServiceClient) error { clientID, clientType, err := authenticate(ctx, req, authn, clients) if err != nil { - return nil + return err } if err := authorize(ctx, clientID, clientType, req.chanID, req.domain, channels); err != nil { return err @@ -234,7 +234,7 @@ func authenticate(ctx context.Context, req listMessagesReq, authn smqauthn.Authe return policies.EncodeDomainUserID(req.domain, session.UserID), policies.UserType, nil case req.key != "": res, err := clients.Authenticate(ctx, &grpcClientsV1.AuthnReq{ - Token: smqauthn.AuthPack(smqauthn.DomainAuth, req.chanID, req.key), + Token: smqauthn.AuthPack(smqauthn.DomainAuth, req.domain, req.key), }) if err != nil { return "", "", err