mirror of
https://github.com/absmach/supermq.git
synced 2026-06-23 07:30:25 +00:00
NOISSUE - Remove SuperMQ duplicates (#23)
* Update docker-compose to use SuperMQ Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove duplicate services Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Update Bootstrap Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Update other services to use SMQ Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Switch config prefix to SMQ Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove leftovers Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove duplicate interface definitions Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove unused actions Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove unused API docs Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Resolve linter comments Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Fix provision Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> --------- Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
This commit is contained in:
+75
-75
@@ -2,68 +2,68 @@
|
||||
|
||||
New devices need to be configured properly and connected to the Magistrala. Bootstrap service is used in order to accomplish that. This service provides the following features:
|
||||
|
||||
1. Creating new Magistrala Things
|
||||
2. Providing basic configuration for the newly created Things
|
||||
3. Enabling/disabling Things
|
||||
1. Creating new Magistrala Clients
|
||||
2. Providing basic configuration for the newly created Clients
|
||||
3. Enabling/disabling Clients
|
||||
|
||||
Pre-provisioning a new Thing is as simple as sending Configuration data to the Bootstrap service. Once the Thing is online, it sends a request for initial config to Bootstrap service. Bootstrap service provides an API for enabling and disabling Things. Only enabled Things can exchange messages over Magistrala. Bootstrapping does not implicitly enable Things, it has to be done manually.
|
||||
Pre-provisioning a new Client is as simple as sending Configuration data to the Bootstrap service. Once the Client is online, it sends a request for initial config to Bootstrap service. Bootstrap service provides an API for enabling and disabling Clients. Only enabled Clients can exchange messages over Magistrala. Bootstrapping does not implicitly enable Clients, it has to be done manually.
|
||||
|
||||
In order to bootstrap successfully, the Thing needs to send bootstrapping request to the specific URL, as well as a secret key. This key and URL are pre-provisioned during the manufacturing process. If the Thing is provisioned on the Bootstrap service side, the corresponding configuration will be sent as a response. Otherwise, the Thing will be saved so that it can be provisioned later.
|
||||
In order to bootstrap successfully, the Client needs to send bootstrapping request to the specific URL, as well as a secret key. This key and URL are pre-provisioned during the manufacturing process. If the Client is provisioned on the Bootstrap service side, the corresponding configuration will be sent as a response. Otherwise, the Client will be saved so that it can be provisioned later.
|
||||
|
||||
## Thing Configuration Entity
|
||||
## Client Configuration Entity
|
||||
|
||||
Thing Configuration consists of two logical parts: the custom configuration that can be interpreted by the Thing itself and Magistrala-related configuration. Magistrala config contains:
|
||||
Client Configuration consists of two logical parts: the custom configuration that can be interpreted by the Client itself and Magistrala-related configuration. Magistrala config contains:
|
||||
|
||||
1. corresponding Magistrala Thing ID
|
||||
2. corresponding Magistrala Thing key
|
||||
3. list of the Magistrala channels the Thing is connected to
|
||||
1. corresponding Magistrala Client ID
|
||||
2. corresponding Magistrala Client key
|
||||
3. list of the Magistrala channels the Client is connected to
|
||||
|
||||
> Note: list of channels contains IDs of the Magistrala channels. These channels are _pre-provisioned_ on the Magistrala side and, unlike corresponding Magistrala Thing, Bootstrap service is not able to create Magistrala Channels.
|
||||
> Note: list of channels contains IDs of the Magistrala channels. These channels are _pre-provisioned_ on the Magistrala side and, unlike corresponding Magistrala Client, Bootstrap service is not able to create Magistrala Channels.
|
||||
|
||||
Enabling and disabling Thing (adding Thing to/from whitelist) is as simple as connecting corresponding Magistrala Thing to the given list of Channels. Configuration keeps _state_ of the Thing:
|
||||
Enabling and disabling Client (adding Client to/from whitelist) is as simple as connecting corresponding Magistrala Client to the given list of Channels. Configuration keeps _state_ of the Client:
|
||||
|
||||
| State | What it means |
|
||||
| -------- | --------------------------------------------- |
|
||||
| Inactive | Thing is created, but isn't enabled |
|
||||
| Active | Thing is able to communicate using Magistrala |
|
||||
| State | What it means |
|
||||
| -------- | ---------------------------------------------- |
|
||||
| Inactive | Client is created, but isn't enabled |
|
||||
| Active | Client is able to communicate using Magistrala |
|
||||
|
||||
Switching between states `Active` and `Inactive` enables and disables Thing, respectively.
|
||||
Switching between states `Active` and `Inactive` enables and disables Client, respectively.
|
||||
|
||||
Thing configuration also contains the so-called `external ID` and `external key`. An external ID is a unique identifier of corresponding Thing. For example, a device MAC address is a good choice for external ID. External key is a secret key that is used for authentication during the bootstrapping procedure.
|
||||
Client configuration also contains the so-called `external ID` and `external key`. An external ID is a unique identifier of corresponding Client. For example, a device MAC address is a good choice for external ID. External key is a secret key that is used for authentication during the bootstrapping procedure.
|
||||
|
||||
## Configuration
|
||||
|
||||
The service is configured using the environment variables presented in the following table. Note that any unset variables will be replaced with their default values.
|
||||
|
||||
| Variable | Description | Default |
|
||||
| ----------------------------- | -------------------------------------------------------------------------------- | -------------------------------- |
|
||||
| MG_BOOTSTRAP_LOG_LEVEL | Log level for Bootstrap (debug, info, warn, error) | info |
|
||||
| MG_BOOTSTRAP_DB_HOST | Database host address | localhost |
|
||||
| MG_BOOTSTRAP_DB_PORT | Database host port | 5432 |
|
||||
| MG_BOOTSTRAP_DB_USER | Database user | magistrala |
|
||||
| MG_BOOTSTRAP_DB_PASS | Database password | magistrala |
|
||||
| MG_BOOTSTRAP_DB_NAME | Name of the database used by the service | bootstrap |
|
||||
| MG_BOOTSTRAP_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable |
|
||||
| MG_BOOTSTRAP_DB_SSL_CERT | Path to the PEM encoded certificate file | "" |
|
||||
| MG_BOOTSTRAP_DB_SSL_KEY | Path to the PEM encoded key file | "" |
|
||||
| MG_BOOTSTRAP_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | "" |
|
||||
| MG_BOOTSTRAP_ENCRYPT_KEY | Secret key for secure bootstrapping encryption | 12345678910111213141516171819202 |
|
||||
| MG_BOOTSTRAP_HTTP_HOST | Bootstrap service HTTP host | "" |
|
||||
| MG_BOOTSTRAP_HTTP_PORT | Bootstrap service HTTP port | 9013 |
|
||||
| MG_BOOTSTRAP_HTTP_SERVER_CERT | Path to server certificate in pem format | "" |
|
||||
| MG_BOOTSTRAP_HTTP_SERVER_KEY | Path to server key in pem format | "" |
|
||||
| MG_BOOTSTRAP_EVENT_CONSUMER | Bootstrap service event source consumer name | bootstrap |
|
||||
| MG_ES_URL | Event store URL | <nats://localhost:4222> |
|
||||
| MG_AUTH_GRPC_URL | Auth service Auth gRPC URL | <localhost:8181> |
|
||||
| MG_AUTH_GRPC_TIMEOUT | Auth service Auth gRPC request timeout in seconds | 1s |
|
||||
| MG_AUTH_GRPC_CLIENT_CERT | Path to the PEM encoded auth service Auth gRPC client certificate file | "" |
|
||||
| MG_AUTH_GRPC_CLIENT_KEY | Path to the PEM encoded auth service Auth gRPC client key file | "" |
|
||||
| MG_AUTH_GRPC_SERVER_CERTS | Path to the PEM encoded auth server Auth gRPC server trusted CA certificate file | "" |
|
||||
| MG_THINGS_URL | Base url for Magistrala Things | <http://localhost:9000> |
|
||||
| MG_JAEGER_URL | Jaeger server URL | <http://localhost:4318/v1/traces> |
|
||||
| MG_JAEGER_TRACE_RATIO | Jaeger sampling ratio | 1.0 |
|
||||
| MG_SEND_TELEMETRY | Send telemetry to magistrala call home server | true |
|
||||
| MG_BOOTSTRAP_INSTANCE_ID | Bootstrap service instance ID | "" |
|
||||
| Variable | Description | Default |
|
||||
| ------------------------------ | -------------------------------------------------------------------------------- | --------------------------------- |
|
||||
| SMQ_BOOTSTRAP_LOG_LEVEL | Log level for Bootstrap (debug, info, warn, error) | info |
|
||||
| SMQ_BOOTSTRAP_DB_HOST | Database host address | localhost |
|
||||
| SMQ_BOOTSTRAP_DB_PORT | Database host port | 5432 |
|
||||
| SMQ_BOOTSTRAP_DB_USER | Database user | magistrala |
|
||||
| SMQ_BOOTSTRAP_DB_PASS | Database password | magistrala |
|
||||
| SMQ_BOOTSTRAP_DB_NAME | Name of the database used by the service | bootstrap |
|
||||
| SMQ_BOOTSTRAP_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable |
|
||||
| SMQ_BOOTSTRAP_DB_SSL_CERT | Path to the PEM encoded certificate file | "" |
|
||||
| SMQ_BOOTSTRAP_DB_SSL_KEY | Path to the PEM encoded key file | "" |
|
||||
| SMQ_BOOTSTRAP_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | "" |
|
||||
| SMQ_BOOTSTRAP_ENCRYPT_KEY | Secret key for secure bootstrapping encryption | 12345678910111213141516171819202 |
|
||||
| SMQ_BOOTSTRAP_HTTP_HOST | Bootstrap service HTTP host | "" |
|
||||
| SMQ_BOOTSTRAP_HTTP_PORT | Bootstrap service HTTP port | 9013 |
|
||||
| SMQ_BOOTSTRAP_HTTP_SERVER_CERT | Path to server certificate in pem format | "" |
|
||||
| SMQ_BOOTSTRAP_HTTP_SERVER_KEY | Path to server key in pem format | "" |
|
||||
| SMQ_BOOTSTRAP_EVENT_CONSUMER | Bootstrap service event source consumer name | bootstrap |
|
||||
| SMQ_ES_URL | Event store URL | <nats://localhost:4222> |
|
||||
| SMQ_AUTH_GRPC_URL | Auth service Auth gRPC URL | <localhost:8181> |
|
||||
| SMQ_AUTH_GRPC_TIMEOUT | Auth service Auth gRPC request timeout in seconds | 1s |
|
||||
| SMQ_AUTH_GRPC_CLIENT_CERT | Path to the PEM encoded auth service Auth gRPC client certificate file | "" |
|
||||
| SMQ_AUTH_GRPC_CLIENT_KEY | Path to the PEM encoded auth service Auth gRPC client key file | "" |
|
||||
| SMQ_AUTH_GRPC_SERVER_CERTS | Path to the PEM encoded auth server Auth gRPC server trusted CA certificate file | "" |
|
||||
| SMQ_CLIENTS_URL | Base URL for Magistrala Clients | <http://localhost:9000> |
|
||||
| SMQ_JAEGER_URL | Jaeger server URL | <http://localhost:4318/v1/traces> |
|
||||
| SMQ_JAEGER_TRACE_RATIO | Jaeger sampling ratio | 1.0 |
|
||||
| SMQ_SEND_TELEMETRY | Send telemetry to magistrala call home server | true |
|
||||
| SMQ_BOOTSTRAP_INSTANCE_ID | Bootstrap service instance ID | "" |
|
||||
|
||||
## Deployment
|
||||
|
||||
@@ -84,38 +84,38 @@ make bootstrap
|
||||
make install
|
||||
|
||||
# set the environment variables and run the service
|
||||
MG_BOOTSTRAP_LOG_LEVEL=info \
|
||||
MG_BOOTSTRAP_DB_HOST=localhost \
|
||||
MG_BOOTSTRAP_DB_PORT=5432 \
|
||||
MG_BOOTSTRAP_DB_USER=magistrala \
|
||||
MG_BOOTSTRAP_DB_PASS=magistrala \
|
||||
MG_BOOTSTRAP_DB_NAME=bootstrap \
|
||||
MG_BOOTSTRAP_DB_SSL_MODE=disable \
|
||||
MG_BOOTSTRAP_DB_SSL_CERT="" \
|
||||
MG_BOOTSTRAP_DB_SSL_KEY="" \
|
||||
MG_BOOTSTRAP_DB_SSL_ROOT_CERT="" \
|
||||
MG_BOOTSTRAP_HTTP_HOST=localhost \
|
||||
MG_BOOTSTRAP_HTTP_PORT=9013 \
|
||||
MG_BOOTSTRAP_HTTP_SERVER_CERT="" \
|
||||
MG_BOOTSTRAP_HTTP_SERVER_KEY="" \
|
||||
MG_BOOTSTRAP_EVENT_CONSUMER=bootstrap \
|
||||
MG_ES_URL=nats://localhost:4222 \
|
||||
MG_AUTH_GRPC_URL=localhost:8181 \
|
||||
MG_AUTH_GRPC_TIMEOUT=1s \
|
||||
MG_AUTH_GRPC_CLIENT_CERT="" \
|
||||
MG_AUTH_GRPC_CLIENT_KEY="" \
|
||||
MG_AUTH_GRPC_SERVER_CERTS="" \
|
||||
MG_THINGS_URL=http://localhost:9000 \
|
||||
MG_JAEGER_URL=http://localhost:14268/api/traces \
|
||||
MG_JAEGER_TRACE_RATIO=1.0 \
|
||||
MG_SEND_TELEMETRY=true \
|
||||
MG_BOOTSTRAP_INSTANCE_ID="" \
|
||||
SMQ_BOOTSTRAP_LOG_LEVEL=info \
|
||||
SMQ_BOOTSTRAP_DB_HOST=localhost \
|
||||
SMQ_BOOTSTRAP_DB_PORT=5432 \
|
||||
SMQ_BOOTSTRAP_DB_USER=magistrala \
|
||||
SMQ_BOOTSTRAP_DB_PASS=magistrala \
|
||||
SMQ_BOOTSTRAP_DB_NAME=bootstrap \
|
||||
SMQ_BOOTSTRAP_DB_SSL_MODE=disable \
|
||||
SMQ_BOOTSTRAP_DB_SSL_CERT="" \
|
||||
SMQ_BOOTSTRAP_DB_SSL_KEY="" \
|
||||
SMQ_BOOTSTRAP_DB_SSL_ROOT_CERT="" \
|
||||
SMQ_BOOTSTRAP_HTTP_HOST=localhost \
|
||||
SMQ_BOOTSTRAP_HTTP_PORT=9013 \
|
||||
SMQ_BOOTSTRAP_HTTP_SERVER_CERT="" \
|
||||
SMQ_BOOTSTRAP_HTTP_SERVER_KEY="" \
|
||||
SMQ_BOOTSTRAP_EVENT_CONSUMER=bootstrap \
|
||||
SMQ_ES_URL=nats://localhost:4222 \
|
||||
SMQ_AUTH_GRPC_URL=localhost:8181 \
|
||||
SMQ_AUTH_GRPC_TIMEOUT=1s \
|
||||
SMQ_AUTH_GRPC_CLIENT_CERT="" \
|
||||
SMQ_AUTH_GRPC_CLIENT_KEY="" \
|
||||
SMQ_AUTH_GRPC_SERVER_CERTS="" \
|
||||
SMQ_CLIENTS_URL=http://localhost:9000 \
|
||||
SMQ_JAEGER_URL=http://localhost:14268/api/traces \
|
||||
SMQ_JAEGER_TRACE_RATIO=1.0 \
|
||||
SMQ_SEND_TELEMETRY=true \
|
||||
SMQ_BOOTSTRAP_INSTANCE_ID="" \
|
||||
$GOBIN/magistrala-bootstrap
|
||||
```
|
||||
|
||||
Setting `MG_BOOTSTRAP_HTTP_SERVER_CERT` and `MG_BOOTSTRAP_HTTP_SERVER_KEY` will enable TLS against the service. The service expects a file in PEM format for both the certificate and the key.
|
||||
Setting `SMQ_BOOTSTRAP_HTTP_SERVER_CERT` and `SMQ_BOOTSTRAP_HTTP_SERVER_KEY` will enable TLS against the service. The service expects a file in PEM format for both the certificate and the key.
|
||||
|
||||
Setting `MG_AUTH_GRPC_CLIENT_CERT` and `MG_AUTH_GRPC_CLIENT_KEY` will enable TLS against the auth service. The service expects a file in PEM format for both the certificate and the key. Setting `MG_AUTH_GRPC_SERVER_CERTS` will enable TLS against the auth service trusting only those CAs that are provided. The service expects a file in PEM format of trusted CAs.
|
||||
Setting `SMQ_AUTH_GRPC_CLIENT_CERT` and `SMQ_AUTH_GRPC_CLIENT_KEY` will enable TLS against the auth service. The service expects a file in PEM format for both the certificate and the key. Setting `SMQ_AUTH_GRPC_SERVER_CERTS` will enable TLS against the auth service trusting only those CAs that are provided. The service expects a file in PEM format of trusted CAs.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
+30
-30
@@ -6,12 +6,12 @@ package api
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
"github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
api "github.com/absmach/supermq/api/http"
|
||||
apiutil "github.com/absmach/supermq/api/http/util"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
@@ -33,7 +33,7 @@ func addEndpoint(svc bootstrap.Service) endpoint.Endpoint {
|
||||
}
|
||||
|
||||
config := bootstrap.Config{
|
||||
ThingID: req.ThingID,
|
||||
ClientID: req.ClientID,
|
||||
ExternalID: req.ExternalID,
|
||||
ExternalKey: req.ExternalKey,
|
||||
Channels: channels,
|
||||
@@ -50,7 +50,7 @@ func addEndpoint(svc bootstrap.Service) endpoint.Endpoint {
|
||||
}
|
||||
|
||||
res := configRes{
|
||||
id: saved.ThingID,
|
||||
id: saved.ClientID,
|
||||
created: true,
|
||||
}
|
||||
|
||||
@@ -70,13 +70,13 @@ func updateCertEndpoint(svc bootstrap.Service) endpoint.Endpoint {
|
||||
return nil, svcerr.ErrAuthorization
|
||||
}
|
||||
|
||||
cfg, err := svc.UpdateCert(ctx, session, req.thingID, req.ClientCert, req.ClientKey, req.CACert)
|
||||
cfg, err := svc.UpdateCert(ctx, session, req.clientID, req.ClientCert, req.ClientKey, req.CACert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res := updateConfigRes{
|
||||
ThingID: cfg.ThingID,
|
||||
ClientID: cfg.ClientID,
|
||||
ClientCert: cfg.ClientCert,
|
||||
CACert: cfg.CACert,
|
||||
ClientKey: cfg.ClientKey,
|
||||
@@ -113,14 +113,14 @@ func viewEndpoint(svc bootstrap.Service) endpoint.Endpoint {
|
||||
}
|
||||
|
||||
res := viewRes{
|
||||
ThingID: config.ThingID,
|
||||
ThingKey: config.ThingKey,
|
||||
Channels: channels,
|
||||
ExternalID: config.ExternalID,
|
||||
ExternalKey: config.ExternalKey,
|
||||
Name: config.Name,
|
||||
Content: config.Content,
|
||||
State: config.State,
|
||||
ClientID: config.ClientID,
|
||||
CLientSecret: config.ClientSecret,
|
||||
Channels: channels,
|
||||
ExternalID: config.ExternalID,
|
||||
ExternalKey: config.ExternalKey,
|
||||
Name: config.Name,
|
||||
Content: config.Content,
|
||||
State: config.State,
|
||||
}
|
||||
|
||||
return res, nil
|
||||
@@ -140,9 +140,9 @@ func updateEndpoint(svc bootstrap.Service) endpoint.Endpoint {
|
||||
}
|
||||
|
||||
config := bootstrap.Config{
|
||||
ThingID: req.id,
|
||||
Name: req.Name,
|
||||
Content: req.Content,
|
||||
ClientID: req.id,
|
||||
Name: req.Name,
|
||||
Content: req.Content,
|
||||
}
|
||||
|
||||
if err := svc.Update(ctx, session, config); err != nil {
|
||||
@@ -150,7 +150,7 @@ func updateEndpoint(svc bootstrap.Service) endpoint.Endpoint {
|
||||
}
|
||||
|
||||
res := configRes{
|
||||
id: config.ThingID,
|
||||
id: config.ClientID,
|
||||
created: false,
|
||||
}
|
||||
|
||||
@@ -217,14 +217,14 @@ func listEndpoint(svc bootstrap.Service) endpoint.Endpoint {
|
||||
}
|
||||
|
||||
view := viewRes{
|
||||
ThingID: cfg.ThingID,
|
||||
ThingKey: cfg.ThingKey,
|
||||
Channels: channels,
|
||||
ExternalID: cfg.ExternalID,
|
||||
ExternalKey: cfg.ExternalKey,
|
||||
Name: cfg.Name,
|
||||
Content: cfg.Content,
|
||||
State: cfg.State,
|
||||
ClientID: cfg.ClientID,
|
||||
CLientSecret: cfg.ClientSecret,
|
||||
Channels: channels,
|
||||
ExternalID: cfg.ExternalID,
|
||||
ExternalKey: cfg.ExternalKey,
|
||||
Name: cfg.Name,
|
||||
Content: cfg.Content,
|
||||
State: cfg.State,
|
||||
}
|
||||
res.Configs = append(res.Configs, view)
|
||||
}
|
||||
|
||||
+153
-153
@@ -18,16 +18,16 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
bsapi "github.com/absmach/magistrala/bootstrap/api"
|
||||
"github.com/absmach/magistrala/bootstrap/mocks"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
authnmocks "github.com/absmach/magistrala/pkg/authn/mocks"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
apiutil "github.com/absmach/supermq/api/http/util"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
bsapi "github.com/absmach/supermq/bootstrap/api"
|
||||
"github.com/absmach/supermq/bootstrap/mocks"
|
||||
smqlog "github.com/absmach/supermq/logger"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
authnmocks "github.com/absmach/supermq/pkg/authn/mocks"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
@@ -49,44 +49,44 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
encKey = []byte("1234567891011121")
|
||||
metadata = map[string]interface{}{"meta": "data"}
|
||||
addExternalID = testsutil.GenerateUUID(&testing.T{})
|
||||
addExternalKey = testsutil.GenerateUUID(&testing.T{})
|
||||
addThingID = testsutil.GenerateUUID(&testing.T{})
|
||||
addThingKey = testsutil.GenerateUUID(&testing.T{})
|
||||
addReq = struct {
|
||||
ThingID string `json:"thing_id"`
|
||||
ThingKey string `json:"thing_key"`
|
||||
ExternalID string `json:"external_id"`
|
||||
ExternalKey string `json:"external_key"`
|
||||
Channels []string `json:"channels"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
encKey = []byte("1234567891011121")
|
||||
metadata = map[string]interface{}{"meta": "data"}
|
||||
addExternalID = testsutil.GenerateUUID(&testing.T{})
|
||||
addExternalKey = testsutil.GenerateUUID(&testing.T{})
|
||||
addClientID = testsutil.GenerateUUID(&testing.T{})
|
||||
addClientSecret = testsutil.GenerateUUID(&testing.T{})
|
||||
addReq = struct {
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
ExternalID string `json:"external_id"`
|
||||
ExternalKey string `json:"external_key"`
|
||||
Channels []string `json:"channels"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content"`
|
||||
}{
|
||||
ThingID: addThingID,
|
||||
ThingKey: addThingKey,
|
||||
ExternalID: addExternalID,
|
||||
ExternalKey: addExternalKey,
|
||||
Channels: []string{"1"},
|
||||
Name: "name",
|
||||
Content: "config",
|
||||
ClientID: addClientID,
|
||||
ClientSecret: addClientSecret,
|
||||
ExternalID: addExternalID,
|
||||
ExternalKey: addExternalKey,
|
||||
Channels: []string{"1"},
|
||||
Name: "name",
|
||||
Content: "config",
|
||||
}
|
||||
|
||||
updateReq = struct {
|
||||
Channels []string `json:"channels,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
State bootstrap.State `json:"state,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
Channels []string `json:"channels,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
State bootstrap.State `json:"state,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientSecret string `json:"client_secret,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
}{
|
||||
Channels: []string{"1"},
|
||||
Content: "config update",
|
||||
State: 1,
|
||||
ClientCert: "newcert",
|
||||
ClientKey: "newkey",
|
||||
CACert: "newca",
|
||||
Channels: []string{"1"},
|
||||
Content: "config update",
|
||||
State: 1,
|
||||
ClientCert: "newcert",
|
||||
ClientSecret: "newkey",
|
||||
CACert: "newca",
|
||||
}
|
||||
|
||||
missingIDRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrMissingID.Error(), Msg: apiutil.ErrValidation.Error()})
|
||||
@@ -108,10 +108,10 @@ type testRequest struct {
|
||||
|
||||
func newConfig() bootstrap.Config {
|
||||
return bootstrap.Config{
|
||||
ThingID: addThingID,
|
||||
ThingKey: addThingKey,
|
||||
ExternalID: addExternalID,
|
||||
ExternalKey: addExternalKey,
|
||||
ClientID: addClientID,
|
||||
ClientSecret: addClientSecret,
|
||||
ExternalID: addExternalID,
|
||||
ExternalKey: addExternalKey,
|
||||
Channels: []bootstrap.Channel{
|
||||
{
|
||||
ID: "1",
|
||||
@@ -136,7 +136,7 @@ func (tr testRequest) make() (*http.Response, error) {
|
||||
req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token)
|
||||
}
|
||||
if tr.key != "" {
|
||||
req.Header.Set("Authorization", apiutil.ThingPrefix+tr.key)
|
||||
req.Header.Set("Authorization", apiutil.ClientPrefix+tr.key)
|
||||
}
|
||||
|
||||
if tr.contentType != "" {
|
||||
@@ -177,7 +177,7 @@ func dec(in []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
func newBootstrapServer() (*httptest.Server, *mocks.Service, *authnmocks.Authentication) {
|
||||
logger := mglog.NewMock()
|
||||
logger := smqlog.NewMock()
|
||||
svc := new(mocks.Service)
|
||||
authn := new(authnmocks.Authentication)
|
||||
mux := bsapi.MakeHandler(svc, authn, bootstrap.NewConfigReader(encKey), logger, instanceID)
|
||||
@@ -200,7 +200,7 @@ func TestAdd(t *testing.T) {
|
||||
data := toJSON(addReq)
|
||||
|
||||
neID := addReq
|
||||
neID.ThingID = testsutil.GenerateUUID(t)
|
||||
neID.ClientID = testsutil.GenerateUUID(t)
|
||||
neData := toJSON(neID)
|
||||
|
||||
invalidChannels := addReq
|
||||
@@ -212,7 +212,7 @@ func TestAdd(t *testing.T) {
|
||||
req string
|
||||
domainID string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
contentType string
|
||||
status int
|
||||
location string
|
||||
@@ -237,7 +237,7 @@ func TestAdd(t *testing.T) {
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusCreated,
|
||||
location: "/things/configs/" + c.ThingID,
|
||||
location: "/clients/configs/" + c.ClientID,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
@@ -324,7 +324,7 @@ func TestAdd(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
|
||||
@@ -332,7 +332,7 @@ func TestAdd(t *testing.T) {
|
||||
req := testRequest{
|
||||
client: bs.Client(),
|
||||
method: http.MethodPost,
|
||||
url: fmt.Sprintf("%s/%s/things/configs", bs.URL, tc.domainID),
|
||||
url: fmt.Sprintf("%s/%s/clients/configs", bs.URL, tc.domainID),
|
||||
contentType: tc.contentType,
|
||||
token: tc.token,
|
||||
body: strings.NewReader(tc.req),
|
||||
@@ -359,20 +359,20 @@ func TestView(t *testing.T) {
|
||||
}
|
||||
|
||||
data := config{
|
||||
ThingID: c.ThingID,
|
||||
ThingKey: c.ThingKey,
|
||||
State: c.State,
|
||||
Channels: channels,
|
||||
ExternalID: c.ExternalID,
|
||||
ExternalKey: c.ExternalKey,
|
||||
Name: c.Name,
|
||||
Content: c.Content,
|
||||
ClientID: c.ClientID,
|
||||
ClientSecret: c.ClientSecret,
|
||||
State: c.State,
|
||||
Channels: channels,
|
||||
ExternalID: c.ExternalID,
|
||||
ExternalKey: c.ExternalKey,
|
||||
Name: c.Name,
|
||||
Content: c.Content,
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
id string
|
||||
status int
|
||||
res config
|
||||
@@ -382,7 +382,7 @@ func TestView(t *testing.T) {
|
||||
{
|
||||
desc: "view a config with invalid token",
|
||||
token: invalidToken,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
status: http.StatusUnauthorized,
|
||||
res: config{},
|
||||
authenticateErr: svcerr.ErrAuthentication,
|
||||
@@ -391,7 +391,7 @@ func TestView(t *testing.T) {
|
||||
{
|
||||
desc: "view a config",
|
||||
token: validToken,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
status: http.StatusOK,
|
||||
res: data,
|
||||
err: nil,
|
||||
@@ -407,7 +407,7 @@ func TestView(t *testing.T) {
|
||||
{
|
||||
desc: "view a config with an empty token",
|
||||
token: "",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
status: http.StatusUnauthorized,
|
||||
res: config{},
|
||||
err: apiutil.ErrBearerToken,
|
||||
@@ -415,7 +415,7 @@ func TestView(t *testing.T) {
|
||||
{
|
||||
desc: "view config without authorization",
|
||||
token: validToken,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
status: http.StatusForbidden,
|
||||
res: config{},
|
||||
err: svcerr.ErrAuthorization,
|
||||
@@ -425,14 +425,14 @@ func TestView(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("View", mock.Anything, tc.session, tc.id).Return(c, tc.err)
|
||||
req := testRequest{
|
||||
client: bs.Client(),
|
||||
method: http.MethodGet,
|
||||
url: fmt.Sprintf("%s/%s/things/configs/%s", bs.URL, domainID, tc.id),
|
||||
url: fmt.Sprintf("%s/%s/clients/configs/%s", bs.URL, domainID, tc.id),
|
||||
token: tc.token,
|
||||
}
|
||||
res, err := req.make()
|
||||
@@ -467,7 +467,7 @@ func TestUpdate(t *testing.T) {
|
||||
req string
|
||||
id string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
contentType string
|
||||
status int
|
||||
authenticateErr error
|
||||
@@ -476,7 +476,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
desc: "update with invalid token",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: invalidToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusUnauthorized,
|
||||
@@ -486,7 +486,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
desc: "update with an empty token",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: "",
|
||||
contentType: contentType,
|
||||
status: http.StatusUnauthorized,
|
||||
@@ -495,7 +495,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
desc: "update a valid config",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusOK,
|
||||
@@ -504,7 +504,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
desc: "update a config with wrong content type",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
contentType: "",
|
||||
status: http.StatusUnsupportedMediaType,
|
||||
@@ -522,7 +522,7 @@ func TestUpdate(t *testing.T) {
|
||||
{
|
||||
desc: "update a config with invalid request format",
|
||||
req: "}",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusBadRequest,
|
||||
@@ -530,7 +530,7 @@ func TestUpdate(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update a config with an empty request",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
req: "",
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
@@ -542,14 +542,14 @@ func TestUpdate(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("Update", mock.Anything, tc.session, mock.Anything).Return(tc.err)
|
||||
req := testRequest{
|
||||
client: bs.Client(),
|
||||
method: http.MethodPut,
|
||||
url: fmt.Sprintf("%s/%s/things/configs/%s", bs.URL, domainID, tc.id),
|
||||
url: fmt.Sprintf("%s/%s/clients/configs/%s", bs.URL, domainID, tc.id),
|
||||
contentType: tc.contentType,
|
||||
token: tc.token,
|
||||
body: strings.NewReader(tc.req),
|
||||
@@ -575,7 +575,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
req string
|
||||
id string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
contentType string
|
||||
status int
|
||||
authenticateErr error
|
||||
@@ -584,7 +584,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
{
|
||||
desc: "update with invalid token",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: invalidToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusUnauthorized,
|
||||
@@ -594,7 +594,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
{
|
||||
desc: "update with an empty token",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: "",
|
||||
contentType: contentType,
|
||||
status: http.StatusUnauthorized,
|
||||
@@ -603,7 +603,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
{
|
||||
desc: "update a valid config",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusOK,
|
||||
@@ -612,7 +612,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
{
|
||||
desc: "update a config with wrong content type",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
contentType: "",
|
||||
status: http.StatusUnsupportedMediaType,
|
||||
@@ -630,7 +630,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
{
|
||||
desc: "update a config with invalid request format",
|
||||
req: "}",
|
||||
id: c.ThingKey,
|
||||
id: c.ClientSecret,
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusBadRequest,
|
||||
@@ -638,7 +638,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update a config with an empty request",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
req: "",
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
@@ -650,14 +650,14 @@ func TestUpdateCert(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("UpdateCert", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(c, tc.err)
|
||||
req := testRequest{
|
||||
client: bs.Client(),
|
||||
method: http.MethodPatch,
|
||||
url: fmt.Sprintf("%s/%s/things/configs/certs/%s", bs.URL, domainID, tc.id),
|
||||
url: fmt.Sprintf("%s/%s/clients/configs/certs/%s", bs.URL, domainID, tc.id),
|
||||
contentType: tc.contentType,
|
||||
token: tc.token,
|
||||
body: strings.NewReader(tc.req),
|
||||
@@ -687,7 +687,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
req string
|
||||
id string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
contentType string
|
||||
status int
|
||||
authenticateErr error
|
||||
@@ -696,7 +696,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
{
|
||||
desc: "update connections with invalid token",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: invalidToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusUnauthorized,
|
||||
@@ -706,7 +706,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
{
|
||||
desc: "update connections with an empty token",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: "",
|
||||
contentType: contentType,
|
||||
status: http.StatusUnauthorized,
|
||||
@@ -715,7 +715,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
{
|
||||
desc: "update connections valid config",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusOK,
|
||||
@@ -724,7 +724,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
{
|
||||
desc: "update connections with wrong content type",
|
||||
req: data,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
contentType: "",
|
||||
status: http.StatusUnsupportedMediaType,
|
||||
@@ -742,7 +742,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
{
|
||||
desc: "update connections with invalid channels",
|
||||
req: wrongData,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusNotFound,
|
||||
@@ -751,7 +751,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
{
|
||||
desc: "update a config with invalid request format",
|
||||
req: "}",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
status: http.StatusBadRequest,
|
||||
@@ -759,7 +759,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update a config with an empty request",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
req: "",
|
||||
token: validToken,
|
||||
contentType: contentType,
|
||||
@@ -771,14 +771,14 @@ func TestUpdateConnections(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
repoCall := svc.On("UpdateConnections", mock.Anything, tc.session, tc.token, mock.Anything, mock.Anything).Return(tc.err)
|
||||
req := testRequest{
|
||||
client: bs.Client(),
|
||||
method: http.MethodPut,
|
||||
url: fmt.Sprintf("%s/%s/things/configs/connections/%s", bs.URL, domainID, tc.id),
|
||||
url: fmt.Sprintf("%s/%s/clients/configs/connections/%s", bs.URL, domainID, tc.id),
|
||||
contentType: tc.contentType,
|
||||
token: tc.token,
|
||||
body: strings.NewReader(tc.req),
|
||||
@@ -800,13 +800,13 @@ func TestList(t *testing.T) {
|
||||
|
||||
bs, svc, auth := newBootstrapServer()
|
||||
defer bs.Close()
|
||||
path := fmt.Sprintf("%s/%s/%s", bs.URL, domainID, "things/configs")
|
||||
path := fmt.Sprintf("%s/%s/%s", bs.URL, domainID, "clients/configs")
|
||||
|
||||
c := newConfig()
|
||||
|
||||
for i := 0; i < configNum; i++ {
|
||||
c.ExternalID = strconv.Itoa(i)
|
||||
c.ThingKey = c.ExternalID
|
||||
c.ClientSecret = c.ExternalID
|
||||
c.Name = fmt.Sprintf("%s-%d", addName, i)
|
||||
c.ExternalKey = fmt.Sprintf("%s%s", addExternalKey, strconv.Itoa(i))
|
||||
|
||||
@@ -815,14 +815,14 @@ func TestList(t *testing.T) {
|
||||
channels = append(channels, channel{ID: ch.ID, Name: ch.Name, Metadata: ch.Metadata})
|
||||
}
|
||||
s := config{
|
||||
ThingID: c.ThingID,
|
||||
ThingKey: c.ThingKey,
|
||||
Channels: channels,
|
||||
ExternalID: c.ExternalID,
|
||||
ExternalKey: c.ExternalKey,
|
||||
Name: c.Name,
|
||||
Content: c.Content,
|
||||
State: c.State,
|
||||
ClientID: c.ClientID,
|
||||
ClientSecret: c.ClientSecret,
|
||||
Channels: channels,
|
||||
ExternalID: c.ExternalID,
|
||||
ExternalKey: c.ExternalKey,
|
||||
Name: c.Name,
|
||||
Content: c.Content,
|
||||
State: c.State,
|
||||
}
|
||||
list[i] = s
|
||||
}
|
||||
@@ -833,7 +833,7 @@ func TestList(t *testing.T) {
|
||||
state = bootstrap.Inactive
|
||||
}
|
||||
svcCall := svc.On("ChangeState", context.Background(), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil)
|
||||
err := svc.ChangeState(context.Background(), mgauthn.Session{}, validToken, list[i].ThingID, state)
|
||||
err := svc.ChangeState(context.Background(), smqauthn.Session{}, validToken, list[i].ClientID, state)
|
||||
assert.Nil(t, err, fmt.Sprintf("Changing state expected to succeed: %s.\n", err))
|
||||
|
||||
svcCall.Unset()
|
||||
@@ -849,7 +849,7 @@ func TestList(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
url string
|
||||
status int
|
||||
res configPage
|
||||
@@ -1040,7 +1040,7 @@ func TestList(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("List", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(bootstrap.ConfigsPage{Total: tc.res.Total, Offset: tc.res.Offset, Limit: tc.res.Limit}, tc.err)
|
||||
@@ -1077,14 +1077,14 @@ func TestRemove(t *testing.T) {
|
||||
desc string
|
||||
id string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
status int
|
||||
authenticateErr error
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "remove with invalid token",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: invalidToken,
|
||||
status: http.StatusUnauthorized,
|
||||
authenticateErr: svcerr.ErrAuthentication,
|
||||
@@ -1092,7 +1092,7 @@ func TestRemove(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "remove with an empty token",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: "",
|
||||
status: http.StatusUnauthorized,
|
||||
err: apiutil.ErrBearerToken,
|
||||
@@ -1106,7 +1106,7 @@ func TestRemove(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "remove config",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
status: http.StatusNoContent,
|
||||
err: nil,
|
||||
@@ -1123,14 +1123,14 @@ func TestRemove(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("Remove", mock.Anything, mock.Anything, mock.Anything).Return(tc.err)
|
||||
req := testRequest{
|
||||
client: bs.Client(),
|
||||
method: http.MethodDelete,
|
||||
url: fmt.Sprintf("%s/%s/things/configs/%s", bs.URL, domainID, tc.id),
|
||||
url: fmt.Sprintf("%s/%s/clients/configs/%s", bs.URL, domainID, tc.id),
|
||||
token: tc.token,
|
||||
}
|
||||
res, err := req.make()
|
||||
@@ -1156,21 +1156,21 @@ func TestBootstrap(t *testing.T) {
|
||||
}
|
||||
|
||||
s := struct {
|
||||
ThingID string `json:"thing_id"`
|
||||
ThingKey string `json:"thing_key"`
|
||||
Channels []channel `json:"channels"`
|
||||
Content string `json:"content"`
|
||||
ClientCert string `json:"client_cert"`
|
||||
ClientKey string `json:"client_key"`
|
||||
CACert string `json:"ca_cert"`
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
Channels []channel `json:"channels"`
|
||||
Content string `json:"content"`
|
||||
ClientCert string `json:"client_cert"`
|
||||
ClientKey string `json:"client_key"`
|
||||
CACert string `json:"ca_cert"`
|
||||
}{
|
||||
ThingID: c.ThingID,
|
||||
ThingKey: c.ThingKey,
|
||||
Channels: channels,
|
||||
Content: c.Content,
|
||||
ClientCert: c.ClientCert,
|
||||
ClientKey: c.ClientKey,
|
||||
CACert: c.CACert,
|
||||
ClientID: c.ClientID,
|
||||
ClientSecret: c.ClientSecret,
|
||||
Channels: channels,
|
||||
Content: c.Content,
|
||||
ClientCert: c.ClientCert,
|
||||
ClientKey: c.ClientKey,
|
||||
CACert: c.CACert,
|
||||
}
|
||||
|
||||
data := toJSON(s)
|
||||
@@ -1185,7 +1185,7 @@ func TestBootstrap(t *testing.T) {
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "bootstrap a Thing with unknown ID",
|
||||
desc: "bootstrap a Client with unknown ID",
|
||||
externalID: unknown,
|
||||
externalKey: c.ExternalKey,
|
||||
status: http.StatusNotFound,
|
||||
@@ -1194,7 +1194,7 @@ func TestBootstrap(t *testing.T) {
|
||||
err: bootstrap.ErrBootstrap,
|
||||
},
|
||||
{
|
||||
desc: "bootstrap a Thing with an empty ID",
|
||||
desc: "bootstrap a Client with an empty ID",
|
||||
externalID: "",
|
||||
externalKey: c.ExternalKey,
|
||||
status: http.StatusBadRequest,
|
||||
@@ -1203,7 +1203,7 @@ func TestBootstrap(t *testing.T) {
|
||||
err: errors.Wrap(bootstrap.ErrBootstrap, svcerr.ErrMalformedEntity),
|
||||
},
|
||||
{
|
||||
desc: "bootstrap a Thing with unknown key",
|
||||
desc: "bootstrap a Client with unknown key",
|
||||
externalID: c.ExternalID,
|
||||
externalKey: unknown,
|
||||
status: http.StatusForbidden,
|
||||
@@ -1212,7 +1212,7 @@ func TestBootstrap(t *testing.T) {
|
||||
err: errors.Wrap(bootstrap.ErrExternalKey, errors.New("")),
|
||||
},
|
||||
{
|
||||
desc: "bootstrap a Thing with an empty key",
|
||||
desc: "bootstrap a Client with an empty key",
|
||||
externalID: c.ExternalID,
|
||||
externalKey: "",
|
||||
status: http.StatusBadRequest,
|
||||
@@ -1221,7 +1221,7 @@ func TestBootstrap(t *testing.T) {
|
||||
err: errors.Wrap(bootstrap.ErrBootstrap, svcerr.ErrAuthentication),
|
||||
},
|
||||
{
|
||||
desc: "bootstrap known Thing",
|
||||
desc: "bootstrap known Client",
|
||||
externalID: c.ExternalID,
|
||||
externalKey: c.ExternalKey,
|
||||
status: http.StatusOK,
|
||||
@@ -1255,7 +1255,7 @@ func TestBootstrap(t *testing.T) {
|
||||
req := testRequest{
|
||||
client: bs.Client(),
|
||||
method: http.MethodGet,
|
||||
url: fmt.Sprintf("%s/things/bootstrap/%s", bs.URL, tc.externalID),
|
||||
url: fmt.Sprintf("%s/clients/bootstrap/%s", bs.URL, tc.externalID),
|
||||
key: tc.externalKey,
|
||||
}
|
||||
res, err := req.make()
|
||||
@@ -1287,7 +1287,7 @@ func TestChangeState(t *testing.T) {
|
||||
desc string
|
||||
id string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
state string
|
||||
contentType string
|
||||
status int
|
||||
@@ -1296,7 +1296,7 @@ func TestChangeState(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
desc: "change state with invalid token",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: invalidToken,
|
||||
state: active,
|
||||
contentType: contentType,
|
||||
@@ -1306,7 +1306,7 @@ func TestChangeState(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "change state with an empty token",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: "",
|
||||
state: active,
|
||||
contentType: contentType,
|
||||
@@ -1315,7 +1315,7 @@ func TestChangeState(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "change state with invalid content type",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
state: active,
|
||||
contentType: "",
|
||||
@@ -1324,7 +1324,7 @@ func TestChangeState(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "change state to active",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
state: active,
|
||||
contentType: contentType,
|
||||
@@ -1333,7 +1333,7 @@ func TestChangeState(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "change state to inactive",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
state: inactive,
|
||||
contentType: contentType,
|
||||
@@ -1351,7 +1351,7 @@ func TestChangeState(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "change state to invalid value",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
state: fmt.Sprintf("{\"state\": %d}", -3),
|
||||
contentType: contentType,
|
||||
@@ -1360,7 +1360,7 @@ func TestChangeState(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "change state with invalid data",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
state: "",
|
||||
contentType: contentType,
|
||||
@@ -1372,14 +1372,14 @@ func TestChangeState(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
if tc.token == validToken {
|
||||
tc.session = mgauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID}
|
||||
}
|
||||
authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticateErr)
|
||||
svcCall := svc.On("ChangeState", mock.Anything, tc.session, tc.token, mock.Anything, mock.Anything).Return(tc.err)
|
||||
req := testRequest{
|
||||
client: bs.Client(),
|
||||
method: http.MethodPut,
|
||||
url: fmt.Sprintf("%s/%s/things/state/%s", bs.URL, domainID, tc.id),
|
||||
url: fmt.Sprintf("%s/%s/clients/state/%s", bs.URL, domainID, tc.id),
|
||||
token: tc.token,
|
||||
contentType: tc.contentType,
|
||||
body: strings.NewReader(tc.state),
|
||||
@@ -1400,14 +1400,14 @@ type channel struct {
|
||||
}
|
||||
|
||||
type config struct {
|
||||
ThingID string `json:"thing_id,omitempty"`
|
||||
ThingKey string `json:"thing_key,omitempty"`
|
||||
Channels []channel `json:"channels,omitempty"`
|
||||
ExternalID string `json:"external_id"`
|
||||
ExternalKey string `json:"external_key,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Name string `json:"name"`
|
||||
State bootstrap.State `json:"state"`
|
||||
ClientID string `json:"client_id,omitempty"`
|
||||
ClientSecret string `json:"client_secret,omitempty"`
|
||||
Channels []channel `json:"channels,omitempty"`
|
||||
ExternalID string `json:"external_id"`
|
||||
ExternalKey string `json:"external_key,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Name string `json:"name"`
|
||||
State bootstrap.State `json:"state"`
|
||||
}
|
||||
|
||||
type configPage struct {
|
||||
|
||||
@@ -4,15 +4,15 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
apiutil "github.com/absmach/supermq/api/http/util"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
)
|
||||
|
||||
const maxLimitSize = 100
|
||||
|
||||
type addReq struct {
|
||||
token string
|
||||
ThingID string `json:"thing_id"`
|
||||
ClientID string `json:"client_id"`
|
||||
ExternalID string `json:"external_id"`
|
||||
ExternalKey string `json:"external_key"`
|
||||
Channels []string `json:"channels"`
|
||||
@@ -76,14 +76,14 @@ func (req updateReq) validate() error {
|
||||
}
|
||||
|
||||
type updateCertReq struct {
|
||||
thingID string
|
||||
clientID string
|
||||
ClientCert string `json:"client_cert"`
|
||||
ClientKey string `json:"client_key"`
|
||||
CACert string `json:"ca_cert"`
|
||||
}
|
||||
|
||||
func (req updateCertReq) validate() error {
|
||||
if req.thingID == "" {
|
||||
if req.clientID == "" {
|
||||
return apiutil.ErrMissingID
|
||||
}
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
apiutil "github.com/absmach/supermq/api/http/util"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -151,20 +151,20 @@ func TestUpdateReqValidation(t *testing.T) {
|
||||
|
||||
func TestUpdateCertReqValidation(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
thingID string
|
||||
err error
|
||||
desc string
|
||||
clientID string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "empty thing id",
|
||||
thingID: "",
|
||||
err: apiutil.ErrMissingID,
|
||||
desc: "empty client id",
|
||||
clientID: "",
|
||||
err: apiutil.ErrMissingID,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
req := updateCertReq{
|
||||
thingID: tc.thingID,
|
||||
clientID: tc.clientID,
|
||||
}
|
||||
|
||||
err := req.validate()
|
||||
|
||||
+20
-20
@@ -7,16 +7,16 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/absmach/magistrala"
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/supermq"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
)
|
||||
|
||||
var (
|
||||
_ magistrala.Response = (*removeRes)(nil)
|
||||
_ magistrala.Response = (*configRes)(nil)
|
||||
_ magistrala.Response = (*stateRes)(nil)
|
||||
_ magistrala.Response = (*viewRes)(nil)
|
||||
_ magistrala.Response = (*listRes)(nil)
|
||||
_ supermq.Response = (*removeRes)(nil)
|
||||
_ supermq.Response = (*configRes)(nil)
|
||||
_ supermq.Response = (*stateRes)(nil)
|
||||
_ supermq.Response = (*viewRes)(nil)
|
||||
_ supermq.Response = (*listRes)(nil)
|
||||
)
|
||||
|
||||
type removeRes struct{}
|
||||
@@ -49,7 +49,7 @@ func (res configRes) Code() int {
|
||||
func (res configRes) Headers() map[string]string {
|
||||
if res.created {
|
||||
return map[string]string{
|
||||
"Location": fmt.Sprintf("/things/configs/%s", res.id),
|
||||
"Location": fmt.Sprintf("/clients/configs/%s", res.id),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,16 +67,16 @@ type channelRes struct {
|
||||
}
|
||||
|
||||
type viewRes struct {
|
||||
ThingID string `json:"thing_id,omitempty"`
|
||||
ThingKey string `json:"thing_key,omitempty"`
|
||||
Channels []channelRes `json:"channels,omitempty"`
|
||||
ExternalID string `json:"external_id"`
|
||||
ExternalKey string `json:"external_key,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
State bootstrap.State `json:"state"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
ClientID string `json:"client_id,omitempty"`
|
||||
CLientSecret string `json:"client_secret,omitempty"`
|
||||
Channels []channelRes `json:"channels,omitempty"`
|
||||
ExternalID string `json:"external_id"`
|
||||
ExternalKey string `json:"external_key,omitempty"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
State bootstrap.State `json:"state"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
}
|
||||
|
||||
func (res viewRes) Code() int {
|
||||
@@ -125,9 +125,9 @@ func (res stateRes) Empty() bool {
|
||||
}
|
||||
|
||||
type updateConfigRes struct {
|
||||
ThingID string `json:"thing_id,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientID string `json:"client_id,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
+15
-15
@@ -11,12 +11,12 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/absmach/magistrala"
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/internal/api"
|
||||
"github.com/absmach/magistrala/pkg/apiutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/absmach/supermq"
|
||||
api "github.com/absmach/supermq/api/http"
|
||||
apiutil "github.com/absmach/supermq/api/http/util"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
"github.com/go-chi/chi/v5"
|
||||
kithttp "github.com/go-kit/kit/transport/http"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
@@ -33,21 +33,21 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
fullMatch = []string{"state", "external_id", "thing_id", "thing_key"}
|
||||
fullMatch = []string{"state", "external_id", "client_id", "client_key"}
|
||||
partialMatch = []string{"name"}
|
||||
// ErrBootstrap indicates error in getting bootstrap configuration.
|
||||
ErrBootstrap = errors.New("failed to read bootstrap configuration")
|
||||
)
|
||||
|
||||
// MakeHandler returns a HTTP handler for API endpoints.
|
||||
func MakeHandler(svc bootstrap.Service, authn mgauthn.Authentication, reader bootstrap.ConfigReader, logger *slog.Logger, instanceID string) http.Handler {
|
||||
func MakeHandler(svc bootstrap.Service, authn smqauthn.Authentication, reader bootstrap.ConfigReader, logger *slog.Logger, instanceID string) http.Handler {
|
||||
opts := []kithttp.ServerOption{
|
||||
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)),
|
||||
}
|
||||
|
||||
r := chi.NewRouter()
|
||||
|
||||
r.Route("/{domainID}/things", func(r chi.Router) {
|
||||
r.Route("/{domainID}/clients", func(r chi.Router) {
|
||||
r.Group(func(r chi.Router) {
|
||||
r.Use(api.AuthenticateMiddleware(authn, true))
|
||||
|
||||
@@ -96,14 +96,14 @@ func MakeHandler(svc bootstrap.Service, authn mgauthn.Authentication, reader boo
|
||||
})
|
||||
})
|
||||
|
||||
r.With(api.AuthenticateMiddleware(authn, true)).Put("/state/{thingID}", otelhttp.NewHandler(kithttp.NewServer(
|
||||
r.With(api.AuthenticateMiddleware(authn, true)).Put("/state/{clientID}", otelhttp.NewHandler(kithttp.NewServer(
|
||||
stateEndpoint(svc),
|
||||
decodeStateRequest,
|
||||
api.EncodeResponse,
|
||||
opts...), "update_state").ServeHTTP)
|
||||
})
|
||||
|
||||
r.Route("/things/bootstrap", func(r chi.Router) {
|
||||
r.Route("/clients/bootstrap", func(r chi.Router) {
|
||||
r.Get("/", otelhttp.NewHandler(kithttp.NewServer(
|
||||
bootstrapEndpoint(svc, reader, false),
|
||||
decodeBootstrapRequest,
|
||||
@@ -121,7 +121,7 @@ func MakeHandler(svc bootstrap.Service, authn mgauthn.Authentication, reader boo
|
||||
opts...), "bootstrap_secure").ServeHTTP)
|
||||
})
|
||||
|
||||
r.Get("/health", magistrala.Health("bootstrap", instanceID))
|
||||
r.Get("/health", supermq.Health("bootstrap", instanceID))
|
||||
r.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
return r
|
||||
@@ -163,7 +163,7 @@ func decodeUpdateCertRequest(_ context.Context, r *http.Request) (interface{}, e
|
||||
}
|
||||
|
||||
req := updateCertReq{
|
||||
thingID: chi.URLParam(r, "certID"),
|
||||
clientID: chi.URLParam(r, "certID"),
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity))
|
||||
@@ -216,7 +216,7 @@ func decodeListRequest(_ context.Context, r *http.Request) (interface{}, error)
|
||||
func decodeBootstrapRequest(_ context.Context, r *http.Request) (interface{}, error) {
|
||||
req := bootstrapReq{
|
||||
id: chi.URLParam(r, "externalID"),
|
||||
key: apiutil.ExtractThingKey(r),
|
||||
key: apiutil.ExtractClientSecret(r),
|
||||
}
|
||||
|
||||
return req, nil
|
||||
@@ -229,7 +229,7 @@ func decodeStateRequest(_ context.Context, r *http.Request) (interface{}, error)
|
||||
|
||||
req := changeStateReq{
|
||||
token: apiutil.ExtractBearerToken(r),
|
||||
id: chi.URLParam(r, "thingID"),
|
||||
id: chi.URLParam(r, "clientID"),
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity))
|
||||
|
||||
+28
-28
@@ -7,30 +7,30 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/things"
|
||||
"github.com/absmach/supermq/clients"
|
||||
)
|
||||
|
||||
// Config represents Configuration entity. It wraps information about external entity
|
||||
// as well as info about corresponding Magistrala entities.
|
||||
// MGThing represents corresponding Magistrala Thing ID.
|
||||
// MGKey is key of corresponding Magistrala Thing.
|
||||
// MGChannels is a list of Magistrala Channels corresponding Magistrala Thing connects to.
|
||||
// as well as info about corresponding SuperMQ entities.
|
||||
// MGClient represents corresponding SuperMQ Client ID.
|
||||
// MGKey is key of corresponding SuperMQ Client.
|
||||
// MGChannels is a list of SuperMQ Channels corresponding SuperMQ Client connects to.
|
||||
type Config struct {
|
||||
ThingID string `json:"thing_id"`
|
||||
DomainID string `json:"domain_id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
ThingKey string `json:"thing_key"`
|
||||
Channels []Channel `json:"channels,omitempty"`
|
||||
ExternalID string `json:"external_id"`
|
||||
ExternalKey string `json:"external_key"`
|
||||
Content string `json:"content,omitempty"`
|
||||
State State `json:"state"`
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
DomainID string `json:"domain_id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
Channels []Channel `json:"channels,omitempty"`
|
||||
ExternalID string `json:"external_id"`
|
||||
ExternalKey string `json:"external_key"`
|
||||
Content string `json:"content,omitempty"`
|
||||
State State `json:"state"`
|
||||
}
|
||||
|
||||
// Channel represents Magistrala channel corresponding Magistrala Thing is connected to.
|
||||
// Channel represents SuperMQ channel corresponding SuperMQ Client is connected to.
|
||||
type Channel struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name,omitempty"`
|
||||
@@ -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 things.Status `json:"status"`
|
||||
Status clients.Status `json:"status"`
|
||||
}
|
||||
|
||||
// Filter is used for the search filters.
|
||||
@@ -73,7 +73,7 @@ type ConfigRepository interface {
|
||||
|
||||
// RetrieveAll retrieves a subset of Configs that are owned
|
||||
// by the specific user, with given filter parameters.
|
||||
RetrieveAll(ctx context.Context, domainID string, thingIDs []string, filter Filter, offset, limit uint64) ConfigsPage
|
||||
RetrieveAll(ctx context.Context, domainID string, clientIDs []string, filter Filter, offset, limit uint64) ConfigsPage
|
||||
|
||||
// RetrieveByExternalID returns Config for given external ID.
|
||||
RetrieveByExternalID(ctx context.Context, externalID string) (Config, error)
|
||||
@@ -84,7 +84,7 @@ type ConfigRepository interface {
|
||||
|
||||
// UpdateCerts updates and returns an existing Config certificate and domainID.
|
||||
// A non-nil error is returned to indicate operation failure.
|
||||
UpdateCert(ctx context.Context, domainID, thingID, clientCert, clientKey, caCert string) (Config, error)
|
||||
UpdateCert(ctx context.Context, domainID, clientID, clientCert, clientKey, caCert string) (Config, error)
|
||||
|
||||
// UpdateConnections updates a list of Channels the Config is connected to
|
||||
// adding new Channels if needed.
|
||||
@@ -100,11 +100,11 @@ type ConfigRepository interface {
|
||||
// ListExisting retrieves those channels from the given list that exist in DB.
|
||||
ListExisting(ctx context.Context, domainID string, ids []string) ([]Channel, error)
|
||||
|
||||
// Methods RemoveThing, UpdateChannel, and RemoveChannel are related to
|
||||
// Methods RemoveClient, UpdateChannel, and RemoveChannel are related to
|
||||
// event sourcing. That's why these methods surpass ownership check.
|
||||
|
||||
// RemoveThing removes Config of the Thing with the given ID.
|
||||
RemoveThing(ctx context.Context, id string) error
|
||||
// RemoveClient removes Config of the Client with the given ID.
|
||||
RemoveClient(ctx context.Context, id string) error
|
||||
|
||||
// UpdateChannel updates channel with the given ID.
|
||||
UpdateChannel(ctx context.Context, c Channel) error
|
||||
@@ -112,9 +112,9 @@ type ConfigRepository interface {
|
||||
// RemoveChannel removes channel with the given ID.
|
||||
RemoveChannel(ctx context.Context, id string) error
|
||||
|
||||
// ConnectThing changes state of the Config when the corresponding Thing is connected to the Channel.
|
||||
ConnectThing(ctx context.Context, channelID, thingID string) error
|
||||
// ConnectClient changes state of the Config when the corresponding Client is connected to the Channel.
|
||||
ConnectClient(ctx context.Context, channelID, clientID string) error
|
||||
|
||||
// DisconnectThing changes state of the Config when the corresponding Thing is disconnected from the Channel.
|
||||
DisconnectThing(ctx context.Context, channelID, thingID string) error
|
||||
// DisconnectClient changes state of the Config when the corresponding Client is disconnected from the Channel.
|
||||
DisconnectClient(ctx context.Context, channelID, clientID string) error
|
||||
}
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package bootstrap contains the domain concept definitions needed to support
|
||||
// Magistrala bootstrap service functionality.
|
||||
// SuperMQ bootstrap service functionality.
|
||||
package bootstrap
|
||||
|
||||
@@ -19,6 +19,6 @@ type updateChannelEvent struct {
|
||||
|
||||
// Connection event is either connect or disconnect event.
|
||||
type connectionEvent struct {
|
||||
thingIDs []string
|
||||
clientIDs []string
|
||||
channelID string
|
||||
}
|
||||
|
||||
@@ -7,21 +7,21 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/events"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
"github.com/absmach/supermq/pkg/events"
|
||||
)
|
||||
|
||||
const (
|
||||
thingRemove = "thing.remove"
|
||||
thingConnect = "group.assign"
|
||||
thingDisconnect = "group.unassign"
|
||||
clientRemove = "client.remove"
|
||||
clientConnect = "group.assign"
|
||||
clientDisconnect = "group.unassign"
|
||||
|
||||
channelPrefix = "group."
|
||||
channelPrefix = "channels."
|
||||
channelUpdate = channelPrefix + "update"
|
||||
channelRemove = channelPrefix + "remove"
|
||||
|
||||
memberKind = "things"
|
||||
memberKind = "client"
|
||||
relation = "group"
|
||||
)
|
||||
|
||||
@@ -43,35 +43,35 @@ func (es *eventHandler) Handle(ctx context.Context, event events.Event) error {
|
||||
}
|
||||
|
||||
switch msg["operation"] {
|
||||
case thingRemove:
|
||||
rte := decodeRemoveThing(msg)
|
||||
case clientRemove:
|
||||
rte := decodeRemoveClient(msg)
|
||||
err = es.svc.RemoveConfigHandler(ctx, rte.id)
|
||||
case thingConnect:
|
||||
cte := decodeConnectThing(msg)
|
||||
if cte.channelID == "" || len(cte.thingIDs) == 0 {
|
||||
case clientConnect:
|
||||
cte := decodeConnectClient(msg)
|
||||
if cte.channelID == "" || len(cte.clientIDs) == 0 {
|
||||
return svcerr.ErrMalformedEntity
|
||||
}
|
||||
for _, thingID := range cte.thingIDs {
|
||||
if thingID == "" {
|
||||
for _, clientID := range cte.clientIDs {
|
||||
if clientID == "" {
|
||||
return svcerr.ErrMalformedEntity
|
||||
}
|
||||
if err := es.svc.ConnectThingHandler(ctx, cte.channelID, thingID); err != nil {
|
||||
if err := es.svc.ConnectClientHandler(ctx, cte.channelID, clientID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case thingDisconnect:
|
||||
dte := decodeDisconnectThing(msg)
|
||||
if dte.channelID == "" || len(dte.thingIDs) == 0 {
|
||||
case clientDisconnect:
|
||||
dte := decodeDisconnectClient(msg)
|
||||
if dte.channelID == "" || len(dte.clientIDs) == 0 {
|
||||
return svcerr.ErrMalformedEntity
|
||||
}
|
||||
for _, thingID := range dte.thingIDs {
|
||||
if thingID == "" {
|
||||
for _, clientID := range dte.clientIDs {
|
||||
if clientID == "" {
|
||||
return svcerr.ErrMalformedEntity
|
||||
}
|
||||
}
|
||||
|
||||
for _, thingID := range dte.thingIDs {
|
||||
if err = es.svc.DisconnectThingHandler(ctx, dte.channelID, thingID); err != nil {
|
||||
for _, c := range dte.clientIDs {
|
||||
if err = es.svc.DisconnectClientHandler(ctx, dte.channelID, c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func (es *eventHandler) Handle(ctx context.Context, event events.Event) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeRemoveThing(event map[string]interface{}) removeEvent {
|
||||
func decodeRemoveClient(event map[string]interface{}) removeEvent {
|
||||
return removeEvent{
|
||||
id: events.Read(event, "id", ""),
|
||||
}
|
||||
@@ -113,25 +113,25 @@ func decodeRemoveChannel(event map[string]interface{}) removeEvent {
|
||||
}
|
||||
}
|
||||
|
||||
func decodeConnectThing(event map[string]interface{}) connectionEvent {
|
||||
func decodeConnectClient(event map[string]interface{}) connectionEvent {
|
||||
if events.Read(event, "memberKind", "") != memberKind && events.Read(event, "relation", "") != relation {
|
||||
return connectionEvent{}
|
||||
}
|
||||
|
||||
return connectionEvent{
|
||||
channelID: events.Read(event, "group_id", ""),
|
||||
thingIDs: events.ReadStringSlice(event, "member_ids"),
|
||||
clientIDs: events.ReadStringSlice(event, "member_ids"),
|
||||
}
|
||||
}
|
||||
|
||||
func decodeDisconnectThing(event map[string]interface{}) connectionEvent {
|
||||
func decodeDisconnectClient(event map[string]interface{}) connectionEvent {
|
||||
if events.Read(event, "memberKind", "") != memberKind && events.Read(event, "relation", "") != relation {
|
||||
return connectionEvent{}
|
||||
}
|
||||
|
||||
return connectionEvent{
|
||||
channelID: events.Read(event, "group_id", ""),
|
||||
thingIDs: events.ReadStringSlice(event, "member_ids"),
|
||||
clientIDs: events.ReadStringSlice(event, "member_ids"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
package producer
|
||||
|
||||
import (
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/pkg/events"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
"github.com/absmach/supermq/pkg/events"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -17,12 +17,12 @@ const (
|
||||
configList = configPrefix + "list"
|
||||
configHandlerRemove = configPrefix + "remove_handler"
|
||||
|
||||
thingPrefix = "bootstrap.thing."
|
||||
thingBootstrap = thingPrefix + "bootstrap"
|
||||
thingStateChange = thingPrefix + "change_state"
|
||||
thingUpdateConnections = thingPrefix + "update_connections"
|
||||
thingConnect = thingPrefix + "connect"
|
||||
thingDisconnect = thingPrefix + "disconnect"
|
||||
clientPrefix = "bootstrap.client."
|
||||
clientBootstrap = clientPrefix + "bootstrap"
|
||||
clientStateChange = clientPrefix + "change_state"
|
||||
clientUpdateConnections = clientPrefix + "update_connections"
|
||||
clientConnect = clientPrefix + "connect"
|
||||
clientDisconnect = clientPrefix + "disconnect"
|
||||
|
||||
channelPrefix = "bootstrap.channel."
|
||||
channelHandlerRemove = channelPrefix + "remove_handler"
|
||||
@@ -52,8 +52,8 @@ func (ce configEvent) Encode() (map[string]interface{}, error) {
|
||||
"state": ce.State.String(),
|
||||
"operation": ce.operation,
|
||||
}
|
||||
if ce.ThingID != "" {
|
||||
val["thing_id"] = ce.ThingID
|
||||
if ce.ClientID != "" {
|
||||
val["client_id"] = ce.ClientID
|
||||
}
|
||||
if ce.Content != "" {
|
||||
val["content"] = ce.Content
|
||||
@@ -91,12 +91,12 @@ func (ce configEvent) Encode() (map[string]interface{}, error) {
|
||||
}
|
||||
|
||||
type removeConfigEvent struct {
|
||||
mgThing string
|
||||
client string
|
||||
}
|
||||
|
||||
func (rce removeConfigEvent) Encode() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"thing_id": rce.mgThing,
|
||||
"client_id": rce.client,
|
||||
"operation": configRemove,
|
||||
}, nil
|
||||
}
|
||||
@@ -134,11 +134,11 @@ func (be bootstrapEvent) Encode() (map[string]interface{}, error) {
|
||||
val := map[string]interface{}{
|
||||
"external_id": be.externalID,
|
||||
"success": be.success,
|
||||
"operation": thingBootstrap,
|
||||
"operation": clientBootstrap,
|
||||
}
|
||||
|
||||
if be.ThingID != "" {
|
||||
val["thing_id"] = be.ThingID
|
||||
if be.ClientID != "" {
|
||||
val["client_id"] = be.ClientID
|
||||
}
|
||||
if be.Content != "" {
|
||||
val["content"] = be.Content
|
||||
@@ -175,38 +175,41 @@ func (be bootstrapEvent) Encode() (map[string]interface{}, error) {
|
||||
}
|
||||
|
||||
type changeStateEvent struct {
|
||||
mgThing string
|
||||
state bootstrap.State
|
||||
mgClient string
|
||||
state bootstrap.State
|
||||
}
|
||||
|
||||
func (cse changeStateEvent) Encode() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"thing_id": cse.mgThing,
|
||||
"client_id": cse.mgClient,
|
||||
"state": cse.state.String(),
|
||||
"operation": thingStateChange,
|
||||
"operation": clientStateChange,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type updateConnectionsEvent struct {
|
||||
mgThing string
|
||||
mgClient string
|
||||
mgChannels []string
|
||||
}
|
||||
|
||||
func (uce updateConnectionsEvent) Encode() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"thing_id": uce.mgThing,
|
||||
"client_id": uce.mgClient,
|
||||
"channels": uce.mgChannels,
|
||||
"operation": thingUpdateConnections,
|
||||
"operation": clientUpdateConnections,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type updateCertEvent struct {
|
||||
thingKey, clientCert, clientKey, caCert string
|
||||
clientID string
|
||||
clientCert string
|
||||
clientKey string
|
||||
caCert string
|
||||
}
|
||||
|
||||
func (uce updateCertEvent) Encode() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"thing_key": uce.thingKey,
|
||||
"client_id": uce.clientID,
|
||||
"client_cert": uce.clientCert,
|
||||
"client_key": uce.clientKey,
|
||||
"ca_cert": uce.caCert,
|
||||
@@ -247,28 +250,28 @@ func (uche updateChannelHandlerEvent) Encode() (map[string]interface{}, error) {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
type connectThingEvent struct {
|
||||
thingID string
|
||||
type connectClientEvent struct {
|
||||
clientID string
|
||||
channelID string
|
||||
}
|
||||
|
||||
func (cte connectThingEvent) Encode() (map[string]interface{}, error) {
|
||||
func (cte connectClientEvent) Encode() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"thing_id": cte.thingID,
|
||||
"client_id": cte.clientID,
|
||||
"channel_id": cte.channelID,
|
||||
"operation": thingConnect,
|
||||
"operation": clientConnect,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type disconnectThingEvent struct {
|
||||
thingID string
|
||||
type disconnectClientEvent struct {
|
||||
clientID string
|
||||
channelID string
|
||||
}
|
||||
|
||||
func (dte disconnectThingEvent) Encode() (map[string]interface{}, error) {
|
||||
func (dte disconnectClientEvent) Encode() (map[string]interface{}, error) {
|
||||
return map[string]interface{}{
|
||||
"thing_id": dte.thingID,
|
||||
"client_id": dte.clientID,
|
||||
"channel_id": dte.channelID,
|
||||
"operation": thingDisconnect,
|
||||
"operation": clientDisconnect,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ package producer
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/events"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/events"
|
||||
)
|
||||
|
||||
var _ bootstrap.Service = (*eventStore)(nil)
|
||||
@@ -27,7 +27,7 @@ func NewEventStoreMiddleware(svc bootstrap.Service, publisher events.Publisher)
|
||||
}
|
||||
}
|
||||
|
||||
func (es *eventStore) Add(ctx context.Context, session mgauthn.Session, token string, cfg bootstrap.Config) (bootstrap.Config, error) {
|
||||
func (es *eventStore) Add(ctx context.Context, session smqauthn.Session, token string, cfg bootstrap.Config) (bootstrap.Config, error) {
|
||||
saved, err := es.svc.Add(ctx, session, token, cfg)
|
||||
if err != nil {
|
||||
return saved, err
|
||||
@@ -44,7 +44,7 @@ func (es *eventStore) Add(ctx context.Context, session mgauthn.Session, token st
|
||||
return saved, err
|
||||
}
|
||||
|
||||
func (es *eventStore) View(ctx context.Context, session mgauthn.Session, id string) (bootstrap.Config, error) {
|
||||
func (es *eventStore) View(ctx context.Context, session smqauthn.Session, id string) (bootstrap.Config, error) {
|
||||
cfg, err := es.svc.View(ctx, session, id)
|
||||
if err != nil {
|
||||
return cfg, err
|
||||
@@ -60,7 +60,7 @@ func (es *eventStore) View(ctx context.Context, session mgauthn.Session, id stri
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
func (es *eventStore) Update(ctx context.Context, session mgauthn.Session, cfg bootstrap.Config) error {
|
||||
func (es *eventStore) Update(ctx context.Context, session smqauthn.Session, cfg bootstrap.Config) error {
|
||||
if err := es.svc.Update(ctx, session, cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -72,14 +72,14 @@ func (es *eventStore) Update(ctx context.Context, session mgauthn.Session, cfg b
|
||||
return es.Publish(ctx, ev)
|
||||
}
|
||||
|
||||
func (es eventStore) UpdateCert(ctx context.Context, session mgauthn.Session, thingKey, clientCert, clientKey, caCert string) (bootstrap.Config, error) {
|
||||
cfg, err := es.svc.UpdateCert(ctx, session, thingKey, clientCert, clientKey, caCert)
|
||||
func (es eventStore) UpdateCert(ctx context.Context, session smqauthn.Session, clientID, clientCert, clientKey, caCert string) (bootstrap.Config, error) {
|
||||
cfg, err := es.svc.UpdateCert(ctx, session, clientID, clientCert, clientKey, caCert)
|
||||
if err != nil {
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
ev := updateCertEvent{
|
||||
thingKey: thingKey,
|
||||
clientID: clientID,
|
||||
clientCert: clientCert,
|
||||
clientKey: clientKey,
|
||||
caCert: caCert,
|
||||
@@ -92,20 +92,20 @@ func (es eventStore) UpdateCert(ctx context.Context, session mgauthn.Session, th
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) UpdateConnections(ctx context.Context, session mgauthn.Session, token, id string, connections []string) error {
|
||||
func (es *eventStore) UpdateConnections(ctx context.Context, session smqauthn.Session, token, id string, connections []string) error {
|
||||
if err := es.svc.UpdateConnections(ctx, session, token, id, connections); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ev := updateConnectionsEvent{
|
||||
mgThing: id,
|
||||
mgClient: id,
|
||||
mgChannels: connections,
|
||||
}
|
||||
|
||||
return es.Publish(ctx, ev)
|
||||
}
|
||||
|
||||
func (es *eventStore) List(ctx context.Context, session mgauthn.Session, filter bootstrap.Filter, offset, limit uint64) (bootstrap.ConfigsPage, error) {
|
||||
func (es *eventStore) List(ctx context.Context, session smqauthn.Session, filter bootstrap.Filter, offset, limit uint64) (bootstrap.ConfigsPage, error) {
|
||||
bp, err := es.svc.List(ctx, session, filter, offset, limit)
|
||||
if err != nil {
|
||||
return bp, err
|
||||
@@ -125,13 +125,13 @@ func (es *eventStore) List(ctx context.Context, session mgauthn.Session, filter
|
||||
return bp, nil
|
||||
}
|
||||
|
||||
func (es *eventStore) Remove(ctx context.Context, session mgauthn.Session, id string) error {
|
||||
func (es *eventStore) Remove(ctx context.Context, session smqauthn.Session, id string) error {
|
||||
if err := es.svc.Remove(ctx, session, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ev := removeConfigEvent{
|
||||
mgThing: id,
|
||||
client: id,
|
||||
}
|
||||
|
||||
return es.Publish(ctx, ev)
|
||||
@@ -157,14 +157,14 @@ func (es *eventStore) Bootstrap(ctx context.Context, externalKey, externalID str
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
func (es *eventStore) ChangeState(ctx context.Context, session mgauthn.Session, token, id string, state bootstrap.State) error {
|
||||
func (es *eventStore) ChangeState(ctx context.Context, session smqauthn.Session, token, id string, state bootstrap.State) error {
|
||||
if err := es.svc.ChangeState(ctx, session, token, id, state); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ev := changeStateEvent{
|
||||
mgThing: id,
|
||||
state: state,
|
||||
mgClient: id,
|
||||
state: state,
|
||||
}
|
||||
|
||||
return es.Publish(ctx, ev)
|
||||
@@ -208,26 +208,26 @@ func (es *eventStore) UpdateChannelHandler(ctx context.Context, channel bootstra
|
||||
return es.Publish(ctx, ev)
|
||||
}
|
||||
|
||||
func (es *eventStore) ConnectThingHandler(ctx context.Context, channelID, thingID string) error {
|
||||
if err := es.svc.ConnectThingHandler(ctx, channelID, thingID); err != nil {
|
||||
func (es *eventStore) ConnectClientHandler(ctx context.Context, channelID, clientID string) error {
|
||||
if err := es.svc.ConnectClientHandler(ctx, channelID, clientID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ev := connectThingEvent{
|
||||
thingID: thingID,
|
||||
ev := connectClientEvent{
|
||||
clientID: clientID,
|
||||
channelID: channelID,
|
||||
}
|
||||
|
||||
return es.Publish(ctx, ev)
|
||||
}
|
||||
|
||||
func (es *eventStore) DisconnectThingHandler(ctx context.Context, channelID, thingID string) error {
|
||||
if err := es.svc.DisconnectThingHandler(ctx, channelID, thingID); err != nil {
|
||||
func (es *eventStore) DisconnectClientHandler(ctx context.Context, channelID, clientID string) error {
|
||||
if err := es.svc.DisconnectClientHandler(ctx, channelID, clientID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ev := disconnectThingEvent{
|
||||
thingID: thingID,
|
||||
ev := disconnectClientEvent{
|
||||
clientID: clientID,
|
||||
channelID: channelID,
|
||||
}
|
||||
|
||||
|
||||
@@ -11,20 +11,20 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala"
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/bootstrap/events/producer"
|
||||
"github.com/absmach/magistrala/bootstrap/mocks"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/events/store"
|
||||
policysvc "github.com/absmach/magistrala/pkg/policies"
|
||||
policymocks "github.com/absmach/magistrala/pkg/policies/mocks"
|
||||
mgsdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
sdkmocks "github.com/absmach/magistrala/pkg/sdk/mocks"
|
||||
"github.com/absmach/magistrala/pkg/uuid"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
"github.com/absmach/supermq/bootstrap/events/producer"
|
||||
"github.com/absmach/supermq/bootstrap/mocks"
|
||||
"github.com/absmach/supermq/pkg/authn"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
"github.com/absmach/supermq/pkg/events/store"
|
||||
policysvc "github.com/absmach/supermq/pkg/policies"
|
||||
policymocks "github.com/absmach/supermq/pkg/policies/mocks"
|
||||
mgsdk "github.com/absmach/supermq/pkg/sdk"
|
||||
sdkmocks "github.com/absmach/supermq/pkg/sdk/mocks"
|
||||
"github.com/absmach/supermq/pkg/uuid"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
@@ -32,13 +32,13 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
streamID = "magistrala.bootstrap"
|
||||
email = "user@example.com"
|
||||
validToken = "validToken"
|
||||
invalidToken = "invalid"
|
||||
unknownThingID = "unknown"
|
||||
channelsNum = 3
|
||||
defaultTimout = 5
|
||||
streamID = "supermq.bootstrap"
|
||||
email = "user@example.com"
|
||||
validToken = "validToken"
|
||||
invalidToken = "invalid"
|
||||
unknownClientID = "unknown"
|
||||
channelsNum = 3
|
||||
defaultTimout = 5
|
||||
|
||||
configPrefix = "config."
|
||||
configCreate = configPrefix + "create"
|
||||
@@ -48,12 +48,12 @@ const (
|
||||
configList = configPrefix + "list"
|
||||
configHandlerRemove = configPrefix + "remove_handler"
|
||||
|
||||
thingPrefix = "thing."
|
||||
thingBootstrap = thingPrefix + "bootstrap"
|
||||
thingStateChange = thingPrefix + "change_state"
|
||||
thingUpdateConnections = thingPrefix + "update_connections"
|
||||
thingConnect = thingPrefix + "connect"
|
||||
thingDisconnect = thingPrefix + "disconnect"
|
||||
clientPrefix = "client."
|
||||
clientBootstrap = clientPrefix + "bootstrap"
|
||||
clientStateChange = clientPrefix + "change_state"
|
||||
clientUpdateConnections = clientPrefix + "update_connections"
|
||||
clientConnect = clientPrefix + "connect"
|
||||
clientDisconnect = clientPrefix + "disconnect"
|
||||
|
||||
channelPrefix = "group."
|
||||
channelHandlerRemove = channelPrefix + "remove_handler"
|
||||
@@ -76,12 +76,12 @@ var (
|
||||
}
|
||||
|
||||
config = bootstrap.Config{
|
||||
ThingID: testsutil.GenerateUUID(&testing.T{}),
|
||||
ThingKey: testsutil.GenerateUUID(&testing.T{}),
|
||||
ExternalID: testsutil.GenerateUUID(&testing.T{}),
|
||||
ExternalKey: testsutil.GenerateUUID(&testing.T{}),
|
||||
Channels: []bootstrap.Channel{channel},
|
||||
Content: "config",
|
||||
ClientID: testsutil.GenerateUUID(&testing.T{}),
|
||||
ClientSecret: testsutil.GenerateUUID(&testing.T{}),
|
||||
ExternalID: testsutil.GenerateUUID(&testing.T{}),
|
||||
ExternalKey: testsutil.GenerateUUID(&testing.T{}),
|
||||
Channels: []bootstrap.Channel{channel},
|
||||
Content: "config",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -125,18 +125,18 @@ func TestAdd(t *testing.T) {
|
||||
invalidConfig.Channels = []bootstrap.Channel{{ID: "empty"}}
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
config bootstrap.Config
|
||||
token string
|
||||
session mgauthn.Session
|
||||
id string
|
||||
domainID string
|
||||
thingErr error
|
||||
channel []bootstrap.Channel
|
||||
listErr error
|
||||
saveErr error
|
||||
err error
|
||||
event map[string]interface{}
|
||||
desc string
|
||||
config bootstrap.Config
|
||||
token string
|
||||
session smqauthn.Session
|
||||
id string
|
||||
domainID string
|
||||
clientErr error
|
||||
channel []bootstrap.Channel
|
||||
listErr error
|
||||
saveErr error
|
||||
err error
|
||||
event map[string]interface{}
|
||||
}{
|
||||
{
|
||||
desc: "create config successfully",
|
||||
@@ -146,7 +146,7 @@ func TestAdd(t *testing.T) {
|
||||
domainID: domainID,
|
||||
channel: config.Channels,
|
||||
event: map[string]interface{}{
|
||||
"thing_id": "1",
|
||||
"client_id": "1",
|
||||
"domain_id": domainID,
|
||||
"name": config.Name,
|
||||
"channels": channels,
|
||||
@@ -158,14 +158,14 @@ func TestAdd(t *testing.T) {
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "create config with failed to fetch thing",
|
||||
config: config,
|
||||
token: validToken,
|
||||
id: validID,
|
||||
domainID: domainID,
|
||||
event: nil,
|
||||
thingErr: svcerr.ErrNotFound,
|
||||
err: svcerr.ErrNotFound,
|
||||
desc: "create config with failed to fetch client",
|
||||
config: config,
|
||||
token: validToken,
|
||||
id: validID,
|
||||
domainID: domainID,
|
||||
event: nil,
|
||||
clientErr: svcerr.ErrNotFound,
|
||||
err: svcerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "create config with failed to list existing",
|
||||
@@ -191,8 +191,8 @@ func TestAdd(t *testing.T) {
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
tc.session = mgauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
sdkCall := tv.sdk.On("Thing", tc.config.ThingID, tc.domainID, tc.token).Return(mgsdk.Thing{ID: tc.config.ThingID, Credentials: mgsdk.ClientCredentials{Secret: tc.config.ThingKey}}, errors.NewSDKError(tc.thingErr))
|
||||
tc.session = smqauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
sdkCall := tv.sdk.On("Client", tc.config.ClientID, tc.domainID, tc.token).Return(mgsdk.Client{ID: tc.config.ClientID, Credentials: mgsdk.ClientCredentials{Secret: tc.config.ClientSecret}}, errors.NewSDKError(tc.clientErr))
|
||||
repoCall := tv.boot.On("ListExisting", context.Background(), domainID, mock.Anything).Return(tc.config.Channels, tc.listErr)
|
||||
repoCall1 := tv.boot.On("Save", context.Background(), mock.Anything, mock.Anything).Return(mock.Anything, tc.saveErr)
|
||||
|
||||
@@ -226,13 +226,13 @@ func TestView(t *testing.T) {
|
||||
tv := newTestVariable(t, redisURL)
|
||||
|
||||
nonExisting := config
|
||||
nonExisting.ThingID = unknownThingID
|
||||
nonExisting.ClientID = unknownClientID
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
config bootstrap.Config
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
id string
|
||||
domainID string
|
||||
retrieveErr error
|
||||
@@ -247,7 +247,7 @@ func TestView(t *testing.T) {
|
||||
domainID: domainID,
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"thing_id": config.ThingID,
|
||||
"client_id": config.ClientID,
|
||||
"domain_id": config.DomainID,
|
||||
"name": config.Name,
|
||||
"channels": config.Channels,
|
||||
@@ -271,9 +271,9 @@ func TestView(t *testing.T) {
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
tc.session = mgauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := tv.boot.On("RetrieveByID", context.Background(), tc.domainID, tc.config.ThingID).Return(config, tc.retrieveErr)
|
||||
_, err := tv.svc.View(context.Background(), tc.session, tc.config.ThingID)
|
||||
tc.session = smqauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := tv.boot.On("RetrieveByID", context.Background(), tc.domainID, tc.config.ClientID).Return(config, tc.retrieveErr)
|
||||
_, err := tv.svc.View(context.Background(), tc.session, tc.config.ClientID)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
|
||||
streams := redisClient.XRead(context.Background(), &redis.XReadArgs{
|
||||
@@ -316,7 +316,7 @@ func TestUpdate(t *testing.T) {
|
||||
modified.Name = "new name"
|
||||
|
||||
nonExisting := config
|
||||
nonExisting.ThingID = unknownThingID
|
||||
nonExisting.ClientID = unknownClientID
|
||||
|
||||
channels := []string{modified.Channels[0].ID, modified.Channels[1].ID}
|
||||
|
||||
@@ -324,7 +324,7 @@ func TestUpdate(t *testing.T) {
|
||||
desc string
|
||||
config bootstrap.Config
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
id string
|
||||
domainID string
|
||||
updateErr error
|
||||
@@ -345,7 +345,7 @@ func TestUpdate(t *testing.T) {
|
||||
"operation": configUpdate,
|
||||
"channels": channels,
|
||||
"external_id": modified.ExternalID,
|
||||
"thing_id": modified.ThingID,
|
||||
"client_id": modified.ClientID,
|
||||
"domain_id": domainID,
|
||||
"state": "0",
|
||||
"occurred_at": time.Now().UnixNano(),
|
||||
@@ -365,7 +365,7 @@ func TestUpdate(t *testing.T) {
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
tc.session = mgauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := tv.boot.On("Update", context.Background(), mock.Anything).Return(tc.updateErr)
|
||||
err := tv.svc.Update(context.Background(), tc.session, tc.config)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
@@ -401,9 +401,9 @@ func TestUpdateConnections(t *testing.T) {
|
||||
id string
|
||||
domainID string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
connections []string
|
||||
thingErr error
|
||||
clientErr error
|
||||
channelErr error
|
||||
retrieveErr error
|
||||
listErr error
|
||||
@@ -413,22 +413,22 @@ func TestUpdateConnections(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
desc: "update connections successfully",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
id: validID,
|
||||
domainID: domainID,
|
||||
connections: []string{config.Channels[0].ID},
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"thing_id": config.ThingID,
|
||||
"client_id": config.ClientID,
|
||||
"channels": "2",
|
||||
"timestamp": time.Now().Unix(),
|
||||
"operation": thingUpdateConnections,
|
||||
"operation": clientUpdateConnections,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "update connections with failed channel fetch",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
id: validID,
|
||||
domainID: domainID,
|
||||
@@ -439,7 +439,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update connections with failed RetrieveByID",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
id: validID,
|
||||
domainID: domainID,
|
||||
@@ -450,7 +450,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update connections with failed ListExisting",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
id: validID,
|
||||
domainID: domainID,
|
||||
@@ -461,7 +461,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update connections with failed UpdateConnections",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
id: validID,
|
||||
domainID: domainID,
|
||||
@@ -474,7 +474,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
tc.session = mgauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
sdkCall := tv.sdk.On("Channel", mock.Anything, tc.domainID, tc.token).Return(mgsdk.Channel{}, tc.channelErr)
|
||||
repoCall := tv.boot.On("RetrieveByID", context.Background(), tc.domainID, tc.configID).Return(config, tc.retrieveErr)
|
||||
repoCall1 := tv.boot.On("ListExisting", context.Background(), domainID, mock.Anything, mock.Anything).Return(config.Channels, tc.listErr)
|
||||
@@ -514,7 +514,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
userID string
|
||||
domainID string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
clientCert string
|
||||
clientKey string
|
||||
caCert string
|
||||
@@ -524,7 +524,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
desc: "update cert successfully",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
token: validToken,
|
||||
@@ -533,16 +533,16 @@ func TestUpdateCert(t *testing.T) {
|
||||
caCert: "caCert",
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"thing_key": config.ThingKey,
|
||||
"client_cert": "clientCert",
|
||||
"client_key": "clientKey",
|
||||
"ca_cert": "caCert",
|
||||
"operation": certUpdate,
|
||||
"client_secret": config.ClientSecret,
|
||||
"client_cert": "clientCert",
|
||||
"client_key": "clientKey",
|
||||
"ca_cert": "caCert",
|
||||
"operation": certUpdate,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "update cert with failed update",
|
||||
configID: "invalidThingID",
|
||||
configID: "clientID",
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -555,7 +555,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update cert with empty client certificate",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -567,7 +567,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update cert with empty client key",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -579,7 +579,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update cert with empty CA certificate",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -591,7 +591,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "successful update without CA certificate",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -600,19 +600,19 @@ func TestUpdateCert(t *testing.T) {
|
||||
caCert: "",
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"thing_key": config.ThingKey,
|
||||
"client_cert": "clientCert",
|
||||
"client_key": "clientKey",
|
||||
"ca_cert": "caCert",
|
||||
"operation": certUpdate,
|
||||
"timestamp": time.Now().Unix(),
|
||||
"client_secret": config.ClientSecret,
|
||||
"client_cert": "clientCert",
|
||||
"client_key": "clientKey",
|
||||
"ca_cert": "caCert",
|
||||
"operation": certUpdate,
|
||||
"timestamp": time.Now().Unix(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := tv.boot.On("UpdateCert", context.Background(), tc.domainID, tc.configID, tc.clientCert, tc.clientKey, tc.caCert).Return(config, tc.updateErr)
|
||||
_, err := tv.svc.UpdateCert(context.Background(), tc.session, tc.configID, tc.clientCert, tc.clientKey, tc.caCert)
|
||||
|
||||
@@ -639,10 +639,10 @@ func TestUpdateCert(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
tv := newTestVariable(t, redisURL)
|
||||
|
||||
numThings := 101
|
||||
numClients := 101
|
||||
var c bootstrap.Config
|
||||
saved := make([]bootstrap.Config, 0)
|
||||
for i := 0; i < numThings; i++ {
|
||||
for i := 0; i < numClients; i++ {
|
||||
c := config
|
||||
c.ExternalID = testsutil.GenerateUUID(t)
|
||||
c.ExternalKey = testsutil.GenerateUUID(t)
|
||||
@@ -656,7 +656,7 @@ func TestList(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
userID string
|
||||
domainID string
|
||||
config bootstrap.ConfigsPage
|
||||
@@ -674,7 +674,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
config: bootstrap.ConfigsPage{
|
||||
Total: uint64(len(saved)),
|
||||
Offset: 0,
|
||||
@@ -687,7 +687,7 @@ func TestList(t *testing.T) {
|
||||
listObjectsResponse: policysvc.PolicyPage{},
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"thing_id": c.ThingID,
|
||||
"client_id": c.ClientID,
|
||||
"domain_id": c.DomainID,
|
||||
"name": c.Name,
|
||||
"channels": c.Channels,
|
||||
@@ -702,7 +702,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
config: bootstrap.ConfigsPage{
|
||||
Total: uint64(len(saved)),
|
||||
Offset: 0,
|
||||
@@ -715,7 +715,7 @@ func TestList(t *testing.T) {
|
||||
listObjectsResponse: policysvc.PolicyPage{},
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"thing_id": c.ThingID,
|
||||
"client_id": c.ClientID,
|
||||
"domain_id": c.DomainID,
|
||||
"name": c.Name,
|
||||
"channels": c.Channels,
|
||||
@@ -730,7 +730,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
config: bootstrap.ConfigsPage{
|
||||
Total: uint64(len(saved)),
|
||||
Offset: 0,
|
||||
@@ -743,7 +743,7 @@ func TestList(t *testing.T) {
|
||||
listObjectsResponse: policysvc.PolicyPage{},
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"thing_id": c.ThingID,
|
||||
"client_id": c.ClientID,
|
||||
"domain_id": c.DomainID,
|
||||
"name": c.Name,
|
||||
"channels": c.Channels,
|
||||
@@ -758,7 +758,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
filter: bootstrap.Filter{},
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
@@ -773,7 +773,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
filter: bootstrap.Filter{},
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
@@ -787,7 +787,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
filter: bootstrap.Filter{},
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
@@ -801,7 +801,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
filter: bootstrap.Filter{},
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
@@ -818,7 +818,7 @@ func TestList(t *testing.T) {
|
||||
SubjectType: policysvc.UserType,
|
||||
Subject: tc.userID,
|
||||
Permission: policysvc.ViewPermission,
|
||||
ObjectType: policysvc.ThingType,
|
||||
ObjectType: policysvc.ClientType,
|
||||
}).Return(tc.listObjectsResponse, tc.listObjectsErr)
|
||||
repoCall := tv.boot.On("RetrieveAll", context.Background(), mock.Anything, mock.Anything, tc.filter, tc.offset, tc.limit).Return(tc.config, tc.retrieveErr)
|
||||
|
||||
@@ -851,7 +851,7 @@ func TestRemove(t *testing.T) {
|
||||
tv := newTestVariable(t, redisURL)
|
||||
|
||||
nonExisting := config
|
||||
nonExisting.ThingID = unknownThingID
|
||||
nonExisting.ClientID = unknownClientID
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
@@ -859,27 +859,27 @@ func TestRemove(t *testing.T) {
|
||||
userID string
|
||||
domainID string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
removeErr error
|
||||
err error
|
||||
event map[string]interface{}
|
||||
}{
|
||||
{
|
||||
desc: "remove config successfully",
|
||||
configID: config.ThingID,
|
||||
configID: config.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"thing_id": config.ThingID,
|
||||
"client_id": config.ClientID,
|
||||
"timestamp": time.Now().Unix(),
|
||||
"operation": configRemove,
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "remove config with failed removal",
|
||||
configID: nonExisting.ThingID,
|
||||
configID: nonExisting.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -891,7 +891,7 @@ func TestRemove(t *testing.T) {
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
tc.session = mgauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := tv.boot.On("Remove", context.Background(), mock.Anything, mock.Anything).Return(tc.removeErr)
|
||||
err := tv.svc.Remove(context.Background(), tc.session, tc.configID)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
@@ -936,7 +936,7 @@ func TestBootstrap(t *testing.T) {
|
||||
"external_id": config.ExternalID,
|
||||
"success": "1",
|
||||
"timestamp": time.Now().Unix(),
|
||||
"operation": thingBootstrap,
|
||||
"operation": clientBootstrap,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -949,7 +949,7 @@ func TestBootstrap(t *testing.T) {
|
||||
"external_id": "external_id",
|
||||
"success": "0",
|
||||
"timestamp": time.Now().Unix(),
|
||||
"operation": thingBootstrap,
|
||||
"operation": clientBootstrap,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -988,9 +988,9 @@ func TestChangeState(t *testing.T) {
|
||||
userID string
|
||||
domainID string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
state bootstrap.State
|
||||
authResponse *magistrala.AuthZRes
|
||||
authResponse authn.Session
|
||||
authorizeErr error
|
||||
connectErr error
|
||||
retrieveErr error
|
||||
@@ -1001,18 +1001,18 @@ func TestChangeState(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
desc: "change state to active",
|
||||
id: config.ThingID,
|
||||
id: config.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
state: bootstrap.Active,
|
||||
authResponse: &magistrala.AuthZRes{Authorized: true},
|
||||
authResponse: authn.Session{},
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"thing_id": config.ThingID,
|
||||
"client_id": config.ClientID,
|
||||
"state": bootstrap.Active.String(),
|
||||
"timestamp": time.Now().Unix(),
|
||||
"operation": thingStateChange,
|
||||
"operation": clientStateChange,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -1028,18 +1028,18 @@ func TestChangeState(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "change state with failed connect",
|
||||
id: config.ThingID,
|
||||
id: config.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
state: bootstrap.Active,
|
||||
connectErr: bootstrap.ErrThings,
|
||||
err: bootstrap.ErrThings,
|
||||
connectErr: bootstrap.ErrClients,
|
||||
err: bootstrap.ErrClients,
|
||||
event: nil,
|
||||
},
|
||||
{
|
||||
desc: "change state unsuccessfully",
|
||||
id: config.ThingID,
|
||||
id: config.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -1052,9 +1052,9 @@ func TestChangeState(t *testing.T) {
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
tc.session = mgauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: validID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := tv.boot.On("RetrieveByID", context.Background(), tc.domainID, tc.id).Return(config, tc.retrieveErr)
|
||||
sdkCall1 := tv.sdk.On("Connect", mock.Anything, mock.Anything, mock.Anything).Return(errors.NewSDKError(tc.connectErr))
|
||||
sdkCall1 := tv.sdk.On("ConnectClients", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(errors.NewSDKError(tc.connectErr))
|
||||
repoCall1 := tv.boot.On("ChangeState", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(tc.stateErr)
|
||||
err := tv.svc.ChangeState(context.Background(), tc.session, tc.token, tc.id, tc.state)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
@@ -1261,7 +1261,7 @@ func TestRemoveConfigHandler(t *testing.T) {
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
repoCall := tv.boot.On("RemoveThing", context.Background(), mock.Anything).Return(tc.err)
|
||||
repoCall := tv.boot.On("RemoveClient", context.Background(), mock.Anything).Return(tc.err)
|
||||
err := tv.svc.RemoveConfigHandler(context.Background(), tc.configID)
|
||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
|
||||
@@ -1284,7 +1284,7 @@ func TestRemoveConfigHandler(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectThingHandler(t *testing.T) {
|
||||
func TestConnectClientHandler(t *testing.T) {
|
||||
err := redisClient.FlushAll(context.Background()).Err()
|
||||
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
||||
|
||||
@@ -1293,41 +1293,41 @@ func TestConnectThingHandler(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
channelID string
|
||||
thingID string
|
||||
clientID string
|
||||
err error
|
||||
event map[string]interface{}
|
||||
}{
|
||||
{
|
||||
desc: "connect thing handler successfully",
|
||||
desc: "connect client handler successfully",
|
||||
channelID: channel.ID,
|
||||
thingID: "1",
|
||||
clientID: "1",
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"channel_id": channel.ID,
|
||||
"thing_id": "1",
|
||||
"operation": thingConnect,
|
||||
"client_id": "1",
|
||||
"operation": clientConnect,
|
||||
"timestamp": time.Now().UnixNano(),
|
||||
"occurred_at": time.Now().UnixNano(),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "connect non-existing thing handler",
|
||||
desc: "connect non-existing client handler",
|
||||
channelID: channel.ID,
|
||||
thingID: "unknown",
|
||||
clientID: "unknown",
|
||||
err: nil,
|
||||
event: nil,
|
||||
},
|
||||
{
|
||||
desc: "connect thing handler with empty thing ID",
|
||||
desc: "connect client handler with empty client ID",
|
||||
channelID: channel.ID,
|
||||
thingID: "",
|
||||
clientID: "",
|
||||
err: nil,
|
||||
event: nil,
|
||||
},
|
||||
{
|
||||
desc: "connect thing handler with empty channel ID",
|
||||
desc: "connect client handler with empty channel ID",
|
||||
channelID: "",
|
||||
thingID: "1",
|
||||
clientID: "1",
|
||||
err: nil,
|
||||
event: nil,
|
||||
},
|
||||
@@ -1335,8 +1335,8 @@ func TestConnectThingHandler(t *testing.T) {
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
repoCall := tv.boot.On("ConnectThing", context.Background(), mock.Anything, mock.Anything).Return(tc.err)
|
||||
err := tv.svc.ConnectThingHandler(context.Background(), tc.channelID, tc.thingID)
|
||||
repoCall := tv.boot.On("ConnectClient", context.Background(), mock.Anything, mock.Anything).Return(tc.err)
|
||||
err := tv.svc.ConnectClientHandler(context.Background(), tc.channelID, tc.clientID)
|
||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
|
||||
streams := redisClient.XRead(context.Background(), &redis.XReadArgs{
|
||||
@@ -1358,7 +1358,7 @@ func TestConnectThingHandler(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisconnectThingHandler(t *testing.T) {
|
||||
func TestDisconnectClientHandler(t *testing.T) {
|
||||
err := redisClient.FlushAll(context.Background()).Err()
|
||||
assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err))
|
||||
|
||||
@@ -1367,50 +1367,50 @@ func TestDisconnectThingHandler(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
channelID string
|
||||
thingID string
|
||||
clientID string
|
||||
err error
|
||||
event map[string]interface{}
|
||||
}{
|
||||
{
|
||||
desc: "disconnect thing handler successfully",
|
||||
desc: "disconnect client handler successfully",
|
||||
channelID: channel.ID,
|
||||
thingID: "1",
|
||||
clientID: "1",
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"channel_id": channel.ID,
|
||||
"thing_id": "1",
|
||||
"operation": thingDisconnect,
|
||||
"client_id": "1",
|
||||
"operation": clientDisconnect,
|
||||
"timestamp": time.Now().UnixNano(),
|
||||
"occurred_at": time.Now().UnixNano(),
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "remove non-existing thing handler",
|
||||
desc: "remove non-existing client handler",
|
||||
channelID: "unknown",
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "remove thing handler with empty thing ID",
|
||||
desc: "remove client handler with empty client ID",
|
||||
channelID: channel.ID,
|
||||
thingID: "",
|
||||
clientID: "",
|
||||
err: nil,
|
||||
event: nil,
|
||||
},
|
||||
{
|
||||
desc: "remove thing handler with empty channel ID",
|
||||
desc: "remove client handler with empty channel ID",
|
||||
channelID: "",
|
||||
err: nil,
|
||||
event: nil,
|
||||
},
|
||||
{
|
||||
desc: "remove thing handler successfully",
|
||||
desc: "remove client handler successfully",
|
||||
channelID: channel.ID,
|
||||
thingID: "1",
|
||||
clientID: "1",
|
||||
err: nil,
|
||||
event: map[string]interface{}{
|
||||
"channel_id": channel.ID,
|
||||
"thing_id": "1",
|
||||
"operation": thingDisconnect,
|
||||
"client_id": "1",
|
||||
"operation": clientDisconnect,
|
||||
"timestamp": time.Now().UnixNano(),
|
||||
"occurred_at": time.Now().UnixNano(),
|
||||
},
|
||||
@@ -1419,8 +1419,8 @@ func TestDisconnectThingHandler(t *testing.T) {
|
||||
|
||||
lastID := "0"
|
||||
for _, tc := range cases {
|
||||
repoCall := tv.boot.On("DisconnectThing", context.Background(), tc.channelID, tc.thingID).Return(tc.err)
|
||||
err := tv.svc.DisconnectThingHandler(context.Background(), tc.channelID, tc.thingID)
|
||||
repoCall := tv.boot.On("DisconnectClient", context.Background(), tc.channelID, tc.clientID).Return(tc.err)
|
||||
err := tv.svc.DisconnectClientHandler(context.Background(), tc.channelID, tc.clientID)
|
||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
|
||||
streams := redisClient.XRead(context.Background(), &redis.XReadArgs{
|
||||
|
||||
@@ -6,29 +6,29 @@ package middleware
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/authz"
|
||||
mgauthz "github.com/absmach/magistrala/pkg/authz"
|
||||
"github.com/absmach/magistrala/pkg/policies"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/authz"
|
||||
smqauthz "github.com/absmach/supermq/pkg/authz"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
)
|
||||
|
||||
var _ bootstrap.Service = (*authorizationMiddleware)(nil)
|
||||
|
||||
type authorizationMiddleware struct {
|
||||
svc bootstrap.Service
|
||||
authz mgauthz.Authorization
|
||||
authz smqauthz.Authorization
|
||||
}
|
||||
|
||||
// AuthorizationMiddleware adds authorization to the clients service.
|
||||
func AuthorizationMiddleware(svc bootstrap.Service, authz mgauthz.Authorization) bootstrap.Service {
|
||||
func AuthorizationMiddleware(svc bootstrap.Service, authz smqauthz.Authorization) bootstrap.Service {
|
||||
return &authorizationMiddleware{
|
||||
svc: svc,
|
||||
authz: authz,
|
||||
}
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) Add(ctx context.Context, session mgauthn.Session, token string, cfg bootstrap.Config) (bootstrap.Config, error) {
|
||||
func (am *authorizationMiddleware) Add(ctx context.Context, session smqauthn.Session, token string, cfg bootstrap.Config) (bootstrap.Config, error) {
|
||||
if err := am.authorize(ctx, "", policies.UserType, policies.UsersKind, session.DomainUserID, policies.MembershipPermission, policies.DomainType, session.DomainID); err != nil {
|
||||
return bootstrap.Config{}, err
|
||||
}
|
||||
@@ -36,39 +36,39 @@ func (am *authorizationMiddleware) Add(ctx context.Context, session mgauthn.Sess
|
||||
return am.svc.Add(ctx, session, token, cfg)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) View(ctx context.Context, session mgauthn.Session, id string) (bootstrap.Config, error) {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.ViewPermission, policies.ThingType, id); err != nil {
|
||||
func (am *authorizationMiddleware) View(ctx context.Context, session smqauthn.Session, id string) (bootstrap.Config, error) {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.ViewPermission, policies.ClientType, id); err != nil {
|
||||
return bootstrap.Config{}, err
|
||||
}
|
||||
|
||||
return am.svc.View(ctx, session, id)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) Update(ctx context.Context, session mgauthn.Session, cfg bootstrap.Config) error {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.EditPermission, policies.ThingType, cfg.ThingID); err != nil {
|
||||
func (am *authorizationMiddleware) Update(ctx context.Context, session smqauthn.Session, cfg bootstrap.Config) error {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.EditPermission, policies.ClientType, cfg.ClientID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return am.svc.Update(ctx, session, cfg)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateCert(ctx context.Context, session mgauthn.Session, thingID, clientCert, clientKey, caCert string) (bootstrap.Config, error) {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.EditPermission, policies.ThingType, thingID); err != nil {
|
||||
func (am *authorizationMiddleware) UpdateCert(ctx context.Context, session smqauthn.Session, clientID, clientCert, clientKey, caCert string) (bootstrap.Config, error) {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.EditPermission, policies.ClientType, clientID); err != nil {
|
||||
return bootstrap.Config{}, err
|
||||
}
|
||||
|
||||
return am.svc.UpdateCert(ctx, session, thingID, clientCert, clientKey, caCert)
|
||||
return am.svc.UpdateCert(ctx, session, clientID, clientCert, clientKey, caCert)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) UpdateConnections(ctx context.Context, session mgauthn.Session, token, id string, connections []string) error {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.EditPermission, policies.ThingType, id); err != nil {
|
||||
func (am *authorizationMiddleware) UpdateConnections(ctx context.Context, session smqauthn.Session, token, id string, connections []string) error {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.EditPermission, policies.ClientType, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return am.svc.UpdateConnections(ctx, session, token, id, connections)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) List(ctx context.Context, session mgauthn.Session, filter bootstrap.Filter, offset, limit uint64) (bootstrap.ConfigsPage, error) {
|
||||
func (am *authorizationMiddleware) List(ctx context.Context, session smqauthn.Session, filter bootstrap.Filter, offset, limit uint64) (bootstrap.ConfigsPage, error) {
|
||||
if err := am.checkSuperAdmin(ctx, session.DomainUserID); err == nil {
|
||||
session.SuperAdmin = true
|
||||
}
|
||||
@@ -79,8 +79,8 @@ func (am *authorizationMiddleware) List(ctx context.Context, session mgauthn.Ses
|
||||
return am.svc.List(ctx, session, filter, offset, limit)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) Remove(ctx context.Context, session mgauthn.Session, id string) error {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.DeletePermission, policies.ThingType, id); err != nil {
|
||||
func (am *authorizationMiddleware) Remove(ctx context.Context, session smqauthn.Session, id string) error {
|
||||
if err := am.authorize(ctx, session.DomainID, policies.UserType, policies.UsersKind, session.DomainUserID, policies.DeletePermission, policies.ClientType, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ func (am *authorizationMiddleware) Bootstrap(ctx context.Context, externalKey, e
|
||||
return am.svc.Bootstrap(ctx, externalKey, externalID, secure)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ChangeState(ctx context.Context, session mgauthn.Session, token, id string, state bootstrap.State) error {
|
||||
func (am *authorizationMiddleware) ChangeState(ctx context.Context, session smqauthn.Session, token, id string, state bootstrap.State) error {
|
||||
return am.svc.ChangeState(ctx, session, token, id, state)
|
||||
}
|
||||
|
||||
@@ -107,12 +107,12 @@ func (am *authorizationMiddleware) RemoveChannelHandler(ctx context.Context, id
|
||||
return am.svc.RemoveChannelHandler(ctx, id)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) ConnectThingHandler(ctx context.Context, channelID, ThingID string) error {
|
||||
return am.svc.ConnectThingHandler(ctx, channelID, ThingID)
|
||||
func (am *authorizationMiddleware) ConnectClientHandler(ctx context.Context, channelID, clientID string) error {
|
||||
return am.svc.ConnectClientHandler(ctx, channelID, clientID)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) DisconnectThingHandler(ctx context.Context, channelID, ThingID string) error {
|
||||
return am.svc.DisconnectThingHandler(ctx, channelID, ThingID)
|
||||
func (am *authorizationMiddleware) DisconnectClientHandler(ctx context.Context, channelID, clientID string) error {
|
||||
return am.svc.DisconnectClientHandler(ctx, channelID, clientID)
|
||||
}
|
||||
|
||||
func (am *authorizationMiddleware) checkSuperAdmin(ctx context.Context, adminID string) error {
|
||||
@@ -121,7 +121,7 @@ func (am *authorizationMiddleware) checkSuperAdmin(ctx context.Context, adminID
|
||||
Subject: adminID,
|
||||
Permission: policies.AdminPermission,
|
||||
ObjectType: policies.PlatformType,
|
||||
Object: policies.MagistralaObject,
|
||||
Object: policies.SuperMQObject,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
)
|
||||
|
||||
var _ bootstrap.Service = (*loggingMiddleware)(nil)
|
||||
@@ -26,13 +26,13 @@ func LoggingMiddleware(svc bootstrap.Service, logger *slog.Logger) bootstrap.Ser
|
||||
return &loggingMiddleware{logger, svc}
|
||||
}
|
||||
|
||||
// Add logs the add request. It logs the thing ID and the time it took to complete the request.
|
||||
// Add logs the add request. It logs the client ID and the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) Add(ctx context.Context, session mgauthn.Session, token string, cfg bootstrap.Config) (saved bootstrap.Config, err error) {
|
||||
func (lm *loggingMiddleware) Add(ctx context.Context, session smqauthn.Session, token string, cfg bootstrap.Config) (saved bootstrap.Config, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("thing_id", saved.ThingID),
|
||||
slog.String("client_id", saved.ClientID),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.Any("error", err))
|
||||
@@ -45,33 +45,33 @@ func (lm *loggingMiddleware) Add(ctx context.Context, session mgauthn.Session, t
|
||||
return lm.svc.Add(ctx, session, token, cfg)
|
||||
}
|
||||
|
||||
// View logs the view request. It logs the thing ID and the time it took to complete the request.
|
||||
// View logs the view request. It logs the client ID and the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) View(ctx context.Context, session mgauthn.Session, id string) (saved bootstrap.Config, err error) {
|
||||
func (lm *loggingMiddleware) View(ctx context.Context, session smqauthn.Session, id string) (saved bootstrap.Config, 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("View thing config failed", args...)
|
||||
lm.logger.Warn("View client config failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("View thing config completed successfully", args...)
|
||||
lm.logger.Info("View client config completed successfully", args...)
|
||||
}(time.Now())
|
||||
|
||||
return lm.svc.View(ctx, session, id)
|
||||
}
|
||||
|
||||
// Update logs the update request. It logs bootstrap thing ID and the time it took to complete the request.
|
||||
// Update logs the update request. It logs bootstrap client ID and the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) Update(ctx context.Context, session mgauthn.Session, cfg bootstrap.Config) (err error) {
|
||||
func (lm *loggingMiddleware) Update(ctx context.Context, session smqauthn.Session, cfg bootstrap.Config) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.Group("config",
|
||||
slog.String("thing_id", cfg.ThingID),
|
||||
slog.String("client_id", cfg.ClientID),
|
||||
slog.String("name", cfg.Name),
|
||||
),
|
||||
}
|
||||
@@ -86,13 +86,13 @@ func (lm *loggingMiddleware) Update(ctx context.Context, session mgauthn.Session
|
||||
return lm.svc.Update(ctx, session, cfg)
|
||||
}
|
||||
|
||||
// UpdateCert logs the update_cert request. It logs thing ID and the time it took to complete the request.
|
||||
// UpdateCert logs the update_cert request. It logs client ID and the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) UpdateCert(ctx context.Context, session mgauthn.Session, thingID, clientCert, clientKey, caCert string) (cfg bootstrap.Config, err error) {
|
||||
func (lm *loggingMiddleware) UpdateCert(ctx context.Context, session smqauthn.Session, clientID, clientCert, clientKey, caCert string) (cfg bootstrap.Config, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("thing_id", cfg.ThingID),
|
||||
slog.String("client_id", cfg.ClientID),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.Any("error", err))
|
||||
@@ -102,16 +102,16 @@ func (lm *loggingMiddleware) UpdateCert(ctx context.Context, session mgauthn.Ses
|
||||
lm.logger.Info("Update bootstrap config certificate completed successfully", args...)
|
||||
}(time.Now())
|
||||
|
||||
return lm.svc.UpdateCert(ctx, session, thingID, clientCert, clientKey, caCert)
|
||||
return lm.svc.UpdateCert(ctx, session, clientID, clientCert, clientKey, caCert)
|
||||
}
|
||||
|
||||
// UpdateConnections logs the update_connections request. It logs bootstrap ID and the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) UpdateConnections(ctx context.Context, session mgauthn.Session, token, id string, connections []string) (err error) {
|
||||
func (lm *loggingMiddleware) UpdateConnections(ctx context.Context, session smqauthn.Session, token, id string, connections []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),
|
||||
slog.Any("connections", connections),
|
||||
}
|
||||
if err != nil {
|
||||
@@ -127,7 +127,7 @@ func (lm *loggingMiddleware) UpdateConnections(ctx context.Context, session mgau
|
||||
|
||||
// List logs the list request. It logs offset, limit and the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) List(ctx context.Context, session mgauthn.Session, filter bootstrap.Filter, offset, limit uint64) (res bootstrap.ConfigsPage, err error) {
|
||||
func (lm *loggingMiddleware) List(ctx context.Context, session smqauthn.Session, filter bootstrap.Filter, offset, limit uint64) (res bootstrap.ConfigsPage, err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -151,11 +151,11 @@ func (lm *loggingMiddleware) List(ctx context.Context, session mgauthn.Session,
|
||||
|
||||
// Remove logs the remove request. It logs bootstrap ID and the time it took to complete the request.
|
||||
// If the request fails, it logs the error.
|
||||
func (lm *loggingMiddleware) Remove(ctx context.Context, session mgauthn.Session, id string) (err error) {
|
||||
func (lm *loggingMiddleware) Remove(ctx context.Context, session smqauthn.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))
|
||||
@@ -185,7 +185,7 @@ func (lm *loggingMiddleware) Bootstrap(ctx context.Context, externalKey, externa
|
||||
return lm.svc.Bootstrap(ctx, externalKey, externalID, secure)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) ChangeState(ctx context.Context, session mgauthn.Session, token, id string, state bootstrap.State) (err error) {
|
||||
func (lm *loggingMiddleware) ChangeState(ctx context.Context, session smqauthn.Session, token, id string, state bootstrap.State) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
@@ -194,10 +194,10 @@ func (lm *loggingMiddleware) ChangeState(ctx context.Context, session mgauthn.Se
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.Any("error", err))
|
||||
lm.logger.Warn("Change thing state failed", args...)
|
||||
lm.logger.Warn("Change client state failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("Change thing state completed successfully", args...)
|
||||
lm.logger.Info("Change client state completed successfully", args...)
|
||||
}(time.Now())
|
||||
|
||||
return lm.svc.ChangeState(ctx, session, token, id, state)
|
||||
@@ -258,38 +258,38 @@ func (lm *loggingMiddleware) RemoveChannelHandler(ctx context.Context, id string
|
||||
return lm.svc.RemoveChannelHandler(ctx, id)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) ConnectThingHandler(ctx context.Context, channelID, thingID string) (err error) {
|
||||
func (lm *loggingMiddleware) ConnectClientHandler(ctx context.Context, channelID, clientID string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("channel_id", channelID),
|
||||
slog.String("thing_id", thingID),
|
||||
slog.String("client_id", clientID),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.Any("error", err))
|
||||
lm.logger.Warn("Connect thing handler failed", args...)
|
||||
lm.logger.Warn("Connect client handler failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("Connect thing handler completed successfully", args...)
|
||||
lm.logger.Info("Connect client handler completed successfully", args...)
|
||||
}(time.Now())
|
||||
|
||||
return lm.svc.ConnectThingHandler(ctx, channelID, thingID)
|
||||
return lm.svc.ConnectClientHandler(ctx, channelID, clientID)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) DisconnectThingHandler(ctx context.Context, channelID, thingID string) (err error) {
|
||||
func (lm *loggingMiddleware) DisconnectClientHandler(ctx context.Context, channelID, clientID string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
args := []any{
|
||||
slog.String("duration", time.Since(begin).String()),
|
||||
slog.String("channel_id", channelID),
|
||||
slog.String("thing_id", thingID),
|
||||
slog.String("client_id", clientID),
|
||||
}
|
||||
if err != nil {
|
||||
args = append(args, slog.Any("error", err))
|
||||
lm.logger.Warn("Disconnect thing handler failed", args...)
|
||||
lm.logger.Warn("Disconnect client handler failed", args...)
|
||||
return
|
||||
}
|
||||
lm.logger.Info("Disconnect thing handler completed successfully", args...)
|
||||
lm.logger.Info("Disconnect client handler completed successfully", args...)
|
||||
}(time.Now())
|
||||
|
||||
return lm.svc.DisconnectThingHandler(ctx, channelID, thingID)
|
||||
return lm.svc.DisconnectClientHandler(ctx, channelID, clientID)
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/go-kit/kit/metrics"
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ func MetricsMiddleware(svc bootstrap.Service, counter metrics.Counter, latency m
|
||||
}
|
||||
|
||||
// Add instruments Add method with metrics.
|
||||
func (mm *metricsMiddleware) Add(ctx context.Context, session mgauthn.Session, token string, cfg bootstrap.Config) (saved bootstrap.Config, err error) {
|
||||
func (mm *metricsMiddleware) Add(ctx context.Context, session smqauthn.Session, token string, cfg bootstrap.Config) (saved bootstrap.Config, err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "add").Add(1)
|
||||
mm.latency.With("method", "add").Observe(time.Since(begin).Seconds())
|
||||
@@ -42,7 +42,7 @@ func (mm *metricsMiddleware) Add(ctx context.Context, session mgauthn.Session, t
|
||||
}
|
||||
|
||||
// View instruments View method with metrics.
|
||||
func (mm *metricsMiddleware) View(ctx context.Context, session mgauthn.Session, id string) (saved bootstrap.Config, err error) {
|
||||
func (mm *metricsMiddleware) View(ctx context.Context, session smqauthn.Session, id string) (saved bootstrap.Config, err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "view").Add(1)
|
||||
mm.latency.With("method", "view").Observe(time.Since(begin).Seconds())
|
||||
@@ -52,7 +52,7 @@ func (mm *metricsMiddleware) View(ctx context.Context, session mgauthn.Session,
|
||||
}
|
||||
|
||||
// Update instruments Update method with metrics.
|
||||
func (mm *metricsMiddleware) Update(ctx context.Context, session mgauthn.Session, cfg bootstrap.Config) (err error) {
|
||||
func (mm *metricsMiddleware) Update(ctx context.Context, session smqauthn.Session, cfg bootstrap.Config) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "update").Add(1)
|
||||
mm.latency.With("method", "update").Observe(time.Since(begin).Seconds())
|
||||
@@ -62,17 +62,17 @@ func (mm *metricsMiddleware) Update(ctx context.Context, session mgauthn.Session
|
||||
}
|
||||
|
||||
// UpdateCert instruments UpdateCert method with metrics.
|
||||
func (mm *metricsMiddleware) UpdateCert(ctx context.Context, session mgauthn.Session, thingKey, clientCert, clientKey, caCert string) (cfg bootstrap.Config, err error) {
|
||||
func (mm *metricsMiddleware) UpdateCert(ctx context.Context, session smqauthn.Session, clientID, clientCert, clientKey, caCert string) (cfg bootstrap.Config, err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "update_cert").Add(1)
|
||||
mm.latency.With("method", "update_cert").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.svc.UpdateCert(ctx, session, thingKey, clientCert, clientKey, caCert)
|
||||
return mm.svc.UpdateCert(ctx, session, clientID, clientCert, clientKey, caCert)
|
||||
}
|
||||
|
||||
// UpdateConnections instruments UpdateConnections method with metrics.
|
||||
func (mm *metricsMiddleware) UpdateConnections(ctx context.Context, session mgauthn.Session, token, id string, connections []string) (err error) {
|
||||
func (mm *metricsMiddleware) UpdateConnections(ctx context.Context, session smqauthn.Session, token, id string, connections []string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "update_connections").Add(1)
|
||||
mm.latency.With("method", "update_connections").Observe(time.Since(begin).Seconds())
|
||||
@@ -82,7 +82,7 @@ func (mm *metricsMiddleware) UpdateConnections(ctx context.Context, session mgau
|
||||
}
|
||||
|
||||
// List instruments List method with metrics.
|
||||
func (mm *metricsMiddleware) List(ctx context.Context, session mgauthn.Session, filter bootstrap.Filter, offset, limit uint64) (saved bootstrap.ConfigsPage, err error) {
|
||||
func (mm *metricsMiddleware) List(ctx context.Context, session smqauthn.Session, filter bootstrap.Filter, offset, limit uint64) (saved bootstrap.ConfigsPage, err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "list").Add(1)
|
||||
mm.latency.With("method", "list").Observe(time.Since(begin).Seconds())
|
||||
@@ -92,7 +92,7 @@ func (mm *metricsMiddleware) List(ctx context.Context, session mgauthn.Session,
|
||||
}
|
||||
|
||||
// Remove instruments Remove method with metrics.
|
||||
func (mm *metricsMiddleware) Remove(ctx context.Context, session mgauthn.Session, id string) (err error) {
|
||||
func (mm *metricsMiddleware) Remove(ctx context.Context, session smqauthn.Session, id string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "remove").Add(1)
|
||||
mm.latency.With("method", "remove").Observe(time.Since(begin).Seconds())
|
||||
@@ -112,7 +112,7 @@ func (mm *metricsMiddleware) Bootstrap(ctx context.Context, externalKey, externa
|
||||
}
|
||||
|
||||
// ChangeState instruments ChangeState method with metrics.
|
||||
func (mm *metricsMiddleware) ChangeState(ctx context.Context, session mgauthn.Session, token, id string, state bootstrap.State) (err error) {
|
||||
func (mm *metricsMiddleware) ChangeState(ctx context.Context, session smqauthn.Session, token, id string, state bootstrap.State) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "change_state").Add(1)
|
||||
mm.latency.With("method", "change_state").Observe(time.Since(begin).Seconds())
|
||||
@@ -151,22 +151,22 @@ func (mm *metricsMiddleware) RemoveChannelHandler(ctx context.Context, id string
|
||||
return mm.svc.RemoveChannelHandler(ctx, id)
|
||||
}
|
||||
|
||||
// ConnectThingHandler instruments ConnectThingHandler method with metrics.
|
||||
func (mm *metricsMiddleware) ConnectThingHandler(ctx context.Context, channelID, thingID string) (err error) {
|
||||
// ConnectClientHandler instruments ConnectClientHandler method with metrics.
|
||||
func (mm *metricsMiddleware) ConnectClientHandler(ctx context.Context, channelID, clientID string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "connect_thing_handler").Add(1)
|
||||
mm.latency.With("method", "connect_thing_handler").Observe(time.Since(begin).Seconds())
|
||||
mm.counter.With("method", "connect_client_handler").Add(1)
|
||||
mm.latency.With("method", "connect_client_handler").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.svc.ConnectThingHandler(ctx, channelID, thingID)
|
||||
return mm.svc.ConnectClientHandler(ctx, channelID, clientID)
|
||||
}
|
||||
|
||||
// DisconnectThingHandler instruments DisconnectThingHandler method with metrics.
|
||||
func (mm *metricsMiddleware) DisconnectThingHandler(ctx context.Context, channelID, thingID string) (err error) {
|
||||
// DisconnectClientHandler instruments DisconnectClientHandler method with metrics.
|
||||
func (mm *metricsMiddleware) DisconnectClientHandler(ctx context.Context, channelID, clientID string) (err error) {
|
||||
defer func(begin time.Time) {
|
||||
mm.counter.With("method", "disconnect_thing_handler").Add(1)
|
||||
mm.latency.With("method", "disconnect_thing_handler").Observe(time.Since(begin).Seconds())
|
||||
mm.counter.With("method", "disconnect_client_handler").Add(1)
|
||||
mm.latency.With("method", "disconnect_client_handler").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return mm.svc.DisconnectThingHandler(ctx, channelID, thingID)
|
||||
return mm.svc.DisconnectClientHandler(ctx, channelID, clientID)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
bootstrap "github.com/absmach/magistrala/bootstrap"
|
||||
bootstrap "github.com/absmach/supermq/bootstrap"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
|
||||
+24
-24
@@ -7,7 +7,7 @@ package mocks
|
||||
import (
|
||||
context "context"
|
||||
|
||||
bootstrap "github.com/absmach/magistrala/bootstrap"
|
||||
bootstrap "github.com/absmach/supermq/bootstrap"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
@@ -35,17 +35,17 @@ func (_m *ConfigRepository) ChangeState(ctx context.Context, domainID string, id
|
||||
return r0
|
||||
}
|
||||
|
||||
// ConnectThing provides a mock function with given fields: ctx, channelID, thingID
|
||||
func (_m *ConfigRepository) ConnectThing(ctx context.Context, channelID string, thingID string) error {
|
||||
ret := _m.Called(ctx, channelID, thingID)
|
||||
// ConnectClient provides a mock function with given fields: ctx, channelID, clientID
|
||||
func (_m *ConfigRepository) ConnectClient(ctx context.Context, channelID string, clientID string) error {
|
||||
ret := _m.Called(ctx, channelID, clientID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ConnectThing")
|
||||
panic("no return value specified for ConnectClient")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
|
||||
r0 = rf(ctx, channelID, thingID)
|
||||
r0 = rf(ctx, channelID, clientID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -53,17 +53,17 @@ func (_m *ConfigRepository) ConnectThing(ctx context.Context, channelID string,
|
||||
return r0
|
||||
}
|
||||
|
||||
// DisconnectThing provides a mock function with given fields: ctx, channelID, thingID
|
||||
func (_m *ConfigRepository) DisconnectThing(ctx context.Context, channelID string, thingID string) error {
|
||||
ret := _m.Called(ctx, channelID, thingID)
|
||||
// DisconnectClient provides a mock function with given fields: ctx, channelID, clientID
|
||||
func (_m *ConfigRepository) DisconnectClient(ctx context.Context, channelID string, clientID string) error {
|
||||
ret := _m.Called(ctx, channelID, clientID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DisconnectThing")
|
||||
panic("no return value specified for DisconnectClient")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
|
||||
r0 = rf(ctx, channelID, thingID)
|
||||
r0 = rf(ctx, channelID, clientID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -137,12 +137,12 @@ func (_m *ConfigRepository) RemoveChannel(ctx context.Context, id string) error
|
||||
return r0
|
||||
}
|
||||
|
||||
// RemoveThing provides a mock function with given fields: ctx, id
|
||||
func (_m *ConfigRepository) RemoveThing(ctx context.Context, id string) error {
|
||||
// RemoveClient provides a mock function with given fields: ctx, id
|
||||
func (_m *ConfigRepository) RemoveClient(ctx context.Context, id string) error {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveThing")
|
||||
panic("no return value specified for RemoveClient")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
@@ -155,9 +155,9 @@ func (_m *ConfigRepository) RemoveThing(ctx context.Context, id string) error {
|
||||
return r0
|
||||
}
|
||||
|
||||
// RetrieveAll provides a mock function with given fields: ctx, domainID, thingIDs, filter, offset, limit
|
||||
func (_m *ConfigRepository) RetrieveAll(ctx context.Context, domainID string, thingIDs []string, filter bootstrap.Filter, offset uint64, limit uint64) bootstrap.ConfigsPage {
|
||||
ret := _m.Called(ctx, domainID, thingIDs, filter, offset, limit)
|
||||
// RetrieveAll provides a mock function with given fields: ctx, domainID, clientIDs, filter, offset, limit
|
||||
func (_m *ConfigRepository) RetrieveAll(ctx context.Context, domainID string, clientIDs []string, filter bootstrap.Filter, offset uint64, limit uint64) bootstrap.ConfigsPage {
|
||||
ret := _m.Called(ctx, domainID, clientIDs, filter, offset, limit)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RetrieveAll")
|
||||
@@ -165,7 +165,7 @@ func (_m *ConfigRepository) RetrieveAll(ctx context.Context, domainID string, th
|
||||
|
||||
var r0 bootstrap.ConfigsPage
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, []string, bootstrap.Filter, uint64, uint64) bootstrap.ConfigsPage); ok {
|
||||
r0 = rf(ctx, domainID, thingIDs, filter, offset, limit)
|
||||
r0 = rf(ctx, domainID, clientIDs, filter, offset, limit)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bootstrap.ConfigsPage)
|
||||
}
|
||||
@@ -275,9 +275,9 @@ func (_m *ConfigRepository) Update(ctx context.Context, cfg bootstrap.Config) er
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateCert provides a mock function with given fields: ctx, domainID, thingID, clientCert, clientKey, caCert
|
||||
func (_m *ConfigRepository) UpdateCert(ctx context.Context, domainID string, thingID string, clientCert string, clientKey string, caCert string) (bootstrap.Config, error) {
|
||||
ret := _m.Called(ctx, domainID, thingID, clientCert, clientKey, caCert)
|
||||
// UpdateCert provides a mock function with given fields: ctx, domainID, clientID, clientCert, clientKey, caCert
|
||||
func (_m *ConfigRepository) UpdateCert(ctx context.Context, domainID string, clientID string, clientCert string, clientKey string, caCert string) (bootstrap.Config, error) {
|
||||
ret := _m.Called(ctx, domainID, clientID, clientCert, clientKey, caCert)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateCert")
|
||||
@@ -286,16 +286,16 @@ func (_m *ConfigRepository) UpdateCert(ctx context.Context, domainID string, thi
|
||||
var r0 bootstrap.Config
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string, string) (bootstrap.Config, error)); ok {
|
||||
return rf(ctx, domainID, thingID, clientCert, clientKey, caCert)
|
||||
return rf(ctx, domainID, clientID, clientCert, clientKey, caCert)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string, string) bootstrap.Config); ok {
|
||||
r0 = rf(ctx, domainID, thingID, clientCert, clientKey, caCert)
|
||||
r0 = rf(ctx, domainID, clientID, clientCert, clientKey, caCert)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bootstrap.Config)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, string, string, string, string) error); ok {
|
||||
r1 = rf(ctx, domainID, thingID, clientCert, clientKey, caCert)
|
||||
r1 = rf(ctx, domainID, clientID, clientCert, clientKey, caCert)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
+18
-18
@@ -5,8 +5,8 @@
|
||||
package mocks
|
||||
|
||||
import (
|
||||
bootstrap "github.com/absmach/magistrala/bootstrap"
|
||||
authn "github.com/absmach/magistrala/pkg/authn"
|
||||
bootstrap "github.com/absmach/supermq/bootstrap"
|
||||
authn "github.com/absmach/supermq/pkg/authn"
|
||||
|
||||
context "context"
|
||||
|
||||
@@ -92,17 +92,17 @@ func (_m *Service) ChangeState(ctx context.Context, session authn.Session, token
|
||||
return r0
|
||||
}
|
||||
|
||||
// ConnectThingHandler provides a mock function with given fields: ctx, channelID, ThingID
|
||||
func (_m *Service) ConnectThingHandler(ctx context.Context, channelID string, ThingID string) error {
|
||||
ret := _m.Called(ctx, channelID, ThingID)
|
||||
// ConnectClientHandler provides a mock function with given fields: ctx, channelID, clientID
|
||||
func (_m *Service) ConnectClientHandler(ctx context.Context, channelID string, clientID string) error {
|
||||
ret := _m.Called(ctx, channelID, clientID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ConnectThingHandler")
|
||||
panic("no return value specified for ConnectClientHandler")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
|
||||
r0 = rf(ctx, channelID, ThingID)
|
||||
r0 = rf(ctx, channelID, clientID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -110,17 +110,17 @@ func (_m *Service) ConnectThingHandler(ctx context.Context, channelID string, Th
|
||||
return r0
|
||||
}
|
||||
|
||||
// DisconnectThingHandler provides a mock function with given fields: ctx, channelID, ThingID
|
||||
func (_m *Service) DisconnectThingHandler(ctx context.Context, channelID string, ThingID string) error {
|
||||
ret := _m.Called(ctx, channelID, ThingID)
|
||||
// DisconnectClientHandler provides a mock function with given fields: ctx, channelID, clientID
|
||||
func (_m *Service) DisconnectClientHandler(ctx context.Context, channelID string, clientID string) error {
|
||||
ret := _m.Called(ctx, channelID, clientID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DisconnectThingHandler")
|
||||
panic("no return value specified for DisconnectClientHandler")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok {
|
||||
r0 = rf(ctx, channelID, ThingID)
|
||||
r0 = rf(ctx, channelID, clientID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
@@ -228,9 +228,9 @@ func (_m *Service) Update(ctx context.Context, session authn.Session, cfg bootst
|
||||
return r0
|
||||
}
|
||||
|
||||
// UpdateCert provides a mock function with given fields: ctx, session, thingID, clientCert, clientKey, caCert
|
||||
func (_m *Service) UpdateCert(ctx context.Context, session authn.Session, thingID string, clientCert string, clientKey string, caCert string) (bootstrap.Config, error) {
|
||||
ret := _m.Called(ctx, session, thingID, clientCert, clientKey, caCert)
|
||||
// UpdateCert provides a mock function with given fields: ctx, session, clientID, clientCert, clientKey, caCert
|
||||
func (_m *Service) UpdateCert(ctx context.Context, session authn.Session, clientID string, clientCert string, clientKey string, caCert string) (bootstrap.Config, error) {
|
||||
ret := _m.Called(ctx, session, clientID, clientCert, clientKey, caCert)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateCert")
|
||||
@@ -239,16 +239,16 @@ func (_m *Service) UpdateCert(ctx context.Context, session authn.Session, thingI
|
||||
var r0 bootstrap.Config
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string, string, string) (bootstrap.Config, error)); ok {
|
||||
return rf(ctx, session, thingID, clientCert, clientKey, caCert)
|
||||
return rf(ctx, session, clientID, clientCert, clientKey, caCert)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string, string, string) bootstrap.Config); ok {
|
||||
r0 = rf(ctx, session, thingID, clientCert, clientKey, caCert)
|
||||
r0 = rf(ctx, session, clientID, clientCert, clientKey, caCert)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bootstrap.Config)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, string, string, string) error); ok {
|
||||
r1 = rf(ctx, session, thingID, clientCert, clientKey, caCert)
|
||||
r1 = rf(ctx, session, clientID, clientCert, clientKey, caCert)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
@@ -12,11 +12,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"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/absmach/supermq/bootstrap"
|
||||
"github.com/absmach/supermq/clients"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
"github.com/absmach/supermq/pkg/postgres"
|
||||
"github.com/jackc/pgerrcode"
|
||||
"github.com/jackc/pgtype"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
@@ -24,12 +24,12 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
errSaveChannels = errors.New("failed to insert channels to database")
|
||||
errSaveConnections = errors.New("failed to insert connections to database")
|
||||
errUpdateChannels = errors.New("failed to update channels in bootstrap configuration database")
|
||||
errRemoveChannels = errors.New("failed to remove channels from bootstrap configuration in database")
|
||||
errConnectThing = errors.New("failed to connect thing in bootstrap configuration in database")
|
||||
errDisconnectThing = errors.New("failed to disconnect thing in bootstrap configuration in database")
|
||||
errSaveChannels = errors.New("failed to insert channels to database")
|
||||
errSaveConnections = errors.New("failed to insert connections to database")
|
||||
errUpdateChannels = errors.New("failed to update channels in bootstrap configuration database")
|
||||
errRemoveChannels = errors.New("failed to remove channels from bootstrap configuration in database")
|
||||
errConnectClient = errors.New("failed to connect client in bootstrap configuration in database")
|
||||
errDisconnectClient = errors.New("failed to disconnect client in bootstrap configuration in database")
|
||||
)
|
||||
|
||||
const cleanupQuery = `DELETE FROM channels ch WHERE NOT EXISTS (
|
||||
@@ -48,9 +48,9 @@ func NewConfigRepository(db postgres.Database, log *slog.Logger) bootstrap.Confi
|
||||
return &configRepository{db: db, log: log}
|
||||
}
|
||||
|
||||
func (cr configRepository) Save(ctx context.Context, cfg bootstrap.Config, chsConnIDs []string) (thingID string, err error) {
|
||||
q := `INSERT INTO configs (magistrala_thing, domain_id, name, client_cert, client_key, ca_cert, magistrala_key, external_id, external_key, content, state)
|
||||
VALUES (:magistrala_thing, :domain_id, :name, :client_cert, :client_key, :ca_cert, :magistrala_key, :external_id, :external_key, :content, :state)`
|
||||
func (cr configRepository) Save(ctx context.Context, cfg bootstrap.Config, chsConnIDs []string) (clientID string, err error) {
|
||||
q := `INSERT INTO configs (magistrala_client, domain_id, name, client_cert, client_key, ca_cert, magistrala_secret, external_id, external_key, content, state)
|
||||
VALUES (:magistrala_client, :domain_id, :name, :client_cert, :client_key, :ca_cert, :magistrala_secret, :external_id, :external_key, :content, :state)`
|
||||
|
||||
tx, err := cr.db.BeginTxx(ctx, nil)
|
||||
if err != nil {
|
||||
@@ -86,16 +86,16 @@ func (cr configRepository) Save(ctx context.Context, cfg bootstrap.Config, chsCo
|
||||
return "", commitErr
|
||||
}
|
||||
|
||||
return cfg.ThingID, nil
|
||||
return cfg.ClientID, nil
|
||||
}
|
||||
|
||||
func (cr configRepository) RetrieveByID(ctx context.Context, domainID, id string) (bootstrap.Config, error) {
|
||||
q := `SELECT magistrala_thing, magistrala_key, external_id, external_key, name, content, state, client_cert, ca_cert
|
||||
q := `SELECT magistrala_client, magistrala_secret, external_id, external_key, name, content, state, client_cert, ca_cert
|
||||
FROM configs
|
||||
WHERE magistrala_thing = :magistrala_thing AND domain_id = :domain_id`
|
||||
WHERE magistrala_client = :magistrala_client AND domain_id = :domain_id`
|
||||
|
||||
dbcfg := dbConfig{
|
||||
ThingID: id,
|
||||
ClientID: id,
|
||||
DomainID: domainID,
|
||||
}
|
||||
row, err := cr.db.NamedQueryContext(ctx, q, dbcfg)
|
||||
@@ -118,7 +118,7 @@ func (cr configRepository) RetrieveByID(ctx context.Context, domainID, id string
|
||||
q = `SELECT magistrala_channel, name, metadata FROM channels ch
|
||||
INNER JOIN connections conn
|
||||
ON ch.magistrala_channel = conn.channel_id AND ch.domain_id = conn.domain_id
|
||||
WHERE conn.config_id = :magistrala_thing AND conn.domain_id = :domain_id`
|
||||
WHERE conn.config_id = :magistrala_client AND conn.domain_id = :domain_id`
|
||||
|
||||
rows, err := cr.db.NamedQueryContext(ctx, q, dbcfg)
|
||||
if err != nil {
|
||||
@@ -131,7 +131,7 @@ func (cr configRepository) RetrieveByID(ctx context.Context, domainID, id string
|
||||
for rows.Next() {
|
||||
dbch := dbChannel{}
|
||||
if err := rows.StructScan(&dbch); err != nil {
|
||||
cr.log.Error(fmt.Sprintf("Failed to read connected thing due to %s", err))
|
||||
cr.log.Error(fmt.Sprintf("Failed to read connected client due to %s", err))
|
||||
return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
dbch.DomainID = nullString(dbcfg.DomainID)
|
||||
@@ -149,12 +149,12 @@ func (cr configRepository) RetrieveByID(ctx context.Context, domainID, id string
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (cr configRepository) RetrieveAll(ctx context.Context, domainID string, thingIDs []string, filter bootstrap.Filter, offset, limit uint64) bootstrap.ConfigsPage {
|
||||
search, params := buildRetrieveQueryParams(domainID, thingIDs, filter)
|
||||
func (cr configRepository) RetrieveAll(ctx context.Context, domainID string, clientIDs []string, filter bootstrap.Filter, offset, limit uint64) bootstrap.ConfigsPage {
|
||||
search, params := buildRetrieveQueryParams(domainID, clientIDs, filter)
|
||||
n := len(params)
|
||||
|
||||
q := `SELECT magistrala_thing, magistrala_key, external_id, external_key, name, content, state
|
||||
FROM configs %s ORDER BY magistrala_thing LIMIT $%d OFFSET $%d`
|
||||
q := `SELECT magistrala_client, magistrala_secret, external_id, external_key, name, content, state
|
||||
FROM configs %s ORDER BY magistrala_client LIMIT $%d OFFSET $%d`
|
||||
q = fmt.Sprintf(q, search, n+1, n+2)
|
||||
|
||||
rows, err := cr.db.QueryContext(ctx, q, append(params, limit, offset)...)
|
||||
@@ -169,7 +169,7 @@ func (cr configRepository) RetrieveAll(ctx context.Context, domainID string, thi
|
||||
|
||||
for rows.Next() {
|
||||
c := bootstrap.Config{DomainID: domainID}
|
||||
if err := rows.Scan(&c.ThingID, &c.ThingKey, &c.ExternalID, &c.ExternalKey, &name, &content, &c.State); err != nil {
|
||||
if err := rows.Scan(&c.ClientID, &c.ClientSecret, &c.ExternalID, &c.ExternalKey, &name, &content, &c.State); err != nil {
|
||||
cr.log.Error(fmt.Sprintf("Failed to read retrieved config due to %s", err))
|
||||
return bootstrap.ConfigsPage{}
|
||||
}
|
||||
@@ -196,7 +196,7 @@ func (cr configRepository) RetrieveAll(ctx context.Context, domainID string, thi
|
||||
}
|
||||
|
||||
func (cr configRepository) RetrieveByExternalID(ctx context.Context, externalID string) (bootstrap.Config, error) {
|
||||
q := `SELECT magistrala_thing, magistrala_key, external_key, domain_id, name, client_cert, client_key, ca_cert, content, state
|
||||
q := `SELECT magistrala_client, magistrala_secret, external_key, domain_id, name, client_cert, client_key, ca_cert, content, state
|
||||
FROM configs
|
||||
WHERE external_id = :external_id`
|
||||
dbcfg := dbConfig{
|
||||
@@ -222,7 +222,7 @@ func (cr configRepository) RetrieveByExternalID(ctx context.Context, externalID
|
||||
q = `SELECT magistrala_channel, name, metadata FROM channels ch
|
||||
INNER JOIN connections conn
|
||||
ON ch.magistrala_channel = conn.channel_id AND ch.domain_id = conn.domain_id
|
||||
WHERE conn.config_id = :magistrala_thing AND conn.domain_id = :domain_id`
|
||||
WHERE conn.config_id = :magistrala_client AND conn.domain_id = :domain_id`
|
||||
|
||||
rows, err := cr.db.NamedQueryContext(ctx, q, dbcfg)
|
||||
if err != nil {
|
||||
@@ -235,7 +235,7 @@ func (cr configRepository) RetrieveByExternalID(ctx context.Context, externalID
|
||||
for rows.Next() {
|
||||
dbch := dbChannel{}
|
||||
if err := rows.StructScan(&dbch); err != nil {
|
||||
cr.log.Error(fmt.Sprintf("Failed to read connected thing due to %s", err))
|
||||
cr.log.Error(fmt.Sprintf("Failed to read connected client due to %s", err))
|
||||
return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err)
|
||||
}
|
||||
|
||||
@@ -255,12 +255,12 @@ func (cr configRepository) RetrieveByExternalID(ctx context.Context, externalID
|
||||
}
|
||||
|
||||
func (cr configRepository) Update(ctx context.Context, cfg bootstrap.Config) error {
|
||||
q := `UPDATE configs SET name = :name, content = :content WHERE magistrala_thing = :magistrala_thing AND domain_id = :domain_id `
|
||||
q := `UPDATE configs SET name = :name, content = :content WHERE magistrala_client = :magistrala_client AND domain_id = :domain_id `
|
||||
|
||||
dbcfg := dbConfig{
|
||||
Name: nullString(cfg.Name),
|
||||
Content: nullString(cfg.Content),
|
||||
ThingID: cfg.ThingID,
|
||||
ClientID: cfg.ClientID,
|
||||
DomainID: cfg.DomainID,
|
||||
}
|
||||
|
||||
@@ -281,12 +281,12 @@ func (cr configRepository) Update(ctx context.Context, cfg bootstrap.Config) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cr configRepository) UpdateCert(ctx context.Context, domainID, thingID, clientCert, clientKey, caCert string) (bootstrap.Config, error) {
|
||||
q := `UPDATE configs SET client_cert = :client_cert, client_key = :client_key, ca_cert = :ca_cert WHERE magistrala_thing = :magistrala_thing AND domain_id = :domain_id
|
||||
RETURNING magistrala_thing, client_cert, client_key, ca_cert`
|
||||
func (cr configRepository) UpdateCert(ctx context.Context, domainID, clientID, clientCert, clientKey, caCert string) (bootstrap.Config, error) {
|
||||
q := `UPDATE configs SET client_cert = :client_cert, client_key = :client_key, ca_cert = :ca_cert WHERE magistrala_client = :magistrala_client AND domain_id = :domain_id
|
||||
RETURNING magistrala_client, client_cert, client_key, ca_cert`
|
||||
|
||||
dbcfg := dbConfig{
|
||||
ThingID: thingID,
|
||||
ClientID: clientID,
|
||||
ClientCert: nullString(clientCert),
|
||||
DomainID: domainID,
|
||||
ClientKey: nullString(clientKey),
|
||||
@@ -345,9 +345,9 @@ func (cr configRepository) UpdateConnections(ctx context.Context, domainID, id s
|
||||
}
|
||||
|
||||
func (cr configRepository) Remove(ctx context.Context, domainID, id string) error {
|
||||
q := `DELETE FROM configs WHERE magistrala_thing = :magistrala_thing AND domain_id = :domain_id`
|
||||
q := `DELETE FROM configs WHERE magistrala_client = :magistrala_client AND domain_id = :domain_id`
|
||||
dbcfg := dbConfig{
|
||||
ThingID: id,
|
||||
ClientID: id,
|
||||
DomainID: domainID,
|
||||
}
|
||||
|
||||
@@ -363,10 +363,10 @@ func (cr configRepository) Remove(ctx context.Context, domainID, id string) erro
|
||||
}
|
||||
|
||||
func (cr configRepository) ChangeState(ctx context.Context, domainID, id string, state bootstrap.State) error {
|
||||
q := `UPDATE configs SET state = :state WHERE magistrala_thing = :magistrala_thing AND domain_id = :domain_id;`
|
||||
q := `UPDATE configs SET state = :state WHERE magistrala_client = :magistrala_client AND domain_id = :domain_id;`
|
||||
|
||||
dbcfg := dbConfig{
|
||||
ThingID: id,
|
||||
ClientID: id,
|
||||
State: state,
|
||||
DomainID: domainID,
|
||||
}
|
||||
@@ -424,8 +424,8 @@ func (cr configRepository) ListExisting(ctx context.Context, domainID string, id
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
func (cr configRepository) RemoveThing(ctx context.Context, id string) error {
|
||||
q := `DELETE FROM configs WHERE magistrala_thing = $1`
|
||||
func (cr configRepository) RemoveClient(ctx context.Context, id string) error {
|
||||
q := `DELETE FROM configs WHERE magistrala_client = $1`
|
||||
_, err := cr.db.ExecContext(ctx, q, id)
|
||||
|
||||
if _, err := cr.db.ExecContext(ctx, cleanupQuery); err != nil {
|
||||
@@ -459,14 +459,14 @@ func (cr configRepository) RemoveChannel(ctx context.Context, id string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cr configRepository) ConnectThing(ctx context.Context, channelID, thingID string) error {
|
||||
func (cr configRepository) ConnectClient(ctx context.Context, channelID, clientID string) error {
|
||||
q := `UPDATE configs SET state = $1
|
||||
WHERE magistrala_thing = $2
|
||||
WHERE magistrala_client = $2
|
||||
AND EXISTS (SELECT 1 FROM connections WHERE config_id = $2 AND channel_id = $3)`
|
||||
|
||||
result, err := cr.db.ExecContext(ctx, q, bootstrap.Active, thingID, channelID)
|
||||
result, err := cr.db.ExecContext(ctx, q, bootstrap.Active, clientID, channelID)
|
||||
if err != nil {
|
||||
return errors.Wrap(errConnectThing, err)
|
||||
return errors.Wrap(errConnectClient, err)
|
||||
}
|
||||
if rows, _ := result.RowsAffected(); rows == 0 {
|
||||
return repoerr.ErrNotFound
|
||||
@@ -474,23 +474,23 @@ func (cr configRepository) ConnectThing(ctx context.Context, channelID, thingID
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cr configRepository) DisconnectThing(ctx context.Context, channelID, thingID string) error {
|
||||
func (cr configRepository) DisconnectClient(ctx context.Context, channelID, clientID string) error {
|
||||
q := `UPDATE configs SET state = $1
|
||||
WHERE magistrala_thing = $2
|
||||
WHERE magistrala_client = $2
|
||||
AND EXISTS (SELECT 1 FROM connections WHERE config_id = $2 AND channel_id = $3)`
|
||||
_, err := cr.db.ExecContext(ctx, q, bootstrap.Inactive, thingID, channelID)
|
||||
_, err := cr.db.ExecContext(ctx, q, bootstrap.Inactive, clientID, channelID)
|
||||
if err != nil {
|
||||
return errors.Wrap(errDisconnectThing, err)
|
||||
return errors.Wrap(errDisconnectClient, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildRetrieveQueryParams(domainID string, thingIDs []string, filter bootstrap.Filter) (string, []interface{}) {
|
||||
func buildRetrieveQueryParams(domainID string, clientIDs []string, filter bootstrap.Filter) (string, []interface{}) {
|
||||
params := []interface{}{}
|
||||
queries := []string{}
|
||||
|
||||
if len(thingIDs) != 0 {
|
||||
queries = append(queries, fmt.Sprintf("magistrala_thing IN ('%s')", strings.Join(thingIDs, "','")))
|
||||
if len(clientIDs) != 0 {
|
||||
queries = append(queries, fmt.Sprintf("magistrala_client IN ('%s')", strings.Join(clientIDs, "','")))
|
||||
} else if domainID != "" {
|
||||
params = append(params, domainID)
|
||||
queries = append(queries, fmt.Sprintf("domain_id = $%d", len(params)))
|
||||
@@ -560,7 +560,7 @@ func insertConnections(_ context.Context, cfg bootstrap.Config, connections []st
|
||||
conns := []dbConnection{}
|
||||
for _, conn := range connections {
|
||||
dbconn := dbConnection{
|
||||
Config: cfg.ThingID,
|
||||
Config: cfg.ClientID,
|
||||
Channel: conn,
|
||||
DomainID: cfg.DomainID,
|
||||
}
|
||||
@@ -644,43 +644,43 @@ func nullTime(t time.Time) sql.NullTime {
|
||||
}
|
||||
|
||||
type dbConfig struct {
|
||||
ThingID string `db:"magistrala_thing"`
|
||||
DomainID string `db:"domain_id"`
|
||||
Name sql.NullString `db:"name"`
|
||||
ClientCert sql.NullString `db:"client_cert"`
|
||||
ClientKey sql.NullString `db:"client_key"`
|
||||
CaCert sql.NullString `db:"ca_cert"`
|
||||
ThingKey string `db:"magistrala_key"`
|
||||
ExternalID string `db:"external_id"`
|
||||
ExternalKey string `db:"external_key"`
|
||||
Content sql.NullString `db:"content"`
|
||||
State bootstrap.State `db:"state"`
|
||||
DomainID string `db:"domain_id"`
|
||||
ClientID string `db:"magistrala_client"`
|
||||
ClientSecret string `db:"magistrala_secret"`
|
||||
Name sql.NullString `db:"name"`
|
||||
ClientCert sql.NullString `db:"client_cert"`
|
||||
ClientKey sql.NullString `db:"client_key"`
|
||||
CaCert sql.NullString `db:"ca_cert"`
|
||||
ExternalID string `db:"external_id"`
|
||||
ExternalKey string `db:"external_key"`
|
||||
Content sql.NullString `db:"content"`
|
||||
State bootstrap.State `db:"state"`
|
||||
}
|
||||
|
||||
func toDBConfig(cfg bootstrap.Config) dbConfig {
|
||||
return dbConfig{
|
||||
ThingID: cfg.ThingID,
|
||||
DomainID: cfg.DomainID,
|
||||
Name: nullString(cfg.Name),
|
||||
ClientCert: nullString(cfg.ClientCert),
|
||||
ClientKey: nullString(cfg.ClientKey),
|
||||
CaCert: nullString(cfg.CACert),
|
||||
ThingKey: cfg.ThingKey,
|
||||
ExternalID: cfg.ExternalID,
|
||||
ExternalKey: cfg.ExternalKey,
|
||||
Content: nullString(cfg.Content),
|
||||
State: cfg.State,
|
||||
ClientID: cfg.ClientID,
|
||||
ClientSecret: cfg.ClientSecret,
|
||||
DomainID: cfg.DomainID,
|
||||
Name: nullString(cfg.Name),
|
||||
ClientCert: nullString(cfg.ClientCert),
|
||||
ClientKey: nullString(cfg.ClientKey),
|
||||
CaCert: nullString(cfg.CACert),
|
||||
ExternalID: cfg.ExternalID,
|
||||
ExternalKey: cfg.ExternalKey,
|
||||
Content: nullString(cfg.Content),
|
||||
State: cfg.State,
|
||||
}
|
||||
}
|
||||
|
||||
func toConfig(dbcfg dbConfig) bootstrap.Config {
|
||||
cfg := bootstrap.Config{
|
||||
ThingID: dbcfg.ThingID,
|
||||
DomainID: dbcfg.DomainID,
|
||||
ThingKey: dbcfg.ThingKey,
|
||||
ExternalID: dbcfg.ExternalID,
|
||||
ExternalKey: dbcfg.ExternalKey,
|
||||
State: dbcfg.State,
|
||||
ClientID: dbcfg.ClientID,
|
||||
ClientSecret: dbcfg.ClientSecret,
|
||||
DomainID: dbcfg.DomainID,
|
||||
ExternalID: dbcfg.ExternalID,
|
||||
ExternalKey: dbcfg.ExternalKey,
|
||||
State: dbcfg.State,
|
||||
}
|
||||
|
||||
if dbcfg.Name.Valid {
|
||||
@@ -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 things.Status `db:"status"`
|
||||
Status clients.Status `db:"status"`
|
||||
}
|
||||
|
||||
func toDBChannel(domainID string, ch bootstrap.Channel) (dbChannel, error) {
|
||||
|
||||
+113
-113
@@ -9,11 +9,11 @@ import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/bootstrap/postgres"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
"github.com/absmach/supermq/bootstrap/postgres"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
"github.com/gofrs/uuid/v5"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -23,11 +23,11 @@ const numConfigs = 10
|
||||
|
||||
var (
|
||||
config = bootstrap.Config{
|
||||
ThingID: "mg-thing",
|
||||
ThingKey: "mg-key",
|
||||
ExternalID: "external-id",
|
||||
ExternalKey: "external-key",
|
||||
DomainID: testsutil.GenerateUUID(&testing.T{}),
|
||||
ClientID: "smq-client",
|
||||
ClientSecret: "smq-key",
|
||||
ExternalID: "external-id",
|
||||
ExternalKey: "external-key",
|
||||
DomainID: testsutil.GenerateUUID(&testing.T{}),
|
||||
Channels: []bootstrap.Channel{
|
||||
{ID: "1", Name: "name 1", Metadata: map[string]interface{}{"meta": 1.0}},
|
||||
{ID: "2", Name: "name 2", Metadata: map[string]interface{}{"meta": 2.0}},
|
||||
@@ -46,20 +46,20 @@ func TestSave(t *testing.T) {
|
||||
|
||||
diff := "different"
|
||||
|
||||
duplicateThing := config
|
||||
duplicateThing.ExternalID = diff
|
||||
duplicateThing.ThingKey = diff
|
||||
duplicateThing.Channels = []bootstrap.Channel{}
|
||||
duplicateClient := config
|
||||
duplicateClient.ExternalID = diff
|
||||
duplicateClient.ClientSecret = diff
|
||||
duplicateClient.Channels = []bootstrap.Channel{}
|
||||
|
||||
duplicateExternal := config
|
||||
duplicateExternal.ThingID = diff
|
||||
duplicateExternal.ThingKey = diff
|
||||
duplicateExternal.ClientID = diff
|
||||
duplicateExternal.ClientSecret = diff
|
||||
duplicateExternal.Channels = []bootstrap.Channel{}
|
||||
|
||||
duplicateChannels := config
|
||||
duplicateChannels.ExternalID = diff
|
||||
duplicateChannels.ThingKey = diff
|
||||
duplicateChannels.ThingID = diff
|
||||
duplicateChannels.ClientSecret = diff
|
||||
duplicateChannels.ClientID = diff
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
@@ -74,8 +74,8 @@ func TestSave(t *testing.T) {
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "save config with same Thing ID",
|
||||
config: duplicateThing,
|
||||
desc: "save config with same Client ID",
|
||||
config: duplicateClient,
|
||||
connections: nil,
|
||||
err: repoerr.ErrConflict,
|
||||
},
|
||||
@@ -96,7 +96,7 @@ func TestSave(t *testing.T) {
|
||||
id, err := repo.Save(context.Background(), tc.config, tc.connections)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
if err == nil {
|
||||
assert.Equal(t, id, tc.config.ThingID, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.config.ThingID, id))
|
||||
assert.Equal(t, id, tc.config.ClientID, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.config.ClientID, id))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,8 +110,8 @@ func TestRetrieveByID(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
require.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
id, err := repo.Save(context.Background(), c, channels)
|
||||
@@ -162,7 +162,7 @@ func TestRetrieveAll(t *testing.T) {
|
||||
err := deleteChannels(context.Background(), repo)
|
||||
require.Nil(t, err, "Channels cleanup expected to succeed.")
|
||||
|
||||
thingIDs := make([]string, numConfigs)
|
||||
clientIDs := make([]string, numConfigs)
|
||||
|
||||
for i := 0; i < numConfigs; i++ {
|
||||
c := config
|
||||
@@ -172,10 +172,10 @@ func TestRetrieveAll(t *testing.T) {
|
||||
require.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ExternalID = uid.String()
|
||||
c.Name = fmt.Sprintf("name %d", i)
|
||||
c.ThingID = uid.String()
|
||||
c.ThingKey = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
|
||||
thingIDs[i] = c.ThingID
|
||||
clientIDs[i] = c.ClientID
|
||||
|
||||
if i%2 == 0 {
|
||||
c.State = bootstrap.Active
|
||||
@@ -191,7 +191,7 @@ func TestRetrieveAll(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
domainID string
|
||||
thingID []string
|
||||
clientID []string
|
||||
offset uint64
|
||||
limit uint64
|
||||
filter bootstrap.Filter
|
||||
@@ -200,7 +200,7 @@ func TestRetrieveAll(t *testing.T) {
|
||||
{
|
||||
desc: "retrieve all configs",
|
||||
domainID: config.DomainID,
|
||||
thingID: []string{},
|
||||
clientID: []string{},
|
||||
offset: 0,
|
||||
limit: uint64(numConfigs),
|
||||
size: numConfigs,
|
||||
@@ -208,7 +208,7 @@ func TestRetrieveAll(t *testing.T) {
|
||||
{
|
||||
desc: "retrieve a subset of configs",
|
||||
domainID: config.DomainID,
|
||||
thingID: []string{},
|
||||
clientID: []string{},
|
||||
offset: 5,
|
||||
limit: uint64(numConfigs - 5),
|
||||
size: numConfigs - 5,
|
||||
@@ -216,7 +216,7 @@ func TestRetrieveAll(t *testing.T) {
|
||||
{
|
||||
desc: "retrieve with wrong domain ID ",
|
||||
domainID: "2",
|
||||
thingID: []string{},
|
||||
clientID: []string{},
|
||||
offset: 0,
|
||||
limit: uint64(numConfigs),
|
||||
size: 0,
|
||||
@@ -224,7 +224,7 @@ func TestRetrieveAll(t *testing.T) {
|
||||
{
|
||||
desc: "retrieve all active configs ",
|
||||
domainID: config.DomainID,
|
||||
thingID: []string{},
|
||||
clientID: []string{},
|
||||
offset: 0,
|
||||
limit: uint64(numConfigs),
|
||||
filter: bootstrap.Filter{FullMatch: map[string]string{"state": bootstrap.Active.String()}},
|
||||
@@ -233,7 +233,7 @@ func TestRetrieveAll(t *testing.T) {
|
||||
{
|
||||
desc: "retrieve all with partial match filter",
|
||||
domainID: config.DomainID,
|
||||
thingID: []string{},
|
||||
clientID: []string{},
|
||||
offset: 0,
|
||||
limit: uint64(numConfigs),
|
||||
filter: bootstrap.Filter{PartialMatch: map[string]string{"name": "1"}},
|
||||
@@ -242,31 +242,31 @@ func TestRetrieveAll(t *testing.T) {
|
||||
{
|
||||
desc: "retrieve search by name",
|
||||
domainID: config.DomainID,
|
||||
thingID: []string{},
|
||||
clientID: []string{},
|
||||
offset: 0,
|
||||
limit: uint64(numConfigs),
|
||||
filter: bootstrap.Filter{PartialMatch: map[string]string{"name": "1"}},
|
||||
size: 1,
|
||||
},
|
||||
{
|
||||
desc: "retrieve by valid thingIDs",
|
||||
desc: "retrieve by valid clientIDs",
|
||||
domainID: config.DomainID,
|
||||
thingID: thingIDs,
|
||||
clientID: clientIDs,
|
||||
offset: 0,
|
||||
limit: uint64(numConfigs),
|
||||
size: 10,
|
||||
},
|
||||
{
|
||||
desc: "retrieve by non-existing thingID",
|
||||
desc: "retrieve by non-existing clientID",
|
||||
domainID: config.DomainID,
|
||||
thingID: []string{"non-existing"},
|
||||
clientID: []string{"non-existing"},
|
||||
offset: 0,
|
||||
limit: uint64(numConfigs),
|
||||
size: 0,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
ret := repo.RetrieveAll(context.Background(), tc.domainID, tc.thingID, tc.filter, tc.offset, tc.limit)
|
||||
ret := repo.RetrieveAll(context.Background(), tc.domainID, tc.clientID, tc.filter, tc.offset, tc.limit)
|
||||
size := len(ret.Configs)
|
||||
assert.Equal(t, tc.size, size, fmt.Sprintf("%s: expected %d got %d\n", tc.desc, tc.size, size))
|
||||
}
|
||||
@@ -281,8 +281,8 @@ func TestRetrieveByExternalID(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
_, err = repo.Save(context.Background(), c, channels)
|
||||
@@ -319,8 +319,8 @@ func TestUpdate(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
_, err = repo.Save(context.Background(), c, channels)
|
||||
@@ -364,8 +364,8 @@ func TestUpdateCert(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
_, err = repo.Save(context.Background(), c, channels)
|
||||
@@ -379,7 +379,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
thingID string
|
||||
clientID string
|
||||
domainID string
|
||||
cert string
|
||||
certKey string
|
||||
@@ -389,7 +389,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
desc: "update with wrong domain ID ",
|
||||
thingID: "",
|
||||
clientID: "",
|
||||
cert: "cert",
|
||||
certKey: "certKey",
|
||||
ca: "",
|
||||
@@ -399,13 +399,13 @@ func TestUpdateCert(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "update a config",
|
||||
thingID: c.ThingID,
|
||||
clientID: c.ClientID,
|
||||
cert: "cert",
|
||||
certKey: "certKey",
|
||||
ca: "ca",
|
||||
domainID: c.DomainID,
|
||||
expectedConfig: bootstrap.Config{
|
||||
ThingID: c.ThingID,
|
||||
ClientID: c.ClientID,
|
||||
ClientCert: "cert",
|
||||
CACert: "ca",
|
||||
ClientKey: "certKey",
|
||||
@@ -415,7 +415,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
cfg, err := repo.UpdateCert(context.Background(), tc.domainID, tc.thingID, tc.cert, tc.certKey, tc.ca)
|
||||
cfg, err := repo.UpdateCert(context.Background(), tc.domainID, tc.clientID, tc.cert, tc.certKey, tc.ca)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
assert.Equal(t, tc.expectedConfig, cfg, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.expectedConfig, cfg))
|
||||
}
|
||||
@@ -430,8 +430,8 @@ func TestUpdateConnections(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
_, err = repo.Save(context.Background(), c, channels)
|
||||
@@ -439,8 +439,8 @@ func TestUpdateConnections(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err = uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
c.Channels = []bootstrap.Channel{}
|
||||
@@ -466,7 +466,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
{
|
||||
desc: "update connections",
|
||||
domainID: config.DomainID,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
channels: nil,
|
||||
connections: []string{channels[1]},
|
||||
err: nil,
|
||||
@@ -482,7 +482,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
{
|
||||
desc: "update connections no channels",
|
||||
domainID: config.DomainID,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
channels: nil,
|
||||
connections: nil,
|
||||
err: nil,
|
||||
@@ -503,8 +503,8 @@ func TestRemove(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
id, err := repo.Save(context.Background(), c, channels)
|
||||
@@ -530,8 +530,8 @@ func TestChangeState(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
saved, err := repo.Save(context.Background(), c, channels)
|
||||
@@ -586,8 +586,8 @@ func TestListExisting(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
_, err = repo.Save(context.Background(), c, channels)
|
||||
@@ -628,7 +628,7 @@ func TestListExisting(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveThing(t *testing.T) {
|
||||
func TestRemoveClient(t *testing.T) {
|
||||
repo := postgres.NewConfigRepository(db, testLog)
|
||||
err := deleteChannels(context.Background(), repo)
|
||||
require.Nil(t, err, "Channels cleanup expected to succeed.")
|
||||
@@ -637,14 +637,14 @@ func TestRemoveThing(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
saved, err := repo.Save(context.Background(), c, channels)
|
||||
assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err))
|
||||
for i := 0; i < 2; i++ {
|
||||
err := repo.RemoveThing(context.Background(), saved)
|
||||
err := repo.RemoveClient(context.Background(), saved)
|
||||
assert.Nil(t, err, fmt.Sprintf("an unexpected error occurred: %s\n", err))
|
||||
}
|
||||
}
|
||||
@@ -658,8 +658,8 @@ func TestUpdateChannel(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
_, err = repo.Save(context.Background(), c, channels)
|
||||
@@ -674,7 +674,7 @@ func TestUpdateChannel(t *testing.T) {
|
||||
err = repo.UpdateChannel(context.Background(), update)
|
||||
assert.Nil(t, err, fmt.Sprintf("updating config expected to succeed: %s.\n", err))
|
||||
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ThingID)
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ClientID)
|
||||
assert.Nil(t, err, fmt.Sprintf("Retrieving config expected to succeed: %s.\n", err))
|
||||
var retreved bootstrap.Channel
|
||||
for _, c := range cfg.Channels {
|
||||
@@ -695,8 +695,8 @@ func TestRemoveChannel(t *testing.T) {
|
||||
c := config
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
_, err = repo.Save(context.Background(), c, channels)
|
||||
@@ -705,12 +705,12 @@ func TestRemoveChannel(t *testing.T) {
|
||||
err = repo.RemoveChannel(context.Background(), c.Channels[0].ID)
|
||||
assert.Nil(t, err, fmt.Sprintf("Retrieving config expected to succeed: %s.\n", err))
|
||||
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ThingID)
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ClientID)
|
||||
assert.Nil(t, err, fmt.Sprintf("Retrieving config expected to succeed: %s.\n", err))
|
||||
assert.NotContains(t, cfg.Channels, c.Channels[0], fmt.Sprintf("expected to remove channel %s from %s", c.Channels[0], cfg.Channels))
|
||||
}
|
||||
|
||||
func TestConnectThing(t *testing.T) {
|
||||
func TestConnectClient(t *testing.T) {
|
||||
repo := postgres.NewConfigRepository(db, testLog)
|
||||
err := deleteChannels(context.Background(), repo)
|
||||
require.Nil(t, err, "Channels cleanup expected to succeed.")
|
||||
@@ -719,8 +719,8 @@ func TestConnectThing(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
c.State = bootstrap.Inactive
|
||||
@@ -729,14 +729,14 @@ func TestConnectThing(t *testing.T) {
|
||||
|
||||
wrongID := testsutil.GenerateUUID(&testing.T{})
|
||||
|
||||
connectedThing := c
|
||||
connectedClient := c
|
||||
|
||||
randomThing := c
|
||||
randomThingID, _ := uuid.NewV4()
|
||||
randomThing.ThingID = randomThingID.String()
|
||||
randomClient := c
|
||||
randomClientID, _ := uuid.NewV4()
|
||||
randomClient.ClientID = randomClientID.String()
|
||||
|
||||
emptyThing := c
|
||||
emptyThing.ThingID = ""
|
||||
emptyClient := c
|
||||
emptyClient.ClientID = ""
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
@@ -748,7 +748,7 @@ func TestConnectThing(t *testing.T) {
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "connect disconnected thing",
|
||||
desc: "connect disconnected client",
|
||||
domainID: c.DomainID,
|
||||
id: saved,
|
||||
state: bootstrap.Inactive,
|
||||
@@ -757,16 +757,16 @@ func TestConnectThing(t *testing.T) {
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "connect already connected thing",
|
||||
desc: "connect already connected client",
|
||||
domainID: c.DomainID,
|
||||
id: connectedThing.ThingID,
|
||||
state: connectedThing.State,
|
||||
id: connectedClient.ClientID,
|
||||
state: connectedClient.State,
|
||||
channels: c.Channels,
|
||||
connections: channels,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "connect non-existent thing",
|
||||
desc: "connect non-existent client",
|
||||
domainID: c.DomainID,
|
||||
id: wrongID,
|
||||
channels: c.Channels,
|
||||
@@ -774,17 +774,17 @@ func TestConnectThing(t *testing.T) {
|
||||
err: repoerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "connect random thing",
|
||||
desc: "connect random client",
|
||||
domainID: c.DomainID,
|
||||
id: randomThing.ThingID,
|
||||
id: randomClient.ClientID,
|
||||
channels: c.Channels,
|
||||
connections: channels,
|
||||
err: repoerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "connect empty thing",
|
||||
desc: "connect empty client",
|
||||
domainID: c.DomainID,
|
||||
id: emptyThing.ThingID,
|
||||
id: emptyClient.ClientID,
|
||||
channels: c.Channels,
|
||||
connections: channels,
|
||||
err: repoerr.ErrNotFound,
|
||||
@@ -793,23 +793,23 @@ func TestConnectThing(t *testing.T) {
|
||||
for _, tc := range cases {
|
||||
for i, ch := range tc.channels {
|
||||
if i == 0 {
|
||||
err = repo.ConnectThing(context.Background(), ch.ID, tc.id)
|
||||
err = repo.ConnectClient(context.Background(), ch.ID, tc.id)
|
||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: Expected error: %s, got: %s.\n", tc.desc, tc.err, err))
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ThingID)
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ClientID)
|
||||
assert.Nil(t, err, fmt.Sprintf("Retrieving config expected to succeed: %s.\n", err))
|
||||
assert.Equal(t, cfg.State, bootstrap.Active, fmt.Sprintf("expected to be active when a connection is added from %s", cfg))
|
||||
} else {
|
||||
_ = repo.ConnectThing(context.Background(), ch.ID, tc.id)
|
||||
_ = repo.ConnectClient(context.Background(), ch.ID, tc.id)
|
||||
}
|
||||
}
|
||||
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ThingID)
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ClientID)
|
||||
assert.Nil(t, err, fmt.Sprintf("Retrieving config expected to succeed: %s.\n", err))
|
||||
assert.Equal(t, cfg.State, bootstrap.Active, fmt.Sprintf("expected to be active when a connection is added from %s", cfg))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisconnectThing(t *testing.T) {
|
||||
func TestDisconnectClient(t *testing.T) {
|
||||
repo := postgres.NewConfigRepository(db, testLog)
|
||||
err := deleteChannels(context.Background(), repo)
|
||||
require.Nil(t, err, "Channels cleanup expected to succeed.")
|
||||
@@ -818,8 +818,8 @@ func TestDisconnectThing(t *testing.T) {
|
||||
// Use UUID to prevent conflicts.
|
||||
uid, err := uuid.NewV4()
|
||||
assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err))
|
||||
c.ThingKey = uid.String()
|
||||
c.ThingID = uid.String()
|
||||
c.ClientSecret = uid.String()
|
||||
c.ClientID = uid.String()
|
||||
c.ExternalID = uid.String()
|
||||
c.ExternalKey = uid.String()
|
||||
c.State = bootstrap.Inactive
|
||||
@@ -828,14 +828,14 @@ func TestDisconnectThing(t *testing.T) {
|
||||
|
||||
wrongID := testsutil.GenerateUUID(&testing.T{})
|
||||
|
||||
connectedThing := c
|
||||
connectedClient := c
|
||||
|
||||
randomThing := c
|
||||
randomThingID, _ := uuid.NewV4()
|
||||
randomThing.ThingID = randomThingID.String()
|
||||
randomClient := c
|
||||
randomClientID, _ := uuid.NewV4()
|
||||
randomClient.ClientID = randomClientID.String()
|
||||
|
||||
emptyThing := c
|
||||
emptyThing.ThingID = ""
|
||||
emptyClient := c
|
||||
emptyClient.ClientID = ""
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
@@ -847,16 +847,16 @@ func TestDisconnectThing(t *testing.T) {
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "disconnect connected thing",
|
||||
desc: "disconnect connected client",
|
||||
domainID: c.DomainID,
|
||||
id: connectedThing.ThingID,
|
||||
state: connectedThing.State,
|
||||
id: connectedClient.ClientID,
|
||||
state: connectedClient.State,
|
||||
channels: c.Channels,
|
||||
connections: channels,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "disconnect already disconnected thing",
|
||||
desc: "disconnect already disconnected client",
|
||||
domainID: c.DomainID,
|
||||
id: saved,
|
||||
state: bootstrap.Inactive,
|
||||
@@ -865,7 +865,7 @@ func TestDisconnectThing(t *testing.T) {
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "disconnect invalid thing",
|
||||
desc: "disconnect invalid client",
|
||||
domainID: c.DomainID,
|
||||
id: wrongID,
|
||||
channels: c.Channels,
|
||||
@@ -873,17 +873,17 @@ func TestDisconnectThing(t *testing.T) {
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "disconnect random thing",
|
||||
desc: "disconnect random client",
|
||||
domainID: c.DomainID,
|
||||
id: randomThing.ThingID,
|
||||
id: randomClient.ClientID,
|
||||
channels: c.Channels,
|
||||
connections: channels,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "disconnect empty thing",
|
||||
desc: "disconnect empty client",
|
||||
domainID: c.DomainID,
|
||||
id: emptyThing.ThingID,
|
||||
id: emptyClient.ClientID,
|
||||
channels: c.Channels,
|
||||
connections: channels,
|
||||
err: nil,
|
||||
@@ -892,11 +892,11 @@ func TestDisconnectThing(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
for _, ch := range tc.channels {
|
||||
err = repo.DisconnectThing(context.Background(), ch.ID, tc.id)
|
||||
err = repo.DisconnectClient(context.Background(), ch.ID, tc.id)
|
||||
assert.Equal(t, tc.err, err, fmt.Sprintf("%s: Expected error: %s, got: %s.\n", tc.desc, tc.err, err))
|
||||
}
|
||||
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ThingID)
|
||||
cfg, err := repo.RetrieveByID(context.Background(), c.DomainID, c.ClientID)
|
||||
assert.Nil(t, err, fmt.Sprintf("Retrieving config expected to succeed: %s.\n", err))
|
||||
assert.Equal(t, cfg.State, bootstrap.Inactive, fmt.Sprintf("expected to be inactive when a connection is removed from %s", cfg))
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ func Migration() *migrate.MemoryMigrationSource {
|
||||
Id: "configs_1",
|
||||
Up: []string{
|
||||
`CREATE TABLE IF NOT EXISTS configs (
|
||||
mainflux_thing TEXT UNIQUE NOT NULL,
|
||||
mainflux_client TEXT UNIQUE NOT NULL,
|
||||
owner VARCHAR(254),
|
||||
name TEXT,
|
||||
mainflux_key CHAR(36) UNIQUE NOT NULL,
|
||||
@@ -24,7 +24,7 @@ func Migration() *migrate.MemoryMigrationSource {
|
||||
client_key TEXT,
|
||||
ca_cert TEXT,
|
||||
state BIGINT NOT NULL,
|
||||
PRIMARY KEY (mainflux_thing, owner)
|
||||
PRIMARY KEY (mainflux_client, owner)
|
||||
)`,
|
||||
`CREATE TABLE IF NOT EXISTS unknown_configs (
|
||||
external_id TEXT UNIQUE NOT NULL,
|
||||
@@ -44,7 +44,7 @@ func Migration() *migrate.MemoryMigrationSource {
|
||||
config_id TEXT,
|
||||
config_owner VARCHAR(256),
|
||||
FOREIGN KEY (channel_id, channel_owner) REFERENCES channels (mainflux_channel, owner) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
FOREIGN KEY (config_id, config_owner) REFERENCES configs (mainflux_thing, owner) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
FOREIGN KEY (config_id, config_owner) REFERENCES configs (mainflux_client, owner) ON DELETE CASCADE ON UPDATE CASCADE,
|
||||
PRIMARY KEY (channel_id, channel_owner, config_id, config_owner)
|
||||
)`,
|
||||
},
|
||||
@@ -78,8 +78,8 @@ func Migration() *migrate.MemoryMigrationSource {
|
||||
{
|
||||
Id: "configs_4",
|
||||
Up: []string{
|
||||
`ALTER TABLE IF EXISTS configs RENAME COLUMN mainflux_thing TO magistrala_thing`,
|
||||
`ALTER TABLE IF EXISTS configs RENAME COLUMN mainflux_key TO magistrala_key`,
|
||||
`ALTER TABLE IF EXISTS configs RENAME COLUMN mainflux_client TO magistrala_client`,
|
||||
`ALTER TABLE IF EXISTS configs RENAME COLUMN mainflux_key TO magistrala_secret`,
|
||||
`ALTER TABLE IF EXISTS channels RENAME COLUMN mainflux_channel TO magistrala_channel`,
|
||||
},
|
||||
},
|
||||
@@ -100,7 +100,7 @@ func Migration() *migrate.MemoryMigrationSource {
|
||||
`ALTER TABLE IF EXISTS connections ADD COLUMN IF NOT EXISTS domain_id VARCHAR(256) NOT NULL`,
|
||||
`ALTER TABLE IF EXISTS connections ADD CONSTRAINT connections_pkey PRIMARY KEY (channel_id, config_id, domain_id)`,
|
||||
`ALTER TABLE IF EXISTS connections ADD FOREIGN KEY (channel_id, domain_id) REFERENCES channels (magistrala_channel, domain_id) ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
`ALTER TABLE IF EXISTS connections ADD FOREIGN KEY (config_id, domain_id) REFERENCES configs (magistrala_thing, domain_id) ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
`ALTER TABLE IF EXISTS connections ADD FOREIGN KEY (config_id, domain_id) REFERENCES configs (magistrala_client, domain_id) ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -9,16 +9,16 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap/postgres"
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
pgclient "github.com/absmach/magistrala/pkg/postgres"
|
||||
"github.com/absmach/supermq/bootstrap/postgres"
|
||||
smqlog "github.com/absmach/supermq/logger"
|
||||
pgclient "github.com/absmach/supermq/pkg/postgres"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/ory/dockertest/v3"
|
||||
"github.com/ory/dockertest/v3/docker"
|
||||
)
|
||||
|
||||
var (
|
||||
testLog, _ = mglog.New(os.Stdout, "info")
|
||||
testLog, _ = smqlog.New(os.Stdout, "info")
|
||||
db *sqlx.DB
|
||||
)
|
||||
|
||||
|
||||
+15
-15
@@ -12,17 +12,17 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// bootstrapRes represent Magistrala Response to the Bootatrap request.
|
||||
// bootstrapRes represent SuperMQ Response to the Bootatrap request.
|
||||
// This is used as a response from ConfigReader and can easily be
|
||||
// replace with any other response format.
|
||||
type bootstrapRes struct {
|
||||
ThingID string `json:"thing_id"`
|
||||
ThingKey string `json:"thing_key"`
|
||||
Channels []channelRes `json:"channels"`
|
||||
Content string `json:"content,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
Channels []channelRes `json:"channels"`
|
||||
Content string `json:"content,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
}
|
||||
|
||||
type channelRes struct {
|
||||
@@ -60,13 +60,13 @@ func (r reader) ReadConfig(cfg Config, secure bool) (interface{}, error) {
|
||||
}
|
||||
|
||||
res := bootstrapRes{
|
||||
ThingKey: cfg.ThingKey,
|
||||
ThingID: cfg.ThingID,
|
||||
Channels: channels,
|
||||
Content: cfg.Content,
|
||||
ClientCert: cfg.ClientCert,
|
||||
ClientKey: cfg.ClientKey,
|
||||
CACert: cfg.CACert,
|
||||
ClientID: cfg.ClientID,
|
||||
ClientSecret: cfg.ClientSecret,
|
||||
Channels: channels,
|
||||
Content: cfg.Content,
|
||||
ClientCert: cfg.ClientCert,
|
||||
ClientKey: cfg.ClientKey,
|
||||
CACert: cfg.CACert,
|
||||
}
|
||||
if secure {
|
||||
b, err := json.Marshal(res)
|
||||
|
||||
+22
-22
@@ -11,9 +11,9 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/absmach/magistrala"
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/absmach/supermq"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -24,13 +24,13 @@ type readChan struct {
|
||||
}
|
||||
|
||||
type readResp struct {
|
||||
ThingID string `json:"thing_id"`
|
||||
ThingKey string `json:"thing_key"`
|
||||
Channels []readChan `json:"channels"`
|
||||
Content string `json:"content,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
Channels []readChan `json:"channels"`
|
||||
Content string `json:"content,omitempty"`
|
||||
ClientCert string `json:"client_cert,omitempty"`
|
||||
ClientKey string `json:"client_key,omitempty"`
|
||||
CACert string `json:"ca_cert,omitempty"`
|
||||
}
|
||||
|
||||
func dec(in []byte) ([]byte, error) {
|
||||
@@ -50,27 +50,27 @@ func dec(in []byte) ([]byte, error) {
|
||||
|
||||
func TestReadConfig(t *testing.T) {
|
||||
cfg := bootstrap.Config{
|
||||
ThingID: "mg_id",
|
||||
ClientCert: "client_cert",
|
||||
ClientKey: "client_key",
|
||||
CACert: "ca_cert",
|
||||
ThingKey: "mg_key",
|
||||
ClientID: "smq_id",
|
||||
ClientCert: "client_cert",
|
||||
ClientKey: "client_key",
|
||||
CACert: "ca_cert",
|
||||
ClientSecret: "smq_key",
|
||||
Channels: []bootstrap.Channel{
|
||||
{
|
||||
ID: "mg_id",
|
||||
Name: "mg_name",
|
||||
ID: "smq_id",
|
||||
Name: "smq_name",
|
||||
Metadata: map[string]interface{}{"key": "value}"},
|
||||
},
|
||||
},
|
||||
Content: "content",
|
||||
}
|
||||
ret := readResp{
|
||||
ThingID: "mg_id",
|
||||
ThingKey: "mg_key",
|
||||
ClientID: "smq_id",
|
||||
ClientSecret: "smq_key",
|
||||
Channels: []readChan{
|
||||
{
|
||||
ID: "mg_id",
|
||||
Name: "mg_name",
|
||||
ID: "smq_id",
|
||||
Name: "smq_name",
|
||||
Metadata: map[string]interface{}{"key": "value}"},
|
||||
},
|
||||
},
|
||||
@@ -118,7 +118,7 @@ func TestReadConfig(t *testing.T) {
|
||||
b, err := json.Marshal(res)
|
||||
assert.Nil(t, err, fmt.Sprintf("Marshalling expected to succeed: %s.\n", err))
|
||||
assert.Equal(t, tc.enc, b, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.enc, b))
|
||||
resp, ok := res.(magistrala.Response)
|
||||
resp, ok := res.(supermq.Response)
|
||||
assert.True(t, ok, "If not encrypted, reader should return response.")
|
||||
assert.False(t, resp.Empty(), fmt.Sprintf("Response should not be empty %s.", err))
|
||||
assert.Equal(t, http.StatusOK, resp.Code(), "Default config response code should be 200.")
|
||||
|
||||
+82
-85
@@ -9,19 +9,19 @@ import (
|
||||
"crypto/cipher"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/absmach/magistrala"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
"github.com/absmach/magistrala/pkg/policies"
|
||||
mgsdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
"github.com/absmach/supermq"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
repoerr "github.com/absmach/supermq/pkg/errors/repository"
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
"github.com/absmach/supermq/pkg/policies"
|
||||
mgsdk "github.com/absmach/supermq/pkg/sdk"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrThings indicates failure to communicate with Magistrala Things service.
|
||||
// ErrClients indicates failure to communicate with SuperMQ Clients service.
|
||||
// It can be due to networking error or invalid/unauthenticated request.
|
||||
ErrThings = errors.New("failed to receive response from Things service")
|
||||
ErrClients = errors.New("failed to receive response from Clients service")
|
||||
|
||||
// ErrExternalKey indicates a non-existent bootstrap configuration for given external key.
|
||||
ErrExternalKey = errors.New("failed to get bootstrap configuration for given external key")
|
||||
@@ -44,12 +44,12 @@ var (
|
||||
errUpdateChannel = errors.New("failed to update channel")
|
||||
errRemoveConfig = errors.New("failed to remove bootstrap configuration")
|
||||
errRemoveChannel = errors.New("failed to remove channel")
|
||||
errCreateThing = errors.New("failed to create thing")
|
||||
errConnectThing = errors.New("failed to connect thing")
|
||||
errDisconnectThing = errors.New("failed to disconnect thing")
|
||||
errCreateClient = errors.New("failed to create client")
|
||||
errConnectClient = errors.New("failed to connect client")
|
||||
errDisconnectClient = errors.New("failed to disconnect client")
|
||||
errCheckChannels = errors.New("failed to check if channels exists")
|
||||
errConnectionChannels = errors.New("failed to check channels connections")
|
||||
errThingNotFound = errors.New("failed to find thing")
|
||||
errClientNotFound = errors.New("failed to find client")
|
||||
errUpdateCert = errors.New("failed to update cert")
|
||||
)
|
||||
|
||||
@@ -60,34 +60,34 @@ var _ Service = (*bootstrapService)(nil)
|
||||
//
|
||||
//go:generate mockery --name Service --output=./mocks --filename service.go --quiet --note "Copyright (c) Abstract Machines"
|
||||
type Service interface {
|
||||
// Add adds new Thing Config to the user identified by the provided token.
|
||||
Add(ctx context.Context, session mgauthn.Session, token string, cfg Config) (Config, error)
|
||||
// Add adds new Client Config to the user identified by the provided token.
|
||||
Add(ctx context.Context, session smqauthn.Session, token string, cfg Config) (Config, error)
|
||||
|
||||
// View returns Thing Config with given ID belonging to the user identified by the given token.
|
||||
View(ctx context.Context, session mgauthn.Session, id string) (Config, error)
|
||||
// View returns Client Config with given ID belonging to the user identified by the given token.
|
||||
View(ctx context.Context, session smqauthn.Session, id string) (Config, error)
|
||||
|
||||
// Update updates editable fields of the provided Config.
|
||||
Update(ctx context.Context, session mgauthn.Session, cfg Config) error
|
||||
Update(ctx context.Context, session smqauthn.Session, cfg Config) error
|
||||
|
||||
// UpdateCert updates an existing Config certificate and token.
|
||||
// A non-nil error is returned to indicate operation failure.
|
||||
UpdateCert(ctx context.Context, session mgauthn.Session, thingID, clientCert, clientKey, caCert string) (Config, error)
|
||||
UpdateCert(ctx context.Context, session smqauthn.Session, clientID, clientCert, clientKey, caCert string) (Config, error)
|
||||
|
||||
// UpdateConnections updates list of Channels related to given Config.
|
||||
UpdateConnections(ctx context.Context, session mgauthn.Session, token, id string, connections []string) error
|
||||
UpdateConnections(ctx context.Context, session smqauthn.Session, token, id string, connections []string) error
|
||||
|
||||
// List returns subset of Configs with given search params that belong to the
|
||||
// user identified by the given token.
|
||||
List(ctx context.Context, session mgauthn.Session, filter Filter, offset, limit uint64) (ConfigsPage, error)
|
||||
List(ctx context.Context, session smqauthn.Session, filter Filter, offset, limit uint64) (ConfigsPage, error)
|
||||
|
||||
// Remove removes Config with specified token that belongs to the user identified by the given token.
|
||||
Remove(ctx context.Context, session mgauthn.Session, id string) error
|
||||
Remove(ctx context.Context, session smqauthn.Session, id string) error
|
||||
|
||||
// Bootstrap returns Config to the Thing with provided external ID using external key.
|
||||
// Bootstrap returns Config to the Client with provided external ID using external key.
|
||||
Bootstrap(ctx context.Context, externalKey, externalID string, secure bool) (Config, error)
|
||||
|
||||
// ChangeState changes state of the Thing with given thing ID and domain ID.
|
||||
ChangeState(ctx context.Context, session mgauthn.Session, token, id string, state State) error
|
||||
// ChangeState changes state of the Client with given client ID and domain ID.
|
||||
ChangeState(ctx context.Context, session smqauthn.Session, token, id string, state State) error
|
||||
|
||||
// Methods RemoveConfig, UpdateChannel, and RemoveChannel are used as
|
||||
// handlers for events. That's why these methods surpass ownership check.
|
||||
@@ -101,11 +101,11 @@ type Service interface {
|
||||
// RemoveChannelHandler removes Channel with id received from an event.
|
||||
RemoveChannelHandler(ctx context.Context, id string) error
|
||||
|
||||
// ConnectThingHandler changes state of the Config to active when connect event occurs.
|
||||
ConnectThingHandler(ctx context.Context, channelID, ThingID string) error
|
||||
// ConnectClientHandler changes state of the Config to active when connect event occurs.
|
||||
ConnectClientHandler(ctx context.Context, channelID, clientID string) error
|
||||
|
||||
// DisconnectThingHandler changes state of the Config to inactive when disconnect event occurs.
|
||||
DisconnectThingHandler(ctx context.Context, channelID, ThingID string) error
|
||||
// DisconnectClientHandler changes state of the Config to inactive when disconnect event occurs.
|
||||
DisconnectClientHandler(ctx context.Context, channelID, clientID string) error
|
||||
}
|
||||
|
||||
// ConfigReader is used to parse Config into format which will be encoded
|
||||
@@ -123,11 +123,11 @@ type bootstrapService struct {
|
||||
configs ConfigRepository
|
||||
sdk mgsdk.SDK
|
||||
encKey []byte
|
||||
idProvider magistrala.IDProvider
|
||||
idProvider supermq.IDProvider
|
||||
}
|
||||
|
||||
// New returns new Bootstrap service.
|
||||
func New(policyService policies.Service, configs ConfigRepository, sdk mgsdk.SDK, encKey []byte, idp magistrala.IDProvider) Service {
|
||||
func New(policyService policies.Service, configs ConfigRepository, sdk mgsdk.SDK, encKey []byte, idp supermq.IDProvider) Service {
|
||||
return &bootstrapService{
|
||||
configs: configs,
|
||||
sdk: sdk,
|
||||
@@ -137,7 +137,7 @@ func New(policyService policies.Service, configs ConfigRepository, sdk mgsdk.SDK
|
||||
}
|
||||
}
|
||||
|
||||
func (bs bootstrapService) Add(ctx context.Context, session mgauthn.Session, token string, cfg Config) (Config, error) {
|
||||
func (bs bootstrapService) Add(ctx context.Context, session smqauthn.Session, token string, cfg Config) (Config, error) {
|
||||
toConnect := bs.toIDList(cfg.Channels)
|
||||
|
||||
// Check if channels exist. This is the way to prevent fetching channels that already exist.
|
||||
@@ -151,42 +151,42 @@ func (bs bootstrapService) Add(ctx context.Context, session mgauthn.Session, tok
|
||||
return Config{}, errors.Wrap(errConnectionChannels, err)
|
||||
}
|
||||
|
||||
id := cfg.ThingID
|
||||
mgThing, err := bs.thing(session.DomainID, id, token)
|
||||
id := cfg.ClientID
|
||||
mgClient, err := bs.client(session.DomainID, id, token)
|
||||
if err != nil {
|
||||
return Config{}, errors.Wrap(errThingNotFound, err)
|
||||
return Config{}, errors.Wrap(errClientNotFound, err)
|
||||
}
|
||||
|
||||
for _, channel := range cfg.Channels {
|
||||
if channel.DomainID != mgThing.DomainID {
|
||||
if channel.DomainID != mgClient.DomainID {
|
||||
return Config{}, errors.Wrap(svcerr.ErrMalformedEntity, errNotInSameDomain)
|
||||
}
|
||||
}
|
||||
|
||||
cfg.ThingID = mgThing.ID
|
||||
cfg.ClientID = mgClient.ID
|
||||
cfg.DomainID = session.DomainID
|
||||
cfg.State = Inactive
|
||||
cfg.ThingKey = mgThing.Credentials.Secret
|
||||
cfg.ClientSecret = mgClient.Credentials.Secret
|
||||
|
||||
saved, err := bs.configs.Save(ctx, cfg, toConnect)
|
||||
if err != nil {
|
||||
// If id is empty, then a new thing has been created function - bs.thing(id, token)
|
||||
// So, on bootstrap config save error , delete the newly created thing.
|
||||
// If id is empty, then a new client has been created function - bs.client(id, token)
|
||||
// So, on bootstrap config save error , delete the newly created client.
|
||||
if id == "" {
|
||||
if errT := bs.sdk.DeleteThing(cfg.ThingID, cfg.DomainID, token); errT != nil {
|
||||
if errT := bs.sdk.DeleteClient(cfg.ClientID, cfg.DomainID, token); errT != nil {
|
||||
err = errors.Wrap(err, errT)
|
||||
}
|
||||
}
|
||||
return Config{}, errors.Wrap(ErrAddBootstrap, err)
|
||||
}
|
||||
|
||||
cfg.ThingID = saved
|
||||
cfg.ClientID = saved
|
||||
cfg.Channels = append(cfg.Channels, existing...)
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) View(ctx context.Context, session mgauthn.Session, id string) (Config, error) {
|
||||
func (bs bootstrapService) View(ctx context.Context, session smqauthn.Session, id string) (Config, error) {
|
||||
cfg, err := bs.configs.RetrieveByID(ctx, session.DomainID, id)
|
||||
if err != nil {
|
||||
return Config{}, errors.Wrap(svcerr.ErrViewEntity, err)
|
||||
@@ -194,7 +194,7 @@ func (bs bootstrapService) View(ctx context.Context, session mgauthn.Session, id
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) Update(ctx context.Context, session mgauthn.Session, cfg Config) error {
|
||||
func (bs bootstrapService) Update(ctx context.Context, session smqauthn.Session, cfg Config) error {
|
||||
cfg.DomainID = session.DomainID
|
||||
if err := bs.configs.Update(ctx, cfg); err != nil {
|
||||
return errors.Wrap(errUpdateConnections, err)
|
||||
@@ -202,15 +202,15 @@ func (bs bootstrapService) Update(ctx context.Context, session mgauthn.Session,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) UpdateCert(ctx context.Context, session mgauthn.Session, thingID, clientCert, clientKey, caCert string) (Config, error) {
|
||||
cfg, err := bs.configs.UpdateCert(ctx, session.DomainID, thingID, clientCert, clientKey, caCert)
|
||||
func (bs bootstrapService) UpdateCert(ctx context.Context, session smqauthn.Session, clientID, clientCert, clientKey, caCert string) (Config, error) {
|
||||
cfg, err := bs.configs.UpdateCert(ctx, session.DomainID, clientID, clientCert, clientKey, caCert)
|
||||
if err != nil {
|
||||
return Config{}, errors.Wrap(errUpdateCert, err)
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) UpdateConnections(ctx context.Context, session mgauthn.Session, token, id string, connections []string) error {
|
||||
func (bs bootstrapService) UpdateConnections(ctx context.Context, session smqauthn.Session, token, id string, connections []string) error {
|
||||
cfg, err := bs.configs.RetrieveByID(ctx, session.DomainID, id)
|
||||
if err != nil {
|
||||
return errors.Wrap(errUpdateConnections, err)
|
||||
@@ -238,21 +238,22 @@ func (bs bootstrapService) UpdateConnections(ctx context.Context, session mgauth
|
||||
}
|
||||
|
||||
for _, c := range disconnect {
|
||||
if err := bs.sdk.DisconnectThing(id, c, session.DomainID, token); err != nil {
|
||||
if err := bs.sdk.DisconnectClients(c, []string{id}, []string{"Publish", "Subscribe"}, session.DomainID, token); err != nil {
|
||||
if errors.Contains(err, repoerr.ErrNotFound) {
|
||||
continue
|
||||
}
|
||||
return ErrThings
|
||||
return ErrClients
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range connect {
|
||||
conIDs := mgsdk.Connection{
|
||||
ChannelID: c,
|
||||
ThingID: id,
|
||||
ChannelIDs: []string{c},
|
||||
ClientIDs: []string{id},
|
||||
Types: []string{"Publish", "Subscribe"},
|
||||
}
|
||||
if err := bs.sdk.Connect(conIDs, session.DomainID, token); err != nil {
|
||||
return ErrThings
|
||||
return ErrClients
|
||||
}
|
||||
}
|
||||
if err := bs.configs.UpdateConnections(ctx, session.DomainID, id, channels, connections); err != nil {
|
||||
@@ -266,7 +267,7 @@ func (bs bootstrapService) listClientIDs(ctx context.Context, userID string) ([]
|
||||
SubjectType: policies.UserType,
|
||||
Subject: userID,
|
||||
Permission: policies.ViewPermission,
|
||||
ObjectType: policies.ThingType,
|
||||
ObjectType: policies.ClientType,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
@@ -274,18 +275,18 @@ func (bs bootstrapService) listClientIDs(ctx context.Context, userID string) ([]
|
||||
return tids.Policies, nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) List(ctx context.Context, session mgauthn.Session, filter Filter, offset, limit uint64) (ConfigsPage, error) {
|
||||
func (bs bootstrapService) List(ctx context.Context, session smqauthn.Session, filter Filter, offset, limit uint64) (ConfigsPage, error) {
|
||||
if session.SuperAdmin {
|
||||
return bs.configs.RetrieveAll(ctx, session.DomainID, []string{}, filter, offset, limit), nil
|
||||
}
|
||||
|
||||
// Handle non-admin users
|
||||
thingIDs, err := bs.listClientIDs(ctx, session.DomainUserID)
|
||||
clientIDs, err := bs.listClientIDs(ctx, session.DomainUserID)
|
||||
if err != nil {
|
||||
return ConfigsPage{}, errors.Wrap(svcerr.ErrNotFound, err)
|
||||
}
|
||||
|
||||
if len(thingIDs) == 0 {
|
||||
if len(clientIDs) == 0 {
|
||||
return ConfigsPage{
|
||||
Total: 0,
|
||||
Offset: offset,
|
||||
@@ -294,10 +295,10 @@ func (bs bootstrapService) List(ctx context.Context, session mgauthn.Session, fi
|
||||
}, nil
|
||||
}
|
||||
|
||||
return bs.configs.RetrieveAll(ctx, session.DomainID, thingIDs, filter, offset, limit), nil
|
||||
return bs.configs.RetrieveAll(ctx, session.DomainID, clientIDs, filter, offset, limit), nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) Remove(ctx context.Context, session mgauthn.Session, id string) error {
|
||||
func (bs bootstrapService) Remove(ctx context.Context, session smqauthn.Session, id string) error {
|
||||
if err := bs.configs.Remove(ctx, session.DomainID, id); err != nil {
|
||||
return errors.Wrap(errRemoveBootstrap, err)
|
||||
}
|
||||
@@ -323,7 +324,7 @@ func (bs bootstrapService) Bootstrap(ctx context.Context, externalKey, externalI
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) ChangeState(ctx context.Context, session mgauthn.Session, token, id string, state State) error {
|
||||
func (bs bootstrapService) ChangeState(ctx context.Context, session smqauthn.Session, token, id string, state State) error {
|
||||
cfg, err := bs.configs.RetrieveByID(ctx, session.DomainID, id)
|
||||
if err != nil {
|
||||
return errors.Wrap(errChangeState, err)
|
||||
@@ -336,25 +337,21 @@ func (bs bootstrapService) ChangeState(ctx context.Context, session mgauthn.Sess
|
||||
switch state {
|
||||
case Active:
|
||||
for _, c := range cfg.Channels {
|
||||
conIDs := mgsdk.Connection{
|
||||
ChannelID: c.ID,
|
||||
ThingID: cfg.ThingID,
|
||||
}
|
||||
if err := bs.sdk.Connect(conIDs, session.DomainID, token); err != nil {
|
||||
if err := bs.sdk.ConnectClients(c.ID, []string{cfg.ClientID}, []string{"Publish", "Subscribe"}, session.DomainID, token); err != nil {
|
||||
// Ignore conflict errors as they indicate the connection already exists.
|
||||
if errors.Contains(err, svcerr.ErrConflict) {
|
||||
continue
|
||||
}
|
||||
return ErrThings
|
||||
return ErrClients
|
||||
}
|
||||
}
|
||||
case Inactive:
|
||||
for _, c := range cfg.Channels {
|
||||
if err := bs.sdk.DisconnectThing(cfg.ThingID, c.ID, session.DomainID, token); err != nil {
|
||||
if err := bs.sdk.DisconnectClients(c.ID, []string{cfg.ClientID}, []string{"Publish", "Subscribe"}, session.DomainID, token); err != nil {
|
||||
if errors.Contains(err, repoerr.ErrNotFound) {
|
||||
continue
|
||||
}
|
||||
return ErrThings
|
||||
return ErrClients
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -372,7 +369,7 @@ func (bs bootstrapService) UpdateChannelHandler(ctx context.Context, channel Cha
|
||||
}
|
||||
|
||||
func (bs bootstrapService) RemoveConfigHandler(ctx context.Context, id string) error {
|
||||
if err := bs.configs.RemoveThing(ctx, id); err != nil {
|
||||
if err := bs.configs.RemoveClient(ctx, id); err != nil {
|
||||
return errors.Wrap(errRemoveConfig, err)
|
||||
}
|
||||
return nil
|
||||
@@ -385,41 +382,41 @@ func (bs bootstrapService) RemoveChannelHandler(ctx context.Context, id string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) ConnectThingHandler(ctx context.Context, channelID, thingID string) error {
|
||||
if err := bs.configs.ConnectThing(ctx, channelID, thingID); err != nil {
|
||||
return errors.Wrap(errConnectThing, err)
|
||||
func (bs bootstrapService) ConnectClientHandler(ctx context.Context, channelID, clientID string) error {
|
||||
if err := bs.configs.ConnectClient(ctx, channelID, clientID); err != nil {
|
||||
return errors.Wrap(errConnectClient, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) DisconnectThingHandler(ctx context.Context, channelID, thingID string) error {
|
||||
if err := bs.configs.DisconnectThing(ctx, channelID, thingID); err != nil {
|
||||
return errors.Wrap(errDisconnectThing, err)
|
||||
func (bs bootstrapService) DisconnectClientHandler(ctx context.Context, channelID, clientID string) error {
|
||||
if err := bs.configs.DisconnectClient(ctx, channelID, clientID); err != nil {
|
||||
return errors.Wrap(errDisconnectClient, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Method thing retrieves Magistrala Thing creating one if an empty ID is passed.
|
||||
func (bs bootstrapService) thing(domainID, id, token string) (mgsdk.Thing, error) {
|
||||
// If Thing ID is not provided, then create new thing.
|
||||
// Method client retrieves SuperMQ Client creating one if an empty ID is passed.
|
||||
func (bs bootstrapService) client(domainID, id, token string) (mgsdk.Client, error) {
|
||||
// If Client ID is not provided, then create new client.
|
||||
if id == "" {
|
||||
id, err := bs.idProvider.ID()
|
||||
if err != nil {
|
||||
return mgsdk.Thing{}, errors.Wrap(errCreateThing, err)
|
||||
return mgsdk.Client{}, errors.Wrap(errCreateClient, err)
|
||||
}
|
||||
thing, sdkErr := bs.sdk.CreateThing(mgsdk.Thing{ID: id, Name: "Bootstrapped Thing " + id}, domainID, token)
|
||||
client, sdkErr := bs.sdk.CreateClient(mgsdk.Client{ID: id, Name: "Bootstrapped Client " + id}, domainID, token)
|
||||
if sdkErr != nil {
|
||||
return mgsdk.Thing{}, errors.Wrap(errCreateThing, sdkErr)
|
||||
return mgsdk.Client{}, errors.Wrap(errCreateClient, sdkErr)
|
||||
}
|
||||
return thing, nil
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// If Thing ID is provided, then retrieve thing
|
||||
thing, sdkErr := bs.sdk.Thing(id, domainID, token)
|
||||
// If Client ID is provided, then retrieve client
|
||||
client, sdkErr := bs.sdk.Client(id, domainID, token)
|
||||
if sdkErr != nil {
|
||||
return mgsdk.Thing{}, errors.Wrap(ErrThings, sdkErr)
|
||||
return mgsdk.Client{}, errors.Wrap(ErrClients, sdkErr)
|
||||
}
|
||||
return thing, nil
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func (bs bootstrapService) connectionChannels(channels, existing []string, domainID, token string) ([]Channel, error) {
|
||||
|
||||
+142
-142
@@ -14,17 +14,17 @@ import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
"github.com/absmach/magistrala/bootstrap/mocks"
|
||||
"github.com/absmach/magistrala/internal/testsutil"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
svcerr "github.com/absmach/magistrala/pkg/errors/service"
|
||||
policysvc "github.com/absmach/magistrala/pkg/policies"
|
||||
policymocks "github.com/absmach/magistrala/pkg/policies/mocks"
|
||||
mgsdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
sdkmocks "github.com/absmach/magistrala/pkg/sdk/mocks"
|
||||
"github.com/absmach/magistrala/pkg/uuid"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
"github.com/absmach/supermq/bootstrap/mocks"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"github.com/absmach/supermq/pkg/errors"
|
||||
svcerr "github.com/absmach/supermq/pkg/errors/service"
|
||||
policysvc "github.com/absmach/supermq/pkg/policies"
|
||||
policymocks "github.com/absmach/supermq/pkg/policies/mocks"
|
||||
mgsdk "github.com/absmach/supermq/pkg/sdk"
|
||||
sdkmocks "github.com/absmach/supermq/pkg/sdk/mocks"
|
||||
"github.com/absmach/supermq/pkg/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
)
|
||||
@@ -50,12 +50,12 @@ var (
|
||||
}
|
||||
|
||||
config = bootstrap.Config{
|
||||
ThingID: testsutil.GenerateUUID(&testing.T{}),
|
||||
ThingKey: testsutil.GenerateUUID(&testing.T{}),
|
||||
ExternalID: testsutil.GenerateUUID(&testing.T{}),
|
||||
ExternalKey: testsutil.GenerateUUID(&testing.T{}),
|
||||
Channels: []bootstrap.Channel{channel},
|
||||
Content: "config",
|
||||
ClientID: testsutil.GenerateUUID(&testing.T{}),
|
||||
ClientSecret: testsutil.GenerateUUID(&testing.T{}),
|
||||
ExternalID: testsutil.GenerateUUID(&testing.T{}),
|
||||
ExternalKey: testsutil.GenerateUUID(&testing.T{}),
|
||||
Channels: []bootstrap.Channel{channel},
|
||||
Content: "config",
|
||||
}
|
||||
)
|
||||
|
||||
@@ -92,7 +92,7 @@ func TestAdd(t *testing.T) {
|
||||
svc := newService()
|
||||
|
||||
neID := config
|
||||
neID.ThingID = "non-existent"
|
||||
neID.ClientID = "non-existent"
|
||||
|
||||
wrongChannels := config
|
||||
ch := channel
|
||||
@@ -103,15 +103,15 @@ func TestAdd(t *testing.T) {
|
||||
desc string
|
||||
config bootstrap.Config
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
userID string
|
||||
domainID string
|
||||
thingErr error
|
||||
createThingErr error
|
||||
clientErr error
|
||||
createClientErr error
|
||||
channelErr error
|
||||
listExistingErr error
|
||||
saveErr error
|
||||
deleteThingErr error
|
||||
deleteClientErr error
|
||||
err error
|
||||
}{
|
||||
{
|
||||
@@ -123,13 +123,13 @@ func TestAdd(t *testing.T) {
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "add a config with an invalid ID",
|
||||
config: neID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
thingErr: errors.NewSDKError(svcerr.ErrNotFound),
|
||||
err: svcerr.ErrNotFound,
|
||||
desc: "add a config with an invalid ID",
|
||||
config: neID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
clientErr: errors.NewSDKError(svcerr.ErrNotFound),
|
||||
err: svcerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "add a config with invalid list of channels",
|
||||
@@ -151,10 +151,10 @@ func TestAdd(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := sdk.On("Thing", tc.config.ThingID, mock.Anything, tc.token).Return(mgsdk.Thing{ID: tc.config.ThingID, Credentials: mgsdk.ClientCredentials{Secret: tc.config.ThingKey}}, tc.thingErr)
|
||||
repoCall1 := sdk.On("CreateThing", mock.Anything, tc.domainID, tc.token).Return(mgsdk.Thing{}, tc.createThingErr)
|
||||
repoCall2 := sdk.On("DeleteThing", tc.config.ThingID, tc.domainID, tc.token).Return(tc.deleteThingErr)
|
||||
tc.session = smqauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := sdk.On("Client", tc.config.ClientID, mock.Anything, tc.token).Return(mgsdk.Client{ID: tc.config.ClientID, Credentials: mgsdk.ClientCredentials{Secret: tc.config.ClientSecret}}, tc.clientErr)
|
||||
repoCall1 := sdk.On("CreateClient", mock.Anything, tc.domainID, tc.token).Return(mgsdk.Client{}, tc.createClientErr)
|
||||
repoCall2 := sdk.On("DeleteClient", tc.config.ClientID, tc.domainID, tc.token).Return(tc.deleteClientErr)
|
||||
repoCall3 := boot.On("ListExisting", context.Background(), tc.domainID, mock.Anything).Return(tc.config.Channels, tc.listExistingErr)
|
||||
repoCall4 := boot.On("Save", context.Background(), mock.Anything, mock.Anything).Return(mock.Anything, tc.saveErr)
|
||||
_, err := svc.Add(context.Background(), tc.session, tc.token, tc.config)
|
||||
@@ -172,53 +172,53 @@ func TestView(t *testing.T) {
|
||||
svc := newService()
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
configID string
|
||||
userID string
|
||||
domain string
|
||||
thingDomain string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
retrieveErr error
|
||||
thingErr error
|
||||
channelErr error
|
||||
err error
|
||||
desc string
|
||||
configID string
|
||||
userID string
|
||||
domain string
|
||||
clientDomain string
|
||||
token string
|
||||
session smqauthn.Session
|
||||
retrieveErr error
|
||||
clientErr error
|
||||
channelErr error
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "view an existing config",
|
||||
configID: config.ThingID,
|
||||
userID: validID,
|
||||
thingDomain: domainID,
|
||||
domain: domainID,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
desc: "view an existing config",
|
||||
configID: config.ClientID,
|
||||
userID: validID,
|
||||
clientDomain: domainID,
|
||||
domain: domainID,
|
||||
token: validToken,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "view a non-existing config",
|
||||
configID: unknown,
|
||||
userID: validID,
|
||||
thingDomain: domainID,
|
||||
domain: domainID,
|
||||
token: validToken,
|
||||
retrieveErr: svcerr.ErrNotFound,
|
||||
err: svcerr.ErrNotFound,
|
||||
desc: "view a non-existing config",
|
||||
configID: unknown,
|
||||
userID: validID,
|
||||
clientDomain: domainID,
|
||||
domain: domainID,
|
||||
token: validToken,
|
||||
retrieveErr: svcerr.ErrNotFound,
|
||||
err: svcerr.ErrNotFound,
|
||||
},
|
||||
{
|
||||
desc: "view a config with invalid domain",
|
||||
configID: config.ThingID,
|
||||
userID: validID,
|
||||
thingDomain: invalidDomainID,
|
||||
domain: invalidDomainID,
|
||||
token: validToken,
|
||||
retrieveErr: svcerr.ErrNotFound,
|
||||
err: svcerr.ErrNotFound,
|
||||
desc: "view a config with invalid domain",
|
||||
configID: config.ClientID,
|
||||
userID: validID,
|
||||
clientDomain: invalidDomainID,
|
||||
domain: invalidDomainID,
|
||||
token: validToken,
|
||||
retrieveErr: svcerr.ErrNotFound,
|
||||
err: svcerr.ErrNotFound,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domain, DomainUserID: validID}
|
||||
repoCall := boot.On("RetrieveByID", context.Background(), tc.thingDomain, tc.configID).Return(config, tc.retrieveErr)
|
||||
tc.session = smqauthn.Session{UserID: tc.userID, DomainID: tc.domain, DomainUserID: validID}
|
||||
repoCall := boot.On("RetrieveByID", context.Background(), tc.clientDomain, tc.configID).Return(config, tc.retrieveErr)
|
||||
_, err := svc.View(context.Background(), tc.session, tc.configID)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
repoCall.Unset()
|
||||
@@ -239,13 +239,13 @@ func TestUpdate(t *testing.T) {
|
||||
modifiedCreated.Name = "new name"
|
||||
|
||||
nonExisting := c
|
||||
nonExisting.ThingID = unknown
|
||||
nonExisting.ClientID = unknown
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
config bootstrap.Config
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
userID string
|
||||
domainID string
|
||||
updateErr error
|
||||
@@ -281,7 +281,7 @@ func TestUpdate(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := boot.On("Update", context.Background(), mock.Anything).Return(tc.updateErr)
|
||||
err := svc.Update(context.Background(), tc.session, tc.config)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
@@ -301,10 +301,10 @@ func TestUpdateCert(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
userID string
|
||||
domainID string
|
||||
thingID string
|
||||
clientID string
|
||||
clientCert string
|
||||
clientKey string
|
||||
caCert string
|
||||
@@ -318,24 +318,24 @@ func TestUpdateCert(t *testing.T) {
|
||||
desc: "update certs for the valid config",
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
thingID: c.ThingID,
|
||||
clientID: c.ClientID,
|
||||
clientCert: "newCert",
|
||||
clientKey: "newKey",
|
||||
caCert: "newCert",
|
||||
token: validToken,
|
||||
expectedConfig: bootstrap.Config{
|
||||
Name: c.Name,
|
||||
ThingKey: c.ThingKey,
|
||||
Channels: c.Channels,
|
||||
ExternalID: c.ExternalID,
|
||||
ExternalKey: c.ExternalKey,
|
||||
Content: c.Content,
|
||||
State: c.State,
|
||||
DomainID: c.DomainID,
|
||||
ThingID: c.ThingID,
|
||||
ClientCert: "newCert",
|
||||
CACert: "newCert",
|
||||
ClientKey: "newKey",
|
||||
Name: c.Name,
|
||||
ClientSecret: c.ClientSecret,
|
||||
Channels: c.Channels,
|
||||
ExternalID: c.ExternalID,
|
||||
ExternalKey: c.ExternalKey,
|
||||
Content: c.Content,
|
||||
State: c.State,
|
||||
DomainID: c.DomainID,
|
||||
ClientID: c.ClientID,
|
||||
ClientCert: "newCert",
|
||||
CACert: "newCert",
|
||||
ClientKey: "newKey",
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
@@ -343,7 +343,7 @@ func TestUpdateCert(t *testing.T) {
|
||||
desc: "update cert for a non-existing config",
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
thingID: "empty",
|
||||
clientID: "empty",
|
||||
clientCert: "newCert",
|
||||
clientKey: "newKey",
|
||||
caCert: "newCert",
|
||||
@@ -356,9 +356,9 @@ func TestUpdateCert(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := boot.On("UpdateCert", context.Background(), mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.expectedConfig, tc.updateErr)
|
||||
cfg, err := svc.UpdateCert(context.Background(), tc.session, tc.thingID, tc.clientCert, tc.clientKey, tc.caCert)
|
||||
cfg, err := svc.UpdateCert(context.Background(), tc.session, tc.clientID, tc.clientCert, tc.clientKey, tc.caCert)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
sort.Slice(cfg.Channels, func(i, j int) bool {
|
||||
return cfg.Channels[i].ID < cfg.Channels[j].ID
|
||||
@@ -386,14 +386,14 @@ func TestUpdateConnections(t *testing.T) {
|
||||
cases := []struct {
|
||||
desc string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
id string
|
||||
state bootstrap.State
|
||||
userID string
|
||||
domainID string
|
||||
connections []string
|
||||
updateErr error
|
||||
thingErr error
|
||||
clientErr error
|
||||
channelErr error
|
||||
retrieveErr error
|
||||
listErr error
|
||||
@@ -404,7 +404,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
state: c.State,
|
||||
connections: []string{ch.ID},
|
||||
err: nil,
|
||||
@@ -414,7 +414,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
id: activeConf.ThingID,
|
||||
id: activeConf.ClientID,
|
||||
state: activeConf.State,
|
||||
connections: []string{ch.ID},
|
||||
err: nil,
|
||||
@@ -424,7 +424,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
connections: []string{"wrong"},
|
||||
channelErr: errors.NewSDKError(svcerr.ErrNotFound),
|
||||
err: svcerr.ErrNotFound,
|
||||
@@ -433,7 +433,7 @@ func TestUpdateConnections(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
sdkCall := sdk.On("Channel", mock.Anything, tc.domainID, tc.token).Return(mgsdk.Channel{}, tc.channelErr)
|
||||
repoCall := boot.On("RetrieveByID", context.Background(), tc.domainID, tc.id).Return(c, tc.retrieveErr)
|
||||
repoCall1 := boot.On("ListExisting", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(c.Channels, tc.listErr)
|
||||
@@ -451,9 +451,9 @@ func TestUpdateConnections(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
svc := newService()
|
||||
|
||||
numThings := 101
|
||||
numClients := 101
|
||||
var saved []bootstrap.Config
|
||||
for i := 0; i < numThings; i++ {
|
||||
for i := 0; i < numClients; i++ {
|
||||
c := config
|
||||
c.ExternalID = testsutil.GenerateUUID(t)
|
||||
c.ExternalKey = testsutil.GenerateUUID(t)
|
||||
@@ -470,7 +470,7 @@ func TestList(t *testing.T) {
|
||||
offset uint64
|
||||
limit uint64
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
userID string
|
||||
domainID string
|
||||
listObjectsResponse policysvc.PolicyPage
|
||||
@@ -488,7 +488,7 @@ func TestList(t *testing.T) {
|
||||
},
|
||||
filter: bootstrap.Filter{},
|
||||
token: validToken,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
offset: 0,
|
||||
@@ -500,7 +500,7 @@ func TestList(t *testing.T) {
|
||||
config: bootstrap.ConfigsPage{},
|
||||
filter: bootstrap.Filter{},
|
||||
token: validID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
listObjectsResponse: policysvc.PolicyPage{},
|
||||
@@ -520,7 +520,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
listObjectsResponse: policysvc.PolicyPage{},
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
@@ -538,7 +538,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
listObjectsResponse: policysvc.PolicyPage{Policies: []string{"test", "test"}},
|
||||
offset: 0,
|
||||
limit: 10,
|
||||
@@ -554,7 +554,7 @@ func TestList(t *testing.T) {
|
||||
},
|
||||
filter: bootstrap.Filter{PartialMatch: map[string]string{"name": "95"}},
|
||||
token: validToken,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
offset: 0,
|
||||
@@ -573,7 +573,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
offset: 0,
|
||||
limit: 100,
|
||||
err: nil,
|
||||
@@ -590,7 +590,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
listObjectsResponse: policysvc.PolicyPage{Policies: []string{"test", "test"}},
|
||||
offset: 0,
|
||||
limit: 100,
|
||||
@@ -608,7 +608,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
offset: 95,
|
||||
limit: 10,
|
||||
err: nil,
|
||||
@@ -625,7 +625,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
offset: 95,
|
||||
limit: 10,
|
||||
err: nil,
|
||||
@@ -642,7 +642,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
listObjectsResponse: policysvc.PolicyPage{Policies: []string{"test", "test"}},
|
||||
offset: 95,
|
||||
limit: 10,
|
||||
@@ -660,7 +660,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
offset: 35,
|
||||
limit: 20,
|
||||
err: nil,
|
||||
@@ -677,7 +677,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true},
|
||||
offset: 35,
|
||||
limit: 20,
|
||||
err: nil,
|
||||
@@ -694,7 +694,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
listObjectsResponse: policysvc.PolicyPage{Policies: []string{"test", "test"}},
|
||||
offset: 35,
|
||||
limit: 20,
|
||||
@@ -709,7 +709,7 @@ func TestList(t *testing.T) {
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
session: mgauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID},
|
||||
listObjectsResponse: policysvc.PolicyPage{},
|
||||
listObjectsErr: svcerr.ErrNotFound,
|
||||
err: svcerr.ErrNotFound,
|
||||
@@ -722,7 +722,7 @@ func TestList(t *testing.T) {
|
||||
SubjectType: policysvc.UserType,
|
||||
Subject: tc.userID,
|
||||
Permission: policysvc.ViewPermission,
|
||||
ObjectType: policysvc.ThingType,
|
||||
ObjectType: policysvc.ClientType,
|
||||
}).Return(tc.listObjectsResponse, tc.listObjectsErr)
|
||||
repoCall := boot.On("RetrieveAll", context.Background(), mock.Anything, mock.Anything, tc.filter, tc.offset, tc.limit).Return(tc.config, tc.retrieveErr)
|
||||
|
||||
@@ -744,7 +744,7 @@ func TestRemove(t *testing.T) {
|
||||
desc string
|
||||
id string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
userID string
|
||||
domainID string
|
||||
removeErr error
|
||||
@@ -752,7 +752,7 @@ func TestRemove(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
desc: "remove an existing config",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -760,7 +760,7 @@ func TestRemove(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "remove removed config",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -768,7 +768,7 @@ func TestRemove(t *testing.T) {
|
||||
},
|
||||
{
|
||||
desc: "remove a config with failed remove",
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -779,7 +779,7 @@ func TestRemove(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := boot.On("Remove", context.Background(), mock.Anything, mock.Anything).Return(tc.removeErr)
|
||||
err := svc.Remove(context.Background(), tc.session, tc.id)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
@@ -867,7 +867,7 @@ func TestChangeState(t *testing.T) {
|
||||
state bootstrap.State
|
||||
id string
|
||||
token string
|
||||
session mgauthn.Session
|
||||
session smqauthn.Session
|
||||
userID string
|
||||
domainID string
|
||||
retrieveErr error
|
||||
@@ -889,7 +889,7 @@ func TestChangeState(t *testing.T) {
|
||||
{
|
||||
desc: "change state to Active",
|
||||
state: bootstrap.Active,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -898,7 +898,7 @@ func TestChangeState(t *testing.T) {
|
||||
{
|
||||
desc: "change state to current state",
|
||||
state: bootstrap.Active,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -907,7 +907,7 @@ func TestChangeState(t *testing.T) {
|
||||
{
|
||||
desc: "change state to Inactive",
|
||||
state: bootstrap.Inactive,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -916,17 +916,17 @@ func TestChangeState(t *testing.T) {
|
||||
{
|
||||
desc: "change state with failed Connect",
|
||||
state: bootstrap.Active,
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
connectErr: errors.NewSDKError(bootstrap.ErrThings),
|
||||
err: bootstrap.ErrThings,
|
||||
connectErr: errors.NewSDKError(bootstrap.ErrClients),
|
||||
err: bootstrap.ErrClients,
|
||||
},
|
||||
{
|
||||
desc: "change state with invalid state",
|
||||
state: bootstrap.State(2),
|
||||
id: c.ThingID,
|
||||
id: c.ClientID,
|
||||
token: validToken,
|
||||
userID: validID,
|
||||
domainID: domainID,
|
||||
@@ -937,9 +937,9 @@ func TestChangeState(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
tc.session = mgauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
tc.session = smqauthn.Session{UserID: tc.userID, DomainID: tc.domainID, DomainUserID: validID}
|
||||
repoCall := boot.On("RetrieveByID", context.Background(), tc.domainID, tc.id).Return(c, tc.retrieveErr)
|
||||
sdkCall := sdk.On("Connect", mock.Anything, mock.Anything, mock.Anything).Return(tc.connectErr)
|
||||
sdkCall := sdk.On("ConnectClients", mock.Anything, mock.Anything, []string{"Publish", "Subscribe"}, mock.Anything, tc.token).Return(tc.connectErr)
|
||||
repoCall1 := boot.On("ChangeState", context.Background(), mock.Anything, mock.Anything, mock.Anything).Return(tc.stateErr)
|
||||
err := svc.ChangeState(context.Background(), tc.session, tc.token, tc.id, tc.state)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
@@ -1026,7 +1026,7 @@ func TestRemoveConfigHandler(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
desc: "remove an existing config",
|
||||
id: config.ThingID,
|
||||
id: config.ClientID,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
@@ -1038,7 +1038,7 @@ func TestRemoveConfigHandler(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
repoCall := boot.On("RemoveThing", context.Background(), mock.Anything).Return(tc.err)
|
||||
repoCall := boot.On("RemoveClient", context.Background(), mock.Anything).Return(tc.err)
|
||||
err := svc.RemoveConfigHandler(context.Background(), tc.id)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
repoCall.Unset()
|
||||
@@ -1046,66 +1046,66 @@ func TestRemoveConfigHandler(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectThingsHandler(t *testing.T) {
|
||||
func TestConnectClientHandler(t *testing.T) {
|
||||
svc := newService()
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
thingID string
|
||||
clientID string
|
||||
channelID string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "connect",
|
||||
channelID: channel.ID,
|
||||
thingID: config.ThingID,
|
||||
clientID: config.ClientID,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "connect connected",
|
||||
channelID: channel.ID,
|
||||
thingID: config.ThingID,
|
||||
clientID: config.ClientID,
|
||||
err: svcerr.ErrAddPolicies,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
repoCall := boot.On("ConnectThing", context.Background(), mock.Anything, mock.Anything).Return(tc.err)
|
||||
err := svc.ConnectThingHandler(context.Background(), tc.channelID, tc.thingID)
|
||||
repoCall := boot.On("ConnectClient", context.Background(), mock.Anything, mock.Anything).Return(tc.err)
|
||||
err := svc.ConnectClientHandler(context.Background(), tc.channelID, tc.clientID)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
repoCall.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisconnectThingsHandler(t *testing.T) {
|
||||
func TestDisconnectClientsHandler(t *testing.T) {
|
||||
svc := newService()
|
||||
|
||||
cases := []struct {
|
||||
desc string
|
||||
thingID string
|
||||
clientID string
|
||||
channelID string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
desc: "disconnect",
|
||||
channelID: channel.ID,
|
||||
thingID: config.ThingID,
|
||||
clientID: config.ClientID,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
desc: "disconnect disconnected",
|
||||
channelID: channel.ID,
|
||||
thingID: config.ThingID,
|
||||
clientID: config.ClientID,
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
repoCall := boot.On("DisconnectThing", context.Background(), mock.Anything, mock.Anything).Return(tc.err)
|
||||
err := svc.DisconnectThingHandler(context.Background(), tc.channelID, tc.thingID)
|
||||
repoCall := boot.On("DisconnectClient", context.Background(), mock.Anything, mock.Anything).Return(tc.err)
|
||||
err := svc.DisconnectClientHandler(context.Background(), tc.channelID, tc.clientID)
|
||||
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
|
||||
repoCall.Unset()
|
||||
})
|
||||
|
||||
+5
-5
@@ -6,18 +6,18 @@ package bootstrap
|
||||
import "strconv"
|
||||
|
||||
const (
|
||||
// Inactive Thing is created, but not able to exchange messages using Magistrala.
|
||||
// Inactive Client is created, but not able to exchange messages using SuperMQ.
|
||||
Inactive State = iota
|
||||
// Active Thing is created, configured, and whitelisted.
|
||||
// Active Client is created, configured, and whitelisted.
|
||||
Active
|
||||
)
|
||||
|
||||
// State represents corresponding Magistrala Thing state. The possible Config States
|
||||
// State represents corresponding SuperMQ Client state. The possible Config States
|
||||
// as well as description of what that State represents are given in the table:
|
||||
// | State | What it means |
|
||||
// |----------+--------------------------------------------------------------------------------|
|
||||
// | Inactive | Thing is created, but isn't able to communicate over Magistrala |
|
||||
// | Active | Thing is able to communicate using Magistrala |.
|
||||
// | Inactive | Client is created, but isn't able to communicate over SuperMQ |
|
||||
// | Active | Client is able to communicate using SuperMQ |.
|
||||
type State int
|
||||
|
||||
// String returns string representation of State.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package tracing provides tracing instrumentation for Magistrala Users service.
|
||||
// Package tracing provides tracing instrumentation for SuperMQ Users service.
|
||||
//
|
||||
// This package provides tracing middleware for Magistrala Users service.
|
||||
// This package provides tracing middleware for SuperMQ Users service.
|
||||
// It can be used to trace incoming requests and add tracing capabilities to
|
||||
// Magistrala Users service.
|
||||
// SuperMQ Users service.
|
||||
//
|
||||
// For more details about tracing instrumentation for Magistrala messaging refer
|
||||
// to the documentation at https://docs.magistrala.abstractmachines.fr/tracing/.
|
||||
// For more details about tracing instrumentation for SuperMQ messaging refer
|
||||
// to the documentation at https://docs.supermq.abstractmachines.fr/tracing/.
|
||||
package tracing
|
||||
|
||||
@@ -6,8 +6,8 @@ package tracing
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/absmach/magistrala/bootstrap"
|
||||
mgauthn "github.com/absmach/magistrala/pkg/authn"
|
||||
"github.com/absmach/supermq/bootstrap"
|
||||
smqauthn "github.com/absmach/supermq/pkg/authn"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
@@ -25,9 +25,9 @@ func New(svc bootstrap.Service, tracer trace.Tracer) bootstrap.Service {
|
||||
}
|
||||
|
||||
// Add traces the "Add" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) Add(ctx context.Context, session mgauthn.Session, token string, cfg bootstrap.Config) (bootstrap.Config, error) {
|
||||
func (tm *tracingMiddleware) Add(ctx context.Context, session smqauthn.Session, token string, cfg bootstrap.Config) (bootstrap.Config, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_register_user", trace.WithAttributes(
|
||||
attribute.String("thing_id", cfg.ThingID),
|
||||
attribute.String("client_id", cfg.ClientID),
|
||||
attribute.String("domain_id ", cfg.DomainID),
|
||||
attribute.String("name", cfg.Name),
|
||||
attribute.String("external_id", cfg.ExternalID),
|
||||
@@ -40,7 +40,7 @@ func (tm *tracingMiddleware) Add(ctx context.Context, session mgauthn.Session, t
|
||||
}
|
||||
|
||||
// View traces the "View" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) View(ctx context.Context, session mgauthn.Session, id string) (bootstrap.Config, error) {
|
||||
func (tm *tracingMiddleware) View(ctx context.Context, session smqauthn.Session, id string) (bootstrap.Config, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_view_user", trace.WithAttributes(
|
||||
attribute.String("id", id),
|
||||
))
|
||||
@@ -50,11 +50,11 @@ func (tm *tracingMiddleware) View(ctx context.Context, session mgauthn.Session,
|
||||
}
|
||||
|
||||
// Update traces the "Update" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) Update(ctx context.Context, session mgauthn.Session, cfg bootstrap.Config) error {
|
||||
func (tm *tracingMiddleware) Update(ctx context.Context, session smqauthn.Session, cfg bootstrap.Config) error {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_update_user", trace.WithAttributes(
|
||||
attribute.String("name", cfg.Name),
|
||||
attribute.String("content", cfg.Content),
|
||||
attribute.String("thing_id", cfg.ThingID),
|
||||
attribute.String("client_id", cfg.ClientID),
|
||||
attribute.String("domain_id ", cfg.DomainID),
|
||||
))
|
||||
defer span.End()
|
||||
@@ -63,17 +63,17 @@ func (tm *tracingMiddleware) Update(ctx context.Context, session mgauthn.Session
|
||||
}
|
||||
|
||||
// UpdateCert traces the "UpdateCert" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) UpdateCert(ctx context.Context, session mgauthn.Session, thingID, clientCert, clientKey, caCert string) (bootstrap.Config, error) {
|
||||
func (tm *tracingMiddleware) UpdateCert(ctx context.Context, session smqauthn.Session, clientID, clientCert, clientKey, caCert string) (bootstrap.Config, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_update_cert", trace.WithAttributes(
|
||||
attribute.String("thing_id", thingID),
|
||||
attribute.String("client_id", clientID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.UpdateCert(ctx, session, thingID, clientCert, clientKey, caCert)
|
||||
return tm.svc.UpdateCert(ctx, session, clientID, clientCert, clientKey, caCert)
|
||||
}
|
||||
|
||||
// UpdateConnections traces the "UpdateConnections" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) UpdateConnections(ctx context.Context, session mgauthn.Session, token, id string, connections []string) error {
|
||||
func (tm *tracingMiddleware) UpdateConnections(ctx context.Context, session smqauthn.Session, token, id string, connections []string) error {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_update_connections", trace.WithAttributes(
|
||||
attribute.String("id", id),
|
||||
attribute.StringSlice("connections", connections),
|
||||
@@ -84,7 +84,7 @@ func (tm *tracingMiddleware) UpdateConnections(ctx context.Context, session mgau
|
||||
}
|
||||
|
||||
// List traces the "List" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) List(ctx context.Context, session mgauthn.Session, filter bootstrap.Filter, offset, limit uint64) (bootstrap.ConfigsPage, error) {
|
||||
func (tm *tracingMiddleware) List(ctx context.Context, session smqauthn.Session, filter bootstrap.Filter, offset, limit uint64) (bootstrap.ConfigsPage, error) {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_list_users", trace.WithAttributes(
|
||||
attribute.Int64("offset", int64(offset)),
|
||||
attribute.Int64("limit", int64(limit)),
|
||||
@@ -95,7 +95,7 @@ func (tm *tracingMiddleware) List(ctx context.Context, session mgauthn.Session,
|
||||
}
|
||||
|
||||
// Remove traces the "Remove" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) Remove(ctx context.Context, session mgauthn.Session, id string) error {
|
||||
func (tm *tracingMiddleware) Remove(ctx context.Context, session smqauthn.Session, id string) error {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_remove_user", trace.WithAttributes(
|
||||
attribute.String("id", id),
|
||||
))
|
||||
@@ -117,7 +117,7 @@ func (tm *tracingMiddleware) Bootstrap(ctx context.Context, externalKey, externa
|
||||
}
|
||||
|
||||
// ChangeState traces the "ChangeState" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) ChangeState(ctx context.Context, session mgauthn.Session, token, id string, state bootstrap.State) error {
|
||||
func (tm *tracingMiddleware) ChangeState(ctx context.Context, session smqauthn.Session, token, id string, state bootstrap.State) error {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_change_state", trace.WithAttributes(
|
||||
attribute.String("id", id),
|
||||
attribute.String("state", state.String()),
|
||||
@@ -159,24 +159,24 @@ func (tm *tracingMiddleware) RemoveChannelHandler(ctx context.Context, id string
|
||||
return tm.svc.RemoveChannelHandler(ctx, id)
|
||||
}
|
||||
|
||||
// ConnectThingHandler traces the "ConnectThingHandler" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) ConnectThingHandler(ctx context.Context, channelID, thingID string) error {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_connect_thing_handler", trace.WithAttributes(
|
||||
// ConnectClientHandler traces the "ConnectClientHandler" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) ConnectClientHandler(ctx context.Context, channelID, clientID string) error {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_connect_client_handler", trace.WithAttributes(
|
||||
attribute.String("channel_id", channelID),
|
||||
attribute.String("thing_id", thingID),
|
||||
attribute.String("client_id", clientID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.ConnectThingHandler(ctx, channelID, thingID)
|
||||
return tm.svc.ConnectClientHandler(ctx, channelID, clientID)
|
||||
}
|
||||
|
||||
// DisconnectThingHandler traces the "DisconnectThingHandler" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) DisconnectThingHandler(ctx context.Context, channelID, thingID string) error {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_disconnect_thing_handler", trace.WithAttributes(
|
||||
// DisconnectClientHandler traces the "DisconnectClientHandler" operation of the wrapped bootstrap.Service.
|
||||
func (tm *tracingMiddleware) DisconnectClientHandler(ctx context.Context, channelID, clientID string) error {
|
||||
ctx, span := tm.tracer.Start(ctx, "svc_disconnect_client_handler", trace.WithAttributes(
|
||||
attribute.String("channel_id", channelID),
|
||||
attribute.String("thing_id", thingID),
|
||||
attribute.String("client_id", clientID),
|
||||
))
|
||||
defer span.End()
|
||||
|
||||
return tm.svc.DisconnectThingHandler(ctx, channelID, thingID)
|
||||
return tm.svc.DisconnectClientHandler(ctx, channelID, clientID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user