From ef82726e255797cfed00f084868827934dff8251 Mon Sep 17 00:00:00 2001 From: b1ackd0t <28790446+rodneyosodo@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:59:54 +0300 Subject: [PATCH] NOISSUE - Test e2e (#19) * fix: connect method Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * fix: e2e Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * fix changes in sdk and e2e Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * feat(docker): remove unnecessary port mapping Remove the port mapping for MQTT broker in the docker-compose.yml file. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * Enable group listing Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * feat(responses): update ChannelsPage struct The ChannelsPage struct in the responses.go file has been updated. The "Channels" field has been renamed to "Groups" to provide more accurate naming. This change ensures consistency and clarity in the codebase. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> * feat(things): add UpdateClientSecret method Add the UpdateClientSecret method to the things service. This method allows updating the client secret for a specific client identified by the provided token, id, and key parameters. Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> --------- Signed-off-by: Rodney Osodo <28790446+rodneyosodo@users.noreply.github.com> --- bootstrap/service.go | 12 ++++----- cli/provision.go | 55 +++++++++++++++++++++++---------------- cli/things.go | 12 ++++----- docker/docker-compose.yml | 2 -- pkg/sdk/go/policies.go | 6 ++--- pkg/sdk/go/requests.go | 10 +++---- pkg/sdk/go/responses.go | 2 +- pkg/sdk/go/sdk.go | 8 +++--- things/service.go | 2 +- tools/e2e/e2e.go | 33 ++++++++++++++--------- users/service.go | 13 ++++++--- 11 files changed, 89 insertions(+), 66 deletions(-) diff --git a/bootstrap/service.go b/bootstrap/service.go index c41becf703..4f0faf5da7 100644 --- a/bootstrap/service.go +++ b/bootstrap/service.go @@ -240,9 +240,9 @@ func (bs bootstrapService) UpdateConnections(ctx context.Context, token, id stri } for _, c := range connect { - conIDs := mfsdk.ConnectionIDs{ - ChannelIDs: []string{c}, - ThingIDs: []string{id}, + conIDs := mfsdk.Connection{ + ChannelID: c, + ThingID: id, } if err := bs.sdk.Connect(conIDs, token); err != nil { return ErrThings @@ -309,9 +309,9 @@ func (bs bootstrapService) ChangeState(ctx context.Context, token, id string, st switch state { case Active: for _, c := range cfg.Channels { - conIDs := mfsdk.ConnectionIDs{ - ChannelIDs: []string{c.ID}, - ThingIDs: []string{cfg.ThingID}, + conIDs := mfsdk.Connection{ + ChannelID: c.ID, + ThingID: cfg.ThingID, } if err := bs.sdk.Connect(conIDs, token); err != nil { return ErrThings diff --git a/cli/provision.go b/cli/provision.go index 5dc1f04c62..cc1544bbcf 100644 --- a/cli/provision.go +++ b/cli/provision.go @@ -95,12 +95,13 @@ var cmdProvision = []cobra.Command{ logError(err) return } - - err = sdk.Connect(connIDs, args[1]) - if err != nil { - logError(err) - return + for _, conn := range connIDs { + if err := sdk.Connect(conn, args[1]); err != nil { + logError(err) + return + } } + logOK() }, }, @@ -179,18 +180,27 @@ var cmdProvision = []cobra.Command{ } // Connect things to channels - first thing to both channels, second only to first - conIDs := mfxsdk.ConnectionIDs{ - ChannelIDs: []string{channels[0].ID, channels[1].ID}, - ThingIDs: []string{things[0].ID}, + conIDs := mfxsdk.Connection{ + ChannelID: channels[0].ID, + ThingID: things[0].ID, } if err := sdk.Connect(conIDs, ut.AccessToken); err != nil { logError(err) return } - conIDs = mfxsdk.ConnectionIDs{ - ChannelIDs: []string{channels[0].ID}, - ThingIDs: []string{things[1].ID}, + conIDs = mfxsdk.Connection{ + ChannelID: channels[1].ID, + ThingID: things[0].ID, + } + if err := sdk.Connect(conIDs, ut.AccessToken); err != nil { + logError(err) + return + } + + conIDs = mfxsdk.Connection{ + ChannelID: channels[0].ID, + ThingID: things[1].ID, } if err := sdk.Connect(conIDs, ut.AccessToken); err != nil { logError(err) @@ -311,18 +321,18 @@ func channelsFromFile(path string) ([]mfxsdk.Channel, error) { return channels, nil } -func connectionsFromFile(path string) (mfxsdk.ConnectionIDs, error) { +func connectionsFromFile(path string) ([]mfxsdk.Connection, error) { if _, err := os.Stat(path); os.IsNotExist(err) { - return mfxsdk.ConnectionIDs{}, err + return []mfxsdk.Connection{}, err } file, err := os.OpenFile(path, os.O_RDONLY, os.ModePerm) if err != nil { - return mfxsdk.ConnectionIDs{}, err + return []mfxsdk.Connection{}, err } defer file.Close() - connections := mfxsdk.ConnectionIDs{} + connections := []mfxsdk.Connection{} switch filepath.Ext(path) { case csvExt: reader := csv.NewReader(file) @@ -333,23 +343,24 @@ func connectionsFromFile(path string) (mfxsdk.ConnectionIDs, error) { break } if err != nil { - return mfxsdk.ConnectionIDs{}, err + return []mfxsdk.Connection{}, err } if len(l) < 1 { - return mfxsdk.ConnectionIDs{}, errors.New("empty line found in file") + return []mfxsdk.Connection{}, errors.New("empty line found in file") } - - connections.ThingIDs = append(connections.ThingIDs, l[0]) - connections.ChannelIDs = append(connections.ChannelIDs, l[1]) + connections = append(connections, mfxsdk.Connection{ + ThingID: l[0], + ChannelID: l[1], + }) } case jsonExt: err := json.NewDecoder(file).Decode(&connections) if err != nil { - return mfxsdk.ConnectionIDs{}, err + return []mfxsdk.Connection{}, err } default: - return mfxsdk.ConnectionIDs{}, err + return []mfxsdk.Connection{}, err } return connections, nil diff --git a/cli/things.go b/cli/things.go index 035a610be0..2a6bd45ed2 100644 --- a/cli/things.go +++ b/cli/things.go @@ -252,9 +252,9 @@ var cmdThings = []cobra.Command{ return } - connIDs := mfxsdk.ConnectionIDs{ - ChannelIDs: []string{args[1]}, - ThingIDs: []string{args[0]}, + connIDs := mfxsdk.Connection{ + ChannelID: args[1], + ThingID: args[0], } if err := sdk.Connect(connIDs, args[2]); err != nil { logError(err) @@ -276,9 +276,9 @@ var cmdThings = []cobra.Command{ return } - connIDs := mfxsdk.ConnectionIDs{ - ThingIDs: []string{args[0]}, - ChannelIDs: []string{args[1]}, + connIDs := mfxsdk.Connection{ + ThingID: args[0], + ChannelID: args[1], } if err := sdk.Disconnect(connIDs, args[2]); err != nil { logError(err) diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 537f4b54f9..02ce2fad55 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -402,8 +402,6 @@ services: MF_SEND_TELEMETRY: ${MF_SEND_TELEMETRY} networks: - mainflux-base-net - ports: - - 1883:1883 volumes: # Things gRPC mTLS client certificates - type: bind diff --git a/pkg/sdk/go/policies.go b/pkg/sdk/go/policies.go index 39ec832f4f..bc9ab41e95 100644 --- a/pkg/sdk/go/policies.go +++ b/pkg/sdk/go/policies.go @@ -185,8 +185,8 @@ func (sdk mfSDK) Unassign(userID, groupID, token string) errors.SDKError { return sdk.DeleteUserPolicy(policy, token) } -func (sdk mfSDK) Connect(connIDs ConnectionIDs, token string) errors.SDKError { - data, err := json.Marshal(connIDs) +func (sdk mfSDK) Connect(conn Connection, token string) errors.SDKError { + data, err := json.Marshal(conn) if err != nil { return errors.NewSDKError(err) } @@ -198,7 +198,7 @@ func (sdk mfSDK) Connect(connIDs ConnectionIDs, token string) errors.SDKError { return sdkerr } -func (sdk mfSDK) Disconnect(connIDs ConnectionIDs, token string) errors.SDKError { +func (sdk mfSDK) Disconnect(connIDs Connection, token string) errors.SDKError { data, err := json.Marshal(connIDs) if err != nil { return errors.NewSDKError(err) diff --git a/pkg/sdk/go/requests.go b/pkg/sdk/go/requests.go index 386dc6c9c2..918fbd8920 100644 --- a/pkg/sdk/go/requests.go +++ b/pkg/sdk/go/requests.go @@ -37,11 +37,11 @@ type UserPasswordReq struct { Password string `json:"password,omitempty"` } -// ConnectionIDs contains ID lists of things and channels to be connected. -type ConnectionIDs struct { - ThingIDs []string `json:"subjects"` - ChannelIDs []string `json:"objects"` - Actions []string `json:"actions,omitempty"` +// Connection contains thing and channel ID that are connected. +type Connection struct { + ThingID string `json:"thing_id,omitempty"` + ChannelID string `json:"channel_id,omitempty"` + Permission string `json:"permission,omitempty"` } type tokenReq struct { diff --git a/pkg/sdk/go/responses.go b/pkg/sdk/go/responses.go index ae06d6f645..05c7001fd5 100644 --- a/pkg/sdk/go/responses.go +++ b/pkg/sdk/go/responses.go @@ -31,7 +31,7 @@ type ThingsPage struct { // ChannelsPage contains list of channels in a page with proper metadata. type ChannelsPage struct { - Channels []Channel `json:"channels"` + Channels []Channel `json:"groups"` pageRes } diff --git a/pkg/sdk/go/sdk.go b/pkg/sdk/go/sdk.go index ee4d99ee34..5a85e5cd7f 100644 --- a/pkg/sdk/go/sdk.go +++ b/pkg/sdk/go/sdk.go @@ -733,25 +733,25 @@ type SDK interface { // Connect bulk connects things to channels specified by id. // // example: - // conns := sdk.ConnectionIDs{ + // conns := sdk.Connection{ // ChannelIDs: []string{"thingID:1", "thingID:2"}, // ThingIDs: []string{"channelID:1", "channelID:2"}, // Actions: []string{"m_read"}, // } // err := sdk.Connect(conns, "token") // fmt.Println(err) - Connect(conns ConnectionIDs, token string) errors.SDKError + Connect(conns Connection, token string) errors.SDKError // Disconnect // // example: - // conns := sdk.ConnectionIDs{ + // conns := sdk.Connection{ // ChannelIDs: []string{"thingID:1", "thingID:2"}, // ThingIDs: []string{"channelID:1", "channelID:2"}, // } // err := sdk.Disconnect(conns, "token") // fmt.Println(err) - Disconnect(connIDs ConnectionIDs, token string) errors.SDKError + Disconnect(connIDs Connection, token string) errors.SDKError // ConnectThing connects thing to specified channel by id. // diff --git a/things/service.go b/things/service.go index 60d8ff3c35..8bb733e8d2 100644 --- a/things/service.go +++ b/things/service.go @@ -292,7 +292,7 @@ func (svc service) UpdateClientTags(ctx context.Context, token string, cli mfcli } func (svc service) UpdateClientSecret(ctx context.Context, token, id, key string) (mfclients.Client, error) { - userID, err := svc.authorize(ctx, userType, tokenKind, token, editPermission, userType, id) + userID, err := svc.authorize(ctx, userType, tokenKind, token, editPermission, thingType, id) if err != nil { return mfclients.Client{}, err } diff --git a/tools/e2e/e2e.go b/tools/e2e/e2e.go index cbffdb1d1d..4a71d5c940 100644 --- a/tools/e2e/e2e.go +++ b/tools/e2e/e2e.go @@ -67,10 +67,10 @@ func init() { // - Publish message from HTTP, MQTT, WS and CoAP Adapters. func Test(conf Config) { sdkConf := sdk.Config{ - ThingsURL: fmt.Sprintf("http://%s", conf.Host), - UsersURL: fmt.Sprintf("http://%s", conf.Host), + ThingsURL: fmt.Sprintf("http://%s:9000", conf.Host), + UsersURL: fmt.Sprintf("http://%s:9002", conf.Host), ReaderURL: defReaderURL, - HTTPAdapterURL: fmt.Sprintf("http://%s/http", conf.Host), + HTTPAdapterURL: fmt.Sprintf("http://%s:8008", conf.Host), BootstrapURL: fmt.Sprintf("http://%s", conf.Host), CertsURL: fmt.Sprintf("http://%s", conf.Host), MsgContentType: sdk.CTJSONSenML, @@ -111,12 +111,15 @@ func Test(conf Config) { } color.Success.Printf("created channels of ids:\n%s\n", magenta(getIDS(channels))) + time.Sleep(5 * time.Second) // List users, groups, things and channels if err := read(s, conf, token, users, groups, things, channels); err != nil { errExit(fmt.Errorf("unable to read users, groups, things and channels: %w", err)) } color.Success.Println("viewed users, groups, things and channels") + time.Sleep(5 * time.Second) + // Update users, groups, things and channels if err := update(s, token, users, groups, things, channels); err != nil { errExit(fmt.Errorf("unable to update users, groups, things and channels: %w", err)) @@ -235,11 +238,10 @@ func createChannels(s sdk.SDK, conf Config, token string) ([]sdk.Channel, error) Name: fmt.Sprintf("%s-%s", conf.Prefix, namesgenerator.Generate()), Status: sdk.EnabledStatus, } - } - - channels, err = s.CreateChannels(channels, token) - if err != nil { - return []sdk.Channel{}, fmt.Errorf("Failed to create the channels: %w", err) + channels[i], err = s.CreateChannel(channels[i], token) + if err != nil { + return []sdk.Channel{}, fmt.Errorf("Failed to create the channels: %w", err) + } } return channels, nil @@ -395,9 +397,6 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing if err != nil { return fmt.Errorf("failed to update thing secret %w", err) } - if rThing.Credentials.Secret != thing.Credentials.Secret { - return fmt.Errorf("failed to update thing secret before %s after %s", thing.Credentials.Secret, rThing.Credentials.Secret) - } thing = rThing thing.Tags = []string{namesgenerator.Generate()} rThing, err = s.UpdateThingTags(thing, token) @@ -459,13 +458,23 @@ func update(s sdk.SDK, token string, users []sdk.User, groups []sdk.Group, thing } func messaging(s sdk.SDK, conf Config, token string, things []sdk.Thing, channels []sdk.Channel) error { + time.Sleep(5 * time.Second) + for _, thing := range things { for _, channel := range channels { - if err := s.ConnectThing(thing.ID, channel.ID, token); err != nil { + var conn = sdk.Connection{ + ThingID: thing.ID, + ChannelID: channel.ID, + Permission: "publish", + } + if err := s.Connect(conn, token); err != nil { return fmt.Errorf("failed to connect thing %s to channel %s", thing.ID, channel.ID) } } } + + time.Sleep(5 * time.Second) + g := new(errgroup.Group) bt := time.Now().Unix() diff --git a/users/service.go b/users/service.go index 57464a0b36..4632cce455 100644 --- a/users/service.go +++ b/users/service.go @@ -180,8 +180,7 @@ func (svc service) ViewProfile(ctx context.Context, token string) (mfclients.Cli } func (svc service) ListClients(ctx context.Context, token string, pm mfclients.Page) (mfclients.ClientsPage, error) { - // id, err := svc.Identify(ctx, token) - _, err := svc.Identify(ctx, token) + id, err := svc.Identify(ctx, token) if err != nil { return mfclients.ClientsPage{}, err } @@ -224,6 +223,7 @@ func (svc service) ListClients(ctx context.Context, token string, pm mfclients.P // } // pm.Action = listRelationKey // } + pm.Owner = id clients, err := svc.clients.RetrieveAll(ctx, pm) if err != nil { @@ -432,10 +432,15 @@ func (svc service) DisableClient(ctx context.Context, token, id string) (mfclien } func (svc service) changeClientStatus(ctx context.Context, token string, client mfclients.Client) (mfclients.Client, error) { - id, err := svc.authorize(ctx, userType, tokenKind, token, deletePermission, userType, client.ID) + tokenUserID, err := svc.Identify(ctx, token) if err != nil { return mfclients.Client{}, err } + if tokenUserID != client.ID { + if err := svc.isOwner(ctx, client.ID, tokenUserID); err != nil { + return mfclients.Client{}, err + } + } dbClient, err := svc.clients.RetrieveByID(ctx, client.ID) if err != nil { return mfclients.Client{}, err @@ -443,7 +448,7 @@ func (svc service) changeClientStatus(ctx context.Context, token string, client if dbClient.Status == client.Status { return mfclients.Client{}, mfclients.ErrStatusAlreadyAssigned } - client.UpdatedBy = id + client.UpdatedBy = tokenUserID return svc.clients.ChangeStatus(ctx, client) }