Skip to content

Commit

Permalink
MF-707 - Allow custom Thing key (absmach#726)
Browse files Browse the repository at this point in the history
* Add support for setting up thing key manually

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Fix existing tests and add new ones

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Update SQL schema for things entity

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Add update thing key endpoint to swagger docs

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>

* Fix response code when handling conflicting key

Signed-off-by: Aleksandar Novakovic <aleksandar.novakovic@mainflux.com>
  • Loading branch information
Aleksandar Novaković authored and rugwirobaker committed Jun 26, 2019
1 parent afee7a9 commit 756607c
Show file tree
Hide file tree
Showing 17 changed files with 920 additions and 413 deletions.
4 changes: 4 additions & 0 deletions bootstrap/mocks/things.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ func (svc *mainfluxThings) UpdateThing(string, things.Thing) error {
panic("not implemented")
}

func (svc *mainfluxThings) UpdateKey(string, string, string) error {
panic("not implemented")
}

func (svc *mainfluxThings) ListThings(string, uint64, uint64) (things.ThingsPage, error) {
panic("not implemented")
}
Expand Down
46 changes: 32 additions & 14 deletions things/api/http/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ func addThingEndpoint(svc things.Service) endpoint.Endpoint {
}

thing := things.Thing{
Key: req.Key,
Name: req.Name,
Metadata: req.Metadata,
}
saved, err := svc.AddThing(req.key, thing)
saved, err := svc.AddThing(req.token, thing)
if err != nil {
return nil, err
}
Expand All @@ -53,7 +54,24 @@ func updateThingEndpoint(svc things.Service) endpoint.Endpoint {
Metadata: req.Metadata,
}

if err := svc.UpdateThing(req.key, thing); err != nil {
if err := svc.UpdateThing(req.token, thing); err != nil {
return nil, err
}

res := thingRes{id: req.id, created: false}
return res, nil
}
}

func updateKeyEndpoint(svc things.Service) endpoint.Endpoint {
return func(_ context.Context, request interface{}) (interface{}, error) {
req := request.(updateKeyReq)

if err := req.validate(); err != nil {
return nil, err
}

if err := svc.UpdateKey(req.token, req.id, req.Key); err != nil {
return nil, err
}

Expand All @@ -70,7 +88,7 @@ func viewThingEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

thing, err := svc.ViewThing(req.key, req.id)
thing, err := svc.ViewThing(req.token, req.id)
if err != nil {
return nil, err
}
Expand All @@ -94,7 +112,7 @@ func listThingsEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

page, err := svc.ListThings(req.key, req.offset, req.limit)
page, err := svc.ListThings(req.token, req.offset, req.limit)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -130,7 +148,7 @@ func listThingsByChannelEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

page, err := svc.ListThingsByChannel(req.key, req.id, req.offset, req.limit)
page, err := svc.ListThingsByChannel(req.token, req.id, req.offset, req.limit)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -171,7 +189,7 @@ func removeThingEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

if err := svc.RemoveThing(req.key, req.id); err != nil {
if err := svc.RemoveThing(req.token, req.id); err != nil {
return nil, err
}

Expand All @@ -188,7 +206,7 @@ func createChannelEndpoint(svc things.Service) endpoint.Endpoint {
}

channel := things.Channel{Name: req.Name, Metadata: req.Metadata}
saved, err := svc.CreateChannel(req.key, channel)
saved, err := svc.CreateChannel(req.token, channel)
if err != nil {
return nil, err
}
Expand All @@ -214,7 +232,7 @@ func updateChannelEndpoint(svc things.Service) endpoint.Endpoint {
Name: req.Name,
Metadata: req.Metadata,
}
if err := svc.UpdateChannel(req.key, channel); err != nil {
if err := svc.UpdateChannel(req.token, channel); err != nil {
return nil, err
}

Expand All @@ -234,7 +252,7 @@ func viewChannelEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

channel, err := svc.ViewChannel(req.key, req.id)
channel, err := svc.ViewChannel(req.token, req.id)
if err != nil {
return nil, err
}
Expand All @@ -258,7 +276,7 @@ func listChannelsEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

page, err := svc.ListChannels(req.key, req.offset, req.limit)
page, err := svc.ListChannels(req.token, req.offset, req.limit)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -295,7 +313,7 @@ func listChannelsByThingEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

page, err := svc.ListChannelsByThing(req.key, req.id, req.offset, req.limit)
page, err := svc.ListChannelsByThing(req.token, req.id, req.offset, req.limit)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -333,7 +351,7 @@ func removeChannelEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

if err := svc.RemoveChannel(req.key, req.id); err != nil {
if err := svc.RemoveChannel(req.token, req.id); err != nil {
return nil, err
}

Expand All @@ -349,7 +367,7 @@ func connectEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

if err := svc.Connect(cr.key, cr.chanID, cr.thingID); err != nil {
if err := svc.Connect(cr.token, cr.chanID, cr.thingID); err != nil {
return nil, err
}

Expand All @@ -365,7 +383,7 @@ func disconnectEndpoint(svc things.Service) endpoint.Endpoint {
return nil, err
}

if err := svc.Disconnect(cr.key, cr.chanID, cr.thingID); err != nil {
if err := svc.Disconnect(cr.token, cr.chanID, cr.thingID); err != nil {
return nil, err
}

Expand Down
132 changes: 131 additions & 1 deletion things/api/http/endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ func TestAddThing(t *testing.T) {
ts := newServer(svc)
defer ts.Close()

data := toJSON(thing)
th := thing
th.Key = "key"
data := toJSON(th)

cases := []struct {
desc string
Expand All @@ -107,6 +109,14 @@ func TestAddThing(t *testing.T) {
status: http.StatusCreated,
location: "/things/1",
},
{
desc: "add thing with existing key",
req: data,
contentType: contentType,
auth: token,
status: http.StatusUnprocessableEntity,
location: "",
},
{
desc: "add thing with empty JSON request",
req: "{}",
Expand Down Expand Up @@ -280,6 +290,126 @@ func TestUpdateThing(t *testing.T) {
}
}

func TestUpdateKey(t *testing.T) {
svc := newService(map[string]string{token: email})
ts := newServer(svc)
defer ts.Close()

th := thing
th.Key = "key"
sth, _ := svc.AddThing(token, th)

sth.Key = "new-key"
data := toJSON(sth)

sth.Key = "key"
dummyData := toJSON(sth)

cases := []struct {
desc string
req string
id string
contentType string
auth string
status int
}{
{
desc: "update key for an existing thing",
req: data,
id: sth.ID,
contentType: contentType,
auth: token,
status: http.StatusOK,
},
{
desc: "update thing with conflicting key",
req: data,
id: sth.ID,
contentType: contentType,
auth: token,
status: http.StatusUnprocessableEntity,
},
{
desc: "update key with empty JSON request",
req: "{}",
id: sth.ID,
contentType: contentType,
auth: token,
status: http.StatusBadRequest,
},
{
desc: "update key of non-existent thing",
req: dummyData,
id: strconv.FormatUint(wrongID, 10),
contentType: contentType,
auth: token,
status: http.StatusNotFound,
},
{
desc: "update thing with invalid id",
req: dummyData,
id: "invalid",
contentType: contentType,
auth: token,
status: http.StatusNotFound,
},
{
desc: "update thing with invalid user token",
req: data,
id: sth.ID,
contentType: contentType,
auth: wrongValue,
status: http.StatusForbidden,
},
{
desc: "update thing with empty user token",
req: data,
id: sth.ID,
contentType: contentType,
auth: "",
status: http.StatusForbidden,
},
{
desc: "update thing with invalid data format",
req: "{",
id: sth.ID,
contentType: contentType,
auth: token,
status: http.StatusBadRequest,
},
{
desc: "update thing with empty request",
req: "",
id: sth.ID,
contentType: contentType,
auth: token,
status: http.StatusBadRequest,
},
{
desc: "update thing without content type",
req: data,
id: sth.ID,
contentType: "",
auth: token,
status: http.StatusUnsupportedMediaType,
},
}

for _, tc := range cases {
req := testRequest{
client: ts.Client(),
method: http.MethodPatch,
url: fmt.Sprintf("%s/things/%s/key", ts.URL, tc.id),
contentType: tc.contentType,
token: tc.auth,
body: strings.NewReader(tc.req),
}
res, err := req.make()
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode))
}
}

func TestViewThing(t *testing.T) {
svc := newService(map[string]string{token: email})
ts := newServer(svc)
Expand Down
Loading

0 comments on commit 756607c

Please sign in to comment.