mirror of
https://github.com/absmach/supermq.git
synced 2026-06-23 07:20:19 +00:00
MG-2507 - Update auth in readers service (#2514)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
This commit is contained in:
+10
-1
@@ -35,7 +35,7 @@ tags:
|
||||
url: https://docs.magistrala.abstractmachines.fr/
|
||||
|
||||
paths:
|
||||
/channels/{chanId}/messages:
|
||||
/{domainID}/channels/{chanId}/messages:
|
||||
get:
|
||||
operationId: getMessages
|
||||
summary: Retrieves messages sent to single channel
|
||||
@@ -47,6 +47,7 @@ paths:
|
||||
tags:
|
||||
- readers
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/DomainID"
|
||||
- $ref: "#/components/parameters/ChanId"
|
||||
- $ref: "#/components/parameters/Limit"
|
||||
- $ref: "#/components/parameters/Offset"
|
||||
@@ -141,6 +142,14 @@ components:
|
||||
description: Time of updating measurement.
|
||||
|
||||
parameters:
|
||||
DomainID:
|
||||
name: domainID
|
||||
description: Unique domain identifier.
|
||||
in: path
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
required: true
|
||||
ChanId:
|
||||
name: chanId
|
||||
description: Unique channel identifier.
|
||||
|
||||
+4
-4
@@ -28,13 +28,13 @@ var cmdMessages = []cobra.Command{
|
||||
},
|
||||
},
|
||||
{
|
||||
Use: "read <channel_id.subtopic> <user_token>",
|
||||
Use: "read <channel_id.subtopic> <domain_id> <user_token>",
|
||||
Short: "Read messages",
|
||||
Long: "Reads all channel messages\n" +
|
||||
"Usage:\n" +
|
||||
"\tmagistrala-cli messages read <channel_id.subtopic> <user_token> --offset <offset> --limit <limit> - lists all messages with provided offset and limit\n",
|
||||
"\tmagistrala-cli messages read <channel_id.subtopic> <domain_id> <user_token> --offset <offset> --limit <limit> - lists all messages with provided offset and limit\n",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 2 {
|
||||
if len(args) != 3 {
|
||||
logUsageCmd(*cmd, cmd.Use)
|
||||
return
|
||||
}
|
||||
@@ -45,7 +45,7 @@ var cmdMessages = []cobra.Command{
|
||||
},
|
||||
}
|
||||
|
||||
m, err := sdk.ReadMessages(pageMetadata, args[0], args[1])
|
||||
m, err := sdk.ReadMessages(pageMetadata, args[0], args[1], args[2])
|
||||
if err != nil {
|
||||
logErrorCmd(*cmd, err)
|
||||
return
|
||||
|
||||
+4
-1
@@ -104,6 +104,7 @@ func TestReadMesageCmd(t *testing.T) {
|
||||
desc: "read message successfully",
|
||||
args: []string{
|
||||
channel.ID,
|
||||
domainID,
|
||||
validToken,
|
||||
},
|
||||
page: mgsdk.MessagesPage{
|
||||
@@ -124,6 +125,7 @@ func TestReadMesageCmd(t *testing.T) {
|
||||
desc: "read message with invalid args",
|
||||
args: []string{
|
||||
channel.ID,
|
||||
domainID,
|
||||
validToken,
|
||||
extraArg,
|
||||
},
|
||||
@@ -133,6 +135,7 @@ func TestReadMesageCmd(t *testing.T) {
|
||||
desc: "read message with invalid token",
|
||||
args: []string{
|
||||
channel.ID,
|
||||
domainID,
|
||||
invalidToken,
|
||||
},
|
||||
sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized),
|
||||
@@ -143,7 +146,7 @@ func TestReadMesageCmd(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
sdkCall := sdkMock.On("ReadMessages", mock.Anything, tc.args[0], tc.args[1]).Return(tc.page, tc.sdkErr)
|
||||
sdkCall := sdkMock.On("ReadMessages", mock.Anything, tc.args[0], tc.args[1], tc.args[2]).Return(tc.page, tc.sdkErr)
|
||||
out := executeCommand(t, rootCmd, append([]string{readCmd}, tc.args...)...)
|
||||
|
||||
switch tc.logType {
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
chclient "github.com/absmach/callhome/pkg/client"
|
||||
"github.com/absmach/magistrala"
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
authsvcAuthn "github.com/absmach/magistrala/pkg/authn/authsvc"
|
||||
"github.com/absmach/magistrala/pkg/authz/authsvc"
|
||||
"github.com/absmach/magistrala/pkg/grpcclient"
|
||||
pgclient "github.com/absmach/magistrala/pkg/postgres"
|
||||
@@ -84,14 +85,14 @@ func main() {
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
authzCfg := grpcclient.Config{}
|
||||
if err := env.ParseWithOptions(&authzCfg, env.Options{Prefix: envPrefixAuth}); err != nil {
|
||||
clientCfg := grpcclient.Config{}
|
||||
if err := env.ParseWithOptions(&clientCfg, env.Options{Prefix: envPrefixAuth}); err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to load auth gRPC client configuration : %s", err))
|
||||
exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
authz, authzHandler, err := authsvc.NewAuthorization(ctx, authzCfg)
|
||||
authz, authzHandler, err := authsvc.NewAuthorization(ctx, clientCfg)
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
exitCode = 1
|
||||
@@ -100,6 +101,15 @@ func main() {
|
||||
defer authzHandler.Close()
|
||||
logger.Info("Authz successfully connected to auth gRPC server " + authzHandler.Secure())
|
||||
|
||||
authn, authnHandler, err := authsvcAuthn.NewAuthentication(ctx, clientCfg)
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
exitCode = 1
|
||||
return
|
||||
}
|
||||
defer authnHandler.Close()
|
||||
logger.Info("Authn successfully connected to auth gRPC server " + authnHandler.Secure())
|
||||
|
||||
thingsClientCfg := grpcclient.Config{}
|
||||
if err := env.ParseWithOptions(&thingsClientCfg, env.Options{Prefix: envPrefixThings}); err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to load %s auth configuration : %s", svcName, err))
|
||||
@@ -125,7 +135,7 @@ func main() {
|
||||
exitCode = 1
|
||||
return
|
||||
}
|
||||
hs := httpserver.NewServer(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, authz, thingsClient, svcName, cfg.InstanceID), logger)
|
||||
hs := httpserver.NewServer(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, authn, authz, thingsClient, svcName, cfg.InstanceID), logger)
|
||||
|
||||
if cfg.SendTelemetry {
|
||||
chc := chclient.New(svcName, magistrala.Version, logger, cancel)
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
chclient "github.com/absmach/callhome/pkg/client"
|
||||
"github.com/absmach/magistrala"
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
authsvcAuthn "github.com/absmach/magistrala/pkg/authn/authsvc"
|
||||
"github.com/absmach/magistrala/pkg/authz/authsvc"
|
||||
"github.com/absmach/magistrala/pkg/grpcclient"
|
||||
pgclient "github.com/absmach/magistrala/pkg/postgres"
|
||||
@@ -84,14 +85,14 @@ func main() {
|
||||
|
||||
repo := newService(db, logger)
|
||||
|
||||
authzCfg := grpcclient.Config{}
|
||||
if err := env.ParseWithOptions(&authzCfg, env.Options{Prefix: envPrefixAuth}); err != nil {
|
||||
clientCfg := grpcclient.Config{}
|
||||
if err := env.ParseWithOptions(&clientCfg, env.Options{Prefix: envPrefixAuth}); err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to load auth gRPC client configuration : %s", err))
|
||||
exitCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
authz, authzHandler, err := authsvc.NewAuthorization(ctx, authzCfg)
|
||||
authz, authzHandler, err := authsvc.NewAuthorization(ctx, clientCfg)
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
exitCode = 1
|
||||
@@ -100,6 +101,15 @@ func main() {
|
||||
defer authzHandler.Close()
|
||||
logger.Info("Authz successfully connected to auth gRPC server " + authzHandler.Secure())
|
||||
|
||||
authn, authnHandler, err := authsvcAuthn.NewAuthentication(ctx, clientCfg)
|
||||
if err != nil {
|
||||
logger.Error(err.Error())
|
||||
exitCode = 1
|
||||
return
|
||||
}
|
||||
defer authnHandler.Close()
|
||||
logger.Info("Authn successfully connected to auth gRPC server " + authnHandler.Secure())
|
||||
|
||||
thingsClientCfg := grpcclient.Config{}
|
||||
if err := env.ParseWithOptions(&thingsClientCfg, env.Options{Prefix: envPrefixThings}); err != nil {
|
||||
logger.Error(fmt.Sprintf("failed to load %s auth configuration : %s", svcName, err))
|
||||
@@ -123,7 +133,7 @@ func main() {
|
||||
exitCode = 1
|
||||
return
|
||||
}
|
||||
hs := httpserver.NewServer(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, authz, thingsClient, svcName, cfg.InstanceID), logger)
|
||||
hs := httpserver.NewServer(ctx, cancel, svcName, httpServerConfig, api.MakeHandler(repo, authn, authz, thingsClient, svcName, cfg.InstanceID), logger)
|
||||
|
||||
if cfg.SendTelemetry {
|
||||
chc := chclient.New(svcName, magistrala.Version, logger, cancel)
|
||||
|
||||
@@ -13,8 +13,12 @@ import (
|
||||
bmocks "github.com/absmach/magistrala/bootstrap/mocks"
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
authnmocks "github.com/absmach/magistrala/pkg/authn/mocks"
|
||||
authzmocks "github.com/absmach/magistrala/pkg/authz/mocks"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
sdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
readersapi "github.com/absmach/magistrala/readers/api"
|
||||
readersmocks "github.com/absmach/magistrala/readers/mocks"
|
||||
thmocks "github.com/absmach/magistrala/things/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -31,7 +35,7 @@ func TestHealth(t *testing.T) {
|
||||
bootstrapTs := setupMinimalBootstrap()
|
||||
defer bootstrapTs.Close()
|
||||
|
||||
readerTs, _, _ := setupReader()
|
||||
readerTs := setupMinimalReader()
|
||||
defer readerTs.Close()
|
||||
|
||||
httpAdapterTs, _, _ := setupMessages()
|
||||
@@ -128,3 +132,13 @@ func setupMinimalBootstrap() *httptest.Server {
|
||||
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
func setupMinimalReader() *httptest.Server {
|
||||
repo := new(readersmocks.MessageRepository)
|
||||
authz := new(authzmocks.Authorization)
|
||||
authn := new(authnmocks.Authentication)
|
||||
things := new(thmocks.ThingsServiceClient)
|
||||
|
||||
mux := readersapi.MakeHandler(repo, authn, authz, things, "test", "")
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ func (sdk mgSDK) SendMessage(chanName, msg, key string) errors.SDKError {
|
||||
return err
|
||||
}
|
||||
|
||||
func (sdk mgSDK) ReadMessages(pm MessagePageMetadata, chanName, token string) (MessagesPage, errors.SDKError) {
|
||||
func (sdk mgSDK) ReadMessages(pm MessagePageMetadata, chanName, domainID, token string) (MessagesPage, errors.SDKError) {
|
||||
chanNameParts := strings.SplitN(chanName, ".", channelParts)
|
||||
chanID := chanNameParts[0]
|
||||
subtopicPart := ""
|
||||
@@ -40,7 +40,7 @@ func (sdk mgSDK) ReadMessages(pm MessagePageMetadata, chanName, token string) (M
|
||||
subtopicPart = fmt.Sprintf("?subtopic=%s", chanNameParts[1])
|
||||
}
|
||||
|
||||
readMessagesEndpoint := fmt.Sprintf("channels/%s/messages%s", chanID, subtopicPart)
|
||||
readMessagesEndpoint := fmt.Sprintf("%s/channels/%s/messages%s", domainID, chanID, subtopicPart)
|
||||
msgURL, err := sdk.withMessageQueryParams(sdk.readerURL, readMessagesEndpoint, pm)
|
||||
if err != nil {
|
||||
return MessagesPage{}, errors.NewSDKError(err)
|
||||
|
||||
@@ -14,6 +14,8 @@ import (
|
||||
"github.com/absmach/magistrala/http/api"
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
authnmocks "github.com/absmach/magistrala/pkg/authn/mocks"
|
||||
authzmocks "github.com/absmach/magistrala/pkg/authz/mocks"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
@@ -50,13 +52,14 @@ func setupMessages() (*httptest.Server, *thmocks.ThingsServiceClient, *pubsub.Pu
|
||||
return httptest.NewServer(http.HandlerFunc(mp.ServeHTTP)), things, pub
|
||||
}
|
||||
|
||||
func setupReader() (*httptest.Server, *authzmocks.Authorization, *readersmocks.MessageRepository) {
|
||||
func setupReader() (*httptest.Server, *authzmocks.Authorization, *authnmocks.Authentication, *readersmocks.MessageRepository) {
|
||||
repo := new(readersmocks.MessageRepository)
|
||||
authz := new(authzmocks.Authorization)
|
||||
authn := new(authnmocks.Authentication)
|
||||
things := new(thmocks.ThingsServiceClient)
|
||||
|
||||
mux := readersapi.MakeHandler(repo, authz, things, "test", "")
|
||||
return httptest.NewServer(mux), authz, repo
|
||||
mux := readersapi.MakeHandler(repo, authn, authz, things, "test", "")
|
||||
return httptest.NewServer(mux), authz, authn, repo
|
||||
}
|
||||
|
||||
func TestSendMessage(t *testing.T) {
|
||||
@@ -196,7 +199,7 @@ func TestSetContentType(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReadMessages(t *testing.T) {
|
||||
ts, authz, repo := setupReader()
|
||||
ts, authz, authn, repo := setupReader()
|
||||
defer ts.Close()
|
||||
|
||||
channelID := "channelID"
|
||||
@@ -220,8 +223,10 @@ func TestReadMessages(t *testing.T) {
|
||||
desc string
|
||||
token string
|
||||
chanName string
|
||||
domainID string
|
||||
messagePageMeta sdk.MessagePageMetadata
|
||||
authErr error
|
||||
authzErr error
|
||||
authnErr error
|
||||
repoRes readers.MessagesPage
|
||||
repoErr error
|
||||
response sdk.MessagesPage
|
||||
@@ -231,6 +236,7 @@ func TestReadMessages(t *testing.T) {
|
||||
desc: "read messages successfully",
|
||||
token: validToken,
|
||||
chanName: channelID,
|
||||
domainID: validID,
|
||||
messagePageMeta: sdk.MessagePageMetadata{
|
||||
PageMetadata: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
@@ -257,6 +263,7 @@ func TestReadMessages(t *testing.T) {
|
||||
desc: "read messages successfully with subtopic",
|
||||
token: validToken,
|
||||
chanName: channelID + ".subtopic",
|
||||
domainID: validID,
|
||||
messagePageMeta: sdk.MessagePageMetadata{
|
||||
PageMetadata: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
@@ -281,6 +288,7 @@ func TestReadMessages(t *testing.T) {
|
||||
desc: "read messages with invalid token",
|
||||
token: invalidToken,
|
||||
chanName: channelID,
|
||||
domainID: validID,
|
||||
messagePageMeta: sdk.MessagePageMetadata{
|
||||
PageMetadata: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
@@ -289,7 +297,7 @@ func TestReadMessages(t *testing.T) {
|
||||
Subtopic: "subtopic",
|
||||
Publisher: validID,
|
||||
},
|
||||
authErr: svcerr.ErrAuthorization,
|
||||
authzErr: svcerr.ErrAuthorization,
|
||||
repoRes: readers.MessagesPage{},
|
||||
response: sdk.MessagesPage{},
|
||||
err: errors.NewSDKErrorWithStatus(errors.Wrap(svcerr.ErrAuthorization, svcerr.ErrAuthorization), http.StatusUnauthorized),
|
||||
@@ -298,6 +306,7 @@ func TestReadMessages(t *testing.T) {
|
||||
desc: "read messages with empty token",
|
||||
token: "",
|
||||
chanName: channelID,
|
||||
domainID: validID,
|
||||
messagePageMeta: sdk.MessagePageMetadata{
|
||||
PageMetadata: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
@@ -306,7 +315,7 @@ func TestReadMessages(t *testing.T) {
|
||||
Subtopic: "subtopic",
|
||||
Publisher: validID,
|
||||
},
|
||||
authErr: svcerr.ErrAuthorization,
|
||||
authnErr: svcerr.ErrAuthentication,
|
||||
repoRes: readers.MessagesPage{},
|
||||
response: sdk.MessagesPage{},
|
||||
err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrBearerToken), http.StatusUnauthorized),
|
||||
@@ -315,6 +324,7 @@ func TestReadMessages(t *testing.T) {
|
||||
desc: "read messages with empty channel ID",
|
||||
token: validToken,
|
||||
chanName: "",
|
||||
domainID: validID,
|
||||
messagePageMeta: sdk.MessagePageMetadata{
|
||||
PageMetadata: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
@@ -332,6 +342,7 @@ func TestReadMessages(t *testing.T) {
|
||||
desc: "read messages with invalid message page metadata",
|
||||
token: validToken,
|
||||
chanName: channelID,
|
||||
domainID: validID,
|
||||
messagePageMeta: sdk.MessagePageMetadata{
|
||||
PageMetadata: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
@@ -352,6 +363,7 @@ func TestReadMessages(t *testing.T) {
|
||||
desc: "read messages with response that cannot be unmarshalled",
|
||||
token: validToken,
|
||||
chanName: channelID,
|
||||
domainID: validID,
|
||||
messagePageMeta: sdk.MessagePageMetadata{
|
||||
PageMetadata: sdk.PageMetadata{
|
||||
Offset: 0,
|
||||
@@ -371,9 +383,11 @@ func TestReadMessages(t *testing.T) {
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
authCall := authz.On("Authorize", mock.Anything, mock.Anything).Return(tc.authErr)
|
||||
authCall := authz.On("Authorize", mock.Anything, mock.Anything).Return(tc.authzErr)
|
||||
authCall1 := authn.On("Authenticate", mock.Anything, tc.token).Return(mgauthn.Session{UserID: validID}, tc.authnErr)
|
||||
repoCall := repo.On("ReadAll", channelID, mock.Anything).Return(tc.repoRes, tc.repoErr)
|
||||
response, err := mgsdk.ReadMessages(tc.messagePageMeta, tc.chanName, tc.token)
|
||||
response, err := mgsdk.ReadMessages(tc.messagePageMeta, tc.chanName, tc.domainID, tc.token)
|
||||
fmt.Println(err)
|
||||
assert.Equal(t, tc.err, err)
|
||||
assert.Equal(t, tc.response, response)
|
||||
if tc.err == nil {
|
||||
@@ -381,6 +395,7 @@ func TestReadMessages(t *testing.T) {
|
||||
assert.True(t, ok)
|
||||
}
|
||||
authCall.Unset()
|
||||
authCall1.Unset()
|
||||
repoCall.Unset()
|
||||
})
|
||||
}
|
||||
|
||||
+2
-2
@@ -884,9 +884,9 @@ type SDK interface {
|
||||
// Offset: 0,
|
||||
// Limit: 10,
|
||||
// }
|
||||
// msgs, _ := sdk.ReadMessages(pm,"channelID", "token")
|
||||
// msgs, _ := sdk.ReadMessages(pm,"channelID", "domainID", "token")
|
||||
// fmt.Println(msgs)
|
||||
ReadMessages(pm MessagePageMetadata, chanID, token string) (MessagesPage, errors.SDKError)
|
||||
ReadMessages(pm MessagePageMetadata, chanID, domainID, token string) (MessagesPage, errors.SDKError)
|
||||
|
||||
// SetContentType sets message content type.
|
||||
//
|
||||
|
||||
@@ -1820,9 +1820,9 @@ func (_m *SDK) Parents(id string, pm sdk.PageMetadata, domainID string, token st
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ReadMessages provides a mock function with given fields: pm, chanID, token
|
||||
func (_m *SDK) ReadMessages(pm sdk.MessagePageMetadata, chanID string, token string) (sdk.MessagesPage, errors.SDKError) {
|
||||
ret := _m.Called(pm, chanID, token)
|
||||
// ReadMessages provides a mock function with given fields: pm, chanID, domainID, token
|
||||
func (_m *SDK) ReadMessages(pm sdk.MessagePageMetadata, chanID string, domainID string, token string) (sdk.MessagesPage, errors.SDKError) {
|
||||
ret := _m.Called(pm, chanID, domainID, token)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ReadMessages")
|
||||
@@ -1830,17 +1830,17 @@ func (_m *SDK) ReadMessages(pm sdk.MessagePageMetadata, chanID string, token str
|
||||
|
||||
var r0 sdk.MessagesPage
|
||||
var r1 errors.SDKError
|
||||
if rf, ok := ret.Get(0).(func(sdk.MessagePageMetadata, string, string) (sdk.MessagesPage, errors.SDKError)); ok {
|
||||
return rf(pm, chanID, token)
|
||||
if rf, ok := ret.Get(0).(func(sdk.MessagePageMetadata, string, string, string) (sdk.MessagesPage, errors.SDKError)); ok {
|
||||
return rf(pm, chanID, domainID, token)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(sdk.MessagePageMetadata, string, string) sdk.MessagesPage); ok {
|
||||
r0 = rf(pm, chanID, token)
|
||||
if rf, ok := ret.Get(0).(func(sdk.MessagePageMetadata, string, string, string) sdk.MessagesPage); ok {
|
||||
r0 = rf(pm, chanID, domainID, token)
|
||||
} else {
|
||||
r0 = ret.Get(0).(sdk.MessagesPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(sdk.MessagePageMetadata, string, string) errors.SDKError); ok {
|
||||
r1 = rf(pm, chanID, token)
|
||||
if rf, ok := ret.Get(1).(func(sdk.MessagePageMetadata, string, string, string) errors.SDKError); ok {
|
||||
r1 = rf(pm, chanID, domainID, token)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(errors.SDKError)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/absmach/magistrala"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
mgauthz "github.com/absmach/magistrala/pkg/authz"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
@@ -15,14 +16,14 @@ import (
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
func listMessagesEndpoint(svc readers.MessageRepository, authz mgauthz.Authorization, thingsClient magistrala.ThingsServiceClient) endpoint.Endpoint {
|
||||
func listMessagesEndpoint(svc readers.MessageRepository, authn mgauthn.Authentication, authz mgauthz.Authorization, thingsClient magistrala.ThingsServiceClient) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(listMessagesReq)
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
if err := authorize(ctx, req, authz, thingsClient); err != nil {
|
||||
if err := authorize(ctx, req, authn, authz, thingsClient); err != nil {
|
||||
return nil, errors.Wrap(svcerr.ErrAuthorization, err)
|
||||
}
|
||||
|
||||
|
||||
+110
-96
@@ -14,6 +14,8 @@ import (
|
||||
"github.com/absmach/magistrala"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
authnmocks "github.com/absmach/magistrala/pkg/authn/mocks"
|
||||
authzmocks "github.com/absmach/magistrala/pkg/authz/mocks"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/transformers/senml"
|
||||
@@ -42,15 +44,17 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
v float64 = 5
|
||||
vs = "value"
|
||||
vb = true
|
||||
vd = "dataValue"
|
||||
sum float64 = 42
|
||||
v float64 = 5
|
||||
vs = "value"
|
||||
vb = true
|
||||
vd = "dataValue"
|
||||
sum float64 = 42
|
||||
domainID = testsutil.GenerateUUID(&testing.T{})
|
||||
validSession = mgauthn.Session{UserID: testsutil.GenerateUUID(&testing.T{})}
|
||||
)
|
||||
|
||||
func newServer(repo *mocks.MessageRepository, authz *authzmocks.Authorization, thingsAuthzClient *thmocks.ThingsServiceClient) *httptest.Server {
|
||||
mux := api.MakeHandler(repo, authz, thingsAuthzClient, svcName, instanceID)
|
||||
func newServer(repo *mocks.MessageRepository, authn *authnmocks.Authentication, authz *authzmocks.Authorization, thingsAuthzClient *thmocks.ThingsServiceClient) *httptest.Server {
|
||||
mux := api.MakeHandler(repo, authn, authz, thingsAuthzClient, svcName, instanceID)
|
||||
return httptest.NewServer(mux)
|
||||
}
|
||||
|
||||
@@ -129,8 +133,9 @@ func TestReadAll(t *testing.T) {
|
||||
|
||||
repo := new(mocks.MessageRepository)
|
||||
authz := new(authzmocks.Authorization)
|
||||
authn := new(authnmocks.Authentication)
|
||||
things := new(thmocks.ThingsServiceClient)
|
||||
ts := newServer(repo, authz, things)
|
||||
ts := newServer(repo, authn, authz, things)
|
||||
defer ts.Close()
|
||||
|
||||
cases := []struct {
|
||||
@@ -142,11 +147,12 @@ func TestReadAll(t *testing.T) {
|
||||
authResponse bool
|
||||
status int
|
||||
res pageRes
|
||||
authnErr error
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "read page with valid offset and limit",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -158,7 +164,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with valid offset and limit as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -168,73 +174,80 @@ func TestReadAll(t *testing.T) {
|
||||
Messages: messages[0:10],
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "read page as user without domain id",
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages", ts.URL, "", chanID),
|
||||
token: userToken,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with negative offset as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=-1&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=-1&limit=10", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with negative limit as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=-10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=-10", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with zero limit as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=0", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=0", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with non-integer offset as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=abc&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=abc&limit=10", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with non-integer limit as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=abc", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=abc", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with invalid channel id as thing",
|
||||
url: fmt.Sprintf("%s/channels//messages?offset=0&limit=10", ts.URL),
|
||||
url: fmt.Sprintf("%s/%s/channels//messages?offset=0&limit=10", ts.URL, ""),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with multiple offset as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&offset=1&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&offset=1&limit=10", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with multiple limit as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=20&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=20&limit=10", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with empty token as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, "", chanID),
|
||||
token: "",
|
||||
authResponse: false,
|
||||
authnErr: svcerr.ErrAuthentication,
|
||||
status: http.StatusUnauthorized,
|
||||
err: svcerr.ErrAuthorization,
|
||||
err: svcerr.ErrAuthentication,
|
||||
},
|
||||
{
|
||||
desc: "read page with default offset as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?limit=10", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -246,7 +259,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with default limit as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -258,7 +271,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with senml format as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?format=messages", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?format=messages", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -270,7 +283,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with subtopic as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, chanID, subtopic, httpProt),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, "", chanID, subtopic, httpProt),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -282,7 +295,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with subtopic and protocol as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, chanID, subtopic, httpProt),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, "", chanID, subtopic, httpProt),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -294,7 +307,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with publisher as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?publisher=%s", ts.URL, chanID, pubID2),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?publisher=%s", ts.URL, "", chanID, pubID2),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -304,10 +317,9 @@ func TestReadAll(t *testing.T) {
|
||||
Messages: queryMsgs[0:10],
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
desc: "read page with protocol as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?protocol=http", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?protocol=http", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -319,7 +331,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with name as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?name=%s", ts.URL, chanID, msgName),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?name=%s", ts.URL, "", chanID, msgName),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -331,7 +343,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f", ts.URL, chanID, v),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f", ts.URL, "", chanID, v),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -343,7 +355,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and equal comparator as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v, readers.EqualKey),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, "", chanID, v, readers.EqualKey),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -355,7 +367,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and lower-than comparator as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v+1, readers.LowerThanKey),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, "", chanID, v+1, readers.LowerThanKey),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -367,7 +379,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and lower-than-or-equal comparator as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v+1, readers.LowerThanEqualKey),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, "", chanID, v+1, readers.LowerThanEqualKey),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -379,7 +391,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and greater-than comparator as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v-1, readers.GreaterThanKey),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, "", chanID, v-1, readers.GreaterThanKey),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -391,7 +403,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and greater-than-or-equal comparator as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v-1, readers.GreaterThanEqualKey),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, "", chanID, v-1, readers.GreaterThanEqualKey),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -403,21 +415,21 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with non-float value as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=ab01", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?v=ab01", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with value and wrong comparator as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=wrong", ts.URL, chanID, v-1),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f&comparator=wrong", ts.URL, "", chanID, v-1),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with boolean value as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?vb=true", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=true", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -429,14 +441,14 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with non-boolean value as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?vb=yes", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=yes", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with string value as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?vs=%s", ts.URL, chanID, vs),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?vs=%s", ts.URL, "", chanID, vs),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -448,7 +460,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with data value as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?vd=%s", ts.URL, chanID, vd),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?vd=%s", ts.URL, "", chanID, vd),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -460,21 +472,21 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with non-float from as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?from=ABCD", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?from=ABCD", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with non-float to as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?to=ABCD", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?to=ABCD", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with from/to as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?from=%f&to=%f", ts.URL, "", chanID, messages[19].Time, messages[4].Time),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -486,14 +498,14 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with aggregation as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with interval as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?interval=10h", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?interval=10h", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -505,14 +517,14 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with aggregation and interval as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h", ts.URL, "", chanID),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with aggregation, interval, to and from as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=%f", ts.URL, "", chanID, messages[19].Time, messages[4].Time),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -524,42 +536,42 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with invalid aggregation and valid interval, to and from as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=invalid&interval=10h&from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=invalid&interval=10h&from=%f&to=%f", ts.URL, "", chanID, messages[19].Time, messages[4].Time),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with invalid interval and valid aggregation, to and from as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10hrs&from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10hrs&from=%f&to=%f", ts.URL, "", chanID, messages[19].Time, messages[4].Time),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with aggregation, interval and to with missing from as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h&to=%f", ts.URL, chanID, messages[4].Time),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=%f", ts.URL, "", chanID, messages[4].Time),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with aggregation, interval and to with invalid from as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h&to=ABCD&from=%f", ts.URL, chanID, messages[4].Time),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&to=ABCD&from=%f", ts.URL, "", chanID, messages[4].Time),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with aggregation, interval and to with invalid to as thing",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=ABCD", ts.URL, chanID, messages[4].Time),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=ABCD", ts.URL, "", chanID, messages[4].Time),
|
||||
key: thingToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with valid offset and limit as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -571,49 +583,49 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with negative offset as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=-1&limit=10", ts.URL, chanID),
|
||||
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 negative limit as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=-10", ts.URL, chanID),
|
||||
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 zero limit as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=0", ts.URL, chanID),
|
||||
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 non-integer offset as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=abc&limit=10", ts.URL, chanID),
|
||||
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 non-integer limit as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=abc", ts.URL, chanID),
|
||||
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 invalid channel id as user",
|
||||
url: fmt.Sprintf("%s/channels//messages?offset=0&limit=10", ts.URL),
|
||||
url: fmt.Sprintf("%s/%s/channels//messages?offset=0&limit=10", ts.URL, domainID),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
desc: "read page with invalid token as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID),
|
||||
token: invalidToken,
|
||||
authResponse: false,
|
||||
status: http.StatusUnauthorized,
|
||||
@@ -621,21 +633,21 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with multiple offset as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&offset=1&limit=10", ts.URL, chanID),
|
||||
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 multiple limit as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=20&limit=10", ts.URL, chanID),
|
||||
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 empty token as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0&limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0&limit=10", ts.URL, domainID, chanID),
|
||||
token: "",
|
||||
authResponse: false,
|
||||
status: http.StatusUnauthorized,
|
||||
@@ -643,7 +655,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with default offset as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?limit=10", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?limit=10", ts.URL, domainID, chanID),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -655,7 +667,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with default limit as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?offset=0", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?offset=0", ts.URL, domainID, chanID),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -667,7 +679,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with senml format as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?format=messages", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?format=messages", ts.URL, domainID, chanID),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -679,7 +691,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with subtopic as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, chanID, subtopic, httpProt),
|
||||
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,
|
||||
@@ -691,7 +703,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with subtopic and protocol as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?subtopic=%s&protocol=%s", ts.URL, chanID, subtopic, httpProt),
|
||||
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,
|
||||
@@ -703,7 +715,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with publisher as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?publisher=%s", ts.URL, chanID, pubID2),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?publisher=%s", ts.URL, domainID, chanID, pubID2),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -715,7 +727,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with protocol as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?protocol=http", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?protocol=http", ts.URL, domainID, chanID),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -727,7 +739,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with name as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?name=%s", ts.URL, chanID, msgName),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?name=%s", ts.URL, domainID, chanID, msgName),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -739,7 +751,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f", ts.URL, chanID, v),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?v=%f", ts.URL, domainID, chanID, v),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -751,7 +763,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and equal comparator as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v, readers.EqualKey),
|
||||
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,
|
||||
@@ -763,7 +775,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and lower-than comparator as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v+1, readers.LowerThanKey),
|
||||
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,
|
||||
@@ -775,7 +787,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and lower-than-or-equal comparator as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v+1, readers.LowerThanEqualKey),
|
||||
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,
|
||||
@@ -787,7 +799,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and greater-than comparator as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v-1, readers.GreaterThanKey),
|
||||
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,
|
||||
@@ -799,7 +811,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with value and greater-than-or-equal comparator as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=%s", ts.URL, chanID, v-1, readers.GreaterThanEqualKey),
|
||||
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,
|
||||
@@ -811,21 +823,21 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with non-float value as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=ab01", ts.URL, chanID),
|
||||
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 value and wrong comparator as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?v=%f&comparator=wrong", ts.URL, chanID, v-1),
|
||||
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 boolean value as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?vb=true", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?vb=true", ts.URL, domainID, chanID),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -837,14 +849,14 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with non-boolean value as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?vb=yes", ts.URL, chanID),
|
||||
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 string value as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?vs=%s", ts.URL, chanID, vs),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?vs=%s", ts.URL, domainID, chanID, vs),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -856,7 +868,7 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with data value as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?vd=%s", ts.URL, chanID, vd),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?vd=%s", ts.URL, domainID, chanID, vd),
|
||||
token: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -868,21 +880,21 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with non-float from as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?from=ABCD", ts.URL, chanID),
|
||||
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 to as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?to=ABCD", ts.URL, chanID),
|
||||
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 from/to as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
||||
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,
|
||||
@@ -894,14 +906,14 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with aggregation as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX", ts.URL, chanID),
|
||||
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 interval as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?interval=10h", ts.URL, chanID),
|
||||
url: fmt.Sprintf("%s/%s/channels/%s/messages?interval=10h", ts.URL, domainID, chanID),
|
||||
key: userToken,
|
||||
authResponse: true,
|
||||
status: http.StatusOK,
|
||||
@@ -913,14 +925,14 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with aggregation and interval as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h", ts.URL, chanID),
|
||||
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, interval, to and from as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
||||
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,
|
||||
@@ -932,35 +944,35 @@ func TestReadAll(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "read page with invalid aggregation and valid interval, to and from as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=invalid&interval=10h&from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
||||
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 interval and valid aggregation, to and from as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10hrs&from=%f&to=%f", ts.URL, chanID, messages[19].Time, messages[4].Time),
|
||||
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 aggregation, interval and to with missing from as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h&to=%f", ts.URL, chanID, messages[4].Time),
|
||||
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 invalid from as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h&to=ABCD&from=%f", ts.URL, chanID, messages[4].Time),
|
||||
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 to as user",
|
||||
url: fmt.Sprintf("%s/channels/%s/messages?aggregation=MAX&interval=10h&from=%f&to=ABCD", ts.URL, chanID, messages[4].Time),
|
||||
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,
|
||||
@@ -969,6 +981,7 @@ func TestReadAll(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
authCall := authz.On("Authorize", mock.Anything, mock.Anything).Return(tc.err)
|
||||
authCall1 := authn.On("Authenticate", mock.Anything, tc.token).Return(validSession, tc.authnErr)
|
||||
repo.On("ReadAll", chanID, tc.res.PageMetadata).Return(readers.MessagesPage{Total: tc.res.Total, Messages: fromSenml(tc.res.Messages)}, nil)
|
||||
if tc.key != "" {
|
||||
authCall = things.On("Authorize", mock.Anything, mock.Anything).Return(&magistrala.ThingsAuthzRes{Authorized: tc.authResponse}, tc.err)
|
||||
@@ -992,6 +1005,7 @@ func TestReadAll(t *testing.T) {
|
||||
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))
|
||||
authCall.Unset()
|
||||
authCall1.Unset()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ type listMessagesReq struct {
|
||||
chanID string
|
||||
token string
|
||||
key string
|
||||
domainID string
|
||||
pageMeta readers.PageMetadata
|
||||
}
|
||||
|
||||
@@ -27,6 +28,9 @@ func (req listMessagesReq) validate() error {
|
||||
if req.token == "" && req.key == "" {
|
||||
return apiutil.ErrBearerToken
|
||||
}
|
||||
if req.token != "" && req.domainID == "" {
|
||||
return apiutil.ErrMissingDomainID
|
||||
}
|
||||
|
||||
if req.chanID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
|
||||
+23
-21
@@ -10,9 +10,11 @@ import (
|
||||
|
||||
"github.com/absmach/magistrala"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
mgauthz "github.com/absmach/magistrala/pkg/authz"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/policies"
|
||||
"github.com/absmach/magistrala/readers"
|
||||
"github.com/go-chi/chi/v5"
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
@@ -43,26 +45,19 @@ const (
|
||||
defLimit = 10
|
||||
defOffset = 0
|
||||
defFormat = "messages"
|
||||
|
||||
tokenKind = "token"
|
||||
thingType = "thing"
|
||||
userType = "user"
|
||||
subscribePermission = "subscribe"
|
||||
viewPermission = "view"
|
||||
groupType = "group"
|
||||
)
|
||||
|
||||
var errUserAccess = errors.New("user has no permission")
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc readers.MessageRepository, authz mgauthz.Authorization, things magistrala.ThingsServiceClient, svcName, instanceID string) http.Handler {
|
||||
func MakeHandler(svc readers.MessageRepository, authn mgauthn.Authentication, authz mgauthz.Authorization, things magistrala.ThingsServiceClient, svcName, instanceID string) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(encodeError),
|
||||
}
|
||||
|
||||
mux := chi.NewRouter()
|
||||
mux.Get("/channels/{chanID}/messages", kithttp.NewServer(
|
||||
listMessagesEndpoint(svc, authz, things),
|
||||
mux.Get("/{domainID}/channels/{chanID}/messages", kithttp.NewServer(
|
||||
listMessagesEndpoint(svc, authn, authz, things),
|
||||
decodeList,
|
||||
encodeResponse,
|
||||
opts...,
|
||||
@@ -159,9 +154,10 @@ func decodeList(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
}
|
||||
|
||||
req := listMessagesReq{
|
||||
chanID: chi.URLParam(r, "chanID"),
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
key: apiutil.ExtractThingKey(r),
|
||||
chanID: chi.URLParam(r, "chanID"),
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
key: apiutil.ExtractThingKey(r),
|
||||
domainID: chi.URLParam(r, "domainID"),
|
||||
pageMeta: readers.PageMetadata{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
@@ -219,7 +215,8 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
errors.Contains(err, apiutil.ErrInvalidAggregation),
|
||||
errors.Contains(err, apiutil.ErrInvalidInterval),
|
||||
errors.Contains(err, apiutil.ErrMissingFrom),
|
||||
errors.Contains(err, apiutil.ErrMissingTo):
|
||||
errors.Contains(err, apiutil.ErrMissingTo),
|
||||
errors.Contains(err, apiutil.ErrMissingDomainID):
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
case errors.Contains(err, svcerr.ErrAuthentication),
|
||||
errors.Contains(err, svcerr.ErrAuthorization),
|
||||
@@ -242,15 +239,20 @@ func encodeError(_ context.Context, err error, w http.ResponseWriter) {
|
||||
}
|
||||
}
|
||||
|
||||
func authorize(ctx context.Context, req listMessagesReq, authz mgauthz.Authorization, things magistrala.ThingsServiceClient) (err error) {
|
||||
func authorize(ctx context.Context, req listMessagesReq, authn mgauthn.Authentication, authz mgauthz.Authorization, things magistrala.ThingsServiceClient) (err error) {
|
||||
switch {
|
||||
case req.token != "":
|
||||
session, err := authn.Authenticate(ctx, req.token)
|
||||
if err != nil {
|
||||
return errors.Wrap(svcerr.ErrAuthentication, err)
|
||||
}
|
||||
if err = authz.Authorize(ctx, mgauthz.PolicyReq{
|
||||
SubjectType: userType,
|
||||
SubjectKind: tokenKind,
|
||||
Subject: req.token,
|
||||
Permission: viewPermission,
|
||||
ObjectType: groupType,
|
||||
Domain: req.domainID,
|
||||
SubjectType: policies.UserType,
|
||||
SubjectKind: policies.UsersKind,
|
||||
Subject: req.domainID + "_" + session.UserID,
|
||||
Permission: policies.ViewPermission,
|
||||
ObjectType: policies.GroupType,
|
||||
Object: req.chanID,
|
||||
}); err != nil {
|
||||
e, ok := status.FromError(err)
|
||||
@@ -264,7 +266,7 @@ func authorize(ctx context.Context, req listMessagesReq, authz mgauthz.Authoriza
|
||||
if _, err = things.Authorize(ctx, &magistrala.ThingsAuthzReq{
|
||||
ThingKey: req.key,
|
||||
ChannelID: req.chanID,
|
||||
Permission: subscribePermission,
|
||||
Permission: policies.SubscribePermission,
|
||||
}); err != nil {
|
||||
e, ok := status.FromError(err)
|
||||
if ok && e.Code() == codes.PermissionDenied {
|
||||
|
||||
Reference in New Issue
Block a user