// Copyright (c) Mainflux // SPDX-License-Identifier: Apache-2.0 package mocks import ( "context" "strconv" "sync" "github.com/mainflux/mainflux" "github.com/mainflux/mainflux/things" ) var _ things.Service = (*mainfluxThings)(nil) type mainfluxThings struct { mu sync.Mutex counter uint64 things map[string]things.Thing channels map[string]things.Channel auth mainflux.AuthNServiceClient connections map[string][]string } // NewThingsService returns Mainflux Things service mock. // Only methods used by SDK are mocked. func NewThingsService(things map[string]things.Thing, channels map[string]things.Channel, authn mainflux.AuthNServiceClient) things.Service { return &mainfluxThings{ things: things, channels: channels, auth: authn, connections: make(map[string][]string), } } func (svc *mainfluxThings) CreateThings(_ context.Context, owner string, ths ...things.Thing) ([]things.Thing, error) { svc.mu.Lock() defer svc.mu.Unlock() userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { return []things.Thing{}, things.ErrUnauthorizedAccess } for i := range ths { svc.counter++ ths[i].Owner = userID.Value ths[i].ID = strconv.FormatUint(svc.counter, 10) ths[i].Key = ths[i].ID svc.things[ths[i].ID] = ths[i] } return ths, nil } func (svc *mainfluxThings) ViewThing(_ context.Context, owner, id string) (things.Thing, error) { svc.mu.Lock() defer svc.mu.Unlock() userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { return things.Thing{}, things.ErrUnauthorizedAccess } if t, ok := svc.things[id]; ok && t.Owner == userID.Value { return t, nil } return things.Thing{}, things.ErrNotFound } func (svc *mainfluxThings) Connect(_ context.Context, owner string, chIDs, thIDs []string) error { svc.mu.Lock() defer svc.mu.Unlock() userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { return things.ErrUnauthorizedAccess } for _, chID := range chIDs { if svc.channels[chID].Owner != userID.Value { return things.ErrUnauthorizedAccess } for _, thID := range thIDs { svc.connections[chID] = append(svc.connections[chID], thID) } } return nil } func (svc *mainfluxThings) Disconnect(_ context.Context, owner, chanID, thingID string) error { svc.mu.Lock() defer svc.mu.Unlock() userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil || svc.channels[chanID].Owner != userID.Value { return things.ErrUnauthorizedAccess } ids := svc.connections[chanID] i := 0 for _, t := range ids { if t == thingID { break } i++ } if i == len(ids) { return things.ErrNotFound } var tmp []string if i != len(ids)-2 { tmp = ids[i+1:] } ids = append(ids[:i], tmp...) svc.connections[chanID] = ids return nil } func (svc *mainfluxThings) RemoveThing(_ context.Context, owner, id string) error { svc.mu.Lock() defer svc.mu.Unlock() userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { return things.ErrUnauthorizedAccess } if t, ok := svc.things[id]; !ok || t.Owner != userID.Value { return things.ErrNotFound } delete(svc.things, id) conns := make(map[string][]string) for k, v := range svc.connections { i := findIndex(v, id) if i != -1 { var tmp []string if i != len(v)-2 { tmp = v[i+1:] } conns[k] = append(v[:i], tmp...) } } svc.connections = conns return nil } func (svc *mainfluxThings) ViewChannel(_ context.Context, owner, id string) (things.Channel, error) { if c, ok := svc.channels[id]; ok { return c, nil } return things.Channel{}, things.ErrNotFound } func (svc *mainfluxThings) UpdateThing(context.Context, string, things.Thing) error { panic("not implemented") } func (svc *mainfluxThings) UpdateKey(context.Context, string, string, string) error { panic("not implemented") } func (svc *mainfluxThings) ListThings(context.Context, string, uint64, uint64, string, things.Metadata) (things.Page, error) { panic("not implemented") } func (svc *mainfluxThings) ListChannelsByThing(context.Context, string, string, uint64, uint64, bool) (things.ChannelsPage, error) { panic("not implemented") } func (svc *mainfluxThings) ListThingsByChannel(context.Context, string, string, uint64, uint64, bool) (things.Page, error) { panic("not implemented") } func (svc *mainfluxThings) CreateChannels(_ context.Context, owner string, chs ...things.Channel) ([]things.Channel, error) { svc.mu.Lock() defer svc.mu.Unlock() userID, err := svc.auth.Identify(context.Background(), &mainflux.Token{Value: owner}) if err != nil { return []things.Channel{}, things.ErrUnauthorizedAccess } for i := range chs { svc.counter++ chs[i].Owner = userID.Value chs[i].ID = strconv.FormatUint(svc.counter, 10) svc.channels[chs[i].ID] = chs[i] } return chs, nil } func (svc *mainfluxThings) UpdateChannel(context.Context, string, things.Channel) error { panic("not implemented") } func (svc *mainfluxThings) ListChannels(context.Context, string, uint64, uint64, string, things.Metadata) (things.ChannelsPage, error) { panic("not implemented") } func (svc *mainfluxThings) RemoveChannel(context.Context, string, string) error { panic("not implemented") } func (svc *mainfluxThings) CanAccessByKey(context.Context, string, string) (string, error) { panic("not implemented") } func (svc *mainfluxThings) CanAccessByID(context.Context, string, string) error { panic("not implemented") } func (svc *mainfluxThings) Identify(context.Context, string) (string, error) { panic("not implemented") } func findIndex(list []string, val string) int { for i, v := range list { if v == val { return i } } return -1 }