mirror of
https://github.com/absmach/supermq.git
synced 2026-06-23 07:00:25 +00:00
MG-2426 - Replace generic Clients in Things service (#2476)
Signed-off-by: Musilah <nataleigh.nk@gmail.com> Signed-off-by: Felix Gateru <felix.gateru@gmail.com> Co-authored-by: Felix Gateru <felix.gateru@gmail.com>
This commit is contained in:
@@ -160,9 +160,6 @@ jobs:
|
||||
- "logger/**"
|
||||
- "pkg/events/**"
|
||||
|
||||
pkg-clients:
|
||||
- "pkg/clients/**"
|
||||
|
||||
pkg-errors:
|
||||
- "pkg/errors/**"
|
||||
|
||||
@@ -178,7 +175,6 @@ jobs:
|
||||
|
||||
pkg-sdk:
|
||||
- "pkg/sdk/**"
|
||||
- "pkg/clients/**"
|
||||
- "pkg/errors/**"
|
||||
- "pkg/groups/**"
|
||||
- "auth/**"
|
||||
@@ -226,7 +222,6 @@ jobs:
|
||||
- "auth.pb.go"
|
||||
- "auth_grpc.pb.go"
|
||||
- "auth/**"
|
||||
- "pkg/clients/**"
|
||||
- "pkg/ulid/**"
|
||||
- "pkg/uuid/**"
|
||||
- "pkg/events/**"
|
||||
@@ -237,7 +232,6 @@ jobs:
|
||||
- "auth.pb.go"
|
||||
- "auth_grpc.pb.go"
|
||||
- "auth/**"
|
||||
- "pkg/clients/**"
|
||||
- "pkg/ulid/**"
|
||||
- "pkg/uuid/**"
|
||||
- "pkg/events/**"
|
||||
@@ -314,11 +308,6 @@ jobs:
|
||||
run: |
|
||||
go test --race -v -count=1 -coverprofile=coverage/mqtt.out ./mqtt/...
|
||||
|
||||
- name: Run pkg clients tests
|
||||
if: steps.changes.outputs.pkg-clients == 'true' || steps.changes.outputs.workflow == 'true'
|
||||
run: |
|
||||
go test --race -v -count=1 -coverprofile=coverage/pkg-clients.out ./pkg/clients/...
|
||||
|
||||
- name: Run pkg errors tests
|
||||
if: steps.changes.outputs.pkg-errors == 'true' || steps.changes.outputs.workflow == 'true'
|
||||
run: |
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/absmach/magistrala/auth"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
@@ -72,7 +71,7 @@ func updateDomainEndpoint(svc auth.Service) endpoint.Endpoint {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var metadata clients.Metadata
|
||||
var metadata auth.Metadata
|
||||
if req.Metadata != nil {
|
||||
metadata = *req.Metadata
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
policies "github.com/absmach/magistrala/pkg/policies"
|
||||
@@ -29,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
validCMetadata = mgclients.Metadata{"role": "client"}
|
||||
validCMetadata = auth.Metadata{"role": "client"}
|
||||
ID = testsutil.GenerateUUID(&testing.T{})
|
||||
domain = auth.Domain{
|
||||
ID: ID,
|
||||
@@ -114,7 +113,7 @@ func TestCreateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "test",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test",
|
||||
},
|
||||
@@ -128,7 +127,7 @@ func TestCreateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "test",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test",
|
||||
},
|
||||
@@ -142,7 +141,7 @@ func TestCreateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "test",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test",
|
||||
},
|
||||
@@ -157,7 +156,7 @@ func TestCreateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test",
|
||||
},
|
||||
@@ -171,7 +170,7 @@ func TestCreateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "test",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "",
|
||||
},
|
||||
@@ -185,7 +184,7 @@ func TestCreateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "test",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test",
|
||||
},
|
||||
@@ -646,7 +645,7 @@ func TestUpdateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "test",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test",
|
||||
},
|
||||
@@ -660,7 +659,7 @@ func TestUpdateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "test",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test",
|
||||
},
|
||||
@@ -674,7 +673,7 @@ func TestUpdateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "test",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test",
|
||||
},
|
||||
@@ -689,7 +688,7 @@ func TestUpdateDomain(t *testing.T) {
|
||||
domain: auth.Domain{
|
||||
ID: ID,
|
||||
Name: "test",
|
||||
Metadata: mgclients.Metadata{"role": "domain"},
|
||||
Metadata: auth.Metadata{"role": "domain"},
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test",
|
||||
},
|
||||
@@ -1301,11 +1300,11 @@ func TestListDomainsByUserID(t *testing.T) {
|
||||
}
|
||||
|
||||
type respBody struct {
|
||||
Err string `json:"error"`
|
||||
Message string `json:"message"`
|
||||
Total int `json:"total"`
|
||||
Permissions []string `json:"permissions"`
|
||||
ID string `json:"id"`
|
||||
Tags []string `json:"tags"`
|
||||
Status mgclients.Status `json:"status"`
|
||||
Err string `json:"error"`
|
||||
Message string `json:"message"`
|
||||
Total int `json:"total"`
|
||||
Permissions []string `json:"permissions"`
|
||||
ID string `json:"id"`
|
||||
Tags []string `json:"tags"`
|
||||
Status auth.Status `json:"status"`
|
||||
}
|
||||
|
||||
+33
-31
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/policies"
|
||||
)
|
||||
@@ -87,41 +86,44 @@ func (s *Status) UnmarshalJSON(data []byte) error {
|
||||
}
|
||||
|
||||
type DomainReq struct {
|
||||
Name *string `json:"name,omitempty"`
|
||||
Metadata *clients.Metadata `json:"metadata,omitempty"`
|
||||
Tags *[]string `json:"tags,omitempty"`
|
||||
Alias *string `json:"alias,omitempty"`
|
||||
Status *Status `json:"status,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Metadata *Metadata `json:"metadata,omitempty"`
|
||||
Tags *[]string `json:"tags,omitempty"`
|
||||
Alias *string `json:"alias,omitempty"`
|
||||
Status *Status `json:"status,omitempty"`
|
||||
}
|
||||
type Domain struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Metadata clients.Metadata `json:"metadata,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Alias string `json:"alias,omitempty"`
|
||||
Status Status `json:"status"`
|
||||
Permission string `json:"permission,omitempty"`
|
||||
CreatedBy string `json:"created_by,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Alias string `json:"alias,omitempty"`
|
||||
Status Status `json:"status"`
|
||||
Permission string `json:"permission,omitempty"`
|
||||
CreatedBy string `json:"created_by,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
}
|
||||
|
||||
// Metadata represents arbitrary JSON.
|
||||
type Metadata map[string]interface{}
|
||||
|
||||
type Page struct {
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Order string `json:"-"`
|
||||
Dir string `json:"-"`
|
||||
Metadata clients.Metadata `json:"metadata,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Permission string `json:"permission,omitempty"`
|
||||
Status Status `json:"status,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
IDs []string `json:"-"`
|
||||
Identity string `json:"identity,omitempty"`
|
||||
SubjectID string `json:"-"`
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Order string `json:"-"`
|
||||
Dir string `json:"-"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Permission string `json:"permission,omitempty"`
|
||||
Status Status `json:"status,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
IDs []string `json:"-"`
|
||||
Identity string `json:"identity,omitempty"`
|
||||
SubjectID string `json:"-"`
|
||||
}
|
||||
|
||||
type DomainsPage struct {
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
|
||||
"github.com/absmach/magistrala/auth"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
"github.com/absmach/magistrala/pkg/postgres"
|
||||
@@ -473,7 +472,7 @@ func toDBDomain(d auth.Domain) (dbDomain, error) {
|
||||
}
|
||||
|
||||
func toDomain(d dbDomain) (auth.Domain, error) {
|
||||
var metadata clients.Metadata
|
||||
var metadata auth.Metadata
|
||||
if d.Metadata != nil {
|
||||
if err := json.Unmarshal([]byte(d.Metadata), &metadata); err != nil {
|
||||
return auth.Domain{}, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/absmach/magistrala/auth"
|
||||
"github.com/absmach/magistrala/auth/postgres"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
"github.com/absmach/magistrala/pkg/policies"
|
||||
@@ -813,7 +812,7 @@ func TestUpdate(t *testing.T) {
|
||||
})
|
||||
|
||||
updatedName := "test1"
|
||||
updatedMetadata := clients.Metadata{
|
||||
updatedMetadata := auth.Metadata{
|
||||
"test1": "test1",
|
||||
}
|
||||
updatedTags := []string{"test1"}
|
||||
@@ -917,7 +916,7 @@ func TestUpdate(t *testing.T) {
|
||||
domainID: domainID,
|
||||
d: auth.DomainReq{
|
||||
Name: &updatedName,
|
||||
Metadata: &clients.Metadata{"key": make(chan int)},
|
||||
Metadata: &auth.Metadata{"key": make(chan int)},
|
||||
},
|
||||
response: auth.Domain{},
|
||||
err: repoerr.ErrUpdateEntity,
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/things"
|
||||
)
|
||||
|
||||
// Config represents Configuration entity. It wraps information about external entity
|
||||
@@ -41,7 +41,7 @@ type Channel struct {
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
Status clients.Status `json:"status"`
|
||||
Status things.Status `json:"status"`
|
||||
}
|
||||
|
||||
// Filter is used for the search filters.
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
"github.com/absmach/magistrala/pkg/postgres"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/jackc/pgerrcode"
|
||||
"github.com/jackc/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
@@ -715,7 +715,7 @@ type dbChannel struct {
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt sql.NullTime `db:"updated_at,omitempty"`
|
||||
UpdatedBy sql.NullString `db:"updated_by,omitempty"`
|
||||
Status clients.Status `db:"status"`
|
||||
Status things.Status `db:"status"`
|
||||
}
|
||||
|
||||
func toDBChannel(domainID string, ch bootstrap.Channel) (dbChannel, error) {
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ package cli
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/internal/groups"
|
||||
mgxsdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -28,7 +28,7 @@ var cmdGroups = []cobra.Command{
|
||||
logErrorCmd(*cmd, err)
|
||||
return
|
||||
}
|
||||
group.Status = mgclients.EnabledStatus.String()
|
||||
group.Status = groups.EnabledStatus.String()
|
||||
group, err := sdk.CreateGroup(group, args[1], args[2])
|
||||
if err != nil {
|
||||
logErrorCmd(*cmd, err)
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@ package cli
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
mgxsdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -29,7 +29,7 @@ var cmdThings = []cobra.Command{
|
||||
logErrorCmd(*cmd, err)
|
||||
return
|
||||
}
|
||||
thing.Status = mgclients.EnabledStatus.String()
|
||||
thing.Status = things.EnabledStatus.String()
|
||||
thing, err := sdk.CreateThing(thing, args[1], args[2])
|
||||
if err != nil {
|
||||
logErrorCmd(*cmd, err)
|
||||
|
||||
+2
-2
@@ -13,11 +13,11 @@ import (
|
||||
"github.com/absmach/magistrala/cli"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
sdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
sdkmocks "github.com/absmach/magistrala/pkg/sdk/mocks"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
@@ -37,7 +37,7 @@ var thing = sdk.Thing{
|
||||
Secret: "secret",
|
||||
},
|
||||
DomainID: testsutil.GenerateUUID(&testing.T{}),
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: things.EnabledStatus.String(),
|
||||
}
|
||||
|
||||
func TestCreateThingsCmd(t *testing.T) {
|
||||
|
||||
+2
-2
@@ -12,11 +12,11 @@ import (
|
||||
|
||||
"github.com/absmach/magistrala/cli"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
mgsdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
sdkmocks "github.com/absmach/magistrala/pkg/sdk/mocks"
|
||||
"github.com/absmach/magistrala/users"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
@@ -29,7 +29,7 @@ var user = mgsdk.User{
|
||||
Secret: "testpassword",
|
||||
Username: "testusername",
|
||||
},
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: users.EnabledStatus.String(),
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -15,7 +15,6 @@ import (
|
||||
chclient "github.com/absmach/callhome/pkg/client"
|
||||
"github.com/absmach/magistrala"
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
mggroups "github.com/absmach/magistrala/pkg/groups"
|
||||
mgsdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
@@ -24,6 +23,7 @@ import (
|
||||
"github.com/absmach/magistrala/pkg/uuid"
|
||||
"github.com/absmach/magistrala/provision"
|
||||
"github.com/absmach/magistrala/provision/api"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/caarlos0/env/v11"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
@@ -147,7 +147,7 @@ func loadConfig() (provision.Config, error) {
|
||||
Metadata: map[string]interface{}{"type": "data"},
|
||||
},
|
||||
}
|
||||
cfg.Things = []mgclients.Client{
|
||||
cfg.Things = []things.Client{
|
||||
{
|
||||
Name: "thing",
|
||||
Metadata: map[string]interface{}{"external_id": "xxxxxx"},
|
||||
|
||||
+1
-1
@@ -246,7 +246,7 @@ func newService(ctx context.Context, db *sqlx.DB, dbConfig pgclient.Config, auth
|
||||
|
||||
thingCache := thcache.NewCache(cacheClient, keyDuration)
|
||||
|
||||
csvc := things.NewService(pe, ps, cRepo, gRepo, thingCache, idp)
|
||||
csvc := things.NewService(pe, ps, cRepo, thingCache, idp)
|
||||
gsvc := mggroups.NewService(gRepo, idp, ps)
|
||||
|
||||
csvc, err := thevents.NewEventStoreMiddleware(ctx, csvc, esURL)
|
||||
|
||||
@@ -51,7 +51,6 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.31.0
|
||||
go.opentelemetry.io/otel/trace v1.31.0
|
||||
golang.org/x/crypto v0.28.0
|
||||
golang.org/x/net v0.30.0
|
||||
golang.org/x/oauth2 v0.23.0
|
||||
golang.org/x/sync v0.8.0
|
||||
gonum.org/v1/gonum v0.15.1
|
||||
@@ -110,6 +109,7 @@ require (
|
||||
github.com/jackc/pgio v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/pgx/v4 v4.18.3 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jtolds/gls v4.20.0+incompatible // indirect
|
||||
github.com/jzelinskie/stringz v0.0.3 // indirect
|
||||
@@ -164,6 +164,7 @@ require (
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
|
||||
golang.org/x/net v0.30.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/time v0.6.0 // indirect
|
||||
|
||||
@@ -233,8 +233,9 @@ github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08
|
||||
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
|
||||
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
|
||||
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
|
||||
github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU=
|
||||
github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
|
||||
github.com/jackc/pgx/v4 v4.18.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA=
|
||||
github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw=
|
||||
github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs=
|
||||
github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA=
|
||||
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||
|
||||
@@ -11,10 +11,12 @@ import (
|
||||
"github.com/absmach/magistrala"
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/certs"
|
||||
"github.com/absmach/magistrala/internal/groups"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/absmach/magistrala/users"
|
||||
"github.com/gofrs/uuid/v5"
|
||||
)
|
||||
|
||||
@@ -56,8 +58,9 @@ const (
|
||||
DefLimit = 10
|
||||
DefLevel = 0
|
||||
DefStatus = "enabled"
|
||||
DefClientStatus = mgclients.Enabled
|
||||
DefGroupStatus = mgclients.Enabled
|
||||
DefClientStatus = things.Enabled
|
||||
DefUserStatus = users.Enabled
|
||||
DefGroupStatus = groups.Enabled
|
||||
DefListPerms = false
|
||||
SharedVisibility = "shared"
|
||||
MyVisibility = "mine"
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
mggroups "github.com/absmach/magistrala/pkg/groups"
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -245,7 +244,7 @@ func decodePageMeta(r *http.Request) (mggroups.PageMeta, error) {
|
||||
if err != nil {
|
||||
return mggroups.PageMeta{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
st, err := mgclients.ToStatus(s)
|
||||
st, err := mggroups.ToStatus(s)
|
||||
if err != nil {
|
||||
return mggroups.PageMeta{}, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -51,11 +50,11 @@ func TestDecodeListGroupsRequest(t *testing.T) {
|
||||
resp: listGroupsReq{
|
||||
Page: groups.Page{
|
||||
PageMeta: groups.PageMeta{
|
||||
Status: clients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
Offset: 10,
|
||||
Limit: 10,
|
||||
Name: "random",
|
||||
Metadata: clients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": "test",
|
||||
},
|
||||
},
|
||||
@@ -166,11 +165,11 @@ func TestDecodeListParentsRequest(t *testing.T) {
|
||||
resp: listGroupsReq{
|
||||
Page: groups.Page{
|
||||
PageMeta: groups.PageMeta{
|
||||
Status: clients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
Offset: 10,
|
||||
Limit: 10,
|
||||
Name: "random",
|
||||
Metadata: clients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": "test",
|
||||
},
|
||||
},
|
||||
@@ -261,11 +260,11 @@ func TestDecodeListChildrenRequest(t *testing.T) {
|
||||
resp: listGroupsReq{
|
||||
Page: groups.Page{
|
||||
PageMeta: groups.PageMeta{
|
||||
Status: clients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
Offset: 10,
|
||||
Limit: 10,
|
||||
Name: "random",
|
||||
Metadata: clients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": "test",
|
||||
},
|
||||
},
|
||||
@@ -400,11 +399,11 @@ func TestDecodePageMeta(t *testing.T) {
|
||||
desc: "valid request with all parameters",
|
||||
url: "http://localhost:8080?status=enabled&offset=10&limit=10&name=random&metadata={\"test\":\"test\"}",
|
||||
resp: groups.PageMeta{
|
||||
Status: clients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
Offset: 10,
|
||||
Limit: 10,
|
||||
Name: "random",
|
||||
Metadata: clients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": "test",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
@@ -31,14 +30,14 @@ var (
|
||||
Description: valid,
|
||||
Domain: testsutil.GenerateUUID(&testing.T{}),
|
||||
Parent: testsutil.GenerateUUID(&testing.T{}),
|
||||
Metadata: clients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"name": "test",
|
||||
},
|
||||
Children: []*groups.Group{},
|
||||
CreatedAt: time.Now().Add(-1 * time.Second),
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedBy: testsutil.GenerateUUID(&testing.T{}),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
}
|
||||
validID = testsutil.GenerateUUID(&testing.T{})
|
||||
)
|
||||
@@ -564,7 +563,7 @@ func TestListGroupsEndpoint(t *testing.T) {
|
||||
Description: valid,
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Parent: validGroupResp.ID,
|
||||
Metadata: clients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"name": "test",
|
||||
},
|
||||
Level: -1,
|
||||
@@ -572,14 +571,14 @@ func TestListGroupsEndpoint(t *testing.T) {
|
||||
CreatedAt: time.Now().Add(-1 * time.Second),
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedBy: testsutil.GenerateUUID(t),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
}
|
||||
parentGroup := groups.Group{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: valid,
|
||||
Description: valid,
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Metadata: clients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"name": "test",
|
||||
},
|
||||
Level: 1,
|
||||
@@ -587,7 +586,7 @@ func TestListGroupsEndpoint(t *testing.T) {
|
||||
CreatedAt: time.Now().Add(-1 * time.Second),
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedBy: testsutil.GenerateUUID(t),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
}
|
||||
|
||||
validGroupResp.Children = append(validGroupResp.Children, &childGroup)
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
mggroups "github.com/absmach/magistrala/pkg/groups"
|
||||
"github.com/absmach/magistrala/pkg/postgres"
|
||||
"github.com/jmoiron/sqlx"
|
||||
@@ -71,7 +71,7 @@ func (repo groupRepository) Update(ctx context.Context, g mggroups.Group) (mggro
|
||||
if len(query) > 0 {
|
||||
upq = strings.Join(query, " ")
|
||||
}
|
||||
g.Status = mgclients.EnabledStatus
|
||||
g.Status = mggroups.EnabledStatus
|
||||
q := fmt.Sprintf(`UPDATE groups SET %s updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, description, domain_id, COALESCE(parent_id, '') AS parent_id, metadata, created_at, updated_at, updated_by, status`, upq)
|
||||
@@ -337,7 +337,7 @@ func buildQuery(gm mggroups.Page, ids ...string) string {
|
||||
if gm.PageMeta.ID != "" {
|
||||
queries = append(queries, "g.id ILIKE '%' || :id || '%'")
|
||||
}
|
||||
if gm.Status != mgclients.AllStatus {
|
||||
if gm.Status != mggroups.AllStatus {
|
||||
queries = append(queries, "g.status = :status")
|
||||
}
|
||||
if gm.DomainID != "" {
|
||||
@@ -354,18 +354,18 @@ func buildQuery(gm mggroups.Page, ids ...string) string {
|
||||
}
|
||||
|
||||
type dbGroup struct {
|
||||
ID string `db:"id"`
|
||||
ParentID *string `db:"parent_id,omitempty"`
|
||||
DomainID string `db:"domain_id,omitempty"`
|
||||
Name string `db:"name"`
|
||||
Description string `db:"description,omitempty"`
|
||||
Level int `db:"level"`
|
||||
Path string `db:"path,omitempty"`
|
||||
Metadata []byte `db:"metadata,omitempty"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt sql.NullTime `db:"updated_at,omitempty"`
|
||||
UpdatedBy *string `db:"updated_by,omitempty"`
|
||||
Status mgclients.Status `db:"status"`
|
||||
ID string `db:"id"`
|
||||
ParentID *string `db:"parent_id,omitempty"`
|
||||
DomainID string `db:"domain_id,omitempty"`
|
||||
Name string `db:"name"`
|
||||
Description string `db:"description,omitempty"`
|
||||
Level int `db:"level"`
|
||||
Path string `db:"path,omitempty"`
|
||||
Metadata []byte `db:"metadata,omitempty"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt sql.NullTime `db:"updated_at,omitempty"`
|
||||
UpdatedBy *string `db:"updated_by,omitempty"`
|
||||
Status mggroups.Status `db:"status"`
|
||||
}
|
||||
|
||||
func toDBGroup(g mggroups.Group) (dbGroup, error) {
|
||||
@@ -405,7 +405,7 @@ func toDBGroup(g mggroups.Group) (dbGroup, error) {
|
||||
}
|
||||
|
||||
func toGroup(g dbGroup) (mggroups.Group, error) {
|
||||
var metadata mgclients.Metadata
|
||||
var metadata groups.Metadata
|
||||
if g.Metadata != nil {
|
||||
if err := json.Unmarshal(g.Metadata, &metadata); err != nil {
|
||||
return mggroups.Group{}, errors.Wrap(repoerr.ErrMalformedEntity, err)
|
||||
@@ -469,20 +469,20 @@ func toDBGroupPage(pm mggroups.Page) (dbGroupPage, error) {
|
||||
}
|
||||
|
||||
type dbGroupPage struct {
|
||||
ClientID string `db:"client_id"`
|
||||
ID string `db:"id"`
|
||||
Name string `db:"name"`
|
||||
ParentID string `db:"parent_id"`
|
||||
DomainID string `db:"domain_id"`
|
||||
Metadata []byte `db:"metadata"`
|
||||
Path string `db:"path"`
|
||||
Level uint64 `db:"level"`
|
||||
Total uint64 `db:"total"`
|
||||
Limit uint64 `db:"limit"`
|
||||
Offset uint64 `db:"offset"`
|
||||
Subject string `db:"subject"`
|
||||
Action string `db:"action"`
|
||||
Status mgclients.Status `db:"status"`
|
||||
ClientID string `db:"client_id"`
|
||||
ID string `db:"id"`
|
||||
Name string `db:"name"`
|
||||
ParentID string `db:"parent_id"`
|
||||
DomainID string `db:"domain_id"`
|
||||
Metadata []byte `db:"metadata"`
|
||||
Path string `db:"path"`
|
||||
Level uint64 `db:"level"`
|
||||
Total uint64 `db:"total"`
|
||||
Limit uint64 `db:"limit"`
|
||||
Offset uint64 `db:"offset"`
|
||||
Subject string `db:"subject"`
|
||||
Action string `db:"action"`
|
||||
Status mggroups.Status `db:"status"`
|
||||
}
|
||||
|
||||
func (repo groupRepository) processRows(rows *sqlx.Rows) ([]mggroups.Group, error) {
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/0x6flab/namegenerator"
|
||||
"github.com/absmach/magistrala/internal/groups/postgres"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
mggroups "github.com/absmach/magistrala/pkg/groups"
|
||||
@@ -31,7 +30,7 @@ var (
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"key": "value"},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -67,7 +66,7 @@ func TestSave(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"key": "value"},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
err: repoerr.ErrMalformedEntity,
|
||||
},
|
||||
@@ -80,7 +79,7 @@ func TestSave(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"key": "value"},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
err: repoerr.ErrMalformedEntity,
|
||||
},
|
||||
@@ -93,7 +92,7 @@ func TestSave(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"key": "value"},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
err: repoerr.ErrMalformedEntity,
|
||||
},
|
||||
@@ -106,7 +105,7 @@ func TestSave(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"key": "value"},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
err: repoerr.ErrMalformedEntity,
|
||||
},
|
||||
@@ -119,7 +118,7 @@ func TestSave(t *testing.T) {
|
||||
Description: strings.Repeat("a", 1025),
|
||||
Metadata: map[string]interface{}{"key": "value"},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
err: repoerr.ErrMalformedEntity,
|
||||
},
|
||||
@@ -134,7 +133,7 @@ func TestSave(t *testing.T) {
|
||||
"key": make(chan int),
|
||||
},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
err: repoerr.ErrMalformedEntity,
|
||||
},
|
||||
@@ -146,7 +145,7 @@ func TestSave(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"key": "value"},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
err: repoerr.ErrMalformedEntity,
|
||||
},
|
||||
@@ -158,7 +157,7 @@ func TestSave(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"key": "value"},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
err: repoerr.ErrMalformedEntity,
|
||||
},
|
||||
@@ -291,7 +290,7 @@ func TestChangeStatus(t *testing.T) {
|
||||
desc: "change status group successfully",
|
||||
group: mggroups.Group{
|
||||
ID: group.ID,
|
||||
Status: clients.DisabledStatus,
|
||||
Status: mggroups.DisabledStatus,
|
||||
UpdatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
UpdatedBy: testsutil.GenerateUUID(t),
|
||||
},
|
||||
@@ -301,7 +300,7 @@ func TestChangeStatus(t *testing.T) {
|
||||
desc: "change status group with invalid ID",
|
||||
group: mggroups.Group{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Status: clients.DisabledStatus,
|
||||
Status: mggroups.DisabledStatus,
|
||||
UpdatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
UpdatedBy: testsutil.GenerateUUID(t),
|
||||
},
|
||||
@@ -310,7 +309,7 @@ func TestChangeStatus(t *testing.T) {
|
||||
{
|
||||
desc: "change status group with empty ID",
|
||||
group: mggroups.Group{
|
||||
Status: clients.DisabledStatus,
|
||||
Status: mggroups.DisabledStatus,
|
||||
UpdatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
UpdatedBy: testsutil.GenerateUUID(t),
|
||||
},
|
||||
@@ -400,7 +399,7 @@ func TestRetrieveAll(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"name": name},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
}
|
||||
_, err := repo.Save(context.Background(), group)
|
||||
require.Nil(t, err, fmt.Sprintf("create invitation unexpected error: %s", err))
|
||||
@@ -712,7 +711,7 @@ func TestRetrieveByIDs(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"name": name},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
}
|
||||
_, err := repo.Save(context.Background(), group)
|
||||
require.Nil(t, err, fmt.Sprintf("create invitation unexpected error: %s", err))
|
||||
@@ -1069,7 +1068,7 @@ func TestAssignParentGroup(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"name": name},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
}
|
||||
_, err := repo.Save(context.Background(), group)
|
||||
require.Nil(t, err, fmt.Sprintf("create invitation unexpected error: %s", err))
|
||||
@@ -1147,7 +1146,7 @@ func TestUnassignParentGroup(t *testing.T) {
|
||||
Description: strings.Repeat("a", 64),
|
||||
Metadata: map[string]interface{}{"name": name},
|
||||
CreatedAt: time.Now().UTC().Truncate(time.Microsecond),
|
||||
Status: clients.EnabledStatus,
|
||||
Status: mggroups.EnabledStatus,
|
||||
}
|
||||
_, err := repo.Save(context.Background(), group)
|
||||
require.Nil(t, err, fmt.Sprintf("create invitation unexpected error: %s", err))
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
mgauth "github.com/absmach/magistrala/auth"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
@@ -45,7 +44,7 @@ func (svc service) CreateGroup(ctx context.Context, session authn.Session, kind
|
||||
if err != nil {
|
||||
return groups.Group{}, err
|
||||
}
|
||||
if g.Status != mgclients.EnabledStatus && g.Status != mgclients.DisabledStatus {
|
||||
if g.Status != groups.EnabledStatus && g.Status != groups.DisabledStatus {
|
||||
return groups.Group{}, svcerr.ErrInvalidStatus
|
||||
}
|
||||
|
||||
@@ -282,7 +281,7 @@ func (svc service) UpdateGroup(ctx context.Context, session authn.Session, g gro
|
||||
func (svc service) EnableGroup(ctx context.Context, session authn.Session, id string) (groups.Group, error) {
|
||||
group := groups.Group{
|
||||
ID: id,
|
||||
Status: mgclients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
group, err := svc.changeGroupStatus(ctx, session, group)
|
||||
@@ -295,7 +294,7 @@ func (svc service) EnableGroup(ctx context.Context, session authn.Session, id st
|
||||
func (svc service) DisableGroup(ctx context.Context, session authn.Session, id string) (groups.Group, error) {
|
||||
group := groups.Group{
|
||||
ID: id,
|
||||
Status: mgclients.DisabledStatus,
|
||||
Status: groups.DisabledStatus,
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
group, err := svc.changeGroupStatus(ctx, session, group)
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
@@ -38,7 +37,7 @@ var (
|
||||
Metadata: map[string]interface{}{
|
||||
"key": "value",
|
||||
},
|
||||
Status: clients.Status(groups.EnabledStatus),
|
||||
Status: mggroups.EnabledStatus,
|
||||
}
|
||||
allowedIDs = []string{
|
||||
testsutil.GenerateUUID(&testing.T{}),
|
||||
@@ -83,7 +82,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
group: mggroups.Group{
|
||||
Name: namegen.Generate(),
|
||||
Description: namegen.Generate(),
|
||||
Status: clients.Status(100),
|
||||
Status: mggroups.Status(100),
|
||||
},
|
||||
err: svcerr.ErrInvalidStatus,
|
||||
},
|
||||
@@ -94,7 +93,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
group: mggroups.Group{
|
||||
Name: namegen.Generate(),
|
||||
Description: namegen.Generate(),
|
||||
Status: clients.Status(groups.EnabledStatus),
|
||||
Status: mggroups.EnabledStatus,
|
||||
Parent: testsutil.GenerateUUID(t),
|
||||
},
|
||||
repoResp: mggroups.Group{
|
||||
@@ -131,7 +130,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
group: mggroups.Group{
|
||||
Name: namegen.Generate(),
|
||||
Description: namegen.Generate(),
|
||||
Status: clients.Status(groups.EnabledStatus),
|
||||
Status: mggroups.EnabledStatus,
|
||||
Parent: testsutil.GenerateUUID(t),
|
||||
},
|
||||
repoErr: errors.ErrMalformedEntity,
|
||||
@@ -327,7 +326,7 @@ func TestEnableGroup(t *testing.T) {
|
||||
session: authn.Session{UserID: validID, DomainID: validID, DomainUserID: validID},
|
||||
id: testsutil.GenerateUUID(t),
|
||||
retrieveResp: mggroups.Group{
|
||||
Status: clients.Status(groups.DisabledStatus),
|
||||
Status: mggroups.DisabledStatus,
|
||||
},
|
||||
changeResp: validGroup,
|
||||
},
|
||||
@@ -336,7 +335,7 @@ func TestEnableGroup(t *testing.T) {
|
||||
session: authn.Session{UserID: validID, DomainID: validID, DomainUserID: validID},
|
||||
id: testsutil.GenerateUUID(t),
|
||||
retrieveResp: mggroups.Group{
|
||||
Status: clients.Status(groups.EnabledStatus),
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
err: errors.ErrStatusAlreadyAssigned,
|
||||
},
|
||||
@@ -387,7 +386,7 @@ func TestDisableGroup(t *testing.T) {
|
||||
session: authn.Session{UserID: validID, DomainID: validID, DomainUserID: validID},
|
||||
id: testsutil.GenerateUUID(t),
|
||||
retrieveResp: mggroups.Group{
|
||||
Status: clients.Status(groups.EnabledStatus),
|
||||
Status: mggroups.EnabledStatus,
|
||||
},
|
||||
changeResp: validGroup,
|
||||
},
|
||||
@@ -396,7 +395,7 @@ func TestDisableGroup(t *testing.T) {
|
||||
session: authn.Session{UserID: validID, DomainID: validID, DomainUserID: validID},
|
||||
id: testsutil.GenerateUUID(t),
|
||||
retrieveResp: mggroups.Group{
|
||||
Status: clients.Status(groups.DisabledStatus),
|
||||
Status: mggroups.DisabledStatus,
|
||||
},
|
||||
err: errors.ErrStatusAlreadyAssigned,
|
||||
},
|
||||
|
||||
@@ -1,175 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clients
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"golang.org/x/net/idna"
|
||||
)
|
||||
|
||||
const (
|
||||
maxLocalLen = 64
|
||||
maxDomainLen = 255
|
||||
maxTLDLen = 24 // longest TLD currently in existence
|
||||
|
||||
atSeparator = "@"
|
||||
dotSeparator = "."
|
||||
)
|
||||
|
||||
var (
|
||||
userRegexp = regexp.MustCompile("^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+$")
|
||||
hostRegexp = regexp.MustCompile(`^[^\s]+\.[^\s]+$`)
|
||||
userDotRegexp = regexp.MustCompile("(^[.]{1})|([.]{1}$)|([.]{2,})")
|
||||
)
|
||||
|
||||
// Credentials represent client credentials: its
|
||||
// "identity" which can be a username, email, generated name;
|
||||
// and "secret" which can be a password or access token.
|
||||
type Credentials struct {
|
||||
Identity string `json:"identity,omitempty"` // username or generated login ID
|
||||
Secret string `json:"secret,omitempty"` // password or token
|
||||
}
|
||||
|
||||
// Client represents generic Client.
|
||||
type Client struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Domain string `json:"domain_id,omitempty"`
|
||||
Credentials Credentials `json:"credentials,omitempty"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
Status Status `json:"status,omitempty"` // 1 for enabled, 0 for disabled
|
||||
Permissions []string `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
// ClientsPage contains page related metadata as well as list
|
||||
// of Clients that belong to the page.
|
||||
type ClientsPage struct {
|
||||
Page
|
||||
Clients []Client
|
||||
}
|
||||
|
||||
// MembersPage contains page related metadata as well as list of members that
|
||||
// belong to this page.
|
||||
type MembersPage struct {
|
||||
Page
|
||||
Members []Client
|
||||
}
|
||||
|
||||
// Repository specifies an account persistence API.
|
||||
type Repository interface {
|
||||
// RetrieveByID retrieves client by its unique ID.
|
||||
RetrieveByID(ctx context.Context, id string) (Client, error)
|
||||
|
||||
// RetrieveByIdentity retrieves client by its unique credentials
|
||||
RetrieveByIdentity(ctx context.Context, identity string) (Client, error)
|
||||
|
||||
// RetrieveAll retrieves all clients.
|
||||
RetrieveAll(ctx context.Context, pm Page) (ClientsPage, error)
|
||||
|
||||
// SearchClients retrieves clients based on search criteria.
|
||||
SearchClients(ctx context.Context, pm Page) (ClientsPage, error)
|
||||
|
||||
// RetrieveAllByIDs retrieves for given client IDs .
|
||||
RetrieveAllByIDs(ctx context.Context, pm Page) (ClientsPage, error)
|
||||
|
||||
// Update updates the client name and metadata.
|
||||
Update(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// UpdateTags updates the client tags.
|
||||
UpdateTags(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// UpdateIdentity updates identity for client with given id.
|
||||
UpdateIdentity(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// UpdateSecret updates secret for client with given identity.
|
||||
UpdateSecret(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// UpdateRole updates role for client with given id.
|
||||
UpdateRole(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// ChangeStatus changes client status to enabled or disabled
|
||||
ChangeStatus(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// Delete deletes client with given id
|
||||
Delete(ctx context.Context, id string) error
|
||||
}
|
||||
|
||||
// Validate returns an error if client representation is invalid.
|
||||
func (u Client) Validate() error {
|
||||
if !isEmail(u.Credentials.Identity) {
|
||||
return errors.ErrMalformedEntity
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isEmail(email string) bool {
|
||||
if email == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
es := strings.Split(email, atSeparator)
|
||||
if len(es) != 2 {
|
||||
return false
|
||||
}
|
||||
local, host := es[0], es[1]
|
||||
|
||||
if local == "" || len(local) > maxLocalLen {
|
||||
return false
|
||||
}
|
||||
|
||||
hs := strings.Split(host, dotSeparator)
|
||||
if len(hs) < 2 {
|
||||
return false
|
||||
}
|
||||
domain, ext := hs[0], hs[1]
|
||||
|
||||
// Check subdomain and validate
|
||||
if len(hs) > 2 {
|
||||
if domain == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 1; i < len(hs)-1; i++ {
|
||||
sub := hs[i]
|
||||
if sub == "" {
|
||||
return false
|
||||
}
|
||||
domain = fmt.Sprintf("%s.%s", domain, sub)
|
||||
}
|
||||
|
||||
ext = hs[len(hs)-1]
|
||||
}
|
||||
|
||||
if domain == "" || len(domain) > maxDomainLen {
|
||||
return false
|
||||
}
|
||||
if ext == "" || len(ext) > maxTLDLen {
|
||||
return false
|
||||
}
|
||||
|
||||
punyLocal, err := idna.ToASCII(local)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
punyHost, err := idna.ToASCII(host)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if userDotRegexp.MatchString(punyLocal) || !userRegexp.MatchString(punyLocal) || !hostRegexp.MatchString(punyHost) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clients
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidateClient(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
identity string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "valid identity",
|
||||
identity: "user@example.com",
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "invalid identity",
|
||||
identity: "user@example",
|
||||
err: errors.ErrMalformedEntity,
|
||||
},
|
||||
{
|
||||
desc: "empty identity",
|
||||
err: errors.ErrMalformedEntity,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
client := Client{
|
||||
Credentials: Credentials{
|
||||
Identity: c.identity,
|
||||
},
|
||||
}
|
||||
err := client.Validate()
|
||||
assert.Equal(t, c.err, err, "ValidateClient() error = %v, expected %v", err, c.err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsEmail(t *testing.T) {
|
||||
cases := []struct {
|
||||
email string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
email: "test@example.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
email: "test-test@example.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
email: "test.test@example.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
email: "test_test@example.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
email: "test@",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "@",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test.example.com",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "@example.com",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@example",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@example.",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@.com",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@.example.com",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@example.com.",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@example.",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@subdomain.example.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
email: "test@subdomain-example.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
email: "test@subdomain_example.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
email: "@subdomain.example.com",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@subdomain.subdomain.example.com",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
email: "test@subdomain..com",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@subdomain..example.com",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@subdomain.example..com",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@subdomain.example.com.",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
email: "test@subdomain.example.com..",
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
isValid := isEmail(c.email)
|
||||
if isValid != c.expected {
|
||||
t.Errorf("Expected isEmail(%s) to be %v, but got %v", c.email, c.expected, isValid)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package clients contains the domain concept definitions needed to support
|
||||
// Magistrala clients functionality.
|
||||
package clients
|
||||
@@ -1,27 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clients
|
||||
|
||||
// Page contains page metadata that helps navigation.
|
||||
type Page struct {
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Id string `json:"id,omitempty"`
|
||||
Order string `json:"order,omitempty"`
|
||||
Dir string `json:"dir,omitempty"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Permission string `json:"permission,omitempty"`
|
||||
Status Status `json:"status,omitempty"`
|
||||
IDs []string `json:"ids,omitempty"`
|
||||
Identity string `json:"identity,omitempty"`
|
||||
Role Role `json:"-"`
|
||||
ListPerms bool `json:"-"`
|
||||
Username string `json:"username,omitempty"`
|
||||
FirstName string `json:"first_name,omitempty"`
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
}
|
||||
@@ -1,525 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
"github.com/absmach/magistrala/pkg/postgres"
|
||||
"github.com/jackc/pgtype"
|
||||
)
|
||||
|
||||
type Repository struct {
|
||||
DB postgres.Database
|
||||
}
|
||||
|
||||
func (repo *Repository) Update(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
var query []string
|
||||
var upq string
|
||||
if client.Name != "" {
|
||||
query = append(query, "name = :name,")
|
||||
}
|
||||
if client.Metadata != nil {
|
||||
query = append(query, "metadata = :metadata,")
|
||||
}
|
||||
if len(query) > 0 {
|
||||
upq = strings.Join(query, " ")
|
||||
}
|
||||
|
||||
q := fmt.Sprintf(`UPDATE clients SET %s updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, tags, identity, secret, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`,
|
||||
upq)
|
||||
client.Status = clients.EnabledStatus
|
||||
return repo.update(ctx, client, q)
|
||||
}
|
||||
|
||||
func (repo *Repository) UpdateTags(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
q := `UPDATE clients SET tags = :tags, updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, tags, identity, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`
|
||||
client.Status = clients.EnabledStatus
|
||||
return repo.update(ctx, client, q)
|
||||
}
|
||||
|
||||
func (repo *Repository) UpdateIdentity(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
q := `UPDATE clients SET identity = :identity, updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, tags, identity, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`
|
||||
client.Status = clients.EnabledStatus
|
||||
return repo.update(ctx, client, q)
|
||||
}
|
||||
|
||||
func (repo *Repository) UpdateSecret(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
q := `UPDATE clients SET secret = :secret, updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, tags, identity, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`
|
||||
client.Status = clients.EnabledStatus
|
||||
return repo.update(ctx, client, q)
|
||||
}
|
||||
|
||||
func (repo *Repository) UpdateRole(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
q := `UPDATE clients SET role = :role, updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, tags, identity, metadata, COALESCE(domain_id, '') AS domain_id, status, role, created_at, updated_at, updated_by`
|
||||
client.Status = clients.EnabledStatus
|
||||
return repo.update(ctx, client, q)
|
||||
}
|
||||
|
||||
func (repo *Repository) ChangeStatus(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
q := `UPDATE clients SET status = :status, updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id
|
||||
RETURNING id, name, tags, identity, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`
|
||||
|
||||
return repo.update(ctx, client, q)
|
||||
}
|
||||
|
||||
func (repo *Repository) RetrieveByID(ctx context.Context, id string) (clients.Client, error) {
|
||||
q := `SELECT id, name, tags, COALESCE(domain_id, '') AS domain_id, identity, secret, metadata, created_at, updated_at, updated_by, status
|
||||
FROM clients WHERE id = :id`
|
||||
|
||||
dbc := DBClient{
|
||||
ID: id,
|
||||
}
|
||||
|
||||
row, err := repo.DB.NamedQueryContext(ctx, q, dbc)
|
||||
if err != nil {
|
||||
return clients.Client{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
defer row.Close()
|
||||
|
||||
dbc = DBClient{}
|
||||
if row.Next() {
|
||||
if err := row.StructScan(&dbc); err != nil {
|
||||
return clients.Client{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
return ToClient(dbc)
|
||||
}
|
||||
|
||||
return clients.Client{}, repoerr.ErrNotFound
|
||||
}
|
||||
|
||||
func (repo *Repository) RetrieveByIdentity(ctx context.Context, identity string) (clients.Client, error) {
|
||||
q := `SELECT id, name, tags, COALESCE(domain_id, '') AS domain_id, identity, secret, metadata, created_at, updated_at, updated_by, status
|
||||
FROM clients WHERE identity = :identity AND status = :status`
|
||||
|
||||
dbc := DBClient{
|
||||
Identity: identity,
|
||||
Status: clients.EnabledStatus,
|
||||
}
|
||||
|
||||
row, err := repo.DB.NamedQueryContext(ctx, q, dbc)
|
||||
if err != nil {
|
||||
return clients.Client{}, postgres.HandleError(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
defer row.Close()
|
||||
|
||||
dbc = DBClient{}
|
||||
if row.Next() {
|
||||
if err := row.StructScan(&dbc); err != nil {
|
||||
return clients.Client{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
return ToClient(dbc)
|
||||
}
|
||||
|
||||
return clients.Client{}, repoerr.ErrNotFound
|
||||
}
|
||||
|
||||
func (repo *Repository) RetrieveAll(ctx context.Context, pm clients.Page) (clients.ClientsPage, error) {
|
||||
query, err := PageQuery(pm)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
query = applyOrdering(query, pm)
|
||||
|
||||
q := fmt.Sprintf(`SELECT c.id, c.name, c.tags, c.identity, c.metadata, COALESCE(c.domain_id, '') AS domain_id, c.status,
|
||||
c.created_at, c.updated_at, COALESCE(c.updated_by, '') AS updated_by FROM clients c %s ORDER BY c.created_at LIMIT :limit OFFSET :offset;`, query)
|
||||
|
||||
dbPage, err := ToDBClientsPage(pm)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var items []clients.Client
|
||||
for rows.Next() {
|
||||
dbc := DBClient{}
|
||||
if err := rows.StructScan(&dbc); err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
c, err := ToClient(dbc)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, err
|
||||
}
|
||||
|
||||
items = append(items, c)
|
||||
}
|
||||
cq := fmt.Sprintf(`SELECT COUNT(*) FROM clients c %s;`, query)
|
||||
|
||||
total, err := postgres.Total(ctx, repo.DB, cq, dbPage)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
page := clients.ClientsPage{
|
||||
Clients: items,
|
||||
Page: clients.Page{
|
||||
Total: total,
|
||||
Offset: pm.Offset,
|
||||
Limit: pm.Limit,
|
||||
},
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (repo *Repository) SearchClients(ctx context.Context, pm clients.Page) (clients.ClientsPage, error) {
|
||||
query, err := PageQuery(pm)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
tq := query
|
||||
query = applyOrdering(query, pm)
|
||||
|
||||
q := fmt.Sprintf(`SELECT c.id, c.name, c.created_at, c.updated_at FROM clients c %s LIMIT :limit OFFSET :offset;`, query)
|
||||
|
||||
dbPage, err := ToDBClientsPage(pm)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
|
||||
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var items []clients.Client
|
||||
for rows.Next() {
|
||||
dbc := DBClient{}
|
||||
if err := rows.StructScan(&dbc); err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
c, err := ToClient(dbc)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, err
|
||||
}
|
||||
|
||||
items = append(items, c)
|
||||
}
|
||||
|
||||
cq := fmt.Sprintf(`SELECT COUNT(*) FROM clients c %s;`, tq)
|
||||
total, err := postgres.Total(ctx, repo.DB, cq, dbPage)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
page := clients.ClientsPage{
|
||||
Clients: items,
|
||||
Page: clients.Page{
|
||||
Total: total,
|
||||
Offset: pm.Offset,
|
||||
Limit: pm.Limit,
|
||||
},
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (repo *Repository) RetrieveAllByIDs(ctx context.Context, pm clients.Page) (clients.ClientsPage, error) {
|
||||
if (len(pm.IDs) == 0) && (pm.Domain == "") {
|
||||
return clients.ClientsPage{
|
||||
Page: clients.Page{Total: pm.Total, Offset: pm.Offset, Limit: pm.Limit},
|
||||
}, nil
|
||||
}
|
||||
query, err := PageQuery(pm)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
query = applyOrdering(query, pm)
|
||||
|
||||
q := fmt.Sprintf(`SELECT c.id, c.name, c.tags, c.identity, c.metadata, COALESCE(c.domain_id, '') AS domain_id, c.status,
|
||||
c.created_at, c.updated_at, COALESCE(c.updated_by, '') AS updated_by FROM clients c %s ORDER BY c.created_at LIMIT :limit OFFSET :offset;`, query)
|
||||
|
||||
dbPage, err := ToDBClientsPage(pm)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
rows, err := repo.DB.NamedQueryContext(ctx, q, dbPage)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var items []clients.Client
|
||||
for rows.Next() {
|
||||
dbc := DBClient{}
|
||||
if err := rows.StructScan(&dbc); err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
c, err := ToClient(dbc)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, err
|
||||
}
|
||||
|
||||
items = append(items, c)
|
||||
}
|
||||
cq := fmt.Sprintf(`SELECT COUNT(*) FROM clients c %s;`, query)
|
||||
|
||||
total, err := postgres.Total(ctx, repo.DB, cq, dbPage)
|
||||
if err != nil {
|
||||
return clients.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
page := clients.ClientsPage{
|
||||
Clients: items,
|
||||
Page: clients.Page{
|
||||
Total: total,
|
||||
Offset: pm.Offset,
|
||||
Limit: pm.Limit,
|
||||
},
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (repo *Repository) update(ctx context.Context, client clients.Client, query string) (clients.Client, error) {
|
||||
dbc, err := ToDBClient(client)
|
||||
if err != nil {
|
||||
return clients.Client{}, errors.Wrap(repoerr.ErrUpdateEntity, err)
|
||||
}
|
||||
|
||||
row, err := repo.DB.NamedQueryContext(ctx, query, dbc)
|
||||
if err != nil {
|
||||
return clients.Client{}, postgres.HandleError(repoerr.ErrUpdateEntity, err)
|
||||
}
|
||||
defer row.Close()
|
||||
|
||||
dbc = DBClient{}
|
||||
if row.Next() {
|
||||
if err := row.StructScan(&dbc); err != nil {
|
||||
return clients.Client{}, errors.Wrap(repoerr.ErrUpdateEntity, err)
|
||||
}
|
||||
|
||||
return ToClient(dbc)
|
||||
}
|
||||
|
||||
return clients.Client{}, repoerr.ErrNotFound
|
||||
}
|
||||
|
||||
func (repo *Repository) Delete(ctx context.Context, id string) error {
|
||||
q := "DELETE FROM clients AS c WHERE c.id = $1 ;"
|
||||
|
||||
result, err := repo.DB.ExecContext(ctx, q, id)
|
||||
if err != nil {
|
||||
return postgres.HandleError(repoerr.ErrRemoveEntity, err)
|
||||
}
|
||||
if rows, _ := result.RowsAffected(); rows == 0 {
|
||||
return repoerr.ErrNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DBClient struct {
|
||||
ID string `db:"id"`
|
||||
Name string `db:"name,omitempty"`
|
||||
Tags pgtype.TextArray `db:"tags,omitempty"`
|
||||
Identity string `db:"identity"`
|
||||
Domain string `db:"domain_id"`
|
||||
Secret string `db:"secret"`
|
||||
Metadata []byte `db:"metadata,omitempty"`
|
||||
CreatedAt time.Time `db:"created_at,omitempty"`
|
||||
UpdatedAt sql.NullTime `db:"updated_at,omitempty"`
|
||||
UpdatedBy *string `db:"updated_by,omitempty"`
|
||||
Groups []groups.Group `db:"groups,omitempty"`
|
||||
Status clients.Status `db:"status,omitempty"`
|
||||
Role *clients.Role `db:"role,omitempty"`
|
||||
}
|
||||
|
||||
func ToDBClient(c clients.Client) (DBClient, error) {
|
||||
data := []byte("{}")
|
||||
if len(c.Metadata) > 0 {
|
||||
b, err := json.Marshal(c.Metadata)
|
||||
if err != nil {
|
||||
return DBClient{}, errors.Wrap(repoerr.ErrMalformedEntity, err)
|
||||
}
|
||||
data = b
|
||||
}
|
||||
var tags pgtype.TextArray
|
||||
if err := tags.Set(c.Tags); err != nil {
|
||||
return DBClient{}, err
|
||||
}
|
||||
var updatedBy *string
|
||||
if c.UpdatedBy != "" {
|
||||
updatedBy = &c.UpdatedBy
|
||||
}
|
||||
var updatedAt sql.NullTime
|
||||
if c.UpdatedAt != (time.Time{}) {
|
||||
updatedAt = sql.NullTime{Time: c.UpdatedAt, Valid: true}
|
||||
}
|
||||
|
||||
return DBClient{
|
||||
ID: c.ID,
|
||||
Name: c.Name,
|
||||
Tags: tags,
|
||||
Domain: c.Domain,
|
||||
Identity: c.Credentials.Identity,
|
||||
Secret: c.Credentials.Secret,
|
||||
Metadata: data,
|
||||
CreatedAt: c.CreatedAt,
|
||||
UpdatedAt: updatedAt,
|
||||
UpdatedBy: updatedBy,
|
||||
Status: c.Status,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ToClient(c DBClient) (clients.Client, error) {
|
||||
var metadata clients.Metadata
|
||||
if c.Metadata != nil {
|
||||
if err := json.Unmarshal([]byte(c.Metadata), &metadata); err != nil {
|
||||
return clients.Client{}, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
}
|
||||
var tags []string
|
||||
for _, e := range c.Tags.Elements {
|
||||
tags = append(tags, e.String)
|
||||
}
|
||||
var updatedBy string
|
||||
if c.UpdatedBy != nil {
|
||||
updatedBy = *c.UpdatedBy
|
||||
}
|
||||
var updatedAt time.Time
|
||||
if c.UpdatedAt.Valid {
|
||||
updatedAt = c.UpdatedAt.Time
|
||||
}
|
||||
|
||||
cli := clients.Client{
|
||||
ID: c.ID,
|
||||
Name: c.Name,
|
||||
Tags: tags,
|
||||
Domain: c.Domain,
|
||||
Credentials: clients.Credentials{
|
||||
Identity: c.Identity,
|
||||
Secret: c.Secret,
|
||||
},
|
||||
Metadata: metadata,
|
||||
CreatedAt: c.CreatedAt,
|
||||
UpdatedAt: updatedAt,
|
||||
UpdatedBy: updatedBy,
|
||||
Status: c.Status,
|
||||
}
|
||||
return cli, nil
|
||||
}
|
||||
|
||||
func ToDBClientsPage(pm clients.Page) (dbClientsPage, error) {
|
||||
_, data, err := postgres.CreateMetadataQuery("", pm.Metadata)
|
||||
if err != nil {
|
||||
return dbClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
return dbClientsPage{
|
||||
Name: pm.Name,
|
||||
Identity: pm.Identity,
|
||||
Id: pm.Id,
|
||||
Metadata: data,
|
||||
Domain: pm.Domain,
|
||||
Total: pm.Total,
|
||||
Offset: pm.Offset,
|
||||
Limit: pm.Limit,
|
||||
Status: pm.Status,
|
||||
Tag: pm.Tag,
|
||||
Role: pm.Role,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type dbClientsPage struct {
|
||||
Total uint64 `db:"total"`
|
||||
Limit uint64 `db:"limit"`
|
||||
Offset uint64 `db:"offset"`
|
||||
Name string `db:"name"`
|
||||
Id string `db:"id"`
|
||||
Domain string `db:"domain_id"`
|
||||
Identity string `db:"identity"`
|
||||
Metadata []byte `db:"metadata"`
|
||||
Tag string `db:"tag"`
|
||||
Status clients.Status `db:"status"`
|
||||
GroupID string `db:"group_id"`
|
||||
Role clients.Role `db:"role"`
|
||||
}
|
||||
|
||||
func PageQuery(pm clients.Page) (string, error) {
|
||||
mq, _, err := postgres.CreateMetadataQuery("", pm.Metadata)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
|
||||
var query []string
|
||||
if pm.Name != "" {
|
||||
query = append(query, "name ILIKE '%' || :name || '%'")
|
||||
}
|
||||
if pm.Identity != "" {
|
||||
query = append(query, "identity ILIKE '%' || :identity || '%'")
|
||||
}
|
||||
if pm.Id != "" {
|
||||
query = append(query, "id ILIKE '%' || :id || '%'")
|
||||
}
|
||||
if pm.Tag != "" {
|
||||
query = append(query, "EXISTS (SELECT 1 FROM unnest(tags) AS tag WHERE tag ILIKE '%' || :tag || '%')")
|
||||
}
|
||||
// If there are search params presents, use search and ignore other options.
|
||||
// Always combine role with search params, so len(query) > 1.
|
||||
if len(query) > 1 {
|
||||
return fmt.Sprintf("WHERE %s", strings.Join(query, " AND ")), nil
|
||||
}
|
||||
|
||||
if mq != "" {
|
||||
query = append(query, mq)
|
||||
}
|
||||
|
||||
if len(pm.IDs) != 0 {
|
||||
query = append(query, fmt.Sprintf("id IN ('%s')", strings.Join(pm.IDs, "','")))
|
||||
}
|
||||
if pm.Status != clients.AllStatus {
|
||||
query = append(query, "c.status = :status")
|
||||
}
|
||||
if pm.Domain != "" {
|
||||
query = append(query, "c.domain_id = :domain_id")
|
||||
}
|
||||
var emq string
|
||||
if len(query) > 0 {
|
||||
emq = fmt.Sprintf("WHERE %s", strings.Join(query, " AND "))
|
||||
}
|
||||
return emq, nil
|
||||
}
|
||||
|
||||
func applyOrdering(emq string, pm clients.Page) string {
|
||||
switch pm.Order {
|
||||
case "name", "identity", "created_at", "updated_at":
|
||||
emq = fmt.Sprintf("%s ORDER BY %s", emq, pm.Order)
|
||||
if pm.Dir == api.AscDir || pm.Dir == api.DescDir {
|
||||
emq = fmt.Sprintf("%s %s", emq, pm.Dir)
|
||||
}
|
||||
}
|
||||
return emq
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package postgres contains the database implementation of clients repository layer.
|
||||
package postgres
|
||||
@@ -1,97 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package postgres_test
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/postgres"
|
||||
pgClient "github.com/absmach/magistrala/pkg/postgres"
|
||||
tpostgres "github.com/absmach/magistrala/things/postgres"
|
||||
"github.com/jmoiron/sqlx"
|
||||
dockertest "github.com/ory/dockertest/v3"
|
||||
"github.com/ory/dockertest/v3/docker"
|
||||
"go.opentelemetry.io/otel"
|
||||
)
|
||||
|
||||
var (
|
||||
db *sqlx.DB
|
||||
database postgres.Database
|
||||
tracer = otel.Tracer("repo_tests")
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
pool, err := dockertest.NewPool("")
|
||||
if err != nil {
|
||||
log.Fatalf("Could not connect to docker: %s", err)
|
||||
}
|
||||
|
||||
container, err := pool.RunWithOptions(&dockertest.RunOptions{
|
||||
Repository: "postgres",
|
||||
Tag: "16.2-alpine",
|
||||
Env: []string{
|
||||
"POSTGRES_USER=test",
|
||||
"POSTGRES_PASSWORD=test",
|
||||
"POSTGRES_DB=test",
|
||||
"listen_addresses = '*'",
|
||||
},
|
||||
}, func(config *docker.HostConfig) {
|
||||
config.AutoRemove = true
|
||||
config.RestartPolicy = docker.RestartPolicy{Name: "no"}
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("Could not start container: %s", err)
|
||||
}
|
||||
|
||||
port := container.GetPort("5432/tcp")
|
||||
|
||||
// exponential backoff-retry, because the application in the container might not be ready to accept connections yet
|
||||
pool.MaxWait = 120 * time.Second
|
||||
if err := pool.Retry(func() error {
|
||||
url := fmt.Sprintf("host=localhost port=%s user=test dbname=test password=test sslmode=disable", port)
|
||||
db, err := sql.Open("pgx", url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return db.Ping()
|
||||
}); err != nil {
|
||||
log.Fatalf("Could not connect to docker: %s", err)
|
||||
}
|
||||
|
||||
dbConfig := pgClient.Config{
|
||||
Host: "localhost",
|
||||
Port: port,
|
||||
User: "test",
|
||||
Pass: "test",
|
||||
Name: "test",
|
||||
SSLMode: "disable",
|
||||
SSLCert: "",
|
||||
SSLKey: "",
|
||||
SSLRootCert: "",
|
||||
}
|
||||
|
||||
if db, err = pgClient.Setup(dbConfig, *tpostgres.Migration()); err != nil {
|
||||
log.Fatalf("Could not setup test DB connection: %s", err)
|
||||
}
|
||||
|
||||
if db, err = pgClient.Connect(dbConfig); err != nil {
|
||||
log.Fatalf("Could not setup test DB connection: %s", err)
|
||||
}
|
||||
database = postgres.NewDatabase(db, dbConfig, tracer)
|
||||
|
||||
code := m.Run()
|
||||
|
||||
// Defers will not be run when using os.Exit
|
||||
db.Close()
|
||||
if err := pool.Purge(container); err != nil {
|
||||
log.Fatalf("Could not purge container: %s", err)
|
||||
}
|
||||
|
||||
os.Exit(code)
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clients
|
||||
|
||||
// Metadata represents arbitrary JSON.
|
||||
type Metadata map[string]interface{}
|
||||
+17
-15
@@ -8,7 +8,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
)
|
||||
|
||||
// MaxLevel represents the maximum group hierarchy level.
|
||||
@@ -19,20 +18,20 @@ const MaxLevel = uint64(5)
|
||||
// Path in a tree consisting of group IDs
|
||||
// Paths are unique per domain.
|
||||
type Group struct {
|
||||
ID string `json:"id"`
|
||||
Domain string `json:"domain_id,omitempty"`
|
||||
Parent string `json:"parent_id,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Metadata clients.Metadata `json:"metadata,omitempty"`
|
||||
Level int `json:"level,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Children []*Group `json:"children,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
Status clients.Status `json:"status"`
|
||||
Permissions []string `json:"permissions,omitempty"`
|
||||
ID string `json:"id"`
|
||||
Domain string `json:"domain_id,omitempty"`
|
||||
Parent string `json:"parent_id,omitempty"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
Level int `json:"level,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
Children []*Group `json:"children,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
Status Status `json:"status"`
|
||||
Permissions []string `json:"permissions,omitempty"`
|
||||
}
|
||||
|
||||
type Member struct {
|
||||
@@ -62,6 +61,9 @@ type Page struct {
|
||||
Groups []Group
|
||||
}
|
||||
|
||||
// Metadata represents arbitrary JSON.
|
||||
type Metadata map[string]interface{}
|
||||
|
||||
// Repository specifies a group persistence API.
|
||||
//
|
||||
//go:generate mockery --name Repository --output=./mocks --filename repository.go --quiet --note "Copyright (c) Abstract Machines" --unroll-variadic=false
|
||||
|
||||
+9
-11
@@ -3,17 +3,15 @@
|
||||
|
||||
package groups
|
||||
|
||||
import "github.com/absmach/magistrala/pkg/clients"
|
||||
|
||||
// PageMeta contains page metadata that helps navigation.
|
||||
type PageMeta struct {
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
DomainID string `json:"domain_id,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Metadata clients.Metadata `json:"metadata,omitempty"`
|
||||
Status clients.Status `json:"status,omitempty"`
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
DomainID string `json:"domain_id,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
Status Status `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package groups
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
)
|
||||
|
||||
// Status represents User status.
|
||||
type Status uint8
|
||||
|
||||
// Possible User status values.
|
||||
const (
|
||||
// EnabledStatus represents enabled User.
|
||||
EnabledStatus Status = iota
|
||||
// DisabledStatus represents disabled User.
|
||||
DisabledStatus
|
||||
// DeletedStatus represents a user that will be deleted.
|
||||
DeletedStatus
|
||||
|
||||
// AllStatus is used for querying purposes to list users irrespective
|
||||
// of their status - both enabled and disabled. It is never stored in the
|
||||
// database as the actual User status and should always be the largest
|
||||
// value in this enumeration.
|
||||
AllStatus
|
||||
)
|
||||
|
||||
// String representation of the possible status values.
|
||||
const (
|
||||
Disabled = "disabled"
|
||||
Enabled = "enabled"
|
||||
Deleted = "deleted"
|
||||
All = "all"
|
||||
Unknown = "unknown"
|
||||
)
|
||||
|
||||
// String converts user/group status to string literal.
|
||||
func (s Status) String() string {
|
||||
switch s {
|
||||
case DisabledStatus:
|
||||
return Disabled
|
||||
case EnabledStatus:
|
||||
return Enabled
|
||||
case DeletedStatus:
|
||||
return Deleted
|
||||
case AllStatus:
|
||||
return All
|
||||
default:
|
||||
return Unknown
|
||||
}
|
||||
}
|
||||
|
||||
// ToStatus converts string value to a valid User/Group status.
|
||||
func ToStatus(status string) (Status, error) {
|
||||
switch status {
|
||||
case "", Enabled:
|
||||
return EnabledStatus, nil
|
||||
case Disabled:
|
||||
return DisabledStatus, nil
|
||||
case Deleted:
|
||||
return DeletedStatus, nil
|
||||
case All:
|
||||
return AllStatus, nil
|
||||
}
|
||||
return Status(0), svcerr.ErrInvalidStatus
|
||||
}
|
||||
|
||||
// Custom Marshaller for Uesr/Groups.
|
||||
func (s Status) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(s.String())
|
||||
}
|
||||
|
||||
// Custom Unmarshaler for User/Groups.
|
||||
func (s *Status) UnmarshalJSON(data []byte) error {
|
||||
str := strings.Trim(string(data), "\"")
|
||||
val, err := ToStatus(str)
|
||||
*s = val
|
||||
return err
|
||||
}
|
||||
+34
-35
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
authnmocks "github.com/absmach/magistrala/pkg/authn/mocks"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
@@ -65,14 +64,14 @@ func TestCreateChannel(t *testing.T) {
|
||||
group := convertChannel(channel)
|
||||
createGroupReq := groups.Group{
|
||||
Name: channel.Name,
|
||||
Metadata: mgclients.Metadata{"role": "client"},
|
||||
Status: mgclients.EnabledStatus,
|
||||
Metadata: groups.Metadata{"role": "client"},
|
||||
Status: groups.EnabledStatus,
|
||||
}
|
||||
|
||||
channelReq := sdk.Channel{
|
||||
Name: channel.Name,
|
||||
Metadata: validMetadata,
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
}
|
||||
|
||||
channelKind := "new_channel"
|
||||
@@ -83,7 +82,7 @@ func TestCreateChannel(t *testing.T) {
|
||||
pChannel.ParentID = parentID
|
||||
|
||||
iGroup := group
|
||||
iGroup.Metadata = mgclients.Metadata{
|
||||
iGroup.Metadata = groups.Metadata{
|
||||
"test": make(chan int),
|
||||
}
|
||||
|
||||
@@ -148,14 +147,14 @@ func TestCreateChannel(t *testing.T) {
|
||||
channelReq: sdk.Channel{
|
||||
Name: channel.Name,
|
||||
ParentID: parentID,
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
createGroupReq: groups.Group{
|
||||
Name: channel.Name,
|
||||
Parent: parentID,
|
||||
Status: mgclients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
},
|
||||
svcRes: pGroup,
|
||||
svcErr: nil,
|
||||
@@ -167,14 +166,14 @@ func TestCreateChannel(t *testing.T) {
|
||||
channelReq: sdk.Channel{
|
||||
Name: channel.Name,
|
||||
ParentID: wrongID,
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
createGroupReq: groups.Group{
|
||||
Name: channel.Name,
|
||||
Parent: wrongID,
|
||||
Status: mgclients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
},
|
||||
svcRes: groups.Group{},
|
||||
svcErr: svcerr.ErrCreateEntity,
|
||||
@@ -184,7 +183,7 @@ func TestCreateChannel(t *testing.T) {
|
||||
{
|
||||
desc: "create channel with missing name",
|
||||
channelReq: sdk.Channel{
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
@@ -204,7 +203,7 @@ func TestCreateChannel(t *testing.T) {
|
||||
Metadata: validMetadata,
|
||||
CreatedAt: group.CreatedAt,
|
||||
UpdatedAt: group.UpdatedAt,
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
@@ -213,10 +212,10 @@ func TestCreateChannel(t *testing.T) {
|
||||
Parent: parentID,
|
||||
Name: channel.Name,
|
||||
Description: description,
|
||||
Metadata: mgclients.Metadata{"role": "client"},
|
||||
Metadata: groups.Metadata{"role": "client"},
|
||||
CreatedAt: group.CreatedAt,
|
||||
UpdatedAt: group.UpdatedAt,
|
||||
Status: mgclients.EnabledStatus,
|
||||
Status: groups.EnabledStatus,
|
||||
},
|
||||
svcRes: pGroup,
|
||||
svcErr: nil,
|
||||
@@ -270,7 +269,7 @@ func TestListChannels(t *testing.T) {
|
||||
ID: generateUUID(t),
|
||||
Name: fmt.Sprintf("channel_%d", i),
|
||||
Metadata: sdk.Metadata{"name": fmt.Sprintf("thing_%d", i)},
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
}
|
||||
chs = append(chs, gr)
|
||||
}
|
||||
@@ -280,7 +279,7 @@ func TestListChannels(t *testing.T) {
|
||||
domainID string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
status mgclients.Status
|
||||
status groups.Status
|
||||
total uint64
|
||||
offset uint64
|
||||
limit uint64
|
||||
@@ -438,7 +437,7 @@ func TestListChannels(t *testing.T) {
|
||||
PageMeta: groups.PageMeta{
|
||||
Offset: offset,
|
||||
Limit: 10,
|
||||
Metadata: mgclients.Metadata{"name": "thing_89"},
|
||||
Metadata: groups.Metadata{"name": "thing_89"},
|
||||
},
|
||||
Permission: "view",
|
||||
Direction: -1,
|
||||
@@ -493,7 +492,7 @@ func TestListChannels(t *testing.T) {
|
||||
},
|
||||
Groups: []groups.Group{{
|
||||
ID: generateUUID(t),
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": make(chan int),
|
||||
},
|
||||
}},
|
||||
@@ -609,7 +608,7 @@ func TestViewChannel(t *testing.T) {
|
||||
channelID: groupRes.ID,
|
||||
svcRes: groups.Group{
|
||||
ID: generateUUID(t),
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -660,7 +659,7 @@ func TestUpdateChannel(t *testing.T) {
|
||||
dChannel.Description = newDescription
|
||||
|
||||
mGroup := group
|
||||
mGroup.Metadata = mgclients.Metadata{
|
||||
mGroup.Metadata = groups.Metadata{
|
||||
"field": "value2",
|
||||
}
|
||||
mChannel := channel
|
||||
@@ -671,7 +670,7 @@ func TestUpdateChannel(t *testing.T) {
|
||||
aGroup := group
|
||||
aGroup.Name = newName
|
||||
aGroup.Description = newDescription
|
||||
aGroup.Metadata = mgclients.Metadata{"field": "value2"}
|
||||
aGroup.Metadata = groups.Metadata{"field": "value2"}
|
||||
aChannel := channel
|
||||
aChannel.Name = newName
|
||||
aChannel.Description = newDescription
|
||||
@@ -736,7 +735,7 @@ func TestUpdateChannel(t *testing.T) {
|
||||
},
|
||||
updateGroupReq: groups.Group{
|
||||
ID: group.ID,
|
||||
Metadata: mgclients.Metadata{"field": "value2"},
|
||||
Metadata: groups.Metadata{"field": "value2"},
|
||||
},
|
||||
svcRes: mGroup,
|
||||
svcErr: nil,
|
||||
@@ -757,7 +756,7 @@ func TestUpdateChannel(t *testing.T) {
|
||||
ID: group.ID,
|
||||
Name: newName,
|
||||
Description: newDescription,
|
||||
Metadata: mgclients.Metadata{"field": "value2"},
|
||||
Metadata: groups.Metadata{"field": "value2"},
|
||||
},
|
||||
svcRes: aGroup,
|
||||
svcErr: nil,
|
||||
@@ -810,7 +809,7 @@ func TestUpdateChannel(t *testing.T) {
|
||||
},
|
||||
updateGroupReq: groups.Group{
|
||||
ID: wrongID,
|
||||
Metadata: mgclients.Metadata{"field": "value2"},
|
||||
Metadata: groups.Metadata{"field": "value2"},
|
||||
},
|
||||
svcRes: groups.Group{},
|
||||
svcErr: svcerr.ErrNotFound,
|
||||
@@ -896,7 +895,7 @@ func TestUpdateChannel(t *testing.T) {
|
||||
},
|
||||
svcRes: groups.Group{
|
||||
ID: generateUUID(t),
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -955,7 +954,7 @@ func TestListChannelsByThing(t *testing.T) {
|
||||
ID: generateUUID(t),
|
||||
Name: fmt.Sprintf("membership_%d@example.com", i),
|
||||
Metadata: sdk.Metadata{"role": "channel"},
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
}
|
||||
aChannels = append(aChannels, channel)
|
||||
}
|
||||
@@ -1153,7 +1152,7 @@ func TestListChannelsByThing(t *testing.T) {
|
||||
},
|
||||
Groups: []groups.Group{{
|
||||
ID: generateUUID(t),
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": make(chan int),
|
||||
},
|
||||
}},
|
||||
@@ -1262,7 +1261,7 @@ func TestEnableChannel(t *testing.T) {
|
||||
channelID: channel.ID,
|
||||
svcRes: groups.Group{
|
||||
ID: generateUUID(t),
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -1302,9 +1301,9 @@ func TestDisableChannel(t *testing.T) {
|
||||
|
||||
group := convertChannel(channel)
|
||||
dGroup := group
|
||||
dGroup.Status = mgclients.DisabledStatus
|
||||
dGroup.Status = groups.DisabledStatus
|
||||
dChannel := channel
|
||||
dChannel.Status = mgclients.DisabledStatus.String()
|
||||
dChannel.Status = groups.DisabledStatus.String()
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
@@ -1375,7 +1374,7 @@ func TestDisableChannel(t *testing.T) {
|
||||
channelID: channel.ID,
|
||||
svcRes: groups.Group{
|
||||
ID: generateUUID(t),
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"test": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -2051,7 +2050,7 @@ func TestListChannelUserGroups(t *testing.T) {
|
||||
ID: generateUUID(t),
|
||||
Name: fmt.Sprintf("group_%d", i),
|
||||
Metadata: sdk.Metadata{"role": "group"},
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
}
|
||||
aGroups = append(aGroups, group)
|
||||
}
|
||||
@@ -2257,7 +2256,7 @@ func TestListChannelUserGroups(t *testing.T) {
|
||||
Groups: []groups.Group{
|
||||
{
|
||||
ID: generateUUID(t),
|
||||
Metadata: mgclients.Metadata{"test": make(chan int)},
|
||||
Metadata: groups.Metadata{"test": make(chan int)},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2704,7 +2703,7 @@ func TestListGroupChannels(t *testing.T) {
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: "group_channel",
|
||||
Metadata: sdk.Metadata{"role": "group"},
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
@@ -2854,7 +2853,7 @@ func TestListGroupChannels(t *testing.T) {
|
||||
Groups: []groups.Group{
|
||||
{
|
||||
ID: generateUUID(t),
|
||||
Metadata: mgclients.Metadata{"test": make(chan int)},
|
||||
Metadata: groups.Metadata{"test": make(chan int)},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -2895,7 +2894,7 @@ func generateTestChannel(t *testing.T) sdk.Channel {
|
||||
Metadata: sdk.Metadata{"role": "client"},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
}
|
||||
return ch
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
policies "github.com/absmach/magistrala/pkg/policies"
|
||||
@@ -142,7 +141,7 @@ func TestCreateDomain(t *testing.T) {
|
||||
svcRes: auth.Domain{
|
||||
ID: authDomain.ID,
|
||||
Name: authDomain.Name,
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: auth.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -283,7 +282,7 @@ func TestUpdateDomain(t *testing.T) {
|
||||
svcRes: auth.Domain{
|
||||
ID: authDomain.ID,
|
||||
Name: authDomain.Name,
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: auth.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -379,7 +378,7 @@ func TestViewDomain(t *testing.T) {
|
||||
svcRes: auth.Domain{
|
||||
ID: authDomain.ID,
|
||||
Name: authDomain.Name,
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: auth.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -597,7 +596,7 @@ func TestListDomians(t *testing.T) {
|
||||
Total: 1,
|
||||
Domains: []auth.Domain{{
|
||||
Name: authDomain.Name,
|
||||
Metadata: mgclients.Metadata{"key": make(chan int)},
|
||||
Metadata: auth.Metadata{"key": make(chan int)},
|
||||
}},
|
||||
},
|
||||
svcErr: nil,
|
||||
@@ -734,7 +733,7 @@ func TestListUserDomains(t *testing.T) {
|
||||
Total: 1,
|
||||
Domains: []auth.Domain{{
|
||||
Name: authDomain.Name,
|
||||
Metadata: mgclients.Metadata{"key": make(chan int)},
|
||||
Metadata: auth.Metadata{"key": make(chan int)},
|
||||
}},
|
||||
},
|
||||
svcErr: nil,
|
||||
@@ -1111,7 +1110,7 @@ func generateTestDomain(t *testing.T) (auth.Domain, sdk.Domain) {
|
||||
ad := auth.Domain{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: "test-domain",
|
||||
Metadata: mgclients.Metadata(validMetadata),
|
||||
Metadata: auth.Metadata(validMetadata),
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Alias: "test-alias",
|
||||
Status: auth.EnabledStatus,
|
||||
|
||||
+27
-28
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
authnmocks "github.com/absmach/magistrala/pkg/authn/mocks"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
@@ -74,7 +73,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
psdkGroup.ParentID = pGroup.Parent
|
||||
|
||||
uGroup := group
|
||||
uGroup.Metadata = mgclients.Metadata{
|
||||
uGroup.Metadata = groups.Metadata{
|
||||
"key": make(chan int),
|
||||
}
|
||||
cases := []struct {
|
||||
@@ -98,7 +97,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
svcReq: groups.Group{
|
||||
Name: gName,
|
||||
Description: description,
|
||||
Metadata: mgclients.Metadata{"role": "client"},
|
||||
Metadata: groups.Metadata{"role": "client"},
|
||||
},
|
||||
svcRes: group,
|
||||
svcErr: nil,
|
||||
@@ -113,7 +112,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
svcReq: groups.Group{
|
||||
Name: gName,
|
||||
Description: description,
|
||||
Metadata: mgclients.Metadata{"role": "client"},
|
||||
Metadata: groups.Metadata{"role": "client"},
|
||||
},
|
||||
svcRes: group,
|
||||
svcErr: nil,
|
||||
@@ -133,7 +132,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
svcReq: groups.Group{
|
||||
Name: gName,
|
||||
Description: description,
|
||||
Metadata: mgclients.Metadata{"role": "client"},
|
||||
Metadata: groups.Metadata{"role": "client"},
|
||||
Parent: pGroup.Parent,
|
||||
},
|
||||
svcRes: pGroup,
|
||||
@@ -154,7 +153,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
svcReq: groups.Group{
|
||||
Name: gName,
|
||||
Description: description,
|
||||
Metadata: mgclients.Metadata{"role": "client"},
|
||||
Metadata: groups.Metadata{"role": "client"},
|
||||
Parent: wrongID,
|
||||
},
|
||||
svcRes: groups.Group{},
|
||||
@@ -174,7 +173,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
svcReq: groups.Group{
|
||||
Name: gName,
|
||||
Description: description,
|
||||
Metadata: mgclients.Metadata{"role": "client"},
|
||||
Metadata: groups.Metadata{"role": "client"},
|
||||
},
|
||||
svcRes: groups.Group{},
|
||||
authenticateErr: svcerr.ErrAuthentication,
|
||||
@@ -254,7 +253,7 @@ func TestCreateGroup(t *testing.T) {
|
||||
svcReq: groups.Group{
|
||||
Name: gName,
|
||||
Description: description,
|
||||
Metadata: mgclients.Metadata{"role": "client"},
|
||||
Metadata: groups.Metadata{"role": "client"},
|
||||
},
|
||||
svcRes: uGroup,
|
||||
svcErr: nil,
|
||||
@@ -297,7 +296,7 @@ func TestListGroups(t *testing.T) {
|
||||
ID: generateUUID(t),
|
||||
Name: fmt.Sprintf("group_%d", i),
|
||||
Metadata: sdk.Metadata{"name": fmt.Sprintf("user_%d", i)},
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
}
|
||||
grps = append(grps, gr)
|
||||
}
|
||||
@@ -440,7 +439,7 @@ func TestListGroups(t *testing.T) {
|
||||
PageMeta: groups.PageMeta{
|
||||
Offset: 0,
|
||||
Limit: 10,
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"name": "user_89",
|
||||
},
|
||||
},
|
||||
@@ -517,7 +516,7 @@ func TestListGroups(t *testing.T) {
|
||||
Groups: []groups.Group{{
|
||||
ID: generateUUID(t),
|
||||
Name: "group_1",
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
}},
|
||||
@@ -563,7 +562,7 @@ func TestListParentGroups(t *testing.T) {
|
||||
ID: generateUUID(t),
|
||||
Name: fmt.Sprintf("group_%d", i),
|
||||
Metadata: sdk.Metadata{"name": fmt.Sprintf("user_%d", i)},
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
ParentID: parentID,
|
||||
Level: 1,
|
||||
}
|
||||
@@ -721,7 +720,7 @@ func TestListParentGroups(t *testing.T) {
|
||||
PageMeta: groups.PageMeta{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"name": "user_89",
|
||||
},
|
||||
},
|
||||
@@ -789,7 +788,7 @@ func TestListParentGroups(t *testing.T) {
|
||||
Groups: []groups.Group{{
|
||||
ID: generateUUID(t),
|
||||
Name: "group_1",
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
Level: 1,
|
||||
@@ -836,7 +835,7 @@ func TestListChildrenGroups(t *testing.T) {
|
||||
ID: generateUUID(t),
|
||||
Name: fmt.Sprintf("group_%d", i),
|
||||
Metadata: sdk.Metadata{"name": fmt.Sprintf("user_%d", i)},
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
ParentID: parentID,
|
||||
Level: -1,
|
||||
}
|
||||
@@ -994,7 +993,7 @@ func TestListChildrenGroups(t *testing.T) {
|
||||
PageMeta: groups.PageMeta{
|
||||
Offset: offset,
|
||||
Limit: limit,
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"name": "user_89",
|
||||
},
|
||||
},
|
||||
@@ -1061,7 +1060,7 @@ func TestListChildrenGroups(t *testing.T) {
|
||||
Groups: []groups.Group{{
|
||||
ID: generateUUID(t),
|
||||
Name: "group_1",
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
Level: -1,
|
||||
@@ -1161,7 +1160,7 @@ func TestViewGroup(t *testing.T) {
|
||||
svcRes: groups.Group{
|
||||
ID: group.ID,
|
||||
Name: "group_1",
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -1338,7 +1337,7 @@ func TestUpdateGroup(t *testing.T) {
|
||||
ID: group.ID,
|
||||
Name: updatedName,
|
||||
Description: updatedDescription,
|
||||
Metadata: mgclients.Metadata{"key": "value"},
|
||||
Metadata: groups.Metadata{"key": "value"},
|
||||
},
|
||||
svcRes: convertGroup(upGroup),
|
||||
svcErr: nil,
|
||||
@@ -1359,7 +1358,7 @@ func TestUpdateGroup(t *testing.T) {
|
||||
ID: wrongID,
|
||||
Name: updatedName,
|
||||
Description: updatedDescription,
|
||||
Metadata: mgclients.Metadata{"key": "value"},
|
||||
Metadata: groups.Metadata{"key": "value"},
|
||||
},
|
||||
svcRes: groups.Group{},
|
||||
svcErr: svcerr.ErrNotFound,
|
||||
@@ -1380,7 +1379,7 @@ func TestUpdateGroup(t *testing.T) {
|
||||
ID: group.ID,
|
||||
Name: updatedName,
|
||||
Description: updatedDescription,
|
||||
Metadata: mgclients.Metadata{"key": "value"},
|
||||
Metadata: groups.Metadata{"key": "value"},
|
||||
},
|
||||
svcRes: groups.Group{},
|
||||
authenticateErr: svcerr.ErrAuthentication,
|
||||
@@ -1449,12 +1448,12 @@ func TestUpdateGroup(t *testing.T) {
|
||||
ID: group.ID,
|
||||
Name: updatedName,
|
||||
Description: updatedDescription,
|
||||
Metadata: mgclients.Metadata{"key": "value"},
|
||||
Metadata: groups.Metadata{"key": "value"},
|
||||
},
|
||||
svcRes: groups.Group{
|
||||
ID: group.ID,
|
||||
Name: updatedName,
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -1494,7 +1493,7 @@ func TestEnableGroup(t *testing.T) {
|
||||
mgsdk := sdk.NewSDK(conf)
|
||||
|
||||
enGroup := sdkGroup
|
||||
enGroup.Status = mgclients.EnabledStatus.String()
|
||||
enGroup.Status = groups.EnabledStatus.String()
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
@@ -1566,7 +1565,7 @@ func TestEnableGroup(t *testing.T) {
|
||||
svcRes: groups.Group{
|
||||
ID: group.ID,
|
||||
Name: "group_1",
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -1605,7 +1604,7 @@ func TestDisableGroup(t *testing.T) {
|
||||
mgsdk := sdk.NewSDK(conf)
|
||||
|
||||
disGroup := sdkGroup
|
||||
disGroup.Status = mgclients.DisabledStatus.String()
|
||||
disGroup.Status = groups.DisabledStatus.String()
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
@@ -1677,7 +1676,7 @@ func TestDisableGroup(t *testing.T) {
|
||||
svcRes: groups.Group{
|
||||
ID: group.ID,
|
||||
Name: "group_1",
|
||||
Metadata: mgclients.Metadata{
|
||||
Metadata: groups.Metadata{
|
||||
"key": make(chan int),
|
||||
},
|
||||
},
|
||||
@@ -2033,7 +2032,7 @@ func generateTestGroup(t *testing.T) sdk.Group {
|
||||
Metadata: sdk.Metadata{"role": "client"},
|
||||
CreatedAt: createdAt,
|
||||
UpdatedAt: updatedAt,
|
||||
Status: mgclients.EnabledStatus.String(),
|
||||
Status: groups.EnabledStatus.String(),
|
||||
}
|
||||
return gr
|
||||
}
|
||||
|
||||
+16
-16
@@ -13,10 +13,10 @@ import (
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/invitations"
|
||||
"github.com/absmach/magistrala/journal"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
mggroups "github.com/absmach/magistrala/pkg/groups"
|
||||
sdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
"github.com/absmach/magistrala/pkg/uuid"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/absmach/magistrala/users"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -64,8 +64,8 @@ func convertUsers(cs []sdk.User) []users.User {
|
||||
return ccs
|
||||
}
|
||||
|
||||
func convertThings(cs ...sdk.Thing) []mgclients.Client {
|
||||
ccs := []mgclients.Client{}
|
||||
func convertThings(cs ...sdk.Thing) []things.Client {
|
||||
ccs := []things.Client{}
|
||||
|
||||
for _, c := range cs {
|
||||
ccs = append(ccs, convertThing(c))
|
||||
@@ -96,9 +96,9 @@ func convertChannels(cs []sdk.Channel) []mggroups.Group {
|
||||
|
||||
func convertGroup(g sdk.Group) mggroups.Group {
|
||||
if g.Status == "" {
|
||||
g.Status = mgclients.EnabledStatus.String()
|
||||
g.Status = mggroups.EnabledStatus.String()
|
||||
}
|
||||
status, err := mgclients.ToStatus(g.Status)
|
||||
status, err := mggroups.ToStatus(g.Status)
|
||||
if err != nil {
|
||||
return mggroups.Group{}
|
||||
}
|
||||
@@ -109,7 +109,7 @@ func convertGroup(g sdk.Group) mggroups.Group {
|
||||
Parent: g.ParentID,
|
||||
Name: g.Name,
|
||||
Description: g.Description,
|
||||
Metadata: mgclients.Metadata(g.Metadata),
|
||||
Metadata: mggroups.Metadata(g.Metadata),
|
||||
Level: g.Level,
|
||||
Path: g.Path,
|
||||
Children: convertChildren(g.Children),
|
||||
@@ -162,21 +162,21 @@ func convertUser(c sdk.User) users.User {
|
||||
}
|
||||
}
|
||||
|
||||
func convertThing(c sdk.Thing) mgclients.Client {
|
||||
func convertThing(c sdk.Thing) things.Client {
|
||||
if c.Status == "" {
|
||||
c.Status = mgclients.EnabledStatus.String()
|
||||
c.Status = things.EnabledStatus.String()
|
||||
}
|
||||
status, err := mgclients.ToStatus(c.Status)
|
||||
status, err := things.ToStatus(c.Status)
|
||||
if err != nil {
|
||||
return mgclients.Client{}
|
||||
return things.Client{}
|
||||
}
|
||||
return mgclients.Client{
|
||||
return things.Client{
|
||||
ID: c.ID,
|
||||
Name: c.Name,
|
||||
Tags: c.Tags,
|
||||
Domain: c.DomainID,
|
||||
Credentials: mgclients.Credentials(c.Credentials),
|
||||
Metadata: mgclients.Metadata(c.Metadata),
|
||||
Credentials: things.Credentials(c.Credentials),
|
||||
Metadata: things.Metadata(c.Metadata),
|
||||
CreatedAt: c.CreatedAt,
|
||||
UpdatedAt: c.UpdatedAt,
|
||||
Status: status,
|
||||
@@ -185,9 +185,9 @@ func convertThing(c sdk.Thing) mgclients.Client {
|
||||
|
||||
func convertChannel(g sdk.Channel) mggroups.Group {
|
||||
if g.Status == "" {
|
||||
g.Status = mgclients.EnabledStatus.String()
|
||||
g.Status = mggroups.EnabledStatus.String()
|
||||
}
|
||||
status, err := mgclients.ToStatus(g.Status)
|
||||
status, err := mggroups.ToStatus(g.Status)
|
||||
if err != nil {
|
||||
return mggroups.Group{}
|
||||
}
|
||||
@@ -197,7 +197,7 @@ func convertChannel(g sdk.Channel) mggroups.Group {
|
||||
Parent: g.ParentID,
|
||||
Name: g.Name,
|
||||
Description: g.Description,
|
||||
Metadata: mgclients.Metadata(g.Metadata),
|
||||
Metadata: mggroups.Metadata(g.Metadata),
|
||||
Level: g.Level,
|
||||
Path: g.Path,
|
||||
CreatedAt: g.CreatedAt,
|
||||
|
||||
+181
-195
File diff suppressed because it is too large
Load Diff
+10
-10
@@ -7,9 +7,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/pelletier/go-toml"
|
||||
)
|
||||
|
||||
@@ -60,15 +60,15 @@ type Cert struct {
|
||||
|
||||
// Config struct of Provision.
|
||||
type Config struct {
|
||||
File string `toml:"file" env:"MG_PROVISION_CONFIG_FILE" envDefault:"config.toml"`
|
||||
Server ServiceConf `toml:"server" mapstructure:"server"`
|
||||
Bootstrap Bootstrap `toml:"bootstrap" mapstructure:"bootstrap"`
|
||||
Things []mgclients.Client `toml:"things" mapstructure:"things"`
|
||||
Channels []groups.Group `toml:"channels" mapstructure:"channels"`
|
||||
Cert Cert `toml:"cert" mapstructure:"cert"`
|
||||
BSContent string `env:"MG_PROVISION_BS_CONTENT" envDefault:""`
|
||||
SendTelemetry bool `env:"MG_SEND_TELEMETRY" envDefault:"true"`
|
||||
InstanceID string `env:"MG_MQTT_ADAPTER_INSTANCE_ID" envDefault:""`
|
||||
File string `toml:"file" env:"MG_PROVISION_CONFIG_FILE" envDefault:"config.toml"`
|
||||
Server ServiceConf `toml:"server" mapstructure:"server"`
|
||||
Bootstrap Bootstrap `toml:"bootstrap" mapstructure:"bootstrap"`
|
||||
Things []things.Client `toml:"things" mapstructure:"things"`
|
||||
Channels []groups.Group `toml:"channels" mapstructure:"channels"`
|
||||
Cert Cert `toml:"cert" mapstructure:"cert"`
|
||||
BSContent string `env:"MG_PROVISION_BS_CONTENT" envDefault:""`
|
||||
SendTelemetry bool `env:"MG_SEND_TELEMETRY" envDefault:"true"`
|
||||
InstanceID string `env:"MG_MQTT_ADAPTER_INSTANCE_ID" envDefault:""`
|
||||
}
|
||||
|
||||
// Save - store config in a file.
|
||||
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
"github.com/absmach/magistrala/provision"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/pelletier/go-toml"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -31,7 +31,7 @@ var (
|
||||
"test": "test",
|
||||
},
|
||||
},
|
||||
Things: []mgclients.Client{
|
||||
Things: []things.Client{
|
||||
{
|
||||
ID: "1234567890",
|
||||
Name: "test",
|
||||
|
||||
@@ -49,8 +49,8 @@ func (client grpcClient) Authorize(ctx context.Context, req *magistrala.ThingsAu
|
||||
defer cancel()
|
||||
|
||||
res, err := client.authorize(ctx, things.AuthzReq{
|
||||
ThingID: req.GetThingID(),
|
||||
ThingKey: req.GetThingKey(),
|
||||
ClientID: req.GetThingID(),
|
||||
ClientKey: req.GetThingKey(),
|
||||
ChannelID: req.GetChannelID(),
|
||||
Permission: req.GetPermission(),
|
||||
})
|
||||
@@ -71,8 +71,8 @@ func encodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}
|
||||
req := grpcReq.(things.AuthzReq)
|
||||
return &magistrala.ThingsAuthzReq{
|
||||
ChannelID: req.ChannelID,
|
||||
ThingID: req.ThingID,
|
||||
ThingKey: req.ThingKey,
|
||||
ThingID: req.ClientID,
|
||||
ThingKey: req.ClientKey,
|
||||
Permission: req.Permission,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ func authorizeEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
|
||||
thingID, err := svc.Authorize(ctx, things.AuthzReq{
|
||||
ChannelID: req.ChannelID,
|
||||
ThingID: req.ThingID,
|
||||
ThingKey: req.ThingKey,
|
||||
ClientID: req.ThingID,
|
||||
ClientKey: req.ThingKey,
|
||||
Permission: req.Permission,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -28,7 +28,7 @@ const port = 7000
|
||||
|
||||
var (
|
||||
thingID = "testID"
|
||||
thingKey = "testKey"
|
||||
clientKey = "testKey"
|
||||
channelID = "testID"
|
||||
invalid = "invalid"
|
||||
)
|
||||
@@ -71,17 +71,17 @@ func TestAuthorize(t *testing.T) {
|
||||
desc: "authorize successfully",
|
||||
thingID: thingID,
|
||||
req: &magistrala.ThingsAuthzReq{
|
||||
ThingKey: thingKey,
|
||||
ThingKey: clientKey,
|
||||
ChannelID: channelID,
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
authorizeReq: things.AuthzReq{
|
||||
ThingKey: thingKey,
|
||||
ClientKey: clientKey,
|
||||
ChannelID: channelID,
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
authorizeRes: thingID,
|
||||
identifyKey: thingKey,
|
||||
identifyKey: clientKey,
|
||||
res: &magistrala.ThingsAuthzRes{Authorized: true, Id: thingID},
|
||||
err: nil,
|
||||
},
|
||||
@@ -93,7 +93,7 @@ func TestAuthorize(t *testing.T) {
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
authorizeReq: things.AuthzReq{
|
||||
ThingKey: invalid,
|
||||
ClientKey: invalid,
|
||||
ChannelID: channelID,
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
@@ -107,17 +107,17 @@ func TestAuthorize(t *testing.T) {
|
||||
desc: "authorize with failed authorization",
|
||||
thingID: thingID,
|
||||
req: &magistrala.ThingsAuthzReq{
|
||||
ThingKey: thingKey,
|
||||
ThingKey: clientKey,
|
||||
ChannelID: channelID,
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
authorizeReq: things.AuthzReq{
|
||||
ThingKey: thingKey,
|
||||
ClientKey: clientKey,
|
||||
ChannelID: channelID,
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
authorizeErr: svcerr.ErrAuthorization,
|
||||
identifyKey: thingKey,
|
||||
identifyKey: clientKey,
|
||||
res: &magistrala.ThingsAuthzRes{Authorized: false},
|
||||
err: svcerr.ErrAuthorization,
|
||||
},
|
||||
@@ -126,16 +126,16 @@ func TestAuthorize(t *testing.T) {
|
||||
desc: "authorize with invalid permission",
|
||||
thingID: thingID,
|
||||
req: &magistrala.ThingsAuthzReq{
|
||||
ThingKey: thingKey,
|
||||
ThingKey: clientKey,
|
||||
ChannelID: channelID,
|
||||
Permission: invalid,
|
||||
},
|
||||
authorizeReq: things.AuthzReq{
|
||||
ChannelID: channelID,
|
||||
ThingKey: thingKey,
|
||||
ClientKey: clientKey,
|
||||
Permission: invalid,
|
||||
},
|
||||
identifyKey: thingKey,
|
||||
identifyKey: clientKey,
|
||||
authorizeErr: svcerr.ErrAuthorization,
|
||||
res: &magistrala.ThingsAuthzRes{Authorized: false},
|
||||
err: svcerr.ErrAuthorization,
|
||||
@@ -144,16 +144,16 @@ func TestAuthorize(t *testing.T) {
|
||||
desc: "authorize with invalid channel ID",
|
||||
thingID: thingID,
|
||||
req: &magistrala.ThingsAuthzReq{
|
||||
ThingKey: thingKey,
|
||||
ThingKey: clientKey,
|
||||
ChannelID: invalid,
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
authorizeReq: things.AuthzReq{
|
||||
ChannelID: invalid,
|
||||
ThingKey: thingKey,
|
||||
ClientKey: clientKey,
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
identifyKey: thingKey,
|
||||
identifyKey: clientKey,
|
||||
authorizeErr: svcerr.ErrAuthorization,
|
||||
res: &magistrala.ThingsAuthzRes{Authorized: false},
|
||||
err: svcerr.ErrAuthorization,
|
||||
@@ -162,17 +162,17 @@ func TestAuthorize(t *testing.T) {
|
||||
desc: "authorize with empty channel ID",
|
||||
thingID: thingID,
|
||||
req: &magistrala.ThingsAuthzReq{
|
||||
ThingKey: thingKey,
|
||||
ThingKey: clientKey,
|
||||
ChannelID: "",
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
authorizeReq: things.AuthzReq{
|
||||
ThingKey: thingKey,
|
||||
ClientKey: clientKey,
|
||||
ChannelID: "",
|
||||
Permission: policies.PublishPermission,
|
||||
},
|
||||
authorizeErr: svcerr.ErrAuthorization,
|
||||
identifyKey: thingKey,
|
||||
identifyKey: clientKey,
|
||||
res: &magistrala.ThingsAuthzRes{Authorized: false},
|
||||
err: svcerr.ErrAuthorization,
|
||||
},
|
||||
@@ -180,16 +180,16 @@ func TestAuthorize(t *testing.T) {
|
||||
desc: "authorize with empty permission",
|
||||
thingID: thingID,
|
||||
req: &magistrala.ThingsAuthzReq{
|
||||
ThingKey: thingKey,
|
||||
ThingKey: clientKey,
|
||||
ChannelID: channelID,
|
||||
Permission: "",
|
||||
},
|
||||
authorizeReq: things.AuthzReq{
|
||||
ChannelID: channelID,
|
||||
Permission: "",
|
||||
ThingKey: thingKey,
|
||||
ClientKey: clientKey,
|
||||
},
|
||||
identifyKey: thingKey,
|
||||
identifyKey: clientKey,
|
||||
authorizeErr: svcerr.ErrAuthorization,
|
||||
res: &magistrala.ThingsAuthzRes{Authorized: false},
|
||||
err: svcerr.ErrAuthorization,
|
||||
|
||||
@@ -13,7 +13,6 @@ import (
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -197,7 +196,7 @@ func decodeListClients(_ context.Context, r *http.Request) (interface{}, error)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
st, err := mgclients.ToStatus(s)
|
||||
st, err := things.ToStatus(s)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
@@ -266,12 +265,12 @@ func decodeCreateClientReq(_ context.Context, r *http.Request) (interface{}, err
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType)
|
||||
}
|
||||
|
||||
var c mgclients.Client
|
||||
var c things.Client
|
||||
if err := json.NewDecoder(r.Body).Decode(&c); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(errors.ErrMalformedEntity, err))
|
||||
}
|
||||
req := createClientReq{
|
||||
client: c,
|
||||
thing: c,
|
||||
}
|
||||
|
||||
return req, nil
|
||||
@@ -283,7 +282,7 @@ func decodeCreateClientsReq(_ context.Context, r *http.Request) (interface{}, er
|
||||
}
|
||||
|
||||
c := createClientsReq{}
|
||||
if err := json.NewDecoder(r.Body).Decode(&c.Clients); err != nil {
|
||||
if err := json.NewDecoder(r.Body).Decode(&c.Things); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(errors.ErrMalformedEntity, err))
|
||||
}
|
||||
|
||||
@@ -315,7 +314,7 @@ func decodeListMembersRequest(_ context.Context, r *http.Request) (interface{},
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
st, err := mgclients.ToStatus(s)
|
||||
st, err := things.ToStatus(s)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
@@ -329,7 +328,7 @@ func decodeListMembersRequest(_ context.Context, r *http.Request) (interface{},
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
req := listMembersReq{
|
||||
Page: mgclients.Page{
|
||||
Page: things.Page{
|
||||
Status: st,
|
||||
Offset: o,
|
||||
Limit: l,
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
@@ -30,13 +29,13 @@ func createClientEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
client, err := svc.CreateThings(ctx, session, req.client)
|
||||
thing, err := svc.CreateClients(ctx, session, req.thing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return createClientRes{
|
||||
Client: client[0],
|
||||
Client: thing[0],
|
||||
created: true,
|
||||
}, nil
|
||||
}
|
||||
@@ -54,7 +53,7 @@ func createClientsEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
page, err := svc.CreateThings(ctx, session, req.Clients...)
|
||||
page, err := svc.CreateClients(ctx, session, req.Things...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -85,7 +84,7 @@ func viewClientEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
c, err := svc.ViewClient(ctx, session, req.id)
|
||||
c, err := svc.View(ctx, session, req.id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -106,7 +105,7 @@ func viewClientPermsEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
p, err := svc.ViewClientPerms(ctx, session, req.id)
|
||||
p, err := svc.ViewPerms(ctx, session, req.id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -127,7 +126,7 @@ func listClientsEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
pm := mgclients.Page{
|
||||
pm := things.Page{
|
||||
Status: req.status,
|
||||
Offset: req.offset,
|
||||
Limit: req.limit,
|
||||
@@ -136,7 +135,6 @@ func listClientsEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
Permission: req.permission,
|
||||
Metadata: req.metadata,
|
||||
ListPerms: req.listPerms,
|
||||
Role: mgclients.AllRole, // retrieve all things since things don't have roles
|
||||
Id: req.id,
|
||||
}
|
||||
page, err := svc.ListClients(ctx, session, req.userID, pm)
|
||||
@@ -172,7 +170,6 @@ func listMembersEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
req.Page.Role = mgclients.AllRole // retrieve all things since things don't have roles
|
||||
page, err := svc.ListClientsByGroup(ctx, session, req.groupID, req.Page)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -194,12 +191,12 @@ func updateClientEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
cli := mgclients.Client{
|
||||
cli := things.Client{
|
||||
ID: req.id,
|
||||
Name: req.Name,
|
||||
Metadata: req.Metadata,
|
||||
}
|
||||
client, err := svc.UpdateClient(ctx, session, cli)
|
||||
client, err := svc.Update(ctx, session, cli)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -220,11 +217,11 @@ func updateClientTagsEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
cli := mgclients.Client{
|
||||
cli := things.Client{
|
||||
ID: req.id,
|
||||
Tags: req.Tags,
|
||||
}
|
||||
client, err := svc.UpdateClientTags(ctx, session, cli)
|
||||
client, err := svc.UpdateTags(ctx, session, cli)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -245,7 +242,7 @@ func updateClientSecretEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
client, err := svc.UpdateClientSecret(ctx, session, req.id, req.Secret)
|
||||
client, err := svc.UpdateSecret(ctx, session, req.id, req.Secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -266,7 +263,7 @@ func enableClientEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
client, err := svc.EnableClient(ctx, session, req.id)
|
||||
client, err := svc.Enable(ctx, session, req.id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -287,7 +284,7 @@ func disableClientEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
client, err := svc.DisableClient(ctx, session, req.id)
|
||||
client, err := svc.Disable(ctx, session, req.id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -296,7 +293,7 @@ func disableClientEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
func buildClientsResponse(cp mgclients.MembersPage) clientsPageRes {
|
||||
func buildClientsResponse(cp things.MembersPage) clientsPageRes {
|
||||
res := clientsPageRes{
|
||||
pageRes: pageRes{
|
||||
Total: cp.Total,
|
||||
@@ -524,7 +521,7 @@ func deleteClientEndpoint(svc things.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
if err := svc.DeleteClient(ctx, session, req.id); err != nil {
|
||||
if err := svc.Delete(ctx, session, req.id); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
+139
-139
@@ -19,10 +19,10 @@ import (
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
authnmocks "github.com/absmach/magistrala/pkg/authn/mocks"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
gmocks "github.com/absmach/magistrala/pkg/groups/mocks"
|
||||
"github.com/absmach/magistrala/things"
|
||||
httpapi "github.com/absmach/magistrala/things/api/http"
|
||||
"github.com/absmach/magistrala/things/mocks"
|
||||
"github.com/go-chi/chi/v5"
|
||||
@@ -32,15 +32,15 @@ import (
|
||||
|
||||
var (
|
||||
secret = "strongsecret"
|
||||
validCMetadata = mgclients.Metadata{"role": "client"}
|
||||
validCMetadata = things.Metadata{"role": "client"}
|
||||
ID = testsutil.GenerateUUID(&testing.T{})
|
||||
client = mgclients.Client{
|
||||
client = things.Client{
|
||||
ID: ID,
|
||||
Name: "clientname",
|
||||
Tags: []string{"tag1", "tag2"},
|
||||
Credentials: mgclients.Credentials{Identity: "clientidentity", Secret: secret},
|
||||
Credentials: things.Credentials{Identity: "clientidentity", Secret: secret},
|
||||
Metadata: validCMetadata,
|
||||
Status: mgclients.EnabledStatus,
|
||||
Status: things.EnabledStatus,
|
||||
}
|
||||
validToken = "token"
|
||||
inValidToken = "invalid"
|
||||
@@ -106,7 +106,7 @@ func TestCreateThing(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
client mgclients.Client
|
||||
client things.Client
|
||||
domainID string
|
||||
token string
|
||||
contentType string
|
||||
@@ -147,9 +147,9 @@ func TestCreateThing(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "register a thing with an invalid ID",
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: inValid,
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "user@example.com",
|
||||
Secret: "12345678",
|
||||
},
|
||||
@@ -163,8 +163,8 @@ func TestCreateThing(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "register a thing that can't be marshalled",
|
||||
client: mgclients.Client{
|
||||
Credentials: mgclients.Credentials{
|
||||
client: things.Client{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "user@example.com",
|
||||
Secret: "12345678",
|
||||
},
|
||||
@@ -181,13 +181,13 @@ func TestCreateThing(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "register thing with invalid status",
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "newclientwithinvalidstatus@example.com",
|
||||
Secret: secret,
|
||||
},
|
||||
Status: mgclients.AllStatus,
|
||||
Status: things.AllStatus,
|
||||
},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
@@ -198,9 +198,9 @@ func TestCreateThing(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "create thing with invalid contentype",
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "example@example.com",
|
||||
Secret: secret,
|
||||
},
|
||||
@@ -227,7 +227,7 @@ func TestCreateThing(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("CreateThings", mock.Anything, tc.authnRes, tc.client).Return([]mgclients.Client{tc.client}, tc.err)
|
||||
svcCall := svc.On("CreateClients", mock.Anything, tc.authnRes, tc.client).Return([]things.Client{tc.client}, tc.err)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
var errRes respBody
|
||||
@@ -249,24 +249,24 @@ func TestCreateThings(t *testing.T) {
|
||||
defer ts.Close()
|
||||
|
||||
num := 3
|
||||
var items []mgclients.Client
|
||||
var items []things.Client
|
||||
for i := 0; i < num; i++ {
|
||||
client := mgclients.Client{
|
||||
client := things.Client{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()),
|
||||
Secret: secret,
|
||||
},
|
||||
Metadata: mgclients.Metadata{},
|
||||
Status: mgclients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
}
|
||||
items = append(items, client)
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
client []mgclients.Client
|
||||
client []things.Client
|
||||
domainID string
|
||||
token string
|
||||
contentType string
|
||||
@@ -308,7 +308,7 @@ func TestCreateThings(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "create things with empty request",
|
||||
client: []mgclients.Client{},
|
||||
client: []things.Client{},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
@@ -319,7 +319,7 @@ func TestCreateThings(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "create things with invalid IDs",
|
||||
client: []mgclients.Client{
|
||||
client: []things.Client{
|
||||
{
|
||||
ID: inValid,
|
||||
},
|
||||
@@ -339,7 +339,7 @@ func TestCreateThings(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "create things with invalid contentype",
|
||||
client: []mgclients.Client{
|
||||
client: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
},
|
||||
@@ -353,10 +353,10 @@ func TestCreateThings(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "create a thing that can't be marshalled",
|
||||
client: []mgclients.Client{
|
||||
client: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "user@example.com",
|
||||
Secret: "12345678",
|
||||
},
|
||||
@@ -397,7 +397,7 @@ func TestCreateThings(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("CreateThings", mock.Anything, tc.authnRes, mock.Anything, mock.Anything, mock.Anything).Return(tc.client, tc.err)
|
||||
svcCall := svc.On("CreateClients", mock.Anything, tc.authnRes, mock.Anything, mock.Anything, mock.Anything).Return(tc.client, tc.err)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
|
||||
@@ -425,7 +425,7 @@ func TestListThings(t *testing.T) {
|
||||
query string
|
||||
domainID string
|
||||
token string
|
||||
listThingsResponse mgclients.ClientsPage
|
||||
listThingsResponse things.ClientsPage
|
||||
status int
|
||||
authnRes mgauthn.Session
|
||||
authnErr error
|
||||
@@ -437,11 +437,11 @@ func TestListThings(t *testing.T) {
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
status: http.StatusOK,
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
@@ -451,11 +451,11 @@ func TestListThings(t *testing.T) {
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
status: http.StatusOK,
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
@@ -479,12 +479,12 @@ func TestListThings(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Offset: 1,
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
query: "offset=1",
|
||||
status: http.StatusOK,
|
||||
@@ -504,12 +504,12 @@ func TestListThings(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Limit: 1,
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
query: "limit=1",
|
||||
status: http.StatusOK,
|
||||
@@ -538,11 +538,11 @@ func TestListThings(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
query: "name=clientname",
|
||||
status: http.StatusOK,
|
||||
@@ -571,11 +571,11 @@ func TestListThings(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
query: "status=enabled",
|
||||
status: http.StatusOK,
|
||||
@@ -604,11 +604,11 @@ func TestListThings(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
query: "tag=tag1,tag2",
|
||||
status: http.StatusOK,
|
||||
@@ -637,11 +637,11 @@ func TestListThings(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&",
|
||||
status: http.StatusOK,
|
||||
@@ -670,11 +670,11 @@ func TestListThings(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
query: "permission=view",
|
||||
status: http.StatusOK,
|
||||
@@ -703,11 +703,11 @@ func TestListThings(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: domainID + "_" + validID, SuperAdmin: false},
|
||||
listThingsResponse: mgclients.ClientsPage{
|
||||
Page: mgclients.Page{
|
||||
listThingsResponse: things.ClientsPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Clients: []mgclients.Client{client},
|
||||
Clients: []things.Client{client},
|
||||
},
|
||||
query: "list_perms=true",
|
||||
status: http.StatusOK,
|
||||
@@ -825,7 +825,7 @@ func TestViewThing(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("ViewClient", mock.Anything, tc.authnRes, tc.id).Return(mgclients.Client{}, tc.err)
|
||||
svcCall := svc.On("View", mock.Anything, tc.authnRes, tc.id).Return(things.Client{}, tc.err)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
var errRes respBody
|
||||
@@ -921,7 +921,7 @@ func TestViewThingPerms(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("ViewClientPerms", mock.Anything, tc.authnRes, tc.thingID).Return(tc.response, tc.err)
|
||||
svcCall := svc.On("ViewPerms", mock.Anything, tc.authnRes, tc.thingID).Return(tc.response, tc.err)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
var resBody respBody
|
||||
@@ -945,13 +945,13 @@ func TestUpdateThing(t *testing.T) {
|
||||
|
||||
newName := "newname"
|
||||
newTag := "newtag"
|
||||
newMetadata := mgclients.Metadata{"newkey": "newvalue"}
|
||||
newMetadata := things.Metadata{"newkey": "newvalue"}
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
id string
|
||||
data string
|
||||
clientResponse mgclients.Client
|
||||
clientResponse things.Client
|
||||
domainID string
|
||||
token string
|
||||
contentType string
|
||||
@@ -968,7 +968,7 @@ func TestUpdateThing(t *testing.T) {
|
||||
data: fmt.Sprintf(`{"name":"%s","tags":["%s"],"metadata":%s}`, newName, newTag, toJSON(newMetadata)),
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
clientResponse: mgclients.Client{
|
||||
clientResponse: things.Client{
|
||||
ID: client.ID,
|
||||
Name: newName,
|
||||
Tags: []string{newTag},
|
||||
@@ -1043,7 +1043,7 @@ func TestUpdateThing(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
clientResponse: mgclients.Client{},
|
||||
clientResponse: things.Client{},
|
||||
status: http.StatusBadRequest,
|
||||
err: apiutil.ErrNameSize,
|
||||
},
|
||||
@@ -1061,7 +1061,7 @@ func TestUpdateThing(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("UpdateClient", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err)
|
||||
svcCall := svc.On("Update", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
|
||||
@@ -1094,7 +1094,7 @@ func TestUpdateThingsTags(t *testing.T) {
|
||||
id string
|
||||
data string
|
||||
contentType string
|
||||
clientResponse mgclients.Client
|
||||
clientResponse things.Client
|
||||
domainID string
|
||||
token string
|
||||
status int
|
||||
@@ -1107,7 +1107,7 @@ func TestUpdateThingsTags(t *testing.T) {
|
||||
id: client.ID,
|
||||
data: fmt.Sprintf(`{"tags":["%s"]}`, newTag),
|
||||
contentType: contentType,
|
||||
clientResponse: mgclients.Client{
|
||||
clientResponse: things.Client{
|
||||
ID: client.ID,
|
||||
Tags: []string{newTag},
|
||||
},
|
||||
@@ -1200,7 +1200,7 @@ func TestUpdateThingsTags(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("UpdateClientTags", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err)
|
||||
svcCall := svc.On("UpdateTags", mock.Anything, tc.authnRes, mock.Anything).Return(tc.clientResponse, tc.err)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
var resBody respBody
|
||||
@@ -1224,7 +1224,7 @@ func TestUpdateClientSecret(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
data string
|
||||
client mgclients.Client
|
||||
client things.Client
|
||||
contentType string
|
||||
domainID string
|
||||
token string
|
||||
@@ -1236,9 +1236,9 @@ func TestUpdateClientSecret(t *testing.T) {
|
||||
{
|
||||
desc: "update thing secret with valid token",
|
||||
data: fmt.Sprintf(`{"secret": "%s"}`, "strongersecret"),
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: client.ID,
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "clientname",
|
||||
Secret: "strongersecret",
|
||||
},
|
||||
@@ -1253,9 +1253,9 @@ func TestUpdateClientSecret(t *testing.T) {
|
||||
{
|
||||
desc: "update thing secret with empty token",
|
||||
data: fmt.Sprintf(`{"secret": "%s"}`, "strongersecret"),
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: client.ID,
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "clientname",
|
||||
Secret: "strongersecret",
|
||||
},
|
||||
@@ -1269,9 +1269,9 @@ func TestUpdateClientSecret(t *testing.T) {
|
||||
{
|
||||
desc: "update thing secret with invalid token",
|
||||
data: fmt.Sprintf(`{"secret": "%s"}`, "strongersecret"),
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: client.ID,
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "clientname",
|
||||
Secret: "strongersecret",
|
||||
},
|
||||
@@ -1286,9 +1286,9 @@ func TestUpdateClientSecret(t *testing.T) {
|
||||
{
|
||||
desc: "update thing secret with empty id",
|
||||
data: fmt.Sprintf(`{"secret": "%s"}`, "strongersecret"),
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: "",
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "clientname",
|
||||
Secret: "strongersecret",
|
||||
},
|
||||
@@ -1303,9 +1303,9 @@ func TestUpdateClientSecret(t *testing.T) {
|
||||
{
|
||||
desc: "update thing secret with empty secret",
|
||||
data: fmt.Sprintf(`{"secret": "%s"}`, ""),
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: client.ID,
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "clientname",
|
||||
Secret: "",
|
||||
},
|
||||
@@ -1321,9 +1321,9 @@ func TestUpdateClientSecret(t *testing.T) {
|
||||
{
|
||||
desc: "update thing secret with invalid contentype",
|
||||
data: fmt.Sprintf(`{"secret": "%s"}`, ""),
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: client.ID,
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "clientname",
|
||||
Secret: "",
|
||||
},
|
||||
@@ -1339,9 +1339,9 @@ func TestUpdateClientSecret(t *testing.T) {
|
||||
{
|
||||
desc: "update thing secret with malformed data",
|
||||
data: fmt.Sprintf(`{"secret": %s}`, "invalid"),
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: client.ID,
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: things.Credentials{
|
||||
Identity: "clientname",
|
||||
Secret: "",
|
||||
},
|
||||
@@ -1368,7 +1368,7 @@ func TestUpdateClientSecret(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("UpdateClientSecret", mock.Anything, tc.authnRes, tc.client.ID, mock.Anything).Return(tc.client, tc.err)
|
||||
svcCall := svc.On("UpdateSecret", mock.Anything, tc.authnRes, tc.client.ID, mock.Anything).Return(tc.client, tc.err)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
var resBody respBody
|
||||
@@ -1391,8 +1391,8 @@ func TestEnableThing(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
client mgclients.Client
|
||||
response mgclients.Client
|
||||
client things.Client
|
||||
response things.Client
|
||||
domainID string
|
||||
token string
|
||||
status int
|
||||
@@ -1403,9 +1403,9 @@ func TestEnableThing(t *testing.T) {
|
||||
{
|
||||
desc: "enable thing with valid token",
|
||||
client: client,
|
||||
response: mgclients.Client{
|
||||
response: things.Client{
|
||||
ID: client.ID,
|
||||
Status: mgclients.EnabledStatus,
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
@@ -1425,7 +1425,7 @@ func TestEnableThing(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "enable thing with empty id",
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: "",
|
||||
},
|
||||
domainID: domainID,
|
||||
@@ -1450,7 +1450,7 @@ func TestEnableThing(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("EnableClient", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.response, tc.err)
|
||||
svcCall := svc.On("Enable", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.response, tc.err)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
var resBody respBody
|
||||
@@ -1476,8 +1476,8 @@ func TestDisableThing(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
client mgclients.Client
|
||||
response mgclients.Client
|
||||
client things.Client
|
||||
response things.Client
|
||||
domainID string
|
||||
token string
|
||||
status int
|
||||
@@ -1488,9 +1488,9 @@ func TestDisableThing(t *testing.T) {
|
||||
{
|
||||
desc: "disable thing with valid token",
|
||||
client: client,
|
||||
response: mgclients.Client{
|
||||
response: things.Client{
|
||||
ID: client.ID,
|
||||
Status: mgclients.DisabledStatus,
|
||||
Status: things.DisabledStatus,
|
||||
},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
@@ -1510,7 +1510,7 @@ func TestDisableThing(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "disable thing with empty id",
|
||||
client: mgclients.Client{
|
||||
client: things.Client{
|
||||
ID: "",
|
||||
},
|
||||
domainID: domainID,
|
||||
@@ -1535,7 +1535,7 @@ func TestDisableThing(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("DisableClient", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.response, tc.err)
|
||||
svcCall := svc.On("Disable", mock.Anything, tc.authnRes, tc.client.ID).Return(tc.response, tc.err)
|
||||
res, err := req.make()
|
||||
assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err))
|
||||
var resBody respBody
|
||||
@@ -1933,7 +1933,7 @@ func TestDeleteThing(t *testing.T) {
|
||||
}
|
||||
|
||||
authCall := authn.On("Authenticate", mock.Anything, tc.token).Return(tc.authnRes, tc.authnErr)
|
||||
svcCall := svc.On("DeleteClient", mock.Anything, tc.authnRes, tc.id).Return(tc.err)
|
||||
svcCall := svc.On("Delete", mock.Anything, tc.authnRes, tc.id).Return(tc.err)
|
||||
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))
|
||||
@@ -1953,7 +1953,7 @@ func TestListMembers(t *testing.T) {
|
||||
groupID string
|
||||
domainID string
|
||||
token string
|
||||
listMembersResponse mgclients.MembersPage
|
||||
listMembersResponse things.MembersPage
|
||||
status int
|
||||
authnRes mgauthn.Session
|
||||
authnErr error
|
||||
@@ -1965,11 +1965,11 @@ func TestListMembers(t *testing.T) {
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
groupID: client.ID,
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
status: http.StatusOK,
|
||||
|
||||
@@ -1999,12 +1999,12 @@ func TestListMembers(t *testing.T) {
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
query: "offset=1",
|
||||
groupID: client.ID,
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Offset: 1,
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
status: http.StatusOK,
|
||||
|
||||
@@ -2028,12 +2028,12 @@ func TestListMembers(t *testing.T) {
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
query: "limit=1",
|
||||
groupID: client.ID,
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Limit: 1,
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
status: http.StatusOK,
|
||||
|
||||
@@ -2068,11 +2068,11 @@ func TestListMembers(t *testing.T) {
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
query: fmt.Sprintf("channel_id=%s", validID),
|
||||
groupID: client.ID,
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
status: http.StatusOK,
|
||||
|
||||
@@ -2107,11 +2107,11 @@ func TestListMembers(t *testing.T) {
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
query: "connected=true",
|
||||
groupID: client.ID,
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
status: http.StatusOK,
|
||||
|
||||
@@ -2151,12 +2151,12 @@ func TestListMembers(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "list members with status",
|
||||
query: fmt.Sprintf("status=%s", mgclients.EnabledStatus),
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
query: fmt.Sprintf("status=%s", things.EnabledStatus),
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
@@ -2179,7 +2179,7 @@ func TestListMembers(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "list members with duplicate status",
|
||||
query: fmt.Sprintf("status=%s&status=%s", mgclients.EnabledStatus, mgclients.DisabledStatus),
|
||||
query: fmt.Sprintf("status=%s&status=%s", things.EnabledStatus, things.DisabledStatus),
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
@@ -2193,11 +2193,11 @@ func TestListMembers(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
groupID: client.ID,
|
||||
query: "metadata=%7B%22domain%22%3A%20%22example.com%22%7D&",
|
||||
@@ -2230,11 +2230,11 @@ func TestListMembers(t *testing.T) {
|
||||
{
|
||||
desc: "list members with permission",
|
||||
query: fmt.Sprintf("permission=%s", "view"),
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
@@ -2261,11 +2261,11 @@ func TestListMembers(t *testing.T) {
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
groupID: client.ID,
|
||||
status: http.StatusOK,
|
||||
@@ -2296,18 +2296,18 @@ func TestListMembers(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "list members with all query params",
|
||||
query: fmt.Sprintf("offset=1&limit=1&channel_id=%s&connected=true&status=%s&metadata=%s&permission=%s&list_perms=true", validID, mgclients.EnabledStatus, "%7B%22domain%22%3A%20%22example.com%22%7D", "view"),
|
||||
query: fmt.Sprintf("offset=1&limit=1&channel_id=%s&connected=true&status=%s&metadata=%s&permission=%s&list_perms=true", validID, things.EnabledStatus, "%7B%22domain%22%3A%20%22example.com%22%7D", "view"),
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
authnRes: mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID},
|
||||
groupID: client.ID,
|
||||
listMembersResponse: mgclients.MembersPage{
|
||||
Page: mgclients.Page{
|
||||
listMembersResponse: things.MembersPage{
|
||||
Page: things.Page{
|
||||
Offset: 1,
|
||||
Limit: 1,
|
||||
Total: 1,
|
||||
},
|
||||
Members: []mgclients.Client{client},
|
||||
Members: []things.Client{client},
|
||||
},
|
||||
status: http.StatusOK,
|
||||
|
||||
@@ -3338,13 +3338,13 @@ func TestDisconnect(t *testing.T) {
|
||||
}
|
||||
|
||||
type respBody struct {
|
||||
Err string `json:"error"`
|
||||
Message string `json:"message"`
|
||||
Total int `json:"total"`
|
||||
Permissions []string `json:"permissions"`
|
||||
ID string `json:"id"`
|
||||
Tags []string `json:"tags"`
|
||||
Status mgclients.Status `json:"status"`
|
||||
Err string `json:"error"`
|
||||
Message string `json:"message"`
|
||||
Total int `json:"total"`
|
||||
Permissions []string `json:"permissions"`
|
||||
ID string `json:"id"`
|
||||
Tags []string `json:"tags"`
|
||||
Status things.Status `json:"status"`
|
||||
}
|
||||
|
||||
type groupReqBody struct {
|
||||
|
||||
+14
-14
@@ -6,39 +6,39 @@ package http
|
||||
import (
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/things"
|
||||
)
|
||||
|
||||
type createClientReq struct {
|
||||
client mgclients.Client
|
||||
thing things.Client
|
||||
}
|
||||
|
||||
func (req createClientReq) validate() error {
|
||||
if len(req.client.Name) > api.MaxNameSize {
|
||||
if len(req.thing.Name) > api.MaxNameSize {
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
if req.client.ID != "" {
|
||||
return api.ValidateUUID(req.client.ID)
|
||||
if req.thing.ID != "" {
|
||||
return api.ValidateUUID(req.thing.ID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type createClientsReq struct {
|
||||
Clients []mgclients.Client
|
||||
Things []things.Client
|
||||
}
|
||||
|
||||
func (req createClientsReq) validate() error {
|
||||
if len(req.Clients) == 0 {
|
||||
if len(req.Things) == 0 {
|
||||
return apiutil.ErrEmptyList
|
||||
}
|
||||
for _, client := range req.Clients {
|
||||
if client.ID != "" {
|
||||
if err := api.ValidateUUID(client.ID); err != nil {
|
||||
for _, thing := range req.Things {
|
||||
if thing.ID != "" {
|
||||
if err := api.ValidateUUID(thing.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if len(client.Name) > api.MaxNameSize {
|
||||
if len(thing.Name) > api.MaxNameSize {
|
||||
return apiutil.ErrNameSize
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ func (req viewClientPermsReq) validate() error {
|
||||
}
|
||||
|
||||
type listClientsReq struct {
|
||||
status mgclients.Status
|
||||
status things.Status
|
||||
offset uint64
|
||||
limit uint64
|
||||
name string
|
||||
@@ -80,7 +80,7 @@ type listClientsReq struct {
|
||||
visibility string
|
||||
userID string
|
||||
listPerms bool
|
||||
metadata mgclients.Metadata
|
||||
metadata things.Metadata
|
||||
id string
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func (req listClientsReq) validate() error {
|
||||
}
|
||||
|
||||
type listMembersReq struct {
|
||||
mgclients.Page
|
||||
things.Page
|
||||
groupID string
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -31,7 +31,7 @@ func TestCreateThingReqValidate(t *testing.T) {
|
||||
{
|
||||
desc: "valid request",
|
||||
req: createClientReq{
|
||||
client: mgclients.Client{
|
||||
thing: things.Client{
|
||||
ID: validID,
|
||||
Name: valid,
|
||||
},
|
||||
@@ -41,7 +41,7 @@ func TestCreateThingReqValidate(t *testing.T) {
|
||||
{
|
||||
desc: "name too long",
|
||||
req: createClientReq{
|
||||
client: mgclients.Client{
|
||||
thing: things.Client{
|
||||
ID: validID,
|
||||
Name: strings.Repeat("a", api.MaxNameSize+1),
|
||||
},
|
||||
@@ -51,7 +51,7 @@ func TestCreateThingReqValidate(t *testing.T) {
|
||||
{
|
||||
desc: "invalid id",
|
||||
req: createClientReq{
|
||||
client: mgclients.Client{
|
||||
thing: things.Client{
|
||||
ID: invalid,
|
||||
Name: valid,
|
||||
},
|
||||
@@ -76,7 +76,7 @@ func TestCreateThingsReqValidate(t *testing.T) {
|
||||
{
|
||||
desc: "valid request",
|
||||
req: createClientsReq{
|
||||
Clients: []mgclients.Client{
|
||||
Things: []things.Client{
|
||||
{
|
||||
ID: validID,
|
||||
Name: valid,
|
||||
@@ -88,14 +88,14 @@ func TestCreateThingsReqValidate(t *testing.T) {
|
||||
{
|
||||
desc: "empty list",
|
||||
req: createClientsReq{
|
||||
Clients: []mgclients.Client{},
|
||||
Things: []things.Client{},
|
||||
},
|
||||
err: apiutil.ErrEmptyList,
|
||||
},
|
||||
{
|
||||
desc: "name too long",
|
||||
req: createClientsReq{
|
||||
Clients: []mgclients.Client{
|
||||
Things: []things.Client{
|
||||
{
|
||||
ID: validID,
|
||||
Name: strings.Repeat("a", api.MaxNameSize+1),
|
||||
@@ -107,7 +107,7 @@ func TestCreateThingsReqValidate(t *testing.T) {
|
||||
{
|
||||
desc: "invalid id",
|
||||
req: createClientsReq{
|
||||
Clients: []mgclients.Client{
|
||||
Things: []things.Client{
|
||||
{
|
||||
ID: invalid,
|
||||
Name: valid,
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/absmach/magistrala"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/things"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -32,7 +32,7 @@ type pageRes struct {
|
||||
}
|
||||
|
||||
type createClientRes struct {
|
||||
mgclients.Client
|
||||
things.Client
|
||||
created bool
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ func (res createClientRes) Empty() bool {
|
||||
}
|
||||
|
||||
type updateClientRes struct {
|
||||
mgclients.Client
|
||||
things.Client
|
||||
}
|
||||
|
||||
func (res updateClientRes) Code() int {
|
||||
@@ -75,7 +75,7 @@ func (res updateClientRes) Empty() bool {
|
||||
}
|
||||
|
||||
type viewClientRes struct {
|
||||
mgclients.Client
|
||||
things.Client
|
||||
}
|
||||
|
||||
func (res viewClientRes) Code() int {
|
||||
@@ -124,7 +124,7 @@ func (res clientsPageRes) Empty() bool {
|
||||
}
|
||||
|
||||
type viewMembersRes struct {
|
||||
mgclients.Client
|
||||
things.Client
|
||||
}
|
||||
|
||||
func (res viewMembersRes) Code() int {
|
||||
@@ -140,7 +140,7 @@ func (res viewMembersRes) Empty() bool {
|
||||
}
|
||||
|
||||
type changeClientStatusRes struct {
|
||||
mgclients.Client
|
||||
things.Client
|
||||
}
|
||||
|
||||
func (res changeClientStatusRes) Code() int {
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package things
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/postgres"
|
||||
)
|
||||
|
||||
type AuthzReq struct {
|
||||
ChannelID string
|
||||
ClientID string
|
||||
ClientKey string
|
||||
Permission string
|
||||
}
|
||||
|
||||
type ClientRepository struct {
|
||||
DB postgres.Database
|
||||
}
|
||||
|
||||
// Repository is the interface that wraps the basic methods for
|
||||
// a client repository.
|
||||
//
|
||||
//go:generate mockery --name Repository --output=./mocks --filename repository.go --quiet --note "Copyright (c) Abstract Machines"
|
||||
type Repository interface {
|
||||
// RetrieveByID retrieves client by its unique ID.
|
||||
RetrieveByID(ctx context.Context, id string) (Client, error)
|
||||
|
||||
// RetrieveAll retrieves all clients.
|
||||
RetrieveAll(ctx context.Context, pm Page) (ClientsPage, error)
|
||||
|
||||
// SearchClients retrieves clients based on search criteria.
|
||||
SearchClients(ctx context.Context, pm Page) (ClientsPage, error)
|
||||
|
||||
// RetrieveAllByIDs retrieves for given client IDs .
|
||||
RetrieveAllByIDs(ctx context.Context, pm Page) (ClientsPage, error)
|
||||
|
||||
// Update updates the client name and metadata.
|
||||
Update(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// UpdateTags updates the client tags.
|
||||
UpdateTags(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// UpdateIdentity updates identity for client with given id.
|
||||
UpdateIdentity(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// UpdateSecret updates secret for client with given identity.
|
||||
UpdateSecret(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// ChangeStatus changes client status to enabled or disabled
|
||||
ChangeStatus(ctx context.Context, client Client) (Client, error)
|
||||
|
||||
// Delete deletes client with given id
|
||||
Delete(ctx context.Context, id string) error
|
||||
|
||||
// Save persists the client account. A non-nil error is returned to indicate
|
||||
// operation failure.
|
||||
Save(ctx context.Context, client ...Client) ([]Client, error)
|
||||
|
||||
// RetrieveBySecret retrieves a client based on the secret (key).
|
||||
RetrieveBySecret(ctx context.Context, key string) (Client, error)
|
||||
}
|
||||
|
||||
// Service specifies an API that must be fullfiled by the domain service
|
||||
// implementation, and all of its decorators (e.g. logging & metrics).
|
||||
//
|
||||
//go:generate mockery --name Service --filename service.go --quiet --note "Copyright (c) Abstract Machines"
|
||||
type Service interface {
|
||||
// CreateClients creates new client. In case of the failed registration, a
|
||||
// non-nil error value is returned.
|
||||
CreateClients(ctx context.Context, session authn.Session, client ...Client) ([]Client, error)
|
||||
|
||||
// View retrieves client info for a given client ID and an authorized token.
|
||||
View(ctx context.Context, session authn.Session, id string) (Client, error)
|
||||
|
||||
// ViewPerms retrieves permissions on the client id for the given authorized token.
|
||||
ViewPerms(ctx context.Context, session authn.Session, id string) ([]string, error)
|
||||
|
||||
// ListClients retrieves clients list for a valid auth token.
|
||||
ListClients(ctx context.Context, session authn.Session, reqUserID string, pm Page) (ClientsPage, error)
|
||||
|
||||
// ListClientsByGroup retrieves data about subset of clients that are
|
||||
// connected or not connected to specified channel and belong to the user identified by
|
||||
// the provided key.
|
||||
ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm Page) (MembersPage, error)
|
||||
|
||||
// Update updates the client's name and metadata.
|
||||
Update(ctx context.Context, session authn.Session, client Client) (Client, error)
|
||||
|
||||
// UpdateTags updates the client's tags.
|
||||
UpdateTags(ctx context.Context, session authn.Session, client Client) (Client, error)
|
||||
|
||||
// UpdateSecret updates the client's secret
|
||||
UpdateSecret(ctx context.Context, session authn.Session, id, key string) (Client, error)
|
||||
|
||||
// Enable logically enableds the client identified with the provided ID
|
||||
Enable(ctx context.Context, session authn.Session, id string) (Client, error)
|
||||
|
||||
// Disable logically disables the client identified with the provided ID
|
||||
Disable(ctx context.Context, session authn.Session, id string) (Client, error)
|
||||
|
||||
// Share add share policy to client id with given relation for given user ids
|
||||
Share(ctx context.Context, session authn.Session, id string, relation string, userids ...string) error
|
||||
|
||||
// Unshare remove share policy to client id with given relation for given user ids
|
||||
Unshare(ctx context.Context, session authn.Session, id string, relation string, userids ...string) error
|
||||
|
||||
// Identify returns client ID for given client key.
|
||||
Identify(ctx context.Context, key string) (string, error)
|
||||
|
||||
// Authorize used for Clients authorization.
|
||||
Authorize(ctx context.Context, req AuthzReq) (string, error)
|
||||
|
||||
// Delete deletes client with given ID.
|
||||
Delete(ctx context.Context, session authn.Session, id string) error
|
||||
}
|
||||
|
||||
// Cache contains client caching interface.
|
||||
//
|
||||
//go:generate mockery --name Cache --filename cache.go --quiet --note "Copyright (c) Abstract Machines"
|
||||
type Cache interface {
|
||||
// Save stores pair client secret, client id.
|
||||
Save(ctx context.Context, clientSecret, clientID string) error
|
||||
|
||||
// ID returns client ID for given client secret.
|
||||
ID(ctx context.Context, clientSecret string) (string, error)
|
||||
|
||||
// Removes client from cache.
|
||||
Remove(ctx context.Context, clientID string) error
|
||||
}
|
||||
|
||||
// Client Struct represents a client.
|
||||
|
||||
type Client struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Domain string `json:"domain_id,omitempty"`
|
||||
Credentials Credentials `json:"credentials,omitempty"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
UpdatedAt time.Time `json:"updated_at,omitempty"`
|
||||
UpdatedBy string `json:"updated_by,omitempty"`
|
||||
Status Status `json:"status,omitempty"` // 1 for enabled, 0 for disabled
|
||||
Permissions []string `json:"permissions,omitempty"`
|
||||
Identity string `json:"identity,omitempty"`
|
||||
}
|
||||
|
||||
// ClientsPage contains page related metadata as well as list.
|
||||
type ClientsPage struct {
|
||||
Page
|
||||
Clients []Client
|
||||
}
|
||||
|
||||
// MembersPage contains page related metadata as well as list of members that
|
||||
// belong to this page.
|
||||
|
||||
type MembersPage struct {
|
||||
Page
|
||||
Members []Client
|
||||
}
|
||||
|
||||
// Page contains the page metadata that helps navigation.
|
||||
|
||||
type Page struct {
|
||||
Total uint64 `json:"total"`
|
||||
Offset uint64 `json:"offset"`
|
||||
Limit uint64 `json:"limit"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Id string `json:"id,omitempty"`
|
||||
Order string `json:"order,omitempty"`
|
||||
Dir string `json:"dir,omitempty"`
|
||||
Metadata Metadata `json:"metadata,omitempty"`
|
||||
Domain string `json:"domain,omitempty"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Permission string `json:"permission,omitempty"`
|
||||
Status Status `json:"status,omitempty"`
|
||||
IDs []string `json:"ids,omitempty"`
|
||||
Identity string `json:"identity,omitempty"`
|
||||
ListPerms bool `json:"-"`
|
||||
}
|
||||
|
||||
// Metadata represents arbitrary JSON.
|
||||
type Metadata map[string]interface{}
|
||||
|
||||
// Credentials represent client credentials: its
|
||||
// "identity" which can be a username, email, generated name;
|
||||
// and "secret" which can be a password or access token.
|
||||
type Credentials struct {
|
||||
Identity string `json:"identity,omitempty"` // username or generated login ID
|
||||
Secret string `json:"secret,omitempty"` // password or token
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clients
|
||||
package things
|
||||
|
||||
import "errors"
|
||||
|
||||
@@ -6,12 +6,12 @@ package events
|
||||
import (
|
||||
"time"
|
||||
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/events"
|
||||
"github.com/absmach/magistrala/things"
|
||||
)
|
||||
|
||||
const (
|
||||
clientPrefix = "thing."
|
||||
clientPrefix = "client."
|
||||
clientCreate = clientPrefix + "create"
|
||||
clientUpdate = clientPrefix + "update"
|
||||
clientChangeStatus = clientPrefix + "change_status"
|
||||
@@ -39,7 +39,7 @@ var (
|
||||
)
|
||||
|
||||
type createClientEvent struct {
|
||||
mgclients.Client
|
||||
things.Client
|
||||
}
|
||||
|
||||
func (cce createClientEvent) Encode() (map[string]interface{}, error) {
|
||||
@@ -70,7 +70,7 @@ func (cce createClientEvent) Encode() (map[string]interface{}, error) {
|
||||
}
|
||||
|
||||
type updateClientEvent struct {
|
||||
mgclients.Client
|
||||
things.Client
|
||||
operation string
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ func (rce changeStatusClientEvent) Encode() (map[string]interface{}, error) {
|
||||
}
|
||||
|
||||
type viewClientEvent struct {
|
||||
mgclients.Client
|
||||
things.Client
|
||||
}
|
||||
|
||||
func (vce viewClientEvent) Encode() (map[string]interface{}, error) {
|
||||
@@ -184,7 +184,7 @@ func (vcpe viewClientPermsEvent) Encode() (map[string]interface{}, error) {
|
||||
|
||||
type listClientEvent struct {
|
||||
reqUserID string
|
||||
mgclients.Page
|
||||
things.Page
|
||||
}
|
||||
|
||||
func (lce listClientEvent) Encode() (map[string]interface{}, error) {
|
||||
@@ -231,7 +231,7 @@ func (lce listClientEvent) Encode() (map[string]interface{}, error) {
|
||||
}
|
||||
|
||||
type listClientByGroupEvent struct {
|
||||
mgclients.Page
|
||||
things.Page
|
||||
channelID string
|
||||
}
|
||||
|
||||
|
||||
+36
-37
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/events"
|
||||
"github.com/absmach/magistrala/pkg/events/store"
|
||||
"github.com/absmach/magistrala/things"
|
||||
@@ -36,8 +35,8 @@ func NewEventStoreMiddleware(ctx context.Context, svc things.Service, url string
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) CreateThings(ctx context.Context, session authn.Session, thing ...mgclients.Client) ([]mgclients.Client, error) {
|
||||
sths, err := es.svc.CreateThings(ctx, session, thing...)
|
||||
func (es *eventStore) CreateClients(ctx context.Context, session authn.Session, thing ...things.Client) ([]things.Client, error) {
|
||||
sths, err := es.svc.CreateClients(ctx, session, thing...)
|
||||
if err != nil {
|
||||
return sths, err
|
||||
}
|
||||
@@ -54,8 +53,8 @@ func (es *eventStore) CreateThings(ctx context.Context, session authn.Session, t
|
||||
return sths, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) UpdateClient(ctx context.Context, session authn.Session, thing mgclients.Client) (mgclients.Client, error) {
|
||||
cli, err := es.svc.UpdateClient(ctx, session, thing)
|
||||
func (es *eventStore) Update(ctx context.Context, session authn.Session, thing things.Client) (things.Client, error) {
|
||||
cli, err := es.svc.Update(ctx, session, thing)
|
||||
if err != nil {
|
||||
return cli, err
|
||||
}
|
||||
@@ -63,8 +62,8 @@ func (es *eventStore) UpdateClient(ctx context.Context, session authn.Session, t
|
||||
return es.update(ctx, "", cli)
|
||||
}
|
||||
|
||||
func (es *eventStore) UpdateClientTags(ctx context.Context, session authn.Session, thing mgclients.Client) (mgclients.Client, error) {
|
||||
cli, err := es.svc.UpdateClientTags(ctx, session, thing)
|
||||
func (es *eventStore) UpdateTags(ctx context.Context, session authn.Session, thing things.Client) (things.Client, error) {
|
||||
cli, err := es.svc.UpdateTags(ctx, session, thing)
|
||||
if err != nil {
|
||||
return cli, err
|
||||
}
|
||||
@@ -72,8 +71,8 @@ func (es *eventStore) UpdateClientTags(ctx context.Context, session authn.Sessio
|
||||
return es.update(ctx, "tags", cli)
|
||||
}
|
||||
|
||||
func (es *eventStore) UpdateClientSecret(ctx context.Context, session authn.Session, id, key string) (mgclients.Client, error) {
|
||||
cli, err := es.svc.UpdateClientSecret(ctx, session, id, key)
|
||||
func (es *eventStore) UpdateSecret(ctx context.Context, session authn.Session, id, key string) (things.Client, error) {
|
||||
cli, err := es.svc.UpdateSecret(ctx, session, id, key)
|
||||
if err != nil {
|
||||
return cli, err
|
||||
}
|
||||
@@ -81,7 +80,7 @@ func (es *eventStore) UpdateClientSecret(ctx context.Context, session authn.Sess
|
||||
return es.update(ctx, "secret", cli)
|
||||
}
|
||||
|
||||
func (es *eventStore) update(ctx context.Context, operation string, thing mgclients.Client) (mgclients.Client, error) {
|
||||
func (es *eventStore) update(ctx context.Context, operation string, thing things.Client) (things.Client, error) {
|
||||
event := updateClientEvent{
|
||||
thing, operation,
|
||||
}
|
||||
@@ -93,24 +92,24 @@ func (es *eventStore) update(ctx context.Context, operation string, thing mgclie
|
||||
return thing, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) ViewClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
cli, err := es.svc.ViewClient(ctx, session, id)
|
||||
func (es *eventStore) View(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
thi, err := es.svc.View(ctx, session, id)
|
||||
if err != nil {
|
||||
return cli, err
|
||||
return thi, err
|
||||
}
|
||||
|
||||
event := viewClientEvent{
|
||||
cli,
|
||||
thi,
|
||||
}
|
||||
if err := es.Publish(ctx, event); err != nil {
|
||||
return cli, err
|
||||
return thi, err
|
||||
}
|
||||
|
||||
return cli, nil
|
||||
return thi, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) ViewClientPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
permissions, err := es.svc.ViewClientPerms(ctx, session, id)
|
||||
func (es *eventStore) ViewPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
permissions, err := es.svc.ViewPerms(ctx, session, id)
|
||||
if err != nil {
|
||||
return permissions, err
|
||||
}
|
||||
@@ -125,7 +124,7 @@ func (es *eventStore) ViewClientPerms(ctx context.Context, session authn.Session
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm mgclients.Page) (mgclients.ClientsPage, error) {
|
||||
func (es *eventStore) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm things.Page) (things.ClientsPage, error) {
|
||||
cp, err := es.svc.ListClients(ctx, session, reqUserID, pm)
|
||||
if err != nil {
|
||||
return cp, err
|
||||
@@ -141,7 +140,7 @@ func (es *eventStore) ListClients(ctx context.Context, session authn.Session, re
|
||||
return cp, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) ListClientsByGroup(ctx context.Context, session authn.Session, chID string, pm mgclients.Page) (mgclients.MembersPage, error) {
|
||||
func (es *eventStore) ListClientsByGroup(ctx context.Context, session authn.Session, chID string, pm things.Page) (things.MembersPage, error) {
|
||||
mp, err := es.svc.ListClientsByGroup(ctx, session, chID, pm)
|
||||
if err != nil {
|
||||
return mp, err
|
||||
@@ -156,36 +155,36 @@ func (es *eventStore) ListClientsByGroup(ctx context.Context, session authn.Sess
|
||||
return mp, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) EnableClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
cli, err := es.svc.EnableClient(ctx, session, id)
|
||||
func (es *eventStore) Enable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
thi, err := es.svc.Enable(ctx, session, id)
|
||||
if err != nil {
|
||||
return cli, err
|
||||
return thi, err
|
||||
}
|
||||
|
||||
return es.changeStatus(ctx, cli)
|
||||
return es.changeStatus(ctx, thi)
|
||||
}
|
||||
|
||||
func (es *eventStore) DisableClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
cli, err := es.svc.DisableClient(ctx, session, id)
|
||||
func (es *eventStore) Disable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
thi, err := es.svc.Disable(ctx, session, id)
|
||||
if err != nil {
|
||||
return cli, err
|
||||
return thi, err
|
||||
}
|
||||
|
||||
return es.changeStatus(ctx, cli)
|
||||
return es.changeStatus(ctx, thi)
|
||||
}
|
||||
|
||||
func (es *eventStore) changeStatus(ctx context.Context, cli mgclients.Client) (mgclients.Client, error) {
|
||||
func (es *eventStore) changeStatus(ctx context.Context, thi things.Client) (things.Client, error) {
|
||||
event := changeStatusClientEvent{
|
||||
id: cli.ID,
|
||||
updatedAt: cli.UpdatedAt,
|
||||
updatedBy: cli.UpdatedBy,
|
||||
status: cli.Status.String(),
|
||||
id: thi.ID,
|
||||
updatedAt: thi.UpdatedAt,
|
||||
updatedBy: thi.UpdatedBy,
|
||||
status: thi.Status.String(),
|
||||
}
|
||||
if err := es.Publish(ctx, event); err != nil {
|
||||
return cli, err
|
||||
return thi, err
|
||||
}
|
||||
|
||||
return cli, nil
|
||||
return thi, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) Identify(ctx context.Context, key string) (string, error) {
|
||||
@@ -252,8 +251,8 @@ func (es *eventStore) Unshare(ctx context.Context, session authn.Session, id, re
|
||||
return es.Publish(ctx, event)
|
||||
}
|
||||
|
||||
func (es *eventStore) DeleteClient(ctx context.Context, session authn.Session, id string) error {
|
||||
if err := es.svc.DeleteClient(ctx, session, id); err != nil {
|
||||
func (es *eventStore) Delete(ctx context.Context, session authn.Session, id string) error {
|
||||
if err := es.svc.Delete(ctx, session, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgauthz "github.com/absmach/magistrala/pkg/authz"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/policies"
|
||||
"github.com/absmach/magistrala/things"
|
||||
@@ -29,37 +28,37 @@ func AuthorizationMiddleware(svc things.Service, authz mgauthz.Authorization) th
|
||||
}
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) CreateThings(ctx context.Context, session authn.Session, client ...clients.Client) ([]clients.Client, error) {
|
||||
func (am *authorizationMiddleware) CreateClients(ctx context.Context, session authn.Session, client ...things.Client) ([]things.Client, error) {
|
||||
if err := am.authorize(ctx, "", policies.UserType, policies.UsersKind, session.DomainUserID, policies.CreatePermission, policies.DomainType, session.DomainID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return am.svc.CreateThings(ctx, session, client...)
|
||||
return am.svc.CreateClients(ctx, session, client...)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ViewClient(ctx context.Context, session authn.Session, id string) (clients.Client, error) {
|
||||
func (am *authorizationMiddleware) View(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
if session.DomainUserID == "" {
|
||||
return clients.Client{}, svcerr.ErrDomainAuthorization
|
||||
return things.Client{}, svcerr.ErrDomainAuthorization
|
||||
}
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.ViewPermission, policies.ThingType, id); err != nil {
|
||||
return clients.Client{}, err
|
||||
return things.Client{}, err
|
||||
}
|
||||
|
||||
return am.svc.ViewClient(ctx, session, id)
|
||||
return am.svc.View(ctx, session, id)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ViewClientPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
return am.svc.ViewClientPerms(ctx, session, id)
|
||||
func (am *authorizationMiddleware) ViewPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
return am.svc.ViewPerms(ctx, session, id)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm clients.Page) (clients.ClientsPage, error) {
|
||||
func (am *authorizationMiddleware) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm things.Page) (things.ClientsPage, error) {
|
||||
if session.DomainUserID == "" {
|
||||
return clients.ClientsPage{}, svcerr.ErrDomainAuthorization
|
||||
return things.ClientsPage{}, svcerr.ErrDomainAuthorization
|
||||
}
|
||||
switch {
|
||||
case reqUserID != "" && reqUserID != session.UserID:
|
||||
if err := am.authorize(ctx, "", policies.UserType, policies.UsersKind, session.DomainUserID, policies.AdminPermission, policies.DomainType, session.DomainID); err != nil {
|
||||
return clients.ClientsPage{}, err
|
||||
return things.ClientsPage{}, err
|
||||
}
|
||||
default:
|
||||
err := am.checkSuperAdmin(ctx, session.UserID)
|
||||
@@ -68,7 +67,7 @@ func (am *authorizationMiddleware) ListClients(ctx context.Context, session auth
|
||||
session.SuperAdmin = true
|
||||
default:
|
||||
if err := am.authorize(ctx, "", policies.UserType, policies.UsersKind, session.DomainUserID, policies.MembershipPermission, policies.DomainType, session.DomainID); err != nil {
|
||||
return clients.ClientsPage{}, err
|
||||
return things.ClientsPage{}, err
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,67 +75,67 @@ func (am *authorizationMiddleware) ListClients(ctx context.Context, session auth
|
||||
return am.svc.ListClients(ctx, session, reqUserID, pm)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm clients.Page) (clients.MembersPage, error) {
|
||||
func (am *authorizationMiddleware) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm things.Page) (things.MembersPage, error) {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, pm.Permission, policies.GroupType, groupID); err != nil {
|
||||
return clients.MembersPage{}, err
|
||||
return things.MembersPage{}, err
|
||||
}
|
||||
|
||||
return am.svc.ListClientsByGroup(ctx, session, groupID, pm)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateClient(ctx context.Context, session authn.Session, client clients.Client) (clients.Client, error) {
|
||||
func (am *authorizationMiddleware) Update(ctx context.Context, session authn.Session, client things.Client) (things.Client, error) {
|
||||
if session.DomainUserID == "" {
|
||||
return clients.Client{}, svcerr.ErrDomainAuthorization
|
||||
return things.Client{}, svcerr.ErrDomainAuthorization
|
||||
}
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.EditPermission, policies.ThingType, client.ID); err != nil {
|
||||
return clients.Client{}, err
|
||||
return things.Client{}, err
|
||||
}
|
||||
|
||||
return am.svc.UpdateClient(ctx, session, client)
|
||||
return am.svc.Update(ctx, session, client)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateClientTags(ctx context.Context, session authn.Session, client clients.Client) (clients.Client, error) {
|
||||
func (am *authorizationMiddleware) UpdateTags(ctx context.Context, session authn.Session, client things.Client) (things.Client, error) {
|
||||
if session.DomainUserID == "" {
|
||||
return clients.Client{}, svcerr.ErrDomainAuthorization
|
||||
return things.Client{}, svcerr.ErrDomainAuthorization
|
||||
}
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.EditPermission, policies.ThingType, client.ID); err != nil {
|
||||
return clients.Client{}, err
|
||||
return things.Client{}, err
|
||||
}
|
||||
|
||||
return am.svc.UpdateClientTags(ctx, session, client)
|
||||
return am.svc.UpdateTags(ctx, session, client)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateClientSecret(ctx context.Context, session authn.Session, id, key string) (clients.Client, error) {
|
||||
func (am *authorizationMiddleware) UpdateSecret(ctx context.Context, session authn.Session, id, key string) (things.Client, error) {
|
||||
if session.DomainUserID == "" {
|
||||
return clients.Client{}, svcerr.ErrDomainAuthorization
|
||||
return things.Client{}, svcerr.ErrDomainAuthorization
|
||||
}
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.EditPermission, policies.ThingType, id); err != nil {
|
||||
return clients.Client{}, err
|
||||
return things.Client{}, err
|
||||
}
|
||||
|
||||
return am.svc.UpdateClientSecret(ctx, session, id, key)
|
||||
return am.svc.UpdateSecret(ctx, session, id, key)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) EnableClient(ctx context.Context, session authn.Session, id string) (clients.Client, error) {
|
||||
func (am *authorizationMiddleware) Enable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
if session.DomainUserID == "" {
|
||||
return clients.Client{}, svcerr.ErrDomainAuthorization
|
||||
return things.Client{}, svcerr.ErrDomainAuthorization
|
||||
}
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.DeletePermission, policies.ThingType, id); err != nil {
|
||||
return clients.Client{}, err
|
||||
return things.Client{}, err
|
||||
}
|
||||
|
||||
return am.svc.EnableClient(ctx, session, id)
|
||||
return am.svc.Enable(ctx, session, id)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) DisableClient(ctx context.Context, session authn.Session, id string) (clients.Client, error) {
|
||||
func (am *authorizationMiddleware) Disable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
if session.DomainUserID == "" {
|
||||
return clients.Client{}, svcerr.ErrDomainAuthorization
|
||||
return things.Client{}, svcerr.ErrDomainAuthorization
|
||||
}
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.DeletePermission, policies.ThingType, id); err != nil {
|
||||
return clients.Client{}, err
|
||||
return things.Client{}, err
|
||||
}
|
||||
|
||||
return am.svc.DisableClient(ctx, session, id)
|
||||
return am.svc.Disable(ctx, session, id)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) Share(ctx context.Context, session authn.Session, id string, relation string, userids ...string) error {
|
||||
@@ -163,12 +162,12 @@ func (am *authorizationMiddleware) Authorize(ctx context.Context, req things.Aut
|
||||
return am.svc.Authorize(ctx, req)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) DeleteClient(ctx context.Context, session authn.Session, id string) error {
|
||||
func (am *authorizationMiddleware) Delete(ctx context.Context, session authn.Session, id string) error {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.DeletePermission, policies.ThingType, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return am.svc.DeleteClient(ctx, session, id)
|
||||
return am.svc.Delete(ctx, session, id)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) checkSuperAdmin(ctx context.Context, adminID string) error {
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/things"
|
||||
)
|
||||
|
||||
@@ -25,7 +24,7 @@ func LoggingMiddleware(svc things.Service, logger *slog.Logger) things.Service {
|
||||
return &loggingMiddleware{logger, svc}
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) CreateThings(ctx context.Context, session authn.Session, clients ...mgclients.Client) (cs []mgclients.Client, err error) {
|
||||
func (lm *loggingMiddleware) CreateClients(ctx context.Context, session authn.Session, clients ...things.Client) (cs []things.Client, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -37,10 +36,10 @@ func (lm *loggingMiddleware) CreateThings(ctx context.Context, session authn.Ses
|
||||
}
|
||||
lm.logger.Info(fmt.Sprintf("Create %d things completed successfully", len(clients)), args...)
|
||||
}(time.Now())
|
||||
return lm.svc.CreateThings(ctx, session, clients...)
|
||||
return lm.svc.CreateClients(ctx, session, clients...)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) ViewClient(ctx context.Context, session authn.Session, id string) (c mgclients.Client, err error) {
|
||||
func (lm *loggingMiddleware) View(ctx context.Context, session authn.Session, id string) (c things.Client, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -56,10 +55,10 @@ func (lm *loggingMiddleware) ViewClient(ctx context.Context, session authn.Sessi
|
||||
}
|
||||
lm.logger.Info("View thing completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.ViewClient(ctx, session, id)
|
||||
return lm.svc.View(ctx, session, id)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) ViewClientPerms(ctx context.Context, session authn.Session, id string) (p []string, err error) {
|
||||
func (lm *loggingMiddleware) ViewPerms(ctx context.Context, session authn.Session, id string) (p []string, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -72,10 +71,10 @@ func (lm *loggingMiddleware) ViewClientPerms(ctx context.Context, session authn.
|
||||
}
|
||||
lm.logger.Info("View thing permissions completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.ViewClientPerms(ctx, session, id)
|
||||
return lm.svc.ViewPerms(ctx, session, id)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm mgclients.Page) (cp mgclients.ClientsPage, err error) {
|
||||
func (lm *loggingMiddleware) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm things.Page) (cp things.ClientsPage, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -96,7 +95,7 @@ func (lm *loggingMiddleware) ListClients(ctx context.Context, session authn.Sess
|
||||
return lm.svc.ListClients(ctx, session, reqUserID, pm)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) UpdateClient(ctx context.Context, session authn.Session, client mgclients.Client) (c mgclients.Client, err error) {
|
||||
func (lm *loggingMiddleware) Update(ctx context.Context, session authn.Session, client things.Client) (c things.Client, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -113,10 +112,10 @@ func (lm *loggingMiddleware) UpdateClient(ctx context.Context, session authn.Ses
|
||||
}
|
||||
lm.logger.Info("Update thing completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.UpdateClient(ctx, session, client)
|
||||
return lm.svc.Update(ctx, session, client)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) UpdateClientTags(ctx context.Context, session authn.Session, client mgclients.Client) (c mgclients.Client, err error) {
|
||||
func (lm *loggingMiddleware) UpdateTags(ctx context.Context, session authn.Session, client things.Client) (c things.Client, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -133,10 +132,10 @@ func (lm *loggingMiddleware) UpdateClientTags(ctx context.Context, session authn
|
||||
}
|
||||
lm.logger.Info("Update thing tags completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.UpdateClientTags(ctx, session, client)
|
||||
return lm.svc.UpdateTags(ctx, session, client)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) UpdateClientSecret(ctx context.Context, session authn.Session, oldSecret, newSecret string) (c mgclients.Client, err error) {
|
||||
func (lm *loggingMiddleware) UpdateSecret(ctx context.Context, session authn.Session, oldSecret, newSecret string) (c things.Client, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -152,10 +151,10 @@ func (lm *loggingMiddleware) UpdateClientSecret(ctx context.Context, session aut
|
||||
}
|
||||
lm.logger.Info("Update thing secret completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.UpdateClientSecret(ctx, session, oldSecret, newSecret)
|
||||
return lm.svc.UpdateSecret(ctx, session, oldSecret, newSecret)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) EnableClient(ctx context.Context, session authn.Session, id string) (c mgclients.Client, err error) {
|
||||
func (lm *loggingMiddleware) Enable(ctx context.Context, session authn.Session, id string) (c things.Client, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -171,10 +170,10 @@ func (lm *loggingMiddleware) EnableClient(ctx context.Context, session authn.Ses
|
||||
}
|
||||
lm.logger.Info("Enable thing completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.EnableClient(ctx, session, id)
|
||||
return lm.svc.Enable(ctx, session, id)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) DisableClient(ctx context.Context, session authn.Session, id string) (c mgclients.Client, err error) {
|
||||
func (lm *loggingMiddleware) Disable(ctx context.Context, session authn.Session, id string) (c things.Client, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -190,10 +189,10 @@ func (lm *loggingMiddleware) DisableClient(ctx context.Context, session authn.Se
|
||||
}
|
||||
lm.logger.Info("Disable thing completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.DisableClient(ctx, session, id)
|
||||
return lm.svc.Disable(ctx, session, id)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) ListClientsByGroup(ctx context.Context, session authn.Session, channelID string, cp mgclients.Page) (mp mgclients.MembersPage, err error) {
|
||||
func (lm *loggingMiddleware) ListClientsByGroup(ctx context.Context, session authn.Session, channelID string, cp things.Page) (mp things.MembersPage, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -234,8 +233,8 @@ func (lm *loggingMiddleware) Authorize(ctx context.Context, req things.AuthzReq)
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("thingID", req.ThingID),
|
||||
slog.String("thingID", req.ThingKey),
|
||||
slog.String("clientID", req.ClientID),
|
||||
slog.String("clientKey", req.ClientKey),
|
||||
slog.String("channelID", req.ChannelID),
|
||||
slog.String("permission", req.Permission),
|
||||
}
|
||||
@@ -253,16 +252,16 @@ func (lm *loggingMiddleware) Share(ctx context.Context, session authn.Session, i
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("thing_id", id),
|
||||
slog.String("client_id", id),
|
||||
slog.Any("user_ids", userids),
|
||||
slog.String("relation", relation),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.Any("error", err))
|
||||
lm.logger.Warn("Share thing failed", args...)
|
||||
lm.logger.Warn("Share client failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("Share thing completed successfully", args...)
|
||||
lm.logger.Info("Share client completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.Share(ctx, session, id, relation, userids...)
|
||||
}
|
||||
@@ -271,32 +270,32 @@ func (lm *loggingMiddleware) Unshare(ctx context.Context, session authn.Session,
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("thing_id", id),
|
||||
slog.String("client_id", id),
|
||||
slog.Any("user_ids", userids),
|
||||
slog.String("relation", relation),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.Any("error", err))
|
||||
lm.logger.Warn("Unshare thing failed", args...)
|
||||
lm.logger.Warn("Unshare client failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("Unshare thing completed successfully", args...)
|
||||
lm.logger.Info("Unshare client completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.Unshare(ctx, session, id, relation, userids...)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) DeleteClient(ctx context.Context, session authn.Session, id string) (err error) {
|
||||
func (lm *loggingMiddleware) Delete(ctx context.Context, session authn.Session, id string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("thing_id", id),
|
||||
slog.String("client_id", id),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.Any("error", err))
|
||||
lm.logger.Warn("Delete thing failed", args...)
|
||||
lm.logger.Warn("Delete client failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("Delete thing completed successfully", args...)
|
||||
lm.logger.Info("Delete client completed successfully", args...)
|
||||
}(time.Now())
|
||||
return lm.svc.DeleteClient(ctx, session, id)
|
||||
return lm.svc.Delete(ctx, session, id)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/go-kit/kit/metrics"
|
||||
)
|
||||
@@ -30,90 +29,90 @@ func MetricsMiddleware(svc things.Service, counter metrics.Counter, latency metr
|
||||
}
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) CreateThings(ctx context.Context, session authn.Session, clients ...mgclients.Client) ([]mgclients.Client, error) {
|
||||
func (ms *metricsMiddleware) CreateClients(ctx context.Context, session authn.Session, things ...things.Client) ([]things.Client, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "register_things").Add(1)
|
||||
ms.latency.With("method", "register_things").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "register_clients").Add(1)
|
||||
ms.latency.With("method", "register_clients").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.CreateThings(ctx, session, clients...)
|
||||
return ms.svc.CreateClients(ctx, session, things...)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) ViewClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
func (ms *metricsMiddleware) View(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "view_thing").Add(1)
|
||||
ms.latency.With("method", "view_thing").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "view_client").Add(1)
|
||||
ms.latency.With("method", "view_client").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.ViewClient(ctx, session, id)
|
||||
return ms.svc.View(ctx, session, id)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) ViewClientPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
func (ms *metricsMiddleware) ViewPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "view_thing_permissions").Add(1)
|
||||
ms.latency.With("method", "view_thing_permissions").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "view_client_permissions").Add(1)
|
||||
ms.latency.With("method", "view_client_permissions").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.ViewClientPerms(ctx, session, id)
|
||||
return ms.svc.ViewPerms(ctx, session, id)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm mgclients.Page) (mgclients.ClientsPage, error) {
|
||||
func (ms *metricsMiddleware) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm things.Page) (things.ClientsPage, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "list_things").Add(1)
|
||||
ms.latency.With("method", "list_things").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "list_clients").Add(1)
|
||||
ms.latency.With("method", "list_clients").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.ListClients(ctx, session, reqUserID, pm)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) UpdateClient(ctx context.Context, session authn.Session, client mgclients.Client) (mgclients.Client, error) {
|
||||
func (ms *metricsMiddleware) Update(ctx context.Context, session authn.Session, thing things.Client) (things.Client, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "update_thing_name_and_metadata").Add(1)
|
||||
ms.latency.With("method", "update_thing_name_and_metadata").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "update_client").Add(1)
|
||||
ms.latency.With("method", "update_client").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.UpdateClient(ctx, session, client)
|
||||
return ms.svc.Update(ctx, session, thing)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) UpdateClientTags(ctx context.Context, session authn.Session, client mgclients.Client) (mgclients.Client, error) {
|
||||
func (ms *metricsMiddleware) UpdateTags(ctx context.Context, session authn.Session, thing things.Client) (things.Client, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "update_thing_tags").Add(1)
|
||||
ms.latency.With("method", "update_thing_tags").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "update_client_tags").Add(1)
|
||||
ms.latency.With("method", "update_client_tags").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.UpdateClientTags(ctx, session, client)
|
||||
return ms.svc.UpdateTags(ctx, session, thing)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) UpdateClientSecret(ctx context.Context, session authn.Session, oldSecret, newSecret string) (mgclients.Client, error) {
|
||||
func (ms *metricsMiddleware) UpdateSecret(ctx context.Context, session authn.Session, oldSecret, newSecret string) (things.Client, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "update_thing_secret").Add(1)
|
||||
ms.latency.With("method", "update_thing_secret").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "update_client_secret").Add(1)
|
||||
ms.latency.With("method", "update_client_secret").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.UpdateClientSecret(ctx, session, oldSecret, newSecret)
|
||||
return ms.svc.UpdateSecret(ctx, session, oldSecret, newSecret)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) EnableClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
func (ms *metricsMiddleware) Enable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "enable_thing").Add(1)
|
||||
ms.latency.With("method", "enable_thing").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "enable_client").Add(1)
|
||||
ms.latency.With("method", "enable_client").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.EnableClient(ctx, session, id)
|
||||
return ms.svc.Enable(ctx, session, id)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) DisableClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
func (ms *metricsMiddleware) Disable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "disable_thing").Add(1)
|
||||
ms.latency.With("method", "disable_thing").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "disable_client").Add(1)
|
||||
ms.latency.With("method", "disable_client").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.DisableClient(ctx, session, id)
|
||||
return ms.svc.Disable(ctx, session, id)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm mgclients.Page) (mp mgclients.MembersPage, err error) {
|
||||
func (ms *metricsMiddleware) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm things.Page) (mp things.MembersPage, err error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "list_things_by_channel").Add(1)
|
||||
ms.latency.With("method", "list_things_by_channel").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "list_clients_by_channel").Add(1)
|
||||
ms.latency.With("method", "list_clients_by_channel").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.ListClientsByGroup(ctx, session, groupID, pm)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) Identify(ctx context.Context, key string) (string, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "identify_thing").Add(1)
|
||||
ms.latency.With("method", "identify_thing").Observe(time.Since(begin).Seconds())
|
||||
ms.counter.With("method", "identify_client").Add(1)
|
||||
ms.latency.With("method", "identify_client").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.Identify(ctx, key)
|
||||
}
|
||||
@@ -142,10 +141,10 @@ func (ms *metricsMiddleware) Unshare(ctx context.Context, session authn.Session,
|
||||
return ms.svc.Unshare(ctx, session, id, relation, userids...)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) DeleteClient(ctx context.Context, session authn.Session, id string) error {
|
||||
func (ms *metricsMiddleware) Delete(ctx context.Context, session authn.Session, id string) error {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "delete_client").Add(1)
|
||||
ms.latency.With("method", "delete_client").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
return ms.svc.DeleteClient(ctx, session, id)
|
||||
return ms.svc.Delete(ctx, session, id)
|
||||
}
|
||||
|
||||
+14
-14
@@ -15,9 +15,9 @@ type Cache struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// ID provides a mock function with given fields: ctx, thingSecret
|
||||
func (_m *Cache) ID(ctx context.Context, thingSecret string) (string, error) {
|
||||
ret := _m.Called(ctx, thingSecret)
|
||||
// ID provides a mock function with given fields: ctx, clientSecret
|
||||
func (_m *Cache) ID(ctx context.Context, clientSecret string) (string, error) {
|
||||
ret := _m.Called(ctx, clientSecret)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ID")
|
||||
@@ -26,16 +26,16 @@ func (_m *Cache) ID(ctx context.Context, thingSecret string) (string, error) {
|
||||
var r0 string
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (string, error)); ok {
|
||||
return rf(ctx, thingSecret)
|
||||
return rf(ctx, clientSecret)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) string); ok {
|
||||
r0 = rf(ctx, thingSecret)
|
||||
r0 = rf(ctx, clientSecret)
|
||||
} else {
|
||||
r0 = ret.Get(0).(string)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, thingSecret)
|
||||
r1 = rf(ctx, clientSecret)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
@@ -43,9 +43,9 @@ func (_m *Cache) ID(ctx context.Context, thingSecret string) (string, error) {
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Remove provides a mock function with given fields: ctx, thingID
|
||||
func (_m *Cache) Remove(ctx context.Context, thingID string) error {
|
||||
ret := _m.Called(ctx, thingID)
|
||||
// Remove provides a mock function with given fields: ctx, clientID
|
||||
func (_m *Cache) Remove(ctx context.Context, clientID string) error {
|
||||
ret := _m.Called(ctx, clientID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Remove")
|
||||
@@ -53,7 +53,7 @@ func (_m *Cache) Remove(ctx context.Context, thingID string) error {
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, thingID)
|
||||
r0 = rf(ctx, clientID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -61,9 +61,9 @@ func (_m *Cache) Remove(ctx context.Context, thingID string) error {
|
||||
return r0
|
||||
}
|
||||
|
||||
// Save provides a mock function with given fields: ctx, thingSecret, thingID
|
||||
func (_m *Cache) Save(ctx context.Context, thingSecret string, thingID string) error {
|
||||
ret := _m.Called(ctx, thingSecret, thingID)
|
||||
// Save provides a mock function with given fields: ctx, clientSecret, clientID
|
||||
func (_m *Cache) Save(ctx context.Context, clientSecret string, clientID string) error {
|
||||
ret := _m.Called(ctx, clientSecret, clientID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Save")
|
||||
@@ -71,7 +71,7 @@ func (_m *Cache) Save(ctx context.Context, thingSecret string, thingID string) e
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
|
||||
r0 = rf(ctx, thingSecret, thingID)
|
||||
r0 = rf(ctx, clientSecret, clientID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
+65
-122
@@ -7,8 +7,7 @@ package mocks
|
||||
import (
|
||||
context "context"
|
||||
|
||||
clients "github.com/absmach/magistrala/pkg/clients"
|
||||
|
||||
things "github.com/absmach/magistrala/things"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
@@ -18,25 +17,25 @@ type Repository struct {
|
||||
}
|
||||
|
||||
// ChangeStatus provides a mock function with given fields: ctx, client
|
||||
func (_m *Repository) ChangeStatus(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
func (_m *Repository) ChangeStatus(ctx context.Context, client things.Client) (things.Client, error) {
|
||||
ret := _m.Called(ctx, client)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ChangeStatus")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) (things.Client, error)); ok {
|
||||
return rf(ctx, client)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) things.Client); ok {
|
||||
r0 = rf(ctx, client)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, clients.Client) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, things.Client) error); ok {
|
||||
r1 = rf(ctx, client)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -64,25 +63,25 @@ func (_m *Repository) Delete(ctx context.Context, id string) error {
|
||||
}
|
||||
|
||||
// RetrieveAll provides a mock function with given fields: ctx, pm
|
||||
func (_m *Repository) RetrieveAll(ctx context.Context, pm clients.Page) (clients.ClientsPage, error) {
|
||||
func (_m *Repository) RetrieveAll(ctx context.Context, pm things.Page) (things.ClientsPage, error) {
|
||||
ret := _m.Called(ctx, pm)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RetrieveAll")
|
||||
}
|
||||
|
||||
var r0 clients.ClientsPage
|
||||
var r0 things.ClientsPage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Page) (clients.ClientsPage, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Page) (things.ClientsPage, error)); ok {
|
||||
return rf(ctx, pm)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Page) clients.ClientsPage); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Page) things.ClientsPage); ok {
|
||||
r0 = rf(ctx, pm)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.ClientsPage)
|
||||
r0 = ret.Get(0).(things.ClientsPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, clients.Page) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, things.Page) error); ok {
|
||||
r1 = rf(ctx, pm)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -92,25 +91,25 @@ func (_m *Repository) RetrieveAll(ctx context.Context, pm clients.Page) (clients
|
||||
}
|
||||
|
||||
// RetrieveAllByIDs provides a mock function with given fields: ctx, pm
|
||||
func (_m *Repository) RetrieveAllByIDs(ctx context.Context, pm clients.Page) (clients.ClientsPage, error) {
|
||||
func (_m *Repository) RetrieveAllByIDs(ctx context.Context, pm things.Page) (things.ClientsPage, error) {
|
||||
ret := _m.Called(ctx, pm)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RetrieveAllByIDs")
|
||||
}
|
||||
|
||||
var r0 clients.ClientsPage
|
||||
var r0 things.ClientsPage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Page) (clients.ClientsPage, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Page) (things.ClientsPage, error)); ok {
|
||||
return rf(ctx, pm)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Page) clients.ClientsPage); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Page) things.ClientsPage); ok {
|
||||
r0 = rf(ctx, pm)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.ClientsPage)
|
||||
r0 = ret.Get(0).(things.ClientsPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, clients.Page) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, things.Page) error); ok {
|
||||
r1 = rf(ctx, pm)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -120,22 +119,22 @@ func (_m *Repository) RetrieveAllByIDs(ctx context.Context, pm clients.Page) (cl
|
||||
}
|
||||
|
||||
// RetrieveByID provides a mock function with given fields: ctx, id
|
||||
func (_m *Repository) RetrieveByID(ctx context.Context, id string) (clients.Client, error) {
|
||||
func (_m *Repository) RetrieveByID(ctx context.Context, id string) (things.Client, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RetrieveByID")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (things.Client, error)); ok {
|
||||
return rf(ctx, id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) things.Client); ok {
|
||||
r0 = rf(ctx, id)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
@@ -147,51 +146,23 @@ func (_m *Repository) RetrieveByID(ctx context.Context, id string) (clients.Clie
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RetrieveByIdentity provides a mock function with given fields: ctx, identity
|
||||
func (_m *Repository) RetrieveByIdentity(ctx context.Context, identity string) (clients.Client, error) {
|
||||
ret := _m.Called(ctx, identity)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RetrieveByIdentity")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (clients.Client, error)); ok {
|
||||
return rf(ctx, identity)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) clients.Client); ok {
|
||||
r0 = rf(ctx, identity)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, identity)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// RetrieveBySecret provides a mock function with given fields: ctx, key
|
||||
func (_m *Repository) RetrieveBySecret(ctx context.Context, key string) (clients.Client, error) {
|
||||
func (_m *Repository) RetrieveBySecret(ctx context.Context, key string) (things.Client, error) {
|
||||
ret := _m.Called(ctx, key)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RetrieveBySecret")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (things.Client, error)); ok {
|
||||
return rf(ctx, key)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) things.Client); ok {
|
||||
r0 = rf(ctx, key)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
@@ -204,7 +175,7 @@ func (_m *Repository) RetrieveBySecret(ctx context.Context, key string) (clients
|
||||
}
|
||||
|
||||
// Save provides a mock function with given fields: ctx, client
|
||||
func (_m *Repository) Save(ctx context.Context, client ...clients.Client) ([]clients.Client, error) {
|
||||
func (_m *Repository) Save(ctx context.Context, client ...things.Client) ([]things.Client, error) {
|
||||
_va := make([]interface{}, len(client))
|
||||
for _i := range client {
|
||||
_va[_i] = client[_i]
|
||||
@@ -218,20 +189,20 @@ func (_m *Repository) Save(ctx context.Context, client ...clients.Client) ([]cli
|
||||
panic("no return value specified for Save")
|
||||
}
|
||||
|
||||
var r0 []clients.Client
|
||||
var r0 []things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, ...clients.Client) ([]clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, ...things.Client) ([]things.Client, error)); ok {
|
||||
return rf(ctx, client...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, ...clients.Client) []clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, ...things.Client) []things.Client); ok {
|
||||
r0 = rf(ctx, client...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]clients.Client)
|
||||
r0 = ret.Get(0).([]things.Client)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, ...clients.Client) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, ...things.Client) error); ok {
|
||||
r1 = rf(ctx, client...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -241,25 +212,25 @@ func (_m *Repository) Save(ctx context.Context, client ...clients.Client) ([]cli
|
||||
}
|
||||
|
||||
// SearchClients provides a mock function with given fields: ctx, pm
|
||||
func (_m *Repository) SearchClients(ctx context.Context, pm clients.Page) (clients.ClientsPage, error) {
|
||||
func (_m *Repository) SearchClients(ctx context.Context, pm things.Page) (things.ClientsPage, error) {
|
||||
ret := _m.Called(ctx, pm)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SearchClients")
|
||||
}
|
||||
|
||||
var r0 clients.ClientsPage
|
||||
var r0 things.ClientsPage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Page) (clients.ClientsPage, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Page) (things.ClientsPage, error)); ok {
|
||||
return rf(ctx, pm)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Page) clients.ClientsPage); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Page) things.ClientsPage); ok {
|
||||
r0 = rf(ctx, pm)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.ClientsPage)
|
||||
r0 = ret.Get(0).(things.ClientsPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, clients.Page) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, things.Page) error); ok {
|
||||
r1 = rf(ctx, pm)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -269,25 +240,25 @@ func (_m *Repository) SearchClients(ctx context.Context, pm clients.Page) (clien
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: ctx, client
|
||||
func (_m *Repository) Update(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
func (_m *Repository) Update(ctx context.Context, client things.Client) (things.Client, error) {
|
||||
ret := _m.Called(ctx, client)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Update")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) (things.Client, error)); ok {
|
||||
return rf(ctx, client)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) things.Client); ok {
|
||||
r0 = rf(ctx, client)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, clients.Client) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, things.Client) error); ok {
|
||||
r1 = rf(ctx, client)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -297,53 +268,25 @@ func (_m *Repository) Update(ctx context.Context, client clients.Client) (client
|
||||
}
|
||||
|
||||
// UpdateIdentity provides a mock function with given fields: ctx, client
|
||||
func (_m *Repository) UpdateIdentity(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
func (_m *Repository) UpdateIdentity(ctx context.Context, client things.Client) (things.Client, error) {
|
||||
ret := _m.Called(ctx, client)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateIdentity")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) (things.Client, error)); ok {
|
||||
return rf(ctx, client)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) things.Client); ok {
|
||||
r0 = rf(ctx, client)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, clients.Client) error); ok {
|
||||
r1 = rf(ctx, client)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateRole provides a mock function with given fields: ctx, client
|
||||
func (_m *Repository) UpdateRole(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
ret := _m.Called(ctx, client)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateRole")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) (clients.Client, error)); ok {
|
||||
return rf(ctx, client)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) clients.Client); ok {
|
||||
r0 = rf(ctx, client)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, clients.Client) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, things.Client) error); ok {
|
||||
r1 = rf(ctx, client)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -353,25 +296,25 @@ func (_m *Repository) UpdateRole(ctx context.Context, client clients.Client) (cl
|
||||
}
|
||||
|
||||
// UpdateSecret provides a mock function with given fields: ctx, client
|
||||
func (_m *Repository) UpdateSecret(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
func (_m *Repository) UpdateSecret(ctx context.Context, client things.Client) (things.Client, error) {
|
||||
ret := _m.Called(ctx, client)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateSecret")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) (things.Client, error)); ok {
|
||||
return rf(ctx, client)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) things.Client); ok {
|
||||
r0 = rf(ctx, client)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, clients.Client) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, things.Client) error); ok {
|
||||
r1 = rf(ctx, client)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -381,25 +324,25 @@ func (_m *Repository) UpdateSecret(ctx context.Context, client clients.Client) (
|
||||
}
|
||||
|
||||
// UpdateTags provides a mock function with given fields: ctx, client
|
||||
func (_m *Repository) UpdateTags(ctx context.Context, client clients.Client) (clients.Client, error) {
|
||||
func (_m *Repository) UpdateTags(ctx context.Context, client things.Client) (things.Client, error) {
|
||||
ret := _m.Called(ctx, client)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateTags")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) (things.Client, error)); ok {
|
||||
return rf(ctx, client)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, clients.Client) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, things.Client) things.Client); ok {
|
||||
r0 = rf(ctx, client)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, clients.Client) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, things.Client) error); ok {
|
||||
r1 = rf(ctx, client)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
|
||||
+72
-73
@@ -5,11 +5,10 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
authn "github.com/absmach/magistrala/pkg/authn"
|
||||
clients "github.com/absmach/magistrala/pkg/clients"
|
||||
|
||||
context "context"
|
||||
|
||||
authn "github.com/absmach/magistrala/pkg/authn"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
things "github.com/absmach/magistrala/things"
|
||||
@@ -48,8 +47,8 @@ func (_m *Service) Authorize(ctx context.Context, req things.AuthzReq) (string,
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CreateThings provides a mock function with given fields: ctx, session, client
|
||||
func (_m *Service) CreateThings(ctx context.Context, session authn.Session, client ...clients.Client) ([]clients.Client, error) {
|
||||
// CreateClients provides a mock function with given fields: ctx, session, client
|
||||
func (_m *Service) CreateClients(ctx context.Context, session authn.Session, client ...things.Client) ([]things.Client, error) {
|
||||
_va := make([]interface{}, len(client))
|
||||
for _i := range client {
|
||||
_va[_i] = client[_i]
|
||||
@@ -60,23 +59,23 @@ func (_m *Service) CreateThings(ctx context.Context, session authn.Session, clie
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreateThings")
|
||||
panic("no return value specified for CreateClients")
|
||||
}
|
||||
|
||||
var r0 []clients.Client
|
||||
var r0 []things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, ...clients.Client) ([]clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, ...things.Client) ([]things.Client, error)); ok {
|
||||
return rf(ctx, session, client...)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, ...clients.Client) []clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, ...things.Client) []things.Client); ok {
|
||||
r0 = rf(ctx, session, client...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]clients.Client)
|
||||
r0 = ret.Get(0).([]things.Client)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, ...clients.Client) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, ...things.Client) error); ok {
|
||||
r1 = rf(ctx, session, client...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -85,12 +84,12 @@ func (_m *Service) CreateThings(ctx context.Context, session authn.Session, clie
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// DeleteClient provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) DeleteClient(ctx context.Context, session authn.Session, id string) error {
|
||||
// Delete provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) Delete(ctx context.Context, session authn.Session, id string) error {
|
||||
ret := _m.Called(ctx, session, id)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DeleteClient")
|
||||
panic("no return value specified for Delete")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
@@ -103,23 +102,23 @@ func (_m *Service) DeleteClient(ctx context.Context, session authn.Session, id s
|
||||
return r0
|
||||
}
|
||||
|
||||
// DisableClient provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) DisableClient(ctx context.Context, session authn.Session, id string) (clients.Client, error) {
|
||||
// Disable provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) Disable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
ret := _m.Called(ctx, session, id)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DisableClient")
|
||||
panic("no return value specified for Disable")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) (things.Client, error)); ok {
|
||||
return rf(ctx, session, id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) things.Client); ok {
|
||||
r0 = rf(ctx, session, id)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string) error); ok {
|
||||
@@ -131,23 +130,23 @@ func (_m *Service) DisableClient(ctx context.Context, session authn.Session, id
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// EnableClient provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) EnableClient(ctx context.Context, session authn.Session, id string) (clients.Client, error) {
|
||||
// Enable provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) Enable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
ret := _m.Called(ctx, session, id)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for EnableClient")
|
||||
panic("no return value specified for Enable")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) (things.Client, error)); ok {
|
||||
return rf(ctx, session, id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) things.Client); ok {
|
||||
r0 = rf(ctx, session, id)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string) error); ok {
|
||||
@@ -188,25 +187,25 @@ func (_m *Service) Identify(ctx context.Context, key string) (string, error) {
|
||||
}
|
||||
|
||||
// ListClients provides a mock function with given fields: ctx, session, reqUserID, pm
|
||||
func (_m *Service) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm clients.Page) (clients.ClientsPage, error) {
|
||||
func (_m *Service) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm things.Page) (things.ClientsPage, error) {
|
||||
ret := _m.Called(ctx, session, reqUserID, pm)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListClients")
|
||||
}
|
||||
|
||||
var r0 clients.ClientsPage
|
||||
var r0 things.ClientsPage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, clients.Page) (clients.ClientsPage, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, things.Page) (things.ClientsPage, error)); ok {
|
||||
return rf(ctx, session, reqUserID, pm)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, clients.Page) clients.ClientsPage); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, things.Page) things.ClientsPage); ok {
|
||||
r0 = rf(ctx, session, reqUserID, pm)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.ClientsPage)
|
||||
r0 = ret.Get(0).(things.ClientsPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, clients.Page) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, things.Page) error); ok {
|
||||
r1 = rf(ctx, session, reqUserID, pm)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -216,25 +215,25 @@ func (_m *Service) ListClients(ctx context.Context, session authn.Session, reqUs
|
||||
}
|
||||
|
||||
// ListClientsByGroup provides a mock function with given fields: ctx, session, groupID, pm
|
||||
func (_m *Service) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm clients.Page) (clients.MembersPage, error) {
|
||||
func (_m *Service) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm things.Page) (things.MembersPage, error) {
|
||||
ret := _m.Called(ctx, session, groupID, pm)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListClientsByGroup")
|
||||
}
|
||||
|
||||
var r0 clients.MembersPage
|
||||
var r0 things.MembersPage
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, clients.Page) (clients.MembersPage, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, things.Page) (things.MembersPage, error)); ok {
|
||||
return rf(ctx, session, groupID, pm)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, clients.Page) clients.MembersPage); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, things.Page) things.MembersPage); ok {
|
||||
r0 = rf(ctx, session, groupID, pm)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.MembersPage)
|
||||
r0 = ret.Get(0).(things.MembersPage)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, clients.Page) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, things.Page) error); ok {
|
||||
r1 = rf(ctx, session, groupID, pm)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -293,26 +292,26 @@ func (_m *Service) Unshare(ctx context.Context, session authn.Session, id string
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateClient provides a mock function with given fields: ctx, session, client
|
||||
func (_m *Service) UpdateClient(ctx context.Context, session authn.Session, client clients.Client) (clients.Client, error) {
|
||||
// Update provides a mock function with given fields: ctx, session, client
|
||||
func (_m *Service) Update(ctx context.Context, session authn.Session, client things.Client) (things.Client, error) {
|
||||
ret := _m.Called(ctx, session, client)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateClient")
|
||||
panic("no return value specified for Update")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, clients.Client) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, things.Client) (things.Client, error)); ok {
|
||||
return rf(ctx, session, client)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, clients.Client) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, things.Client) things.Client); ok {
|
||||
r0 = rf(ctx, session, client)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, clients.Client) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, things.Client) error); ok {
|
||||
r1 = rf(ctx, session, client)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -321,23 +320,23 @@ func (_m *Service) UpdateClient(ctx context.Context, session authn.Session, clie
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateClientSecret provides a mock function with given fields: ctx, session, id, key
|
||||
func (_m *Service) UpdateClientSecret(ctx context.Context, session authn.Session, id string, key string) (clients.Client, error) {
|
||||
// UpdateSecret provides a mock function with given fields: ctx, session, id, key
|
||||
func (_m *Service) UpdateSecret(ctx context.Context, session authn.Session, id string, key string) (things.Client, error) {
|
||||
ret := _m.Called(ctx, session, id, key)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateClientSecret")
|
||||
panic("no return value specified for UpdateSecret")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string) (things.Client, error)); ok {
|
||||
return rf(ctx, session, id, key)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string) things.Client); ok {
|
||||
r0 = rf(ctx, session, id, key)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, string) error); ok {
|
||||
@@ -349,26 +348,26 @@ func (_m *Service) UpdateClientSecret(ctx context.Context, session authn.Session
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateClientTags provides a mock function with given fields: ctx, session, client
|
||||
func (_m *Service) UpdateClientTags(ctx context.Context, session authn.Session, client clients.Client) (clients.Client, error) {
|
||||
// UpdateTags provides a mock function with given fields: ctx, session, client
|
||||
func (_m *Service) UpdateTags(ctx context.Context, session authn.Session, client things.Client) (things.Client, error) {
|
||||
ret := _m.Called(ctx, session, client)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateClientTags")
|
||||
panic("no return value specified for UpdateTags")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, clients.Client) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, things.Client) (things.Client, error)); ok {
|
||||
return rf(ctx, session, client)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, clients.Client) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, things.Client) things.Client); ok {
|
||||
r0 = rf(ctx, session, client)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, clients.Client) error); ok {
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, things.Client) error); ok {
|
||||
r1 = rf(ctx, session, client)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
@@ -377,23 +376,23 @@ func (_m *Service) UpdateClientTags(ctx context.Context, session authn.Session,
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ViewClient provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) ViewClient(ctx context.Context, session authn.Session, id string) (clients.Client, error) {
|
||||
// View provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) View(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
ret := _m.Called(ctx, session, id)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ViewClient")
|
||||
panic("no return value specified for View")
|
||||
}
|
||||
|
||||
var r0 clients.Client
|
||||
var r0 things.Client
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) (clients.Client, error)); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) (things.Client, error)); ok {
|
||||
return rf(ctx, session, id)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) clients.Client); ok {
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) things.Client); ok {
|
||||
r0 = rf(ctx, session, id)
|
||||
} else {
|
||||
r0 = ret.Get(0).(clients.Client)
|
||||
r0 = ret.Get(0).(things.Client)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string) error); ok {
|
||||
@@ -405,12 +404,12 @@ func (_m *Service) ViewClient(ctx context.Context, session authn.Session, id str
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ViewClientPerms provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) ViewClientPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
// ViewPerms provides a mock function with given fields: ctx, session, id
|
||||
func (_m *Service) ViewPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
ret := _m.Called(ctx, session, id)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ViewClientPerms")
|
||||
panic("no return value specified for ViewPerms")
|
||||
}
|
||||
|
||||
var r0 []string
|
||||
|
||||
+503
-52
@@ -5,119 +5,570 @@ package postgres
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
pgclients "github.com/absmach/magistrala/pkg/clients/postgres"
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
"github.com/absmach/magistrala/pkg/postgres"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/jackc/pgtype"
|
||||
)
|
||||
|
||||
var _ mgclients.Repository = (*clientRepo)(nil)
|
||||
|
||||
type clientRepo struct {
|
||||
pgclients.Repository
|
||||
}
|
||||
|
||||
// Repository is the interface that wraps the basic methods for
|
||||
// a client repository.
|
||||
//
|
||||
//go:generate mockery --name Repository --output=../mocks --filename repository.go --quiet --note "Copyright (c) Abstract Machines"
|
||||
type Repository interface {
|
||||
mgclients.Repository
|
||||
|
||||
// Save persists the client account. A non-nil error is returned to indicate
|
||||
// operation failure.
|
||||
Save(ctx context.Context, client ...mgclients.Client) ([]mgclients.Client, error)
|
||||
|
||||
// RetrieveBySecret retrieves a client based on the secret (key).
|
||||
RetrieveBySecret(ctx context.Context, key string) (mgclients.Client, error)
|
||||
Repository things.ClientRepository
|
||||
}
|
||||
|
||||
// NewRepository instantiates a PostgreSQL
|
||||
// implementation of Clients repository.
|
||||
func NewRepository(db postgres.Database) Repository {
|
||||
func NewRepository(db postgres.Database) things.Repository {
|
||||
return &clientRepo{
|
||||
Repository: pgclients.Repository{DB: db},
|
||||
Repository: things.ClientRepository{DB: db},
|
||||
}
|
||||
}
|
||||
|
||||
func (repo clientRepo) Save(ctx context.Context, cs ...mgclients.Client) ([]mgclients.Client, error) {
|
||||
tx, err := repo.DB.BeginTxx(ctx, nil)
|
||||
func (repo *clientRepo) Save(ctx context.Context, th ...things.Client) ([]things.Client, error) {
|
||||
tx, err := repo.Repository.DB.BeginTxx(ctx, nil)
|
||||
if err != nil {
|
||||
return []mgclients.Client{}, errors.Wrap(repoerr.ErrCreateEntity, err)
|
||||
return []things.Client{}, errors.Wrap(repoerr.ErrCreateEntity, err)
|
||||
}
|
||||
var clients []mgclients.Client
|
||||
var thingsList []things.Client
|
||||
|
||||
for _, cli := range cs {
|
||||
for _, thi := range th {
|
||||
q := `INSERT INTO clients (id, name, tags, domain_id, identity, secret, metadata, created_at, updated_at, updated_by, status)
|
||||
VALUES (:id, :name, :tags, :domain_id, :identity, :secret, :metadata, :created_at, :updated_at, :updated_by, :status)
|
||||
RETURNING id, name, tags, identity, secret, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`
|
||||
|
||||
dbcli, err := pgclients.ToDBClient(cli)
|
||||
dbthi, err := ToDBClient(thi)
|
||||
if err != nil {
|
||||
return []mgclients.Client{}, errors.Wrap(repoerr.ErrCreateEntity, err)
|
||||
return []things.Client{}, errors.Wrap(repoerr.ErrCreateEntity, err)
|
||||
}
|
||||
|
||||
row, err := repo.DB.NamedQueryContext(ctx, q, dbcli)
|
||||
row, err := repo.Repository.DB.NamedQueryContext(ctx, q, dbthi)
|
||||
if err != nil {
|
||||
if err := tx.Rollback(); err != nil {
|
||||
return []mgclients.Client{}, postgres.HandleError(repoerr.ErrCreateEntity, err)
|
||||
return []things.Client{}, postgres.HandleError(repoerr.ErrCreateEntity, err)
|
||||
}
|
||||
return []mgclients.Client{}, errors.Wrap(repoerr.ErrCreateEntity, err)
|
||||
return []things.Client{}, errors.Wrap(repoerr.ErrCreateEntity, err)
|
||||
}
|
||||
|
||||
defer row.Close()
|
||||
|
||||
if row.Next() {
|
||||
dbcli = pgclients.DBClient{}
|
||||
if err := row.StructScan(&dbcli); err != nil {
|
||||
return []mgclients.Client{}, errors.Wrap(repoerr.ErrFailedOpDB, err)
|
||||
dbthi = DBClient{}
|
||||
if err := row.StructScan(&dbthi); err != nil {
|
||||
return []things.Client{}, errors.Wrap(repoerr.ErrFailedOpDB, err)
|
||||
}
|
||||
|
||||
client, err := pgclients.ToClient(dbcli)
|
||||
thing, err := ToClient(dbthi)
|
||||
if err != nil {
|
||||
return []mgclients.Client{}, errors.Wrap(repoerr.ErrFailedOpDB, err)
|
||||
return []things.Client{}, errors.Wrap(repoerr.ErrFailedOpDB, err)
|
||||
}
|
||||
clients = append(clients, client)
|
||||
thingsList = append(thingsList, thing)
|
||||
}
|
||||
}
|
||||
if err = tx.Commit(); err != nil {
|
||||
return []mgclients.Client{}, errors.Wrap(repoerr.ErrCreateEntity, err)
|
||||
return []things.Client{}, errors.Wrap(repoerr.ErrCreateEntity, err)
|
||||
}
|
||||
|
||||
return clients, nil
|
||||
return thingsList, nil
|
||||
}
|
||||
|
||||
func (repo clientRepo) RetrieveBySecret(ctx context.Context, key string) (mgclients.Client, error) {
|
||||
func (repo *clientRepo) RetrieveBySecret(ctx context.Context, key string) (things.Client, error) {
|
||||
q := fmt.Sprintf(`SELECT id, name, tags, COALESCE(domain_id, '') AS domain_id, identity, secret, metadata, created_at, updated_at, updated_by, status
|
||||
FROM clients
|
||||
WHERE secret = :secret AND status = %d`, mgclients.EnabledStatus)
|
||||
WHERE secret = :secret AND status = %d`, things.EnabledStatus)
|
||||
|
||||
dbc := pgclients.DBClient{
|
||||
dbt := DBClient{
|
||||
Secret: key,
|
||||
}
|
||||
|
||||
rows, err := repo.DB.NamedQueryContext(ctx, q, dbc)
|
||||
rows, err := repo.Repository.DB.NamedQueryContext(ctx, q, dbt)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, postgres.HandleError(repoerr.ErrViewEntity, err)
|
||||
return things.Client{}, postgres.HandleError(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
dbc = pgclients.DBClient{}
|
||||
dbt = DBClient{}
|
||||
if rows.Next() {
|
||||
if err = rows.StructScan(&dbc); err != nil {
|
||||
return mgclients.Client{}, postgres.HandleError(repoerr.ErrViewEntity, err)
|
||||
if err = rows.StructScan(&dbt); err != nil {
|
||||
return things.Client{}, postgres.HandleError(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
client, err := pgclients.ToClient(dbc)
|
||||
thing, err := ToClient(dbt)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, errors.Wrap(repoerr.ErrFailedOpDB, err)
|
||||
return things.Client{}, errors.Wrap(repoerr.ErrFailedOpDB, err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
return thing, nil
|
||||
}
|
||||
|
||||
return mgclients.Client{}, repoerr.ErrNotFound
|
||||
return things.Client{}, repoerr.ErrNotFound
|
||||
}
|
||||
|
||||
func (repo *clientRepo) Update(ctx context.Context, thing things.Client) (things.Client, error) {
|
||||
var query []string
|
||||
var upq string
|
||||
if thing.Name != "" {
|
||||
query = append(query, "name = :name,")
|
||||
}
|
||||
if thing.Metadata != nil {
|
||||
query = append(query, "metadata = :metadata,")
|
||||
}
|
||||
if len(query) > 0 {
|
||||
upq = strings.Join(query, " ")
|
||||
}
|
||||
|
||||
q := fmt.Sprintf(`UPDATE clients SET %s updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, tags, identity, secret, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`,
|
||||
upq)
|
||||
thing.Status = things.EnabledStatus
|
||||
return repo.update(ctx, thing, q)
|
||||
}
|
||||
|
||||
func (repo *clientRepo) UpdateTags(ctx context.Context, thing things.Client) (things.Client, error) {
|
||||
q := `UPDATE clients SET tags = :tags, updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, tags, identity, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`
|
||||
thing.Status = things.EnabledStatus
|
||||
return repo.update(ctx, thing, q)
|
||||
}
|
||||
|
||||
func (repo *clientRepo) UpdateIdentity(ctx context.Context, thing things.Client) (things.Client, error) {
|
||||
q := `UPDATE clients SET identity = :identity, updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, tags, identity, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`
|
||||
thing.Status = things.EnabledStatus
|
||||
return repo.update(ctx, thing, q)
|
||||
}
|
||||
|
||||
func (repo *clientRepo) UpdateSecret(ctx context.Context, thing things.Client) (things.Client, error) {
|
||||
q := `UPDATE clients SET secret = :secret, updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id AND status = :status
|
||||
RETURNING id, name, tags, identity, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`
|
||||
thing.Status = things.EnabledStatus
|
||||
return repo.update(ctx, thing, q)
|
||||
}
|
||||
|
||||
func (repo *clientRepo) ChangeStatus(ctx context.Context, thing things.Client) (things.Client, error) {
|
||||
q := `UPDATE clients SET status = :status, updated_at = :updated_at, updated_by = :updated_by
|
||||
WHERE id = :id
|
||||
RETURNING id, name, tags, identity, metadata, COALESCE(domain_id, '') AS domain_id, status, created_at, updated_at, updated_by`
|
||||
|
||||
return repo.update(ctx, thing, q)
|
||||
}
|
||||
|
||||
func (repo *clientRepo) RetrieveByID(ctx context.Context, id string) (things.Client, error) {
|
||||
q := `SELECT id, name, tags, COALESCE(domain_id, '') AS domain_id, identity, secret, metadata, created_at, updated_at, updated_by, status
|
||||
FROM clients WHERE id = :id`
|
||||
|
||||
dbt := DBClient{
|
||||
ID: id,
|
||||
}
|
||||
|
||||
row, err := repo.Repository.DB.NamedQueryContext(ctx, q, dbt)
|
||||
if err != nil {
|
||||
return things.Client{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
defer row.Close()
|
||||
|
||||
dbt = DBClient{}
|
||||
if row.Next() {
|
||||
if err := row.StructScan(&dbt); err != nil {
|
||||
return things.Client{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
return ToClient(dbt)
|
||||
}
|
||||
|
||||
return things.Client{}, repoerr.ErrNotFound
|
||||
}
|
||||
|
||||
func (repo *clientRepo) RetrieveAll(ctx context.Context, pm things.Page) (things.ClientsPage, error) {
|
||||
query, err := PageQuery(pm)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
query = applyOrdering(query, pm)
|
||||
|
||||
q := fmt.Sprintf(`SELECT c.id, c.name, c.tags, c.identity, c.metadata, COALESCE(c.domain_id, '') AS domain_id, c.status,
|
||||
c.created_at, c.updated_at, COALESCE(c.updated_by, '') AS updated_by FROM clients c %s ORDER BY c.created_at LIMIT :limit OFFSET :offset;`, query)
|
||||
|
||||
dbPage, err := ToDBClientsPage(pm)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
rows, err := repo.Repository.DB.NamedQueryContext(ctx, q, dbPage)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var items []things.Client
|
||||
for rows.Next() {
|
||||
dbt := DBClient{}
|
||||
if err := rows.StructScan(&dbt); err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
c, err := ToClient(dbt)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, err
|
||||
}
|
||||
|
||||
items = append(items, c)
|
||||
}
|
||||
cq := fmt.Sprintf(`SELECT COUNT(*) FROM clients c %s;`, query)
|
||||
|
||||
total, err := postgres.Total(ctx, repo.Repository.DB, cq, dbPage)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
page := things.ClientsPage{
|
||||
Clients: items,
|
||||
Page: things.Page{
|
||||
Total: total,
|
||||
Offset: pm.Offset,
|
||||
Limit: pm.Limit,
|
||||
},
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (repo *clientRepo) SearchClients(ctx context.Context, pm things.Page) (things.ClientsPage, error) {
|
||||
query, err := PageQuery(pm)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
tq := query
|
||||
query = applyOrdering(query, pm)
|
||||
|
||||
q := fmt.Sprintf(`SELECT c.id, c.name, c.created_at, c.updated_at FROM clients c %s LIMIT :limit OFFSET :offset;`, query)
|
||||
|
||||
dbPage, err := ToDBClientsPage(pm)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
|
||||
rows, err := repo.Repository.DB.NamedQueryContext(ctx, q, dbPage)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var items []things.Client
|
||||
for rows.Next() {
|
||||
dbt := DBClient{}
|
||||
if err := rows.StructScan(&dbt); err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
c, err := ToClient(dbt)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, err
|
||||
}
|
||||
|
||||
items = append(items, c)
|
||||
}
|
||||
|
||||
cq := fmt.Sprintf(`SELECT COUNT(*) FROM clients c %s;`, tq)
|
||||
total, err := postgres.Total(ctx, repo.Repository.DB, cq, dbPage)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
page := things.ClientsPage{
|
||||
Clients: items,
|
||||
Page: things.Page{
|
||||
Total: total,
|
||||
Offset: pm.Offset,
|
||||
Limit: pm.Limit,
|
||||
},
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (repo *clientRepo) RetrieveAllByIDs(ctx context.Context, pm things.Page) (things.ClientsPage, error) {
|
||||
if (len(pm.IDs) == 0) && (pm.Domain == "") {
|
||||
return things.ClientsPage{
|
||||
Page: things.Page{Total: pm.Total, Offset: pm.Offset, Limit: pm.Limit},
|
||||
}, nil
|
||||
}
|
||||
query, err := PageQuery(pm)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
query = applyOrdering(query, pm)
|
||||
|
||||
q := fmt.Sprintf(`SELECT c.id, c.name, c.tags, c.identity, c.metadata, COALESCE(c.domain_id, '') AS domain_id, c.status,
|
||||
c.created_at, c.updated_at, COALESCE(c.updated_by, '') AS updated_by FROM clients c %s ORDER BY c.created_at LIMIT :limit OFFSET :offset;`, query)
|
||||
|
||||
dbPage, err := ToDBClientsPage(pm)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
rows, err := repo.Repository.DB.NamedQueryContext(ctx, q, dbPage)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrFailedToRetrieveAllGroups, err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var items []things.Client
|
||||
for rows.Next() {
|
||||
dbt := DBClient{}
|
||||
if err := rows.StructScan(&dbt); err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
c, err := ToClient(dbt)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, err
|
||||
}
|
||||
|
||||
items = append(items, c)
|
||||
}
|
||||
cq := fmt.Sprintf(`SELECT COUNT(*) FROM clients c %s;`, query)
|
||||
|
||||
total, err := postgres.Total(ctx, repo.Repository.DB, cq, dbPage)
|
||||
if err != nil {
|
||||
return things.ClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
page := things.ClientsPage{
|
||||
Clients: items,
|
||||
Page: things.Page{
|
||||
Total: total,
|
||||
Offset: pm.Offset,
|
||||
Limit: pm.Limit,
|
||||
},
|
||||
}
|
||||
|
||||
return page, nil
|
||||
}
|
||||
|
||||
func (repo *clientRepo) update(ctx context.Context, thing things.Client, query string) (things.Client, error) {
|
||||
dbc, err := ToDBClient(thing)
|
||||
if err != nil {
|
||||
return things.Client{}, errors.Wrap(repoerr.ErrUpdateEntity, err)
|
||||
}
|
||||
|
||||
row, err := repo.Repository.DB.NamedQueryContext(ctx, query, dbc)
|
||||
if err != nil {
|
||||
return things.Client{}, postgres.HandleError(repoerr.ErrUpdateEntity, err)
|
||||
}
|
||||
defer row.Close()
|
||||
|
||||
dbc = DBClient{}
|
||||
if row.Next() {
|
||||
if err := row.StructScan(&dbc); err != nil {
|
||||
return things.Client{}, errors.Wrap(repoerr.ErrUpdateEntity, err)
|
||||
}
|
||||
|
||||
return ToClient(dbc)
|
||||
}
|
||||
|
||||
return things.Client{}, repoerr.ErrNotFound
|
||||
}
|
||||
|
||||
func (repo *clientRepo) Delete(ctx context.Context, id string) error {
|
||||
q := "DELETE FROM clients AS c WHERE c.id = $1 ;"
|
||||
|
||||
result, err := repo.Repository.DB.ExecContext(ctx, q, id)
|
||||
if err != nil {
|
||||
return postgres.HandleError(repoerr.ErrRemoveEntity, err)
|
||||
}
|
||||
if rows, _ := result.RowsAffected(); rows == 0 {
|
||||
return repoerr.ErrNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type DBClient struct {
|
||||
ID string `db:"id"`
|
||||
Name string `db:"name,omitempty"`
|
||||
Tags pgtype.TextArray `db:"tags,omitempty"`
|
||||
Identity string `db:"identity"`
|
||||
Domain string `db:"domain_id"`
|
||||
Secret string `db:"secret"`
|
||||
Metadata []byte `db:"metadata,omitempty"`
|
||||
CreatedAt time.Time `db:"created_at,omitempty"`
|
||||
UpdatedAt sql.NullTime `db:"updated_at,omitempty"`
|
||||
UpdatedBy *string `db:"updated_by,omitempty"`
|
||||
Groups []groups.Group `db:"groups,omitempty"`
|
||||
Status things.Status `db:"status,omitempty"`
|
||||
}
|
||||
|
||||
func ToDBClient(c things.Client) (DBClient, error) {
|
||||
data := []byte("{}")
|
||||
if len(c.Metadata) > 0 {
|
||||
b, err := json.Marshal(c.Metadata)
|
||||
if err != nil {
|
||||
return DBClient{}, errors.Wrap(repoerr.ErrMalformedEntity, err)
|
||||
}
|
||||
data = b
|
||||
}
|
||||
var tags pgtype.TextArray
|
||||
if err := tags.Set(c.Tags); err != nil {
|
||||
return DBClient{}, err
|
||||
}
|
||||
var updatedBy *string
|
||||
if c.UpdatedBy != "" {
|
||||
updatedBy = &c.UpdatedBy
|
||||
}
|
||||
var updatedAt sql.NullTime
|
||||
if c.UpdatedAt != (time.Time{}) {
|
||||
updatedAt = sql.NullTime{Time: c.UpdatedAt, Valid: true}
|
||||
}
|
||||
|
||||
return DBClient{
|
||||
ID: c.ID,
|
||||
Name: c.Name,
|
||||
Tags: tags,
|
||||
Domain: c.Domain,
|
||||
Identity: c.Credentials.Identity,
|
||||
Secret: c.Credentials.Secret,
|
||||
Metadata: data,
|
||||
CreatedAt: c.CreatedAt,
|
||||
UpdatedAt: updatedAt,
|
||||
UpdatedBy: updatedBy,
|
||||
Status: c.Status,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ToClient(t DBClient) (things.Client, error) {
|
||||
var metadata things.Metadata
|
||||
if t.Metadata != nil {
|
||||
if err := json.Unmarshal([]byte(t.Metadata), &metadata); err != nil {
|
||||
return things.Client{}, errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
}
|
||||
var tags []string
|
||||
for _, e := range t.Tags.Elements {
|
||||
tags = append(tags, e.String)
|
||||
}
|
||||
var updatedBy string
|
||||
if t.UpdatedBy != nil {
|
||||
updatedBy = *t.UpdatedBy
|
||||
}
|
||||
var updatedAt time.Time
|
||||
if t.UpdatedAt.Valid {
|
||||
updatedAt = t.UpdatedAt.Time
|
||||
}
|
||||
|
||||
thg := things.Client{
|
||||
ID: t.ID,
|
||||
Name: t.Name,
|
||||
Tags: tags,
|
||||
Domain: t.Domain,
|
||||
Credentials: things.Credentials{
|
||||
Identity: t.Identity,
|
||||
Secret: t.Secret,
|
||||
},
|
||||
Metadata: metadata,
|
||||
CreatedAt: t.CreatedAt,
|
||||
UpdatedAt: updatedAt,
|
||||
UpdatedBy: updatedBy,
|
||||
Status: t.Status,
|
||||
}
|
||||
return thg, nil
|
||||
}
|
||||
|
||||
func ToDBClientsPage(pm things.Page) (dbClientsPage, error) {
|
||||
_, data, err := postgres.CreateMetadataQuery("", pm.Metadata)
|
||||
if err != nil {
|
||||
return dbClientsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
return dbClientsPage{
|
||||
Name: pm.Name,
|
||||
Identity: pm.Identity,
|
||||
Id: pm.Id,
|
||||
Metadata: data,
|
||||
Domain: pm.Domain,
|
||||
Total: pm.Total,
|
||||
Offset: pm.Offset,
|
||||
Limit: pm.Limit,
|
||||
Status: pm.Status,
|
||||
Tag: pm.Tag,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type dbClientsPage struct {
|
||||
Total uint64 `db:"total"`
|
||||
Limit uint64 `db:"limit"`
|
||||
Offset uint64 `db:"offset"`
|
||||
Name string `db:"name"`
|
||||
Id string `db:"id"`
|
||||
Domain string `db:"domain_id"`
|
||||
Identity string `db:"identity"`
|
||||
Metadata []byte `db:"metadata"`
|
||||
Tag string `db:"tag"`
|
||||
Status things.Status `db:"status"`
|
||||
GroupID string `db:"group_id"`
|
||||
}
|
||||
|
||||
func PageQuery(pm things.Page) (string, error) {
|
||||
mq, _, err := postgres.CreateMetadataQuery("", pm.Metadata)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(errors.ErrMalformedEntity, err)
|
||||
}
|
||||
|
||||
var query []string
|
||||
if pm.Name != "" {
|
||||
query = append(query, "name ILIKE '%' || :name || '%'")
|
||||
}
|
||||
if pm.Identity != "" {
|
||||
query = append(query, "identity ILIKE '%' || :identity || '%'")
|
||||
}
|
||||
if pm.Id != "" {
|
||||
query = append(query, "id ILIKE '%' || :id || '%'")
|
||||
}
|
||||
if pm.Tag != "" {
|
||||
query = append(query, "EXISTS (SELECT 1 FROM unnest(tags) AS tag WHERE tag ILIKE '%' || :tag || '%')")
|
||||
}
|
||||
// If there are search params presents, use search and ignore other options.
|
||||
// Always combine role with search params, so len(query) > 1.
|
||||
if len(query) > 1 {
|
||||
return fmt.Sprintf("WHERE %s", strings.Join(query, " AND ")), nil
|
||||
}
|
||||
|
||||
if mq != "" {
|
||||
query = append(query, mq)
|
||||
}
|
||||
|
||||
if len(pm.IDs) != 0 {
|
||||
query = append(query, fmt.Sprintf("id IN ('%s')", strings.Join(pm.IDs, "','")))
|
||||
}
|
||||
if pm.Status != things.AllStatus {
|
||||
query = append(query, "c.status = :status")
|
||||
}
|
||||
if pm.Domain != "" {
|
||||
query = append(query, "c.domain_id = :domain_id")
|
||||
}
|
||||
var emq string
|
||||
if len(query) > 0 {
|
||||
emq = fmt.Sprintf("WHERE %s", strings.Join(query, " AND "))
|
||||
}
|
||||
return emq, nil
|
||||
}
|
||||
|
||||
func applyOrdering(emq string, pm things.Page) string {
|
||||
switch pm.Order {
|
||||
case "name", "identity", "created_at", "updated_at":
|
||||
emq = fmt.Sprintf("%s ORDER BY %s", emq, pm.Order)
|
||||
if pm.Dir == api.AscDir || pm.Dir == api.DescDir {
|
||||
emq = fmt.Sprintf("%s %s", emq, pm.Dir)
|
||||
}
|
||||
}
|
||||
return emq
|
||||
}
|
||||
|
||||
+185
-123
@@ -11,9 +11,9 @@ import (
|
||||
|
||||
"github.com/0x6flab/namegenerator"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/absmach/magistrala/things/postgres"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -23,10 +23,10 @@ const maxNameSize = 1024
|
||||
|
||||
var (
|
||||
invalidName = strings.Repeat("m", maxNameSize+10)
|
||||
clientIdentity = "client-identity@example.com"
|
||||
clientName = "client name"
|
||||
thingIdentity = "thing-identity@example.com"
|
||||
thingName = "thing name"
|
||||
invalidDomainID = strings.Repeat("m", maxNameSize+10)
|
||||
namesgen = namegenerator.NewGenerator()
|
||||
namegen = namegenerator.NewGenerator()
|
||||
)
|
||||
|
||||
func TestClientsSave(t *testing.T) {
|
||||
@@ -41,254 +41,254 @@ func TestClientsSave(t *testing.T) {
|
||||
secret := testsutil.GenerateUUID(t)
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
clients []clients.Client
|
||||
err error
|
||||
desc string
|
||||
things []things.Client
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "add new client successfully",
|
||||
clients: []clients.Client{
|
||||
desc: "add new thing successfully",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: uid,
|
||||
Domain: domainID,
|
||||
Name: clientName,
|
||||
Credentials: clients.Credentials{
|
||||
Identity: clientIdentity,
|
||||
Name: thingName,
|
||||
Credentials: things.Credentials{
|
||||
Identity: thingIdentity,
|
||||
Secret: secret,
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "add multiple clients successfully",
|
||||
clients: []clients.Client{
|
||||
desc: "add multiple things successfully",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: clients.Credentials{
|
||||
Name: namegen.Generate(),
|
||||
Credentials: things.Credentials{
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: clients.Credentials{
|
||||
Name: namegen.Generate(),
|
||||
Credentials: things.Credentials{
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: clients.Credentials{
|
||||
Name: namegen.Generate(),
|
||||
Credentials: things.Credentials{
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "add new client with duplicate secret",
|
||||
clients: []clients.Client{
|
||||
desc: "add new thing with duplicate secret",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: domainID,
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: clients.Credentials{
|
||||
Identity: clientIdentity,
|
||||
Name: namegen.Generate(),
|
||||
Credentials: things.Credentials{
|
||||
Identity: thingIdentity,
|
||||
Secret: secret,
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: repoerr.ErrCreateEntity,
|
||||
},
|
||||
{
|
||||
desc: "add multiple clients with one client having duplicate secret",
|
||||
clients: []clients.Client{
|
||||
desc: "add multiple things with one thing having duplicate secret",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: clients.Credentials{
|
||||
Name: namegen.Generate(),
|
||||
Credentials: things.Credentials{
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: domainID,
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: clients.Credentials{
|
||||
Identity: clientIdentity,
|
||||
Name: namegen.Generate(),
|
||||
Credentials: things.Credentials{
|
||||
Identity: thingIdentity,
|
||||
Secret: secret,
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: repoerr.ErrCreateEntity,
|
||||
},
|
||||
{
|
||||
desc: "add new client without domain id",
|
||||
clients: []clients.Client{
|
||||
desc: "add new thing without domain id",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: clientName,
|
||||
Credentials: clients.Credentials{
|
||||
Identity: "withoutdomain-client@example.com",
|
||||
Name: thingName,
|
||||
Credentials: things.Credentials{
|
||||
Identity: "withoutdomain-thing@example.com",
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "add client with invalid client id",
|
||||
clients: []clients.Client{
|
||||
desc: "add thing with invalid thing id",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: invalidName,
|
||||
Domain: domainID,
|
||||
Name: clientName,
|
||||
Credentials: clients.Credentials{
|
||||
Identity: "invalidid-client@example.com",
|
||||
Name: thingName,
|
||||
Credentials: things.Credentials{
|
||||
Identity: "invalidid-thing@example.com",
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: repoerr.ErrCreateEntity,
|
||||
},
|
||||
{
|
||||
desc: "add multiple clients with one client having invalid client id",
|
||||
clients: []clients.Client{
|
||||
desc: "add multiple things with one thing having invalid thing id",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: clients.Credentials{
|
||||
Name: namegen.Generate(),
|
||||
Credentials: things.Credentials{
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
{
|
||||
ID: invalidName,
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: clients.Credentials{
|
||||
Name: namegen.Generate(),
|
||||
Credentials: things.Credentials{
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: repoerr.ErrCreateEntity,
|
||||
},
|
||||
{
|
||||
desc: "add client with invalid client name",
|
||||
clients: []clients.Client{
|
||||
desc: "add thing with invalid thing name",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: invalidName,
|
||||
Domain: domainID,
|
||||
Credentials: clients.Credentials{
|
||||
Identity: "invalidname-client@example.com",
|
||||
Credentials: things.Credentials{
|
||||
Identity: "invalidname-thing@example.com",
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: repoerr.ErrCreateEntity,
|
||||
},
|
||||
{
|
||||
desc: "add client with invalid client domain id",
|
||||
clients: []clients.Client{
|
||||
desc: "add thing with invalid thing domain id",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: invalidDomainID,
|
||||
Credentials: clients.Credentials{
|
||||
Identity: "invaliddomainid-client@example.com",
|
||||
Credentials: things.Credentials{
|
||||
Identity: "invaliddomainid-thing@example.com",
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: repoerr.ErrCreateEntity,
|
||||
},
|
||||
{
|
||||
desc: "add client with invalid client identity",
|
||||
clients: []clients.Client{
|
||||
desc: "add thing with invalid thing identity",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: clientName,
|
||||
Credentials: clients.Credentials{
|
||||
Name: thingName,
|
||||
Credentials: things.Credentials{
|
||||
Identity: invalidName,
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
},
|
||||
},
|
||||
err: repoerr.ErrCreateEntity,
|
||||
},
|
||||
{
|
||||
desc: "add client with a missing client identity",
|
||||
clients: []clients.Client{
|
||||
desc: "add thing with a missing thing identity",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Name: "missing-client-identity",
|
||||
Credentials: clients.Credentials{
|
||||
Name: "missing-thing-identity",
|
||||
Credentials: things.Credentials{
|
||||
Identity: "",
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Metadata: things.Metadata{},
|
||||
},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "add client with a missing client secret",
|
||||
clients: []clients.Client{
|
||||
desc: "add thing with a missing thing secret",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Domain: testsutil.GenerateUUID(t),
|
||||
Credentials: clients.Credentials{
|
||||
Identity: "missing-client-secret@example.com",
|
||||
Credentials: things.Credentials{
|
||||
Identity: "missing-thing-secret@example.com",
|
||||
Secret: "",
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Metadata: things.Metadata{},
|
||||
},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "add a client with invalid metadata",
|
||||
clients: []clients.Client{
|
||||
desc: "add a thing with invalid metadata",
|
||||
things: []things.Client{
|
||||
{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: namesgen.Generate(),
|
||||
Credentials: clients.Credentials{
|
||||
Identity: fmt.Sprintf("%s@example.com", namesgen.Generate()),
|
||||
Name: namegen.Generate(),
|
||||
Credentials: things.Credentials{
|
||||
Identity: fmt.Sprintf("%s@example.com", namegen.Generate()),
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: map[string]interface{}{
|
||||
@@ -300,60 +300,60 @@ func TestClientsSave(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
rClients, err := repo.Save(context.Background(), tc.clients...)
|
||||
rThings, err := repo.Save(context.Background(), tc.things...)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
if err == nil {
|
||||
for i := range rClients {
|
||||
tc.clients[i].Credentials.Secret = rClients[i].Credentials.Secret
|
||||
for i := range rThings {
|
||||
tc.things[i].Credentials.Secret = rThings[i].Credentials.Secret
|
||||
}
|
||||
assert.Equal(t, tc.clients, rClients, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.clients, rClients))
|
||||
assert.Equal(t, tc.things, rThings, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.things, rThings))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClientsRetrieveBySecret(t *testing.T) {
|
||||
func TestThingsRetrieveBySecret(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
_, err := db.Exec("DELETE FROM clients")
|
||||
require.Nil(t, err, fmt.Sprintf("clean clients unexpected error: %s", err))
|
||||
})
|
||||
repo := postgres.NewRepository(database)
|
||||
|
||||
client := clients.Client{
|
||||
thing := things.Client{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: clientName,
|
||||
Credentials: clients.Credentials{
|
||||
Identity: clientIdentity,
|
||||
Name: thingName,
|
||||
Credentials: things.Credentials{
|
||||
Identity: thingIdentity,
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: clients.Metadata{},
|
||||
Status: clients.EnabledStatus,
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
}
|
||||
|
||||
_, err := repo.Save(context.Background(), client)
|
||||
_, err := repo.Save(context.Background(), thing)
|
||||
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
secret string
|
||||
response clients.Client
|
||||
response things.Client
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "retrieve client by secret successfully",
|
||||
secret: client.Credentials.Secret,
|
||||
response: client,
|
||||
desc: "retrieve thing by secret successfully",
|
||||
secret: thing.Credentials.Secret,
|
||||
response: thing,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "retrieve client by invalid secret",
|
||||
desc: "retrieve thing by invalid secret",
|
||||
secret: "non-existent-secret",
|
||||
response: clients.Client{},
|
||||
response: things.Client{},
|
||||
err: repoerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "retrieve client by empty secret",
|
||||
desc: "retrieve thing by empty secret",
|
||||
secret: "",
|
||||
response: clients.Client{},
|
||||
response: things.Client{},
|
||||
err: repoerr.ErrNotFound,
|
||||
},
|
||||
}
|
||||
@@ -364,3 +364,65 @@ func TestClientsRetrieveBySecret(t *testing.T) {
|
||||
assert.Equal(t, res, tc.response, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.response, res))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRetrieveByID(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
_, err := db.Exec("DELETE FROM clients")
|
||||
require.Nil(t, err, fmt.Sprintf("clean clients unexpected error: %s", err))
|
||||
})
|
||||
repo := postgres.NewRepository(database)
|
||||
|
||||
thing := things.Client{
|
||||
ID: testsutil.GenerateUUID(t),
|
||||
Name: thingName,
|
||||
Credentials: things.Credentials{
|
||||
Identity: thingIdentity,
|
||||
Secret: testsutil.GenerateUUID(t),
|
||||
},
|
||||
Metadata: things.Metadata{},
|
||||
Status: things.EnabledStatus,
|
||||
}
|
||||
|
||||
_, err := repo.Save(context.Background(), thing)
|
||||
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
id string
|
||||
response things.Client
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "successfully",
|
||||
id: thing.ID,
|
||||
response: thing,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "with invalid id",
|
||||
id: testsutil.GenerateUUID(t),
|
||||
response: things.Client{},
|
||||
err: repoerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "with empty id",
|
||||
id: "",
|
||||
response: things.Client{},
|
||||
err: repoerr.ErrNotFound,
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
cli, err := repo.RetrieveByID(context.Background(), c.id)
|
||||
assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected %s got %s\n", c.err, err))
|
||||
if err == nil {
|
||||
assert.Equal(t, thing.ID, cli.ID)
|
||||
assert.Equal(t, thing.Name, cli.Name)
|
||||
assert.Equal(t, thing.Metadata, cli.Metadata)
|
||||
assert.Equal(t, thing.Credentials.Identity, cli.Credentials.Identity)
|
||||
assert.Equal(t, thing.Credentials.Secret, cli.Credentials.Secret)
|
||||
assert.Equal(t, thing.Status, cli.Status)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clients
|
||||
package things
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -1,40 +1,40 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clients_test
|
||||
package things_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRoleString(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
role clients.Role
|
||||
role things.Role
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
desc: "User",
|
||||
role: clients.UserRole,
|
||||
role: things.UserRole,
|
||||
expected: "user",
|
||||
},
|
||||
{
|
||||
desc: "Admin",
|
||||
role: clients.AdminRole,
|
||||
role: things.AdminRole,
|
||||
expected: "admin",
|
||||
},
|
||||
{
|
||||
desc: "All",
|
||||
role: clients.AllRole,
|
||||
role: things.AllRole,
|
||||
expected: "all",
|
||||
},
|
||||
{
|
||||
desc: "Unknown",
|
||||
role: clients.Role(100),
|
||||
role: things.Role(100),
|
||||
expected: "unknown",
|
||||
},
|
||||
}
|
||||
@@ -51,38 +51,38 @@ func TestToRole(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
role string
|
||||
expected clients.Role
|
||||
expected things.Role
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "User",
|
||||
role: "user",
|
||||
expected: clients.UserRole,
|
||||
expected: things.UserRole,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Admin",
|
||||
role: "admin",
|
||||
expected: clients.AdminRole,
|
||||
expected: things.AdminRole,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "All",
|
||||
role: "all",
|
||||
expected: clients.AllRole,
|
||||
expected: things.AllRole,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Unknown",
|
||||
role: "unknown",
|
||||
expected: clients.Role(0),
|
||||
expected: things.Role(0),
|
||||
err: apiutil.ErrInvalidRole,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
got, err := clients.ToRole(c.role)
|
||||
got, err := things.ToRole(c.role)
|
||||
assert.Equal(t, c.err, err, "ToRole() error = %v, expected %v", err, c.err)
|
||||
assert.Equal(t, c.expected, got, "ToRole() = %v, expected %v", got, c.expected)
|
||||
})
|
||||
@@ -93,31 +93,31 @@ func TestRoleMarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
expected []byte
|
||||
role clients.Role
|
||||
role things.Role
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "User",
|
||||
expected: []byte(`"user"`),
|
||||
role: clients.UserRole,
|
||||
role: things.UserRole,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Admin",
|
||||
expected: []byte(`"admin"`),
|
||||
role: clients.AdminRole,
|
||||
role: things.AdminRole,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "All",
|
||||
expected: []byte(`"all"`),
|
||||
role: clients.AllRole,
|
||||
role: things.AllRole,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Unknown",
|
||||
expected: []byte(`"unknown"`),
|
||||
role: clients.Role(100),
|
||||
role: things.Role(100),
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
@@ -134,31 +134,31 @@ func TestRoleMarshalJSON(t *testing.T) {
|
||||
func TestRoleUnmarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
expected clients.Role
|
||||
expected things.Role
|
||||
role []byte
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "User",
|
||||
expected: clients.UserRole,
|
||||
expected: things.UserRole,
|
||||
role: []byte(`"user"`),
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Admin",
|
||||
expected: clients.AdminRole,
|
||||
expected: things.AdminRole,
|
||||
role: []byte(`"admin"`),
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "All",
|
||||
expected: clients.AllRole,
|
||||
expected: things.AllRole,
|
||||
role: []byte(`"all"`),
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Unknown",
|
||||
expected: clients.Role(0),
|
||||
expected: things.Role(0),
|
||||
role: []byte(`"unknown"`),
|
||||
err: apiutil.ErrInvalidRole,
|
||||
},
|
||||
@@ -166,7 +166,7 @@ func TestRoleUnmarshalJSON(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
var r clients.Role
|
||||
var r things.Role
|
||||
err := r.UnmarshalJSON(tc.role)
|
||||
assert.Equal(t, tc.err, err, "UnmarshalJSON() error = %v, expected %v", err, tc.err)
|
||||
assert.Equal(t, tc.expected, r, "UnmarshalJSON() = %v, expected %v", r, tc.expected)
|
||||
+79
-84
@@ -9,38 +9,33 @@ import (
|
||||
"github.com/absmach/magistrala"
|
||||
mgauth "github.com/absmach/magistrala/auth"
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
mggroups "github.com/absmach/magistrala/pkg/groups"
|
||||
"github.com/absmach/magistrala/pkg/policies"
|
||||
"github.com/absmach/magistrala/things/postgres"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type service struct {
|
||||
evaluator policies.Evaluator
|
||||
policysvc policies.Service
|
||||
clients postgres.Repository
|
||||
clients Repository
|
||||
clientCache Cache
|
||||
idProvider magistrala.IDProvider
|
||||
grepo mggroups.Repository
|
||||
}
|
||||
|
||||
// NewService returns a new Clients service implementation.
|
||||
func NewService(policyEvaluator policies.Evaluator, policyService policies.Service, c postgres.Repository, grepo mggroups.Repository, tcache Cache, idp magistrala.IDProvider) Service {
|
||||
// NewService returns a new Things service implementation.
|
||||
func NewService(policyEvaluator policies.Evaluator, policyService policies.Service, c Repository, tcache Cache, idp magistrala.IDProvider) Service {
|
||||
return service{
|
||||
evaluator: policyEvaluator,
|
||||
policysvc: policyService,
|
||||
clients: c,
|
||||
grepo: grepo,
|
||||
clientCache: tcache,
|
||||
idProvider: idp,
|
||||
}
|
||||
}
|
||||
|
||||
func (svc service) Authorize(ctx context.Context, req AuthzReq) (string, error) {
|
||||
thingID, err := svc.Identify(ctx, req.ThingKey)
|
||||
clientID, err := svc.Identify(ctx, req.ClientKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -49,7 +44,7 @@ func (svc service) Authorize(ctx context.Context, req AuthzReq) (string, error)
|
||||
SubjectType: policies.GroupType,
|
||||
Subject: req.ChannelID,
|
||||
ObjectType: policies.ThingType,
|
||||
Object: thingID,
|
||||
Object: clientID,
|
||||
Permission: req.Permission,
|
||||
}
|
||||
err = svc.evaluator.CheckPolicy(ctx, r)
|
||||
@@ -57,41 +52,41 @@ func (svc service) Authorize(ctx context.Context, req AuthzReq) (string, error)
|
||||
return "", errors.Wrap(svcerr.ErrAuthorization, err)
|
||||
}
|
||||
|
||||
return thingID, nil
|
||||
return clientID, nil
|
||||
}
|
||||
|
||||
func (svc service) CreateThings(ctx context.Context, session authn.Session, cls ...mgclients.Client) ([]mgclients.Client, error) {
|
||||
var clients []mgclients.Client
|
||||
for _, c := range cls {
|
||||
func (svc service) CreateClients(ctx context.Context, session authn.Session, cli ...Client) ([]Client, error) {
|
||||
var clients []Client
|
||||
for _, c := range cli {
|
||||
if c.ID == "" {
|
||||
clientID, err := svc.idProvider.ID()
|
||||
if err != nil {
|
||||
return []mgclients.Client{}, err
|
||||
return []Client{}, err
|
||||
}
|
||||
c.ID = clientID
|
||||
}
|
||||
if c.Credentials.Secret == "" {
|
||||
key, err := svc.idProvider.ID()
|
||||
if err != nil {
|
||||
return []mgclients.Client{}, err
|
||||
return []Client{}, err
|
||||
}
|
||||
c.Credentials.Secret = key
|
||||
}
|
||||
if c.Status != mgclients.DisabledStatus && c.Status != mgclients.EnabledStatus {
|
||||
return []mgclients.Client{}, svcerr.ErrInvalidStatus
|
||||
if c.Status != DisabledStatus && c.Status != EnabledStatus {
|
||||
return []Client{}, svcerr.ErrInvalidStatus
|
||||
}
|
||||
c.Domain = session.DomainID
|
||||
c.CreatedAt = time.Now()
|
||||
clients = append(clients, c)
|
||||
}
|
||||
|
||||
err := svc.addThingPolicies(ctx, session.DomainUserID, session.DomainID, clients)
|
||||
err := svc.addClientPolicies(ctx, session.DomainUserID, session.DomainID, clients)
|
||||
if err != nil {
|
||||
return []mgclients.Client{}, err
|
||||
return []Client{}, err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if errRollback := svc.addThingPoliciesRollback(ctx, session.DomainUserID, session.DomainID, clients); errRollback != nil {
|
||||
if errRollback := svc.addClientPoliciesRollback(ctx, session.DomainUserID, session.DomainID, clients); errRollback != nil {
|
||||
err = errors.Wrap(errors.Wrap(errors.ErrRollbackTx, errRollback), err)
|
||||
}
|
||||
}
|
||||
@@ -105,16 +100,16 @@ func (svc service) CreateThings(ctx context.Context, session authn.Session, cls
|
||||
return saved, nil
|
||||
}
|
||||
|
||||
func (svc service) ViewClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
func (svc service) View(ctx context.Context, session authn.Session, id string) (Client, error) {
|
||||
client, err := svc.clients.RetrieveByID(ctx, id)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
return Client{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (svc service) ViewClientPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
permissions, err := svc.listUserThingPermission(ctx, session.DomainUserID, id)
|
||||
func (svc service) ViewPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
permissions, err := svc.listUserClientPermission(ctx, session.DomainUserID, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -124,18 +119,18 @@ func (svc service) ViewClientPerms(ctx context.Context, session authn.Session, i
|
||||
return permissions, nil
|
||||
}
|
||||
|
||||
func (svc service) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm mgclients.Page) (mgclients.ClientsPage, error) {
|
||||
func (svc service) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm Page) (ClientsPage, error) {
|
||||
var ids []string
|
||||
var err error
|
||||
switch {
|
||||
case (reqUserID != "" && reqUserID != session.UserID):
|
||||
rtids, err := svc.listClientIDs(ctx, mgauth.EncodeDomainUserID(session.DomainID, reqUserID), pm.Permission)
|
||||
if err != nil {
|
||||
return mgclients.ClientsPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
return ClientsPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
}
|
||||
ids, err = svc.filterAllowedThingIDs(ctx, session.DomainUserID, pm.Permission, rtids)
|
||||
ids, err = svc.filterAllowedClientIDs(ctx, session.DomainUserID, pm.Permission, rtids)
|
||||
if err != nil {
|
||||
return mgclients.ClientsPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
return ClientsPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
}
|
||||
default:
|
||||
switch session.SuperAdmin {
|
||||
@@ -144,18 +139,18 @@ func (svc service) ListClients(ctx context.Context, session authn.Session, reqUs
|
||||
default:
|
||||
ids, err = svc.listClientIDs(ctx, session.DomainUserID, pm.Permission)
|
||||
if err != nil {
|
||||
return mgclients.ClientsPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
return ClientsPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(ids) == 0 && pm.Domain == "" {
|
||||
return mgclients.ClientsPage{}, nil
|
||||
return ClientsPage{}, nil
|
||||
}
|
||||
pm.IDs = ids
|
||||
tp, err := svc.clients.SearchClients(ctx, pm)
|
||||
if err != nil {
|
||||
return mgclients.ClientsPage{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
return ClientsPage{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
if pm.ListPerms && len(tp.Clients) > 0 {
|
||||
@@ -170,15 +165,15 @@ func (svc service) ListClients(ctx context.Context, session authn.Session, reqUs
|
||||
}
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
return mgclients.ClientsPage{}, err
|
||||
return ClientsPage{}, err
|
||||
}
|
||||
}
|
||||
return tp, nil
|
||||
}
|
||||
|
||||
// Experimental functions used for async calling of svc.listUserThingPermission. This might be helpful during listing of large number of entities.
|
||||
func (svc service) retrievePermissions(ctx context.Context, userID string, client *mgclients.Client) error {
|
||||
permissions, err := svc.listUserThingPermission(ctx, userID, client.ID)
|
||||
// Experimental functions used for async calling of svc.listUserClientPermission. This might be helpful during listing of large number of entities.
|
||||
func (svc service) retrievePermissions(ctx context.Context, userID string, client *Client) error {
|
||||
permissions, err := svc.listUserClientPermission(ctx, userID, client.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -186,11 +181,11 @@ func (svc service) retrievePermissions(ctx context.Context, userID string, clien
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc service) listUserThingPermission(ctx context.Context, userID, thingID string) ([]string, error) {
|
||||
func (svc service) listUserClientPermission(ctx context.Context, userID, clientID string) ([]string, error) {
|
||||
permissions, err := svc.policysvc.ListPermissions(ctx, policies.Policy{
|
||||
SubjectType: policies.UserType,
|
||||
Subject: userID,
|
||||
Object: thingID,
|
||||
Object: clientID,
|
||||
ObjectType: policies.ThingType,
|
||||
}, []string{})
|
||||
if err != nil {
|
||||
@@ -212,7 +207,7 @@ func (svc service) listClientIDs(ctx context.Context, userID, permission string)
|
||||
return tids.Policies, nil
|
||||
}
|
||||
|
||||
func (svc service) filterAllowedThingIDs(ctx context.Context, userID, permission string, thingIDs []string) ([]string, error) {
|
||||
func (svc service) filterAllowedClientIDs(ctx context.Context, userID, permission string, clientIDs []string) ([]string, error) {
|
||||
var ids []string
|
||||
tids, err := svc.policysvc.ListAllObjects(ctx, policies.Policy{
|
||||
SubjectType: policies.UserType,
|
||||
@@ -223,85 +218,85 @@ func (svc service) filterAllowedThingIDs(ctx context.Context, userID, permission
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
}
|
||||
for _, thingID := range thingIDs {
|
||||
for _, clientID := range clientIDs {
|
||||
for _, tid := range tids.Policies {
|
||||
if thingID == tid {
|
||||
ids = append(ids, thingID)
|
||||
if clientID == tid {
|
||||
ids = append(ids, clientID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func (svc service) UpdateClient(ctx context.Context, session authn.Session, cli mgclients.Client) (mgclients.Client, error) {
|
||||
client := mgclients.Client{
|
||||
ID: cli.ID,
|
||||
Name: cli.Name,
|
||||
Metadata: cli.Metadata,
|
||||
func (svc service) Update(ctx context.Context, session authn.Session, thi Client) (Client, error) {
|
||||
client := Client{
|
||||
ID: thi.ID,
|
||||
Name: thi.Name,
|
||||
Metadata: thi.Metadata,
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedBy: session.UserID,
|
||||
}
|
||||
client, err := svc.clients.Update(ctx, client)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
return Client{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (svc service) UpdateClientTags(ctx context.Context, session authn.Session, cli mgclients.Client) (mgclients.Client, error) {
|
||||
client := mgclients.Client{
|
||||
ID: cli.ID,
|
||||
Tags: cli.Tags,
|
||||
func (svc service) UpdateTags(ctx context.Context, session authn.Session, thi Client) (Client, error) {
|
||||
client := Client{
|
||||
ID: thi.ID,
|
||||
Tags: thi.Tags,
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedBy: session.UserID,
|
||||
}
|
||||
client, err := svc.clients.UpdateTags(ctx, client)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
return Client{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (svc service) UpdateClientSecret(ctx context.Context, session authn.Session, id, key string) (mgclients.Client, error) {
|
||||
client := mgclients.Client{
|
||||
func (svc service) UpdateSecret(ctx context.Context, session authn.Session, id, key string) (Client, error) {
|
||||
client := Client{
|
||||
ID: id,
|
||||
Credentials: mgclients.Credentials{
|
||||
Credentials: Credentials{
|
||||
Secret: key,
|
||||
},
|
||||
UpdatedAt: time.Now(),
|
||||
UpdatedBy: session.UserID,
|
||||
Status: mgclients.EnabledStatus,
|
||||
Status: EnabledStatus,
|
||||
}
|
||||
client, err := svc.clients.UpdateSecret(ctx, client)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
return Client{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (svc service) EnableClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
client := mgclients.Client{
|
||||
func (svc service) Enable(ctx context.Context, session authn.Session, id string) (Client, error) {
|
||||
client := Client{
|
||||
ID: id,
|
||||
Status: mgclients.EnabledStatus,
|
||||
Status: EnabledStatus,
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
client, err := svc.changeClientStatus(ctx, session, client)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, errors.Wrap(mgclients.ErrEnableClient, err)
|
||||
return Client{}, errors.Wrap(ErrEnableClient, err)
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (svc service) DisableClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
client := mgclients.Client{
|
||||
func (svc service) Disable(ctx context.Context, session authn.Session, id string) (Client, error) {
|
||||
client := Client{
|
||||
ID: id,
|
||||
Status: mgclients.DisabledStatus,
|
||||
Status: DisabledStatus,
|
||||
UpdatedAt: time.Now(),
|
||||
}
|
||||
client, err := svc.changeClientStatus(ctx, session, client)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, errors.Wrap(mgclients.ErrDisableClient, err)
|
||||
return Client{}, errors.Wrap(ErrDisableClient, err)
|
||||
}
|
||||
|
||||
if err := svc.clientCache.Remove(ctx, client.ID); err != nil {
|
||||
@@ -347,7 +342,7 @@ func (svc service) Unshare(ctx context.Context, session authn.Session, id, relat
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc service) DeleteClient(ctx context.Context, session authn.Session, id string) error {
|
||||
func (svc service) Delete(ctx context.Context, session authn.Session, id string) error {
|
||||
if err := svc.clientCache.Remove(ctx, id); err != nil {
|
||||
return errors.Wrap(svcerr.ErrRemoveEntity, err)
|
||||
}
|
||||
@@ -368,25 +363,25 @@ func (svc service) DeleteClient(ctx context.Context, session authn.Session, id s
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc service) changeClientStatus(ctx context.Context, session authn.Session, client mgclients.Client) (mgclients.Client, error) {
|
||||
func (svc service) changeClientStatus(ctx context.Context, session authn.Session, client Client) (Client, error) {
|
||||
dbClient, err := svc.clients.RetrieveByID(ctx, client.ID)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
return Client{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
}
|
||||
if dbClient.Status == client.Status {
|
||||
return mgclients.Client{}, errors.ErrStatusAlreadyAssigned
|
||||
return Client{}, errors.ErrStatusAlreadyAssigned
|
||||
}
|
||||
|
||||
client.UpdatedBy = session.UserID
|
||||
|
||||
client, err = svc.clients.ChangeStatus(ctx, client)
|
||||
if err != nil {
|
||||
return mgclients.Client{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
return Client{}, errors.Wrap(svcerr.ErrUpdateEntity, err)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (svc service) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm mgclients.Page) (mgclients.MembersPage, error) {
|
||||
func (svc service) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm Page) (MembersPage, error) {
|
||||
tids, err := svc.policysvc.ListAllObjects(ctx, policies.Policy{
|
||||
SubjectType: policies.GroupType,
|
||||
Subject: groupID,
|
||||
@@ -394,14 +389,14 @@ func (svc service) ListClientsByGroup(ctx context.Context, session authn.Session
|
||||
ObjectType: policies.ThingType,
|
||||
})
|
||||
if err != nil {
|
||||
return mgclients.MembersPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
return MembersPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
}
|
||||
|
||||
pm.IDs = tids.Policies
|
||||
|
||||
cp, err := svc.clients.RetrieveAllByIDs(ctx, pm)
|
||||
if err != nil {
|
||||
return mgclients.MembersPage{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
return MembersPage{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
if pm.ListPerms && len(cp.Clients) > 0 {
|
||||
@@ -416,11 +411,11 @@ func (svc service) ListClientsByGroup(ctx context.Context, session authn.Session
|
||||
}
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
return mgclients.MembersPage{}, err
|
||||
return MembersPage{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return mgclients.MembersPage{
|
||||
return MembersPage{
|
||||
Page: cp.Page,
|
||||
Members: cp.Clients,
|
||||
}, nil
|
||||
@@ -443,9 +438,9 @@ func (svc service) Identify(ctx context.Context, key string) (string, error) {
|
||||
return client.ID, nil
|
||||
}
|
||||
|
||||
func (svc service) addThingPolicies(ctx context.Context, userID, domainID string, things []mgclients.Client) error {
|
||||
func (svc service) addClientPolicies(ctx context.Context, userID, domainID string, clients []Client) error {
|
||||
policyList := []policies.Policy{}
|
||||
for _, thing := range things {
|
||||
for _, client := range clients {
|
||||
policyList = append(policyList, policies.Policy{
|
||||
Domain: domainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -453,7 +448,7 @@ func (svc service) addThingPolicies(ctx context.Context, userID, domainID string
|
||||
Relation: policies.AdministratorRelation,
|
||||
ObjectKind: policies.NewThingKind,
|
||||
ObjectType: policies.ThingType,
|
||||
Object: thing.ID,
|
||||
Object: client.ID,
|
||||
})
|
||||
policyList = append(policyList, policies.Policy{
|
||||
Domain: domainID,
|
||||
@@ -461,7 +456,7 @@ func (svc service) addThingPolicies(ctx context.Context, userID, domainID string
|
||||
Subject: domainID,
|
||||
Relation: policies.DomainRelation,
|
||||
ObjectType: policies.ThingType,
|
||||
Object: thing.ID,
|
||||
Object: client.ID,
|
||||
})
|
||||
}
|
||||
if err := svc.policysvc.AddPolicies(ctx, policyList); err != nil {
|
||||
@@ -471,9 +466,9 @@ func (svc service) addThingPolicies(ctx context.Context, userID, domainID string
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc service) addThingPoliciesRollback(ctx context.Context, userID, domainID string, things []mgclients.Client) error {
|
||||
func (svc service) addClientPoliciesRollback(ctx context.Context, userID, domainID string, clients []Client) error {
|
||||
policyList := []policies.Policy{}
|
||||
for _, thing := range things {
|
||||
for _, client := range clients {
|
||||
policyList = append(policyList, policies.Policy{
|
||||
Domain: domainID,
|
||||
SubjectType: policies.UserType,
|
||||
@@ -481,7 +476,7 @@ func (svc service) addThingPoliciesRollback(ctx context.Context, userID, domainI
|
||||
Relation: policies.AdministratorRelation,
|
||||
ObjectKind: policies.NewThingKind,
|
||||
ObjectType: policies.ThingType,
|
||||
Object: thing.ID,
|
||||
Object: client.ID,
|
||||
})
|
||||
policyList = append(policyList, policies.Policy{
|
||||
Domain: domainID,
|
||||
@@ -489,7 +484,7 @@ func (svc service) addThingPoliciesRollback(ctx context.Context, userID, domainI
|
||||
Subject: domainID,
|
||||
Relation: policies.DomainRelation,
|
||||
ObjectType: policies.ThingType,
|
||||
Object: thing.ID,
|
||||
Object: client.ID,
|
||||
})
|
||||
}
|
||||
if err := svc.policysvc.DeletePolicies(ctx, policyList); err != nil {
|
||||
|
||||
+324
-327
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clients
|
||||
package things
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
@@ -54,7 +54,7 @@ func (s Status) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
// ToStatus converts string value to a valid Client/Group status.
|
||||
// ToStatus converts string value to a valid Client status.
|
||||
func ToStatus(status string) (Status, error) {
|
||||
switch status {
|
||||
case "", Enabled:
|
||||
@@ -69,7 +69,7 @@ func ToStatus(status string) (Status, error) {
|
||||
return Status(0), svcerr.ErrInvalidStatus
|
||||
}
|
||||
|
||||
// Custom Marshaller for Client/Groups.
|
||||
// Custom Marshaller for Client.
|
||||
func (s Status) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(s.String())
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func (client Client) MarshalJSON() ([]byte, error) {
|
||||
})
|
||||
}
|
||||
|
||||
// Custom Unmarshaler for Client/Groups.
|
||||
// Custom Unmarshaler for Client.
|
||||
func (s *Status) UnmarshalJSON(data []byte) error {
|
||||
str := strings.Trim(string(data), "\"")
|
||||
val, err := ToStatus(str)
|
||||
@@ -1,45 +1,45 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package clients_test
|
||||
package things_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStatusString(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
status clients.Status
|
||||
status things.Status
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
desc: "Enabled",
|
||||
status: clients.EnabledStatus,
|
||||
status: things.EnabledStatus,
|
||||
expected: "enabled",
|
||||
},
|
||||
{
|
||||
desc: "Disabled",
|
||||
status: clients.DisabledStatus,
|
||||
status: things.DisabledStatus,
|
||||
expected: "disabled",
|
||||
},
|
||||
{
|
||||
desc: "Deleted",
|
||||
status: clients.DeletedStatus,
|
||||
status: things.DeletedStatus,
|
||||
expected: "deleted",
|
||||
},
|
||||
{
|
||||
desc: "All",
|
||||
status: clients.AllStatus,
|
||||
status: things.AllStatus,
|
||||
expected: "all",
|
||||
},
|
||||
{
|
||||
desc: "Unknown",
|
||||
status: clients.Status(100),
|
||||
status: things.Status(100),
|
||||
expected: "unknown",
|
||||
},
|
||||
}
|
||||
@@ -56,44 +56,44 @@ func TestToStatus(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
status string
|
||||
expetcted clients.Status
|
||||
expetcted things.Status
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "Enabled",
|
||||
status: "enabled",
|
||||
expetcted: clients.EnabledStatus,
|
||||
expetcted: things.EnabledStatus,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Disabled",
|
||||
status: "disabled",
|
||||
expetcted: clients.DisabledStatus,
|
||||
expetcted: things.DisabledStatus,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Deleted",
|
||||
status: "deleted",
|
||||
expetcted: clients.DeletedStatus,
|
||||
expetcted: things.DeletedStatus,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "All",
|
||||
status: "all",
|
||||
expetcted: clients.AllStatus,
|
||||
expetcted: things.AllStatus,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Unknown",
|
||||
status: "unknown",
|
||||
expetcted: clients.Status(0),
|
||||
expetcted: things.Status(0),
|
||||
err: svcerr.ErrInvalidStatus,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
got, err := clients.ToStatus(tc.status)
|
||||
got, err := things.ToStatus(tc.status)
|
||||
assert.Equal(t, tc.err, err, "ToStatus() error = %v, expected %v", err, tc.err)
|
||||
assert.Equal(t, tc.expetcted, got, "ToStatus() = %v, expected %v", got, tc.expetcted)
|
||||
})
|
||||
@@ -104,37 +104,37 @@ func TestStatusMarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
expected []byte
|
||||
status clients.Status
|
||||
status things.Status
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "Enabled",
|
||||
expected: []byte(`"enabled"`),
|
||||
status: clients.EnabledStatus,
|
||||
status: things.EnabledStatus,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Disabled",
|
||||
expected: []byte(`"disabled"`),
|
||||
status: clients.DisabledStatus,
|
||||
status: things.DisabledStatus,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Deleted",
|
||||
expected: []byte(`"deleted"`),
|
||||
status: clients.DeletedStatus,
|
||||
status: things.DeletedStatus,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "All",
|
||||
expected: []byte(`"all"`),
|
||||
status: clients.AllStatus,
|
||||
status: things.AllStatus,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Unknown",
|
||||
expected: []byte(`"unknown"`),
|
||||
status: clients.Status(100),
|
||||
status: things.Status(100),
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
@@ -151,37 +151,37 @@ func TestStatusMarshalJSON(t *testing.T) {
|
||||
func TestStatusUnmarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
expected clients.Status
|
||||
expected things.Status
|
||||
status []byte
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "Enabled",
|
||||
expected: clients.EnabledStatus,
|
||||
expected: things.EnabledStatus,
|
||||
status: []byte(`"enabled"`),
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Disabled",
|
||||
expected: clients.DisabledStatus,
|
||||
expected: things.DisabledStatus,
|
||||
status: []byte(`"disabled"`),
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Deleted",
|
||||
expected: clients.DeletedStatus,
|
||||
expected: things.DeletedStatus,
|
||||
status: []byte(`"deleted"`),
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "All",
|
||||
expected: clients.AllStatus,
|
||||
expected: things.AllStatus,
|
||||
status: []byte(`"all"`),
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Unknown",
|
||||
expected: clients.Status(0),
|
||||
expected: things.Status(0),
|
||||
status: []byte(`"unknown"`),
|
||||
err: svcerr.ErrInvalidStatus,
|
||||
},
|
||||
@@ -189,7 +189,7 @@ func TestStatusUnmarshalJSON(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
var s clients.Status
|
||||
var s things.Status
|
||||
err := s.UnmarshalJSON(tc.status)
|
||||
assert.Equal(t, tc.err, err, "UnmarshalJSON() error = %v, expected %v", err, tc.err)
|
||||
assert.Equal(t, tc.expected, s, "UnmarshalJSON() = %v, expected %v", s, tc.expected)
|
||||
@@ -201,37 +201,37 @@ func TestUserMarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
expected []byte
|
||||
user clients.Client
|
||||
user things.Client
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "Enabled",
|
||||
expected: []byte(`{"id":"","credentials":{},"created_at":"0001-01-01T00:00:00Z","updated_at":"0001-01-01T00:00:00Z","status":"enabled"}`),
|
||||
user: clients.Client{Status: clients.EnabledStatus},
|
||||
user: things.Client{Status: things.EnabledStatus},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Disabled",
|
||||
expected: []byte(`{"id":"","credentials":{},"created_at":"0001-01-01T00:00:00Z","updated_at":"0001-01-01T00:00:00Z","status":"disabled"}`),
|
||||
user: clients.Client{Status: clients.DisabledStatus},
|
||||
user: things.Client{Status: things.DisabledStatus},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Deleted",
|
||||
expected: []byte(`{"id":"","credentials":{},"created_at":"0001-01-01T00:00:00Z","updated_at":"0001-01-01T00:00:00Z","status":"deleted"}`),
|
||||
user: clients.Client{Status: clients.DeletedStatus},
|
||||
user: things.Client{Status: things.DeletedStatus},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "All",
|
||||
expected: []byte(`{"id":"","credentials":{},"created_at":"0001-01-01T00:00:00Z","updated_at":"0001-01-01T00:00:00Z","status":"all"}`),
|
||||
user: clients.Client{Status: clients.AllStatus},
|
||||
user: things.Client{Status: things.AllStatus},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "Unknown",
|
||||
expected: []byte(`{"id":"","credentials":{},"created_at":"0001-01-01T00:00:00Z","updated_at":"0001-01-01T00:00:00Z","status":"unknown"}`),
|
||||
user: clients.Client{Status: clients.Status(100)},
|
||||
user: things.Client{Status: things.Status(100)},
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package things
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/clients"
|
||||
)
|
||||
|
||||
type AuthzReq struct {
|
||||
ChannelID string
|
||||
ThingID string
|
||||
ThingKey string
|
||||
Permission string
|
||||
}
|
||||
|
||||
// Service specifies an API that must be fullfiled by the domain service
|
||||
// implementation, and all of its decorators (e.g. logging & metrics).
|
||||
//
|
||||
//go:generate mockery --name Service --filename service.go --quiet --note "Copyright (c) Abstract Machines"
|
||||
type Service interface {
|
||||
// CreateThings creates new client. In case of the failed registration, a
|
||||
// non-nil error value is returned.
|
||||
CreateThings(ctx context.Context, session authn.Session, client ...clients.Client) ([]clients.Client, error)
|
||||
|
||||
// ViewClient retrieves client info for a given client ID and an authorized token.
|
||||
ViewClient(ctx context.Context, session authn.Session, id string) (clients.Client, error)
|
||||
|
||||
// ViewClientPerms retrieves permissions on the client id for the given authorized token.
|
||||
ViewClientPerms(ctx context.Context, session authn.Session, id string) ([]string, error)
|
||||
|
||||
// ListClients retrieves clients list for a valid auth token.
|
||||
ListClients(ctx context.Context, session authn.Session, reqUserID string, pm clients.Page) (clients.ClientsPage, error)
|
||||
|
||||
// ListClientsByGroup retrieves data about subset of things that are
|
||||
// connected or not connected to specified channel and belong to the user identified by
|
||||
// the provided key.
|
||||
ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm clients.Page) (clients.MembersPage, error)
|
||||
|
||||
// UpdateClient updates the client's name and metadata.
|
||||
UpdateClient(ctx context.Context, session authn.Session, client clients.Client) (clients.Client, error)
|
||||
|
||||
// UpdateClientTags updates the client's tags.
|
||||
UpdateClientTags(ctx context.Context, session authn.Session, client clients.Client) (clients.Client, error)
|
||||
|
||||
// UpdateClientSecret updates the client's secret
|
||||
UpdateClientSecret(ctx context.Context, session authn.Session, id, key string) (clients.Client, error)
|
||||
|
||||
// EnableClient logically enableds the client identified with the provided ID
|
||||
EnableClient(ctx context.Context, session authn.Session, id string) (clients.Client, error)
|
||||
|
||||
// DisableClient logically disables the client identified with the provided ID
|
||||
DisableClient(ctx context.Context, session authn.Session, id string) (clients.Client, error)
|
||||
|
||||
// Share add share policy to thing id with given relation for given user ids
|
||||
Share(ctx context.Context, session authn.Session, id string, relation string, userids ...string) error
|
||||
|
||||
// Unshare remove share policy to thing id with given relation for given user ids
|
||||
Unshare(ctx context.Context, session authn.Session, id string, relation string, userids ...string) error
|
||||
|
||||
// Identify returns thing ID for given thing key.
|
||||
Identify(ctx context.Context, key string) (string, error)
|
||||
|
||||
// Authorize used for Things authorization.
|
||||
Authorize(ctx context.Context, req AuthzReq) (string, error)
|
||||
|
||||
// DeleteClient deletes client with given ID.
|
||||
DeleteClient(ctx context.Context, session authn.Session, id string) error
|
||||
}
|
||||
|
||||
// Cache contains thing caching interface.
|
||||
//
|
||||
//go:generate mockery --name Cache --filename cache.go --quiet --note "Copyright (c) Abstract Machines"
|
||||
type Cache interface {
|
||||
// Save stores pair thing secret, thing id.
|
||||
Save(ctx context.Context, thingSecret, thingID string) error
|
||||
|
||||
// ID returns thing ID for given thing secret.
|
||||
ID(ctx context.Context, thingSecret string) (string, error)
|
||||
|
||||
// Removes thing from cache.
|
||||
Remove(ctx context.Context, thingID string) error
|
||||
}
|
||||
+32
-33
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/things"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
@@ -25,81 +24,81 @@ func New(svc things.Service, tracer trace.Tracer) things.Service {
|
||||
return &tracingMiddleware{tracer, svc}
|
||||
}
|
||||
|
||||
// CreateThings traces the "CreateThings" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) CreateThings(ctx context.Context, session authn.Session, clis ...mgclients.Client) ([]mgclients.Client, error) {
|
||||
// CreateClients traces the "CreateClients" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) CreateClients(ctx context.Context, session authn.Session, cli ...things.Client) ([]things.Client, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_create_client")
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.CreateThings(ctx, session, clis...)
|
||||
return tm.svc.CreateClients(ctx, session, cli...)
|
||||
}
|
||||
|
||||
// ViewClient traces the "ViewClient" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) ViewClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
// View traces the "View" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) View(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_view_client", trace.WithAttributes(attribute.String("id", id)))
|
||||
defer span.End()
|
||||
return tm.svc.ViewClient(ctx, session, id)
|
||||
return tm.svc.View(ctx, session, id)
|
||||
}
|
||||
|
||||
// ViewClientPerms traces the "ViewClientPerms" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) ViewClientPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
// ViewPerms traces the "ViewPerms" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) ViewPerms(ctx context.Context, session authn.Session, id string) ([]string, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_view_client_permissions", trace.WithAttributes(attribute.String("id", id)))
|
||||
defer span.End()
|
||||
return tm.svc.ViewClientPerms(ctx, session, id)
|
||||
return tm.svc.ViewPerms(ctx, session, id)
|
||||
}
|
||||
|
||||
// ListClients traces the "ListClients" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm mgclients.Page) (mgclients.ClientsPage, error) {
|
||||
func (tm *tracingMiddleware) ListClients(ctx context.Context, session authn.Session, reqUserID string, pm things.Page) (things.ClientsPage, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_list_clients")
|
||||
defer span.End()
|
||||
return tm.svc.ListClients(ctx, session, reqUserID, pm)
|
||||
}
|
||||
|
||||
// UpdateClient traces the "UpdateClient" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) UpdateClient(ctx context.Context, session authn.Session, cli mgclients.Client) (mgclients.Client, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_update_client_name_and_metadata", trace.WithAttributes(attribute.String("id", cli.ID)))
|
||||
// Update traces the "Update" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) Update(ctx context.Context, session authn.Session, cli things.Client) (things.Client, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_update_client", trace.WithAttributes(attribute.String("id", cli.ID)))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.UpdateClient(ctx, session, cli)
|
||||
return tm.svc.Update(ctx, session, cli)
|
||||
}
|
||||
|
||||
// UpdateClientTags traces the "UpdateClientTags" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) UpdateClientTags(ctx context.Context, session authn.Session, cli mgclients.Client) (mgclients.Client, error) {
|
||||
// UpdateTags traces the "UpdateTags" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) UpdateTags(ctx context.Context, session authn.Session, cli things.Client) (things.Client, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_update_client_tags", trace.WithAttributes(
|
||||
attribute.String("id", cli.ID),
|
||||
attribute.StringSlice("tags", cli.Tags),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.UpdateClientTags(ctx, session, cli)
|
||||
return tm.svc.UpdateTags(ctx, session, cli)
|
||||
}
|
||||
|
||||
// UpdateClientSecret traces the "UpdateClientSecret" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) UpdateClientSecret(ctx context.Context, session authn.Session, oldSecret, newSecret string) (mgclients.Client, error) {
|
||||
// UpdateSecret traces the "UpdateSecret" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) UpdateSecret(ctx context.Context, session authn.Session, oldSecret, newSecret string) (things.Client, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_update_client_secret")
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.UpdateClientSecret(ctx, session, oldSecret, newSecret)
|
||||
return tm.svc.UpdateSecret(ctx, session, oldSecret, newSecret)
|
||||
}
|
||||
|
||||
// EnableClient traces the "EnableClient" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) EnableClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
// Enable traces the "Enable" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) Enable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_enable_client", trace.WithAttributes(attribute.String("id", id)))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.EnableClient(ctx, session, id)
|
||||
return tm.svc.Enable(ctx, session, id)
|
||||
}
|
||||
|
||||
// DisableClient traces the "DisableClient" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) DisableClient(ctx context.Context, session authn.Session, id string) (mgclients.Client, error) {
|
||||
// Disable traces the "Disable" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) Disable(ctx context.Context, session authn.Session, id string) (things.Client, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_disable_client", trace.WithAttributes(attribute.String("id", id)))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.DisableClient(ctx, session, id)
|
||||
return tm.svc.Disable(ctx, session, id)
|
||||
}
|
||||
|
||||
// ListClientsByGroup traces the "ListClientsByGroup" operation of the wrapped policies.Service.
|
||||
func (tm *tracingMiddleware) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm mgclients.Page) (mgclients.MembersPage, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_list_things_by_channel", trace.WithAttributes(attribute.String("groupID", groupID)))
|
||||
func (tm *tracingMiddleware) ListClientsByGroup(ctx context.Context, session authn.Session, groupID string, pm things.Page) (things.MembersPage, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_list_clients_by_channel", trace.WithAttributes(attribute.String("groupID", groupID)))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.ListClientsByGroup(ctx, session, groupID, pm)
|
||||
@@ -115,7 +114,7 @@ func (tm *tracingMiddleware) Identify(ctx context.Context, key string) (string,
|
||||
|
||||
// Authorize traces the "Authorize" operation of the wrapped things.Service.
|
||||
func (tm *tracingMiddleware) Authorize(ctx context.Context, req things.AuthzReq) (string, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "connect", trace.WithAttributes(attribute.String("thingKey", req.ThingKey), attribute.String("channelID", req.ChannelID)))
|
||||
ctx, span := tm.tracer.Start(ctx, "connect", trace.WithAttributes(attribute.String("thingKey", req.ClientKey), attribute.String("channelID", req.ChannelID)))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.Authorize(ctx, req)
|
||||
@@ -135,9 +134,9 @@ func (tm *tracingMiddleware) Unshare(ctx context.Context, session authn.Session,
|
||||
return tm.svc.Unshare(ctx, session, id, relation, userids...)
|
||||
}
|
||||
|
||||
// DeleteClient traces the "DeleteClient" operation of the wrapped things.Service.
|
||||
func (tm *tracingMiddleware) DeleteClient(ctx context.Context, session authn.Session, id string) error {
|
||||
// Delete traces the "Delete" operation of the wrapped things.Service.
|
||||
func (tm *tracingMiddleware) Delete(ctx context.Context, session authn.Session, id string) error {
|
||||
ctx, span := tm.tracer.Start(ctx, "delete_client", trace.WithAttributes(attribute.String("id", id)))
|
||||
defer span.End()
|
||||
return tm.svc.DeleteClient(ctx, session, id)
|
||||
return tm.svc.Delete(ctx, session, id)
|
||||
}
|
||||
|
||||
+1
-1
@@ -249,7 +249,7 @@ func decodeViewProfile(_ context.Context, r *http.Request) (interface{}, error)
|
||||
}
|
||||
|
||||
func decodeListUsers(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefClientStatus)
|
||||
s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefUserStatus)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package users
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
// ErrEnableClient indicates error in enabling client.
|
||||
ErrEnableClient = errors.New("failed to enable client")
|
||||
|
||||
// ErrDisableClient indicates error in disabling client.
|
||||
ErrDisableClient = errors.New("failed to disable client")
|
||||
)
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
"github.com/absmach/magistrala/pkg/groups"
|
||||
@@ -65,7 +64,7 @@ func (repo *userRepo) Save(ctx context.Context, c users.User) (users.User, error
|
||||
|
||||
func (repo *userRepo) CheckSuperAdmin(ctx context.Context, adminID string) error {
|
||||
q := "SELECT 1 FROM users WHERE id = $1 AND role = $2"
|
||||
rows, err := repo.Repository.DB.QueryContext(ctx, q, adminID, mgclients.AdminRole)
|
||||
rows, err := repo.Repository.DB.QueryContext(ctx, q, adminID, users.AdminRole)
|
||||
if err != nil {
|
||||
return postgres.HandleError(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
+1
-2
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/absmach/magistrala"
|
||||
mgauth "github.com/absmach/magistrala/auth"
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
mgclients "github.com/absmach/magistrala/pkg/clients"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
@@ -408,7 +407,7 @@ func (svc service) Enable(ctx context.Context, session authn.Session, id string)
|
||||
}
|
||||
user, err := svc.changeUserStatus(ctx, session, u)
|
||||
if err != nil {
|
||||
return User{}, errors.Wrap(mgclients.ErrEnableClient, err)
|
||||
return User{}, errors.Wrap(ErrEnableClient, err)
|
||||
}
|
||||
|
||||
return user, nil
|
||||
|
||||
Reference in New Issue
Block a user