diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index 19a11a3384..6d52258a09 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -11,7 +11,6 @@ on: - ".github/workflows/api-tests.yml" - "api/**" - "auth/api/http/**" - - "bootstrap/api**" - "certs/api/**" - "channels/api/http/**" - "clients/api/http/**" @@ -21,7 +20,6 @@ on: - "http/api/**" - "invitations/api/**" - "journal/api/**" - - "provision/api/**" - "readers/api/**" - "users/api/**" @@ -39,9 +37,7 @@ env: HTTP_ADAPTER_URL: http://localhost:8008 INVITATIONS_URL: http://localhost:9020 AUTH_URL: http://localhost:9001 - BOOTSTRAP_URL: http://localhost:9013 CERTS_URL: http://localhost:9019 - PROVISION_URL: http://localhost:9016 POSTGRES_READER_URL: http://localhost:9009 TIMESCALE_READER_URL: http://localhost:9011 JOURNAL_URL: http://localhost:9021 @@ -88,16 +84,11 @@ jobs: - "apidocs/openapi/auth.yml" - "auth/api/http/**" - bootstrap: - - ".github/workflows/api-tests.yml" - - "apidocs/openapi/bootstrap.yml" - - "bootstrap/api/**" - certs: - ".github/workflows/api-tests.yml" - "apidocs/openapi/certs.yml" - "certs/api/**" - + domains: - ".github/workflows/api-tests.yml" - "apidocs/openapi/domains.yml" @@ -113,11 +104,6 @@ jobs: - "apidocs/openapi/invitations.yml" - "invitations/api/**" - provision: - - ".github/workflows/api-tests.yml" - - "apidocs/openapi/provision.yml" - - "provision/api/**" - readers: - ".github/workflows/api-tests.yml" - "apidocs/openapi/readers.yml" @@ -127,12 +113,12 @@ jobs: - ".github/workflows/api-tests.yml" - "apidocs/openapi/clients.yml" - "clients/api/http/**" - + channels: - ".github/workflows/api-tests.yml" - "apidocs/openapi/channels.yml" - "channels/api/http/**" - + groups: - ".github/workflows/api-tests.yml" - "apidocs/openapi/groups.yml" @@ -152,7 +138,7 @@ jobs: checks: all report: false args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links' - + - name: Run Groups API tests if: steps.changes.outputs.groups == 'true' uses: schemathesis/action@v1 @@ -162,7 +148,7 @@ jobs: checks: all report: false args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links' - + - name: Run Clients API tests if: steps.changes.outputs.clients == 'true' uses: schemathesis/action@v1 @@ -172,7 +158,7 @@ jobs: checks: all report: false args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links' - + - name: Run Channels API tests if: steps.changes.outputs.channels == 'true' uses: schemathesis/action@v1 @@ -212,7 +198,7 @@ jobs: checks: all report: false args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links' - + - name: Run Domains API tests if: steps.changes.outputs.domains == 'true' uses: schemathesis/action@v1 @@ -222,7 +208,7 @@ jobs: checks: all report: false args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links' - + - name: Run Journal API tests if: steps.changes.outputs.journal == 'true' uses: schemathesis/action@v1 @@ -233,16 +219,6 @@ jobs: report: false args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links' - - name: Run Bootstrap API tests - if: steps.changes.outputs.bootstrap == 'true' - uses: schemathesis/action@v1 - with: - schema: apidocs/openapi/bootstrap.yml - base-url: ${{ env.BOOTSTRAP_URL }} - checks: all - report: false - args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links' - - name: Run Certs API tests if: steps.changes.outputs.certs == 'true' uses: schemathesis/action@v1 @@ -253,22 +229,6 @@ jobs: report: false args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links' - - name: Run Provision API tests - if: steps.changes.outputs.provision == 'true' - uses: schemathesis/action@v1 - with: - schema: apidocs/openapi/provision.yml - base-url: ${{ env.PROVISION_URL }} - checks: all - report: false - args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links' - - - name: Seed Messages - if: steps.changes.outputs.readers == 'true' - run: | - make cli - ./build/cli provision test - - name: Run Postgres Reader API tests if: steps.changes.outputs.readers == 'true' uses: schemathesis/action@v1 diff --git a/.github/workflows/check-generated-files.yml b/.github/workflows/check-generated-files.yml index 4bd66241a0..d0a2d9a069 100644 --- a/.github/workflows/check-generated-files.yml +++ b/.github/workflows/check-generated-files.yml @@ -57,10 +57,7 @@ jobs: - "auth/keys.go" - "auth/service.go" - "pkg/events/events.go" - - "provision/service.go" - "pkg/groups/groups.go" - - "bootstrap/service.go" - - "bootstrap/configs.go" - "invitations/invitations.go" - "users/emailer.go" - "users/hasher.go" @@ -132,9 +129,6 @@ jobs: mv ./auth/mocks/authz.go ./auth/mocks/authz.go.tmp mv ./auth/mocks/keys.go ./auth/mocks/keys.go.tmp mv ./auth/mocks/service.go ./auth/mocks/service.go.tmp - mv ./bootstrap/mocks/configs.go ./bootstrap/mocks/configs.go.tmp - mv ./bootstrap/mocks/config_reader.go ./bootstrap/mocks/config_reader.go.tmp - mv ./bootstrap/mocks/service.go ./bootstrap/mocks/service.go.tmp mv ./domains/mocks/domains_client.go ./domains/mocks/domains_client.go.tmp mv ./domains/mocks/repository.go ./domains/mocks/repository.go.tmp mv ./domains/mocks/service.go ./domains/mocks/service.go.tmp @@ -156,7 +150,6 @@ jobs: mv ./consumers/notifiers/mocks/service.go ./consumers/notifiers/mocks/service.go.tmp mv ./certs/mocks/pki.go ./certs/mocks/pki.go.tmp mv ./certs/mocks/service.go ./certs/mocks/service.go.tmp - mv ./provision/mocks/service.go ./provision/mocks/service.go.tmp mv ./clients/private/mocks/service.go ./clients/private/mocks/service.go.tmp mv ./clients/mocks/repository.go ./clients/mocks/repository.go.tmp mv ./clients/mocks/clients_client.go ./clients/mocks/clients_client.go.tmp @@ -197,9 +190,6 @@ jobs: check_mock_changes ./auth/mocks/authz.go " ./auth/mocks/authz.go" check_mock_changes ./auth/mocks/keys.go " ./auth/mocks/keys.go" check_mock_changes ./auth/mocks/service.go " ./auth/mocks/service.go" - check_mock_changes ./bootstrap/mocks/configs.go " ./bootstrap/mocks/configs.go" - check_mock_changes ./bootstrap/mocks/config_reader.go " ./bootstrap/mocks/config_reader.go" - check_mock_changes ./bootstrap/mocks/service.go " ./bootstrap/mocks/service.go" check_mock_changes ./domains/mocks/domains_client.go " ./domains/mocks/domains_client.go" check_mock_changes ./domains/mocks/repository.go " ./domains/mocks/repository.go" check_mock_changes ./domains/mocks/service.go " ./domains/mocks/service.go" @@ -221,7 +211,6 @@ jobs: check_mock_changes ./consumers/notifiers/mocks/service.go " ./consumers/notifiers/mocks/service.go" check_mock_changes ./certs/mocks/pki.go " ./certs/mocks/pki.go" check_mock_changes ./certs/mocks/service.go " ./certs/mocks/service.go" - check_mock_changes ./provision/mocks/service.go " ./provision/mocks/service.go" check_mock_changes ./clients/private/mocks/service.go " ./clients/private/mocks/service.go" check_mock_changes ./clients/mocks/repository.go " ./clients/mocks/repository.go" check_mock_changes ./clients/mocks/clients_client.go " ./clients/mocks/clients_client.go" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 1c407abc13..d2cde1c67a 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: - name: Lint Protobuf Files run: | - protolint . + protolint . - name: golangci-lint uses: golangci/golangci-lint-action@v6 @@ -83,15 +83,6 @@ jobs: - "auth_grpc.pb.go" - "pkg/ulid/**" - "pkg/uuid/**" - - bootstrap: - - "bootstrap/**" - - "cmd/bootstrap/**" - - "auth.pb.go" - - "auth_grpc.pb.go" - - "auth/**" - - "pkg/sdk/**" - - "pkg/events/**" certs: - "certs/**" @@ -100,7 +91,7 @@ jobs: - "auth_grpc.pb.go" - "auth/**" - "pkg/sdk/**" - + channels: - "channels/**" - "cmd/channels/**" @@ -152,7 +143,7 @@ jobs: - "pkg/ulid/**" - "pkg/uuid/**" - "pkg/messaging/**" - + domains: - "domain/**" - "cmd/domain/**" @@ -193,7 +184,7 @@ jobs: - "auth_grpc.pb.go" - "auth/**" - "pkg/sdk/**" - + journal: - "journal/**" - "cmd/journal/**" @@ -201,7 +192,7 @@ jobs: - "auth_grpc.pb.go" - "auth/**" - "pkg/events/**" - + logger: - "logger/**" @@ -233,7 +224,6 @@ jobs: - "pkg/errors/**" - "pkg/groups/**" - "auth/**" - - "bootstrap/**" - "certs/**" - "consumers/**" - "http/**" @@ -242,7 +232,6 @@ jobs: - "internal/apiutil/**" - "internal/groups/**" - "invitations/**" - - "provision/**" - "readers/**" - "clients/**" - "users/**" @@ -256,12 +245,6 @@ jobs: pkg-uuid: - "pkg/uuid/**" - provision: - - "provision/**" - - "cmd/provision/**" - - "logger/**" - - "pkg/sdk/**" - readers: - "readers/**" - "cmd/postgres-reader/**" @@ -302,17 +285,12 @@ jobs: if: steps.changes.outputs.auth == 'true' || steps.changes.outputs.workflow == 'true' run: | go test --race -v -count=1 -coverprofile=coverage/auth.out ./auth/... - + - name: Run domains tests if: steps.changes.outputs.domains == 'true' || steps.changes.outputs.workflow == 'true' run: | go test --race -v -count=1 -coverprofile=coverage/domains.out ./domains/... - - name: Run bootstrap tests - if: steps.changes.outputs.bootstrap == 'true' || steps.changes.outputs.workflow == 'true' - run: | - go test --race -v -count=1 -coverprofile=coverage/bootstrap.out ./bootstrap/... - - name: Run certs tests if: steps.changes.outputs.certs == 'true' || steps.changes.outputs.workflow == 'true' run: | @@ -398,11 +376,6 @@ jobs: run: | go test --race -v -count=1 -coverprofile=coverage/pkg-uuid.out ./pkg/uuid/... - - name: Run provision tests - if: steps.changes.outputs.provision == 'true' || steps.changes.outputs.workflow == 'true' - run: | - go test --race -v -count=1 -coverprofile=coverage/provision.out ./provision/... - - name: Run readers tests if: steps.changes.outputs.readers == 'true' || steps.changes.outputs.workflow == 'true' run: | @@ -412,7 +385,7 @@ jobs: if: steps.changes.outputs.clients == 'true' || steps.changes.outputs.workflow == 'true' run: | go test --race -v -count=1 -coverprofile=coverage/clients.out ./clients/... - + - name: Run channels tests if: steps.changes.outputs.channels == 'true' || steps.changes.outputs.workflow == 'true' run: | @@ -422,7 +395,7 @@ jobs: if: steps.changes.outputs.users == 'true' || steps.changes.outputs.workflow == 'true' run: | go test --race -v -count=1 -coverprofile=coverage/users.out ./users/... - + - name: Run groups tests if: steps.changes.outputs.groups == 'true' || steps.changes.outputs.workflow == 'true' run: | diff --git a/Makefile b/Makefile index 8e175b5e86..37f7c6aeee 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,8 @@ SMQ_DOCKER_IMAGE_NAME_PREFIX ?= supermq BUILD_DIR ?= build SERVICES = auth users clients groups channels domains http coap ws postgres-writer postgres-reader timescale-writer \ - timescale-reader cli bootstrap mqtt provision certs invitations journal -TEST_API_SERVICES = journal auth bootstrap certs http invitations notifiers provision readers clients users channels groups domains + timescale-reader cli mqtt certs invitations journal +TEST_API_SERVICES = journal auth certs http invitations notifiers readers clients users channels groups domains TEST_API = $(addprefix test_api_,$(TEST_API_SERVICES)) DOCKERS = $(addprefix docker_,$(SERVICES)) DOCKERS_DEV = $(addprefix docker_dev_,$(SERVICES)) @@ -73,7 +73,7 @@ define make_docker_dev -f docker/Dockerfile.dev ./build endef -ADDON_SERVICES = bootstrap journal provision certs timescale-reader timescale-writer postgres-reader postgres-writer +ADDON_SERVICES = journal certs timescale-reader timescale-writer postgres-reader postgres-writer EXTERNAL_SERVICES = vault prometheus @@ -175,9 +175,7 @@ test_api_groups: TEST_API_URL := http://localhost:9004 test_api_http: TEST_API_URL := http://localhost:8008 test_api_invitations: TEST_API_URL := http://localhost:9020 test_api_auth: TEST_API_URL := http://localhost:9001 -test_api_bootstrap: TEST_API_URL := http://localhost:9013 test_api_certs: TEST_API_URL := http://localhost:9019 -test_api_provision: TEST_API_URL := http://localhost:9016 test_api_readers: TEST_API_URL := http://localhost:9009 # This can be the URL of any reader service. test_api_journal: TEST_API_URL := http://localhost:9021 diff --git a/api/http/common.go b/api/http/common.go index 802c872e63..b326abecc5 100644 --- a/api/http/common.go +++ b/api/http/common.go @@ -10,7 +10,6 @@ import ( "github.com/absmach/supermq" apiutil "github.com/absmach/supermq/api/http/util" - "github.com/absmach/supermq/bootstrap" "github.com/absmach/supermq/certs" "github.com/absmach/supermq/clients" "github.com/absmach/supermq/groups" @@ -127,9 +126,7 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) { switch { case errors.Contains(err, svcerr.ErrAuthorization), errors.Contains(err, svcerr.ErrDomainAuthorization), - errors.Contains(err, svcerr.ErrUnauthorizedPAT), - errors.Contains(err, bootstrap.ErrExternalKey), - errors.Contains(err, bootstrap.ErrExternalKeySecure): + errors.Contains(err, svcerr.ErrUnauthorizedPAT): err = unwrap(err) w.WriteHeader(http.StatusForbidden) @@ -169,11 +166,9 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) { errors.Contains(err, apiutil.ErrInvitationState), errors.Contains(err, apiutil.ErrInvalidAPIKey), errors.Contains(err, svcerr.ErrViewEntity), - errors.Contains(err, apiutil.ErrBootstrapState), errors.Contains(err, apiutil.ErrMissingCertData), errors.Contains(err, apiutil.ErrInvalidContact), errors.Contains(err, apiutil.ErrInvalidTopic), - errors.Contains(err, bootstrap.ErrAddBootstrap), errors.Contains(err, apiutil.ErrInvalidCertData), errors.Contains(err, apiutil.ErrEmptyMessage), errors.Contains(err, apiutil.ErrInvalidLevel), @@ -214,8 +209,7 @@ func EncodeError(_ context.Context, err error, w http.ResponseWriter) { err = unwrap(err) w.WriteHeader(http.StatusUnprocessableEntity) - case errors.Contains(err, svcerr.ErrNotFound), - errors.Contains(err, bootstrap.ErrBootstrap): + case errors.Contains(err, svcerr.ErrNotFound): err = unwrap(err) w.WriteHeader(http.StatusNotFound) diff --git a/api/http/util/errors.go b/api/http/util/errors.go index 2d0330c7d3..8857c0ec75 100644 --- a/api/http/util/errors.go +++ b/api/http/util/errors.go @@ -156,9 +156,6 @@ var ( // ErrInvalidAPIKey indicates an invalid API key type. ErrInvalidAPIKey = errors.New("invalid api key type") - // ErrBootstrapState indicates an invalid bootstrap state. - ErrBootstrapState = errors.New("invalid bootstrap state") - // ErrInvitationState indicates an invalid invitation state. ErrInvitationState = errors.New("invalid invitation state") diff --git a/apidocs/openapi/bootstrap.yml b/apidocs/openapi/bootstrap.yml deleted file mode 100644 index 47584ce0b9..0000000000 --- a/apidocs/openapi/bootstrap.yml +++ /dev/null @@ -1,690 +0,0 @@ -# Copyright (c) Abstract Machines -# SPDX-License-Identifier: Apache-2.0 - -openapi: 3.0.1 -info: - title: SuperMQ Bootstrap service - description: | - HTTP API for managing platform clients configuration. - Some useful links: - - [The SuperMQ repository](https://github.com/absmach/supermq) - contact: - email: info@abstractmachines.fr - license: - name: Apache 2.0 - url: https://github.com/absmach/supermq/blob/main/LICENSE - version: 0.15.1 - -servers: - - url: http://localhost:9013 - - url: https://localhost:9013 - -tags: - - name: configs - description: Everything about your Configs - externalDocs: - description: Find out more about Configs - url: https://docs.supermq.abstractmachines.fr/ - -paths: - /{domainID}/clients/configs: - post: - operationId: createConfig - summary: Adds new config - description: | - Adds new config to the list of config owned by user identified using - the provided access token. - tags: - - configs - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - requestBody: - $ref: "#/components/requestBodies/ConfigCreateReq" - responses: - "201": - $ref: "#/components/responses/ConfigCreateRes" - "400": - description: Failed due to malformed JSON. - "401": - description: Missing or invalid access token provided. - "403": - description: Failed to perform authorization over the entity. - "404": - description: A non-existent entity request. - "409": - description: Failed due to using an existing identity. - "415": - description: Missing or invalid content type. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - "503": - description: Failed to receive response from the clients service. - get: - operationId: getConfigs - summary: Retrieves managed configs - description: | - Retrieves a list of managed configs. Due to performance concerns, data - is retrieved in subsets. The API configs must ensure that the entire - dataset is consumed either by making subsequent requests, or by - increasing the subset size of the initial request. - tags: - - configs - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - - $ref: "#/components/parameters/Limit" - - $ref: "#/components/parameters/Offset" - - $ref: "#/components/parameters/State" - - $ref: "#/components/parameters/Name" - responses: - "200": - $ref: "#/components/responses/ConfigListRes" - "400": - description: Failed due to malformed query parameters. - "401": - description: Missing or invalid access token provided. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - - /{domainID}/clients/configs/{configId}: - get: - operationId: getConfig - summary: Retrieves config info (with channels). - tags: - - configs - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - - $ref: "#/components/parameters/ConfigId" - responses: - "200": - $ref: "#/components/responses/ConfigRes" - "400": - description: Missing or invalid config. - "401": - description: Missing or invalid access token provided. - "403": - description: Failed to perform authorization over the entity. - "404": - description: Config does not exist. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - put: - operationId: updateConfig - summary: Updates config info - description: | - Update is performed by replacing the current resource data with values - provided in a request payload. Note that the owner, ID, external ID, - external key, SuperMQ Client ID and key cannot be changed. - tags: - - configs - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - - $ref: "#/components/parameters/ConfigId" - requestBody: - $ref: "#/components/requestBodies/ConfigUpdateReq" - responses: - "200": - description: Config updated. - "400": - description: Failed due to malformed JSON. - "401": - description: Missing or invalid access token provided. - "403": - description: Failed to perform authorization over the entity. - "404": - description: Config does not exist. - "415": - description: Missing or invalid content type. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - delete: - operationId: removeConfig - summary: Removes a Config - description: | - Removes a Config. In case of successful removal the service will ensure - that the removed config is disconnected from all of the SuperMQ channels. - tags: - - configs - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - - $ref: "#/components/parameters/ConfigId" - responses: - "204": - description: Config removed. - "400": - description: Failed due to malformed config ID. - "401": - description: Missing or invalid access token provided. - "403": - description: Failed to perform authorization over the entity. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - - /{domainID}/clients/configs/certs/{configId}: - patch: - operationId: updateConfigCerts - summary: Updates certs - description: | - Update is performed by replacing the current certificate data with values - provided in a request payload. - tags: - - configs - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - - $ref: "#/components/parameters/ConfigId" - requestBody: - $ref: "#/components/requestBodies/ConfigCertUpdateReq" - responses: - "200": - description: Config updated. - $ref: "#/components/responses/ConfigUpdateCertsRes" - "400": - description: Failed due to malformed JSON. - "401": - description: Missing or invalid access token provided. - "403": - description: Failed to perform authorization over the entity. - "404": - description: Config does not exist. - "415": - description: Missing or invalid content type. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - - /{domainID}/clients/configs/connections/{configId}: - put: - operationId: updateConfigConnections - summary: Updates channels the client is connected to - description: | - Update connections performs update of the channel list corresponding - Client is connected to. - tags: - - configs - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - - $ref: "#/components/parameters/ConfigId" - requestBody: - $ref: "#/components/requestBodies/ConfigConnUpdateReq" - responses: - "200": - description: Config updated. - "400": - description: Failed due to malformed JSON. - "401": - description: Missing or invalid access token provided. - "403": - description: Failed to perform authorization over the entity. - "404": - description: Config does not exist. - "415": - description: Missing or invalid content type. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - - /clients/bootstrap/{externalId}: - get: - operationId: getBootstrapConfig - summary: Retrieves configuration. - description: | - Retrieves a configuration with given external ID and external key. - tags: - - configs - security: - - bootstrapAuth: [] - parameters: - - $ref: "#/components/parameters/ExternalId" - responses: - "200": - $ref: "#/components/responses/BootstrapConfigRes" - "400": - description: Failed due to malformed JSON. - "401": - description: Missing or invalid external key provided. - "404": - description: Failed to retrieve corresponding config. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - - /clients/bootstrap/secure/{externalId}: - get: - operationId: getSecureBootstrapConfig - summary: Retrieves configuration. - description: | - Retrieves a configuration with given external ID and encrypted external key. - tags: - - configs - security: - - bootstrapEncAuth: [] - parameters: - - $ref: "#/components/parameters/ExternalId" - responses: - "200": - $ref: "#/components/responses/BootstrapConfigRes" - "400": - description: Failed due to malformed JSON. - "401": - description: Missing or invalid access token provided. - "404": - description: | - Failed to retrieve corresponding config. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - - /{domainID}/clients/state/{configId}: - put: - operationId: updateConfigState - summary: Updates Config state. - description: | - Updating state represents enabling/disabling Config, i.e. connecting - and disconnecting corresponding SuperMQ Client to the list of Channels. - tags: - - configs - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - - $ref: "#/components/parameters/ConfigId" - requestBody: - $ref: "#/components/requestBodies/ConfigStateUpdateReq" - responses: - "204": - description: Config removed. - "400": - description: Failed due to malformed config's ID. - "401": - description: Missing or invalid access token provided. - "404": - description: A non-existent entity request. - "415": - description: Missing or invalid content type. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - - /health: - get: - summary: Retrieves service health check info. - tags: - - health - security: [] - responses: - "200": - $ref: "#/components/responses/HealthRes" - "500": - $ref: "#/components/responses/ServiceError" - -components: - schemas: - State: - type: integer - enum: [0, 1] - Config: - type: object - properties: - client_id: - type: string - format: uuid - description: Corresponding SuperMQ Client ID. - magistrala_secret: - type: string - format: uuid - description: Corresponding SuperMQ Client key. - channels: - type: array - minItems: 0 - items: - type: object - properties: - id: - type: string - format: uuid - description: Channel unique identifier. - name: - type: string - description: Name of the Channel. - metadata: - type: object - description: Custom metadata related to the Channel. - external_id: - type: string - description: External ID (MAC address or some unique identifier). - external_key: - type: string - description: External key. - content: - type: string - description: Free-form custom configuration. - state: - $ref: "#/components/schemas/State" - client_cert: - type: string - description: Client certificate. - ca_cert: - type: string - description: Issuing CA certificate. - required: - - external_id - - external_key - ConfigList: - type: object - properties: - total: - type: integer - description: Total number of results. - minimum: 0 - offset: - type: integer - description: Number of items to skip during retrieval. - minimum: 0 - default: 0 - limit: - type: integer - description: Size of the subset to retrieve. - maximum: 100 - default: 10 - configs: - type: array - minItems: 0 - uniqueItems: true - items: - $ref: "#/components/schemas/Config" - required: - - configs - BootstrapConfig: - type: object - properties: - client_id: - type: string - format: uuid - description: Corresponding SuperMQ Client ID. - client_key: - type: string - format: uuid - description: Corresponding SuperMQ Client key. - channels: - type: array - minItems: 0 - items: - type: string - content: - type: string - description: Free-form custom configuration. - client_cert: - type: string - description: Client certificate. - required: - - client_id - - client_key - - channels - - content - ConfigUpdateCerts: - type: object - properties: - client_id: - type: string - format: uuid - description: Corresponding SuperMQ Client ID. - client_cert: - type: string - description: Client certificate. - client_key: - type: string - description: Key for the client_cert. - ca_cert: - type: string - description: Issuing CA certificate. - required: - - client_id - - client_key - - channels - - content - - parameters: - ConfigId: - name: configId - description: Unique Config identifier. It's the ID of the corresponding Client. - in: path - schema: - type: string - format: uuid - required: true - ExternalId: - name: externalId - description: Unique Config identifier provided by external entity. - in: path - schema: - type: string - required: true - Limit: - name: limit - description: Size of the subset to retrieve. - in: query - schema: - type: integer - default: 10 - maximum: 100 - minimum: 1 - required: false - Offset: - name: offset - description: Number of items to skip during retrieval. - in: query - schema: - type: integer - default: 0 - minimum: 0 - required: false - State: - name: state - description: A state of items - in: query - schema: - $ref: "#/components/schemas/State" - required: false - Name: - name: name - description: Name of the config. Search by name is partial-match and case-insensitive. - in: query - schema: - type: string - required: false - - requestBodies: - ConfigCreateReq: - description: JSON-formatted document describing the new config. - required: true - content: - application/json: - schema: - type: object - properties: - external_id: - type: string - description: External ID (MAC address or some unique identifier). - external_key: - type: string - description: External key. - client_id: - type: string - format: uuid - description: ID of the corresponding SuperMQ Client. - channels: - type: array - minItems: 0 - items: - type: string - format: uuid - content: - type: string - name: - type: string - client_cert: - type: string - description: Client Certificate. - client_key: - type: string - description: Client Private Key. - ca_cert: - type: string - required: - - external_id - - external_key - ConfigUpdateReq: - description: JSON-formatted document describing the updated client. - content: - application/json: - schema: - type: object - properties: - content: - type: string - name: - type: string - required: - - content - - name - ConfigCertUpdateReq: - description: JSON-formatted document describing the updated client. - content: - application/json: - schema: - type: object - properties: - client_cert: - type: string - client_key: - type: string - ca_cert: - type: string - ConfigConnUpdateReq: - description: Array if IDs the client is be connected to. - content: - application/json: - schema: - type: object - properties: - channels: - type: array - minItems: 0 - items: - type: string - format: uuid - ConfigStateUpdateReq: - description: Update the state of the Config. - content: - application/json: - schema: - type: object - properties: - state: - $ref: "#/components/schemas/State" - - responses: - ConfigCreateRes: - description: Config registered. - headers: - Location: - content: - text/plain: - schema: - type: string - description: Created configuration's relative URL (i.e. /clients/configs/{configId}). - ConfigListRes: - description: Data retrieved. Configs from this list don't contain channels. - content: - application/json: - schema: - $ref: "#/components/schemas/ConfigList" - ConfigRes: - description: Data retrieved. - content: - application/json: - schema: - $ref: "#/components/schemas/Config" - links: - update: - operationId: updateConfig - parameters: - configId: $response.body#/id - updateCerts: - operationId: updateConfigCerts - parameters: - configId: $response.body#/id - updateConnections: - operationId: updateConfigConnections - parameters: - configId: $response.body#/id - updateState: - operationId: updateConfigState - parameters: - configId: $response.body#/id - delete: - operationId: removeConfig - parameters: - configId: $response.body#/id - BootstrapConfigRes: - description: | - Data retrieved. If secure, a response is encrypted using - the secret key, so the response is in the binary form. - content: - application/json: - schema: - $ref: "#/components/schemas/BootstrapConfig" - ServiceError: - description: Unexpected server-side error occurred. - HealthRes: - description: Service Health Check. - content: - application/health+json: - schema: - $ref: "./schemas/health_info.yml" - ConfigUpdateCertsRes: - description: Data retrieved. Config certs updated. - content: - application/json: - schema: - $ref: "#/components/schemas/ConfigUpdateCerts" - - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - description: | - * Users access: "Authorization: Bearer " - - bootstrapAuth: - type: http - scheme: bearer - bearerFormat: string - description: | - * Clients access: "Authorization: Client " - - bootstrapEncAuth: - type: http - scheme: bearer - bearerFormat: aes-sha256-uuid - description: | - * Clients access: "Authorization: Client " - Hex-encoded configuration external key encrypted using - the AES algorithm and SHA256 sum of the external key - itself as an encryption key. - -security: - - bearerAuth: [] diff --git a/apidocs/openapi/provision.yml b/apidocs/openapi/provision.yml deleted file mode 100644 index d487bbd234..0000000000 --- a/apidocs/openapi/provision.yml +++ /dev/null @@ -1,133 +0,0 @@ -# Copyright (c) Abstract Machines -# SPDX-License-Identifier: Apache-2.0 - -openapi: 3.0.1 -info: - title: SuperMQ Provision service - description: | - HTTP API for Provision service - Some useful links: - - [The SuperMQ repository](https://github.com/absmach/supermq) - contact: - email: info@abstracmachines.fr - license: - name: Apache 2.0 - url: https://github.com/absmach/supermq/blob/main/LICENSE - version: 0.15.1 - -servers: - - url: http://localhost:9016 - - url: https://localhost:9016 - -tags: - - name: provision - description: Everything about your Provision - externalDocs: - description: Find out more about provision - url: https://docs.supermq.abstractmachines.fr/ - -paths: - /{domainID}/mapping: - post: - summary: Adds new device to proxy - description: Adds new device to proxy - tags: - - provision - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - requestBody: - $ref: "#/components/requestBodies/ProvisionReq" - responses: - "201": - description: Created - "400": - description: Failed due to malformed JSON. - "401": - description: Missing or invalid access token provided. - "403": - description: Failed to perform authorization over the entity. - "415": - description: Missing or invalid content type. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - get: - summary: Gets current mapping. - description: Gets current mapping. This can be used in UI - so that when bootstrap config is created from UI matches - configuration created with provision service. - tags: - - provision - parameters: - - $ref: "auth.yml#/components/parameters/DomainID" - responses: - "200": - $ref: "#/components/responses/ProvisionRes" - "401": - description: Missing or invalid access token provided. - "403": - description: Failed to perform authorization over the entity. - "415": - description: Missing or invalid content type. - "422": - description: Database can't process request. - "500": - $ref: "#/components/responses/ServiceError" - /health: - get: - summary: Retrieves service health check info. - tags: - - health - security: [] - responses: - "200": - $ref: "#/components/responses/HealthRes" - "500": - $ref: "#/components/responses/ServiceError" - -components: - requestBodies: - ProvisionReq: - description: MAC address of device or other identifier - content: - application/json: - schema: - type: object - required: - - external_id - - external_key - properties: - external_id: - type: string - external_key: - type: string - name: - type: string - - responses: - ServiceError: - description: Unexpected server-side error occurred. - ProvisionRes: - description: Current mapping JSON representation. - content: - application/json: - schema: - type: object - HealthRes: - description: Service Health Check. - content: - application/health+json: - schema: - $ref: "./schemas/health_info.yml" - - securitySchemes: - bearerAuth: - type: http - scheme: bearer - bearerFormat: JWT - description: | - * Users access: "Authorization: Bearer " - -security: - - bearerAuth: [] diff --git a/bootstrap/README.md b/bootstrap/README.md deleted file mode 100644 index dcd2ddfe1c..0000000000 --- a/bootstrap/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# BOOTSTRAP SERVICE - -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 Clients -2. Providing basic configuration for the newly created Clients -3. Enabling/disabling Clients - -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 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. - -## Client Configuration Entity - -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 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 Client, Bootstrap service is not able to create Magistrala Channels. - -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 | Client is created, but isn't enabled | -| Active | Client is able to communicate using Magistrala | - -Switching between states `Active` and `Inactive` enables and disables Client, respectively. - -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 | -| ------------------------------ | -------------------------------------------------------------------------------- | --------------------------------- | -| 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 | | -| SMQ_AUTH_GRPC_URL | Auth service Auth gRPC URL | | -| 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 | | -| SMQ_JAEGER_URL | Jaeger server URL | | -| 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 - -The service itself is distributed as Docker container. Check the [`bootstrap`](https://github.com/absmach/magistrala/blob/main/docker/addons/bootstrap/docker-compose.yml) service section in docker-compose file to see how service is deployed. - -To start the service outside of the container, execute the following shell script: - -```bash -# download the latest version of the service -git clone https://github.com/absmach/magistrala - -cd magistrala - -# compile the servic e -make bootstrap - -# copy binary to bin -make install - -# set the environment variables and run the service -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 `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 `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 - -For more information about service capabilities and its usage, please check out the [API documentation](https://docs.api.magistrala.abstractmachines.fr/?urls.primaryName=bootstrap.yml). diff --git a/bootstrap/api/doc.go b/bootstrap/api/doc.go deleted file mode 100644 index 1e8268ee69..0000000000 --- a/bootstrap/api/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package api contains implementation of bootstrap service HTTP API. -package api diff --git a/bootstrap/api/endpoint.go b/bootstrap/api/endpoint.go deleted file mode 100644 index 7889c1e98a..0000000000 --- a/bootstrap/api/endpoint.go +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "context" - - 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" -) - -func addEndpoint(svc bootstrap.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(addReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - session, ok := ctx.Value(api.SessionKey).(authn.Session) - if !ok { - return nil, svcerr.ErrAuthorization - } - - channels := []bootstrap.Channel{} - for _, c := range req.Channels { - channels = append(channels, bootstrap.Channel{ID: c}) - } - - config := bootstrap.Config{ - ClientID: req.ClientID, - ExternalID: req.ExternalID, - ExternalKey: req.ExternalKey, - Channels: channels, - Name: req.Name, - ClientCert: req.ClientCert, - ClientKey: req.ClientKey, - CACert: req.CACert, - Content: req.Content, - } - - saved, err := svc.Add(ctx, session, req.token, config) - if err != nil { - return nil, err - } - - res := configRes{ - id: saved.ClientID, - created: true, - } - - return res, nil - } -} - -func updateCertEndpoint(svc bootstrap.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(updateCertReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - session, ok := ctx.Value(api.SessionKey).(authn.Session) - if !ok { - return nil, svcerr.ErrAuthorization - } - - cfg, err := svc.UpdateCert(ctx, session, req.clientID, req.ClientCert, req.ClientKey, req.CACert) - if err != nil { - return nil, err - } - - res := updateConfigRes{ - ClientID: cfg.ClientID, - ClientCert: cfg.ClientCert, - CACert: cfg.CACert, - ClientKey: cfg.ClientKey, - } - - return res, nil - } -} - -func viewEndpoint(svc bootstrap.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(entityReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - session, ok := ctx.Value(api.SessionKey).(authn.Session) - if !ok { - return nil, svcerr.ErrAuthorization - } - - config, err := svc.View(ctx, session, req.id) - if err != nil { - return nil, err - } - - var channels []channelRes - for _, ch := range config.Channels { - channels = append(channels, channelRes{ - ID: ch.ID, - Name: ch.Name, - Metadata: ch.Metadata, - }) - } - - res := viewRes{ - 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 - } -} - -func updateEndpoint(svc bootstrap.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(updateReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - session, ok := ctx.Value(api.SessionKey).(authn.Session) - if !ok { - return nil, svcerr.ErrAuthorization - } - - config := bootstrap.Config{ - ClientID: req.id, - Name: req.Name, - Content: req.Content, - } - - if err := svc.Update(ctx, session, config); err != nil { - return nil, err - } - - res := configRes{ - id: config.ClientID, - created: false, - } - - return res, nil - } -} - -func updateConnEndpoint(svc bootstrap.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(updateConnReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - session, ok := ctx.Value(api.SessionKey).(authn.Session) - if !ok { - return nil, svcerr.ErrAuthorization - } - - if err := svc.UpdateConnections(ctx, session, req.token, req.id, req.Channels); err != nil { - return nil, err - } - - res := configRes{ - id: req.id, - created: false, - } - - return res, nil - } -} - -func listEndpoint(svc bootstrap.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(listReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - session, ok := ctx.Value(api.SessionKey).(authn.Session) - if !ok { - return nil, svcerr.ErrAuthorization - } - - page, err := svc.List(ctx, session, req.filter, req.offset, req.limit) - if err != nil { - return nil, err - } - res := listRes{ - Total: page.Total, - Offset: page.Offset, - Limit: page.Limit, - Configs: []viewRes{}, - } - - for _, cfg := range page.Configs { - var channels []channelRes - for _, ch := range cfg.Channels { - channels = append(channels, channelRes{ - ID: ch.ID, - Name: ch.Name, - Metadata: ch.Metadata, - }) - } - - view := viewRes{ - 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) - } - - return res, nil - } -} - -func removeEndpoint(svc bootstrap.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(entityReq) - if err := req.validate(); err != nil { - return removeRes{}, errors.Wrap(apiutil.ErrValidation, err) - } - - session, ok := ctx.Value(api.SessionKey).(authn.Session) - if !ok { - return nil, svcerr.ErrAuthorization - } - - if err := svc.Remove(ctx, session, req.id); err != nil { - return nil, err - } - - return removeRes{}, nil - } -} - -func bootstrapEndpoint(svc bootstrap.Service, reader bootstrap.ConfigReader, secure bool) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(bootstrapReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - cfg, err := svc.Bootstrap(ctx, req.key, req.id, secure) - if err != nil { - return nil, err - } - - return reader.ReadConfig(cfg, secure) - } -} - -func stateEndpoint(svc bootstrap.Service) endpoint.Endpoint { - return func(ctx context.Context, request interface{}) (interface{}, error) { - req := request.(changeStateReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - session, ok := ctx.Value(api.SessionKey).(authn.Session) - if !ok { - return nil, svcerr.ErrAuthorization - } - - if err := svc.ChangeState(ctx, session, req.token, req.id, req.State); err != nil { - return nil, err - } - - return stateRes{}, nil - } -} diff --git a/bootstrap/api/endpoint_test.go b/bootstrap/api/endpoint_test.go deleted file mode 100644 index 07c604bc94..0000000000 --- a/bootstrap/api/endpoint_test.go +++ /dev/null @@ -1,1418 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api_test - -import ( - "context" - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httptest" - "strconv" - "strings" - "testing" - - 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" - "github.com/absmach/supermq/internal/testsutil" - 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" -) - -const ( - validToken = "validToken" - domainID = "b4d7d79e-fd99-4c2b-ac09-524e43df6888" - invalidToken = "invalid" - email = "test@example.com" - unknown = "unknown" - channelsNum = 3 - contentType = "application/json" - wrongID = "wrong_id" - - addName = "name" - addContent = "config" - instanceID = "5de9b29a-feb9-11ed-be56-0242ac120002" - validID = "d4ebb847-5d0e-4e46-bdd9-b6aceaaa3a22" -) - -var ( - 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"` - }{ - 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"` - ClientSecret string `json:"client_secret,omitempty"` - CACert string `json:"ca_cert,omitempty"` - }{ - 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()}) - missingKeyRes = toJSON(apiutil.ErrorRes{Err: apiutil.ErrBearerKey.Error(), Msg: apiutil.ErrValidation.Error()}) - bsErrorRes = toJSON(apiutil.ErrorRes{Msg: bootstrap.ErrBootstrap.Error()}) - extKeyRes = toJSON(apiutil.ErrorRes{Msg: bootstrap.ErrExternalKey.Error()}) - extSecKeyRes = toJSON(apiutil.ErrorRes{Msg: bootstrap.ErrExternalKeySecure.Error()}) -) - -type testRequest struct { - client *http.Client - method string - url string - contentType string - token string - key string - body io.Reader -} - -func newConfig() bootstrap.Config { - return bootstrap.Config{ - ClientID: addClientID, - ClientSecret: addClientSecret, - ExternalID: addExternalID, - ExternalKey: addExternalKey, - Channels: []bootstrap.Channel{ - { - ID: "1", - Metadata: metadata, - }, - }, - Name: addName, - Content: addContent, - ClientCert: "newcert", - ClientKey: "newkey", - CACert: "newca", - } -} - -func (tr testRequest) make() (*http.Response, error) { - req, err := http.NewRequest(tr.method, tr.url, tr.body) - if err != nil { - return nil, err - } - - if tr.token != "" { - req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token) - } - if tr.key != "" { - req.Header.Set("Authorization", apiutil.ClientPrefix+tr.key) - } - - if tr.contentType != "" { - req.Header.Set("Content-Type", tr.contentType) - } - - return tr.client.Do(req) -} - -func enc(in []byte) ([]byte, error) { - block, err := aes.NewCipher(encKey) - if err != nil { - return nil, err - } - ciphertext := make([]byte, aes.BlockSize+len(in)) - iv := ciphertext[:aes.BlockSize] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return nil, err - } - stream := cipher.NewCFBEncrypter(block, iv) - stream.XORKeyStream(ciphertext[aes.BlockSize:], in) - return ciphertext, nil -} - -func dec(in []byte) ([]byte, error) { - block, err := aes.NewCipher(encKey) - if err != nil { - return nil, err - } - if len(in) < aes.BlockSize { - return nil, errors.ErrMalformedEntity - } - iv := in[:aes.BlockSize] - in = in[aes.BlockSize:] - stream := cipher.NewCFBDecrypter(block, iv) - stream.XORKeyStream(in, in) - return in, nil -} - -func newBootstrapServer() (*httptest.Server, *mocks.Service, *authnmocks.Authentication) { - logger := smqlog.NewMock() - svc := new(mocks.Service) - authn := new(authnmocks.Authentication) - mux := bsapi.MakeHandler(svc, authn, bootstrap.NewConfigReader(encKey), logger, instanceID) - return httptest.NewServer(mux), svc, authn -} - -func toJSON(data interface{}) string { - jsonData, err := json.Marshal(data) - if err != nil { - return "" - } - return string(jsonData) -} - -func TestAdd(t *testing.T) { - bs, svc, auth := newBootstrapServer() - defer bs.Close() - c := newConfig() - - data := toJSON(addReq) - - neID := addReq - neID.ClientID = testsutil.GenerateUUID(t) - neData := toJSON(neID) - - invalidChannels := addReq - invalidChannels.Channels = []string{wrongID} - wrongData := toJSON(invalidChannels) - - cases := []struct { - desc string - req string - domainID string - token string - session smqauthn.Session - contentType string - status int - location string - authenticateErr error - err error - }{ - { - desc: "add a config with invalid token", - req: data, - domainID: domainID, - token: invalidToken, - contentType: contentType, - status: http.StatusUnauthorized, - location: "", - authenticateErr: svcerr.ErrAuthentication, - err: svcerr.ErrAuthentication, - }, - { - desc: "add a valid config", - req: data, - domainID: domainID, - token: validToken, - contentType: contentType, - status: http.StatusCreated, - location: "/clients/configs/" + c.ClientID, - err: nil, - }, - { - desc: "add a config with wrong content type", - req: data, - domainID: domainID, - token: validToken, - contentType: "", - status: http.StatusUnsupportedMediaType, - location: "", - err: apiutil.ErrUnsupportedContentType, - }, - { - desc: "add an existing config", - req: data, - domainID: domainID, - token: validToken, - contentType: contentType, - status: http.StatusConflict, - location: "", - err: svcerr.ErrConflict, - }, - { - desc: "add a config with non-existent ID", - req: neData, - domainID: domainID, - token: validToken, - contentType: contentType, - status: http.StatusConflict, - location: "", - err: svcerr.ErrConflict, - }, - { - desc: "add a config with invalid channels", - req: wrongData, - domainID: domainID, - token: validToken, - contentType: contentType, - status: http.StatusConflict, - location: "", - err: svcerr.ErrConflict, - }, - { - desc: "add a config with wrong JSON", - req: "{\"external_id\": 5}", - domainID: domainID, - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - err: svcerr.ErrMalformedEntity, - }, - { - desc: "add a config with invalid request format", - req: "}", - domainID: domainID, - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - location: "", - err: svcerr.ErrMalformedEntity, - }, - { - desc: "add a config with empty JSON", - req: "{}", - domainID: domainID, - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - location: "", - err: apiutil.ErrInvalidQueryParams, - }, - { - desc: "add a config with an empty request", - req: "", - domainID: domainID, - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - location: "", - err: svcerr.ErrMalformedEntity, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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("Add", mock.Anything, tc.session, tc.token, mock.Anything).Return(c, tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodPost, - url: fmt.Sprintf("%s/%s/clients/configs", bs.URL, tc.domainID), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - location := res.Header.Get("Location") - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - assert.Equal(t, tc.location, location, fmt.Sprintf("%s: expected location '%s' got '%s'", tc.desc, tc.location, location)) - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestView(t *testing.T) { - bs, svc, auth := newBootstrapServer() - defer bs.Close() - c := newConfig() - - var channels []channel - for _, ch := range c.Channels { - channels = append(channels, channel{ID: ch.ID, Name: ch.Name, Metadata: ch.Metadata}) - } - - data := config{ - 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 smqauthn.Session - id string - status int - res config - authenticateErr error - err error - }{ - { - desc: "view a config with invalid token", - token: invalidToken, - id: c.ClientID, - status: http.StatusUnauthorized, - res: config{}, - authenticateErr: svcerr.ErrAuthentication, - err: svcerr.ErrAuthentication, - }, - { - desc: "view a config", - token: validToken, - id: c.ClientID, - status: http.StatusOK, - res: data, - err: nil, - }, - { - desc: "view a non-existing config", - token: validToken, - id: wrongID, - status: http.StatusNotFound, - res: config{}, - err: svcerr.ErrNotFound, - }, - { - desc: "view a config with an empty token", - token: "", - id: c.ClientID, - status: http.StatusUnauthorized, - res: config{}, - err: apiutil.ErrBearerToken, - }, - { - desc: "view config without authorization", - token: validToken, - id: c.ClientID, - status: http.StatusForbidden, - res: config{}, - err: svcerr.ErrAuthorization, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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/clients/configs/%s", bs.URL, domainID, tc.id), - token: tc.token, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - var view config - if err := json.NewDecoder(res.Body).Decode(&view); err != io.EOF { - assert.Nil(t, err, fmt.Sprintf("Decoding expected to succeed %s: %s", tc.desc, err)) - } - - assert.ElementsMatch(t, tc.res.Channels, view.Channels, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res.Channels, view.Channels)) - // Empty channels to prevent order mismatch. - tc.res.Channels = []channel{} - view.Channels = []channel{} - assert.Equal(t, tc.res, view, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res, view)) - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestUpdate(t *testing.T) { - bs, svc, auth := newBootstrapServer() - defer bs.Close() - c := newConfig() - - data := toJSON(updateReq) - - cases := []struct { - desc string - req string - id string - token string - session smqauthn.Session - contentType string - status int - authenticateErr error - err error - }{ - { - desc: "update with invalid token", - req: data, - id: c.ClientID, - token: invalidToken, - contentType: contentType, - status: http.StatusUnauthorized, - authenticateErr: svcerr.ErrAuthentication, - err: svcerr.ErrAuthentication, - }, - { - desc: "update with an empty token", - req: data, - id: c.ClientID, - token: "", - contentType: contentType, - status: http.StatusUnauthorized, - err: apiutil.ErrBearerToken, - }, - { - desc: "update a valid config", - req: data, - id: c.ClientID, - token: validToken, - contentType: contentType, - status: http.StatusOK, - err: nil, - }, - { - desc: "update a config with wrong content type", - req: data, - id: c.ClientID, - token: validToken, - contentType: "", - status: http.StatusUnsupportedMediaType, - err: apiutil.ErrUnsupportedContentType, - }, - { - desc: "update a non-existing config", - req: data, - id: wrongID, - token: validToken, - contentType: contentType, - status: http.StatusNotFound, - err: svcerr.ErrNotFound, - }, - { - desc: "update a config with invalid request format", - req: "}", - id: c.ClientID, - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - err: svcerr.ErrMalformedEntity, - }, - { - desc: "update a config with an empty request", - id: c.ClientID, - req: "", - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - err: svcerr.ErrMalformedEntity, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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/clients/configs/%s", bs.URL, domainID, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestUpdateCert(t *testing.T) { - bs, svc, auth := newBootstrapServer() - defer bs.Close() - c := newConfig() - - data := toJSON(updateReq) - - cases := []struct { - desc string - req string - id string - token string - session smqauthn.Session - contentType string - status int - authenticateErr error - err error - }{ - { - desc: "update with invalid token", - req: data, - id: c.ClientID, - token: invalidToken, - contentType: contentType, - status: http.StatusUnauthorized, - authenticateErr: svcerr.ErrAuthentication, - err: svcerr.ErrAuthentication, - }, - { - desc: "update with an empty token", - req: data, - id: c.ClientID, - token: "", - contentType: contentType, - status: http.StatusUnauthorized, - err: apiutil.ErrBearerToken, - }, - { - desc: "update a valid config", - req: data, - id: c.ClientID, - token: validToken, - contentType: contentType, - status: http.StatusOK, - err: nil, - }, - { - desc: "update a config with wrong content type", - req: data, - id: c.ClientID, - token: validToken, - contentType: "", - status: http.StatusUnsupportedMediaType, - err: apiutil.ErrUnsupportedContentType, - }, - { - desc: "update a non-existing config", - req: data, - id: wrongID, - token: validToken, - contentType: contentType, - status: http.StatusNotFound, - err: svcerr.ErrNotFound, - }, - { - desc: "update a config with invalid request format", - req: "}", - id: c.ClientSecret, - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - err: svcerr.ErrMalformedEntity, - }, - { - desc: "update a config with an empty request", - id: c.ClientID, - req: "", - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - err: svcerr.ErrMalformedEntity, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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/clients/configs/certs/%s", bs.URL, domainID, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestUpdateConnections(t *testing.T) { - bs, svc, auth := newBootstrapServer() - defer bs.Close() - c := newConfig() - data := toJSON(updateReq) - - invalidChannels := updateReq - invalidChannels.Channels = []string{wrongID} - - wrongData := toJSON(invalidChannels) - - cases := []struct { - desc string - req string - id string - token string - session smqauthn.Session - contentType string - status int - authenticateErr error - err error - }{ - { - desc: "update connections with invalid token", - req: data, - id: c.ClientID, - token: invalidToken, - contentType: contentType, - status: http.StatusUnauthorized, - authenticateErr: svcerr.ErrAuthentication, - err: svcerr.ErrAuthentication, - }, - { - desc: "update connections with an empty token", - req: data, - id: c.ClientID, - token: "", - contentType: contentType, - status: http.StatusUnauthorized, - err: apiutil.ErrBearerToken, - }, - { - desc: "update connections valid config", - req: data, - id: c.ClientID, - token: validToken, - contentType: contentType, - status: http.StatusOK, - err: nil, - }, - { - desc: "update connections with wrong content type", - req: data, - id: c.ClientID, - token: validToken, - contentType: "", - status: http.StatusUnsupportedMediaType, - err: apiutil.ErrUnsupportedContentType, - }, - { - desc: "update connections for a non-existing config", - req: data, - id: wrongID, - token: validToken, - contentType: contentType, - status: http.StatusNotFound, - err: svcerr.ErrNotFound, - }, - { - desc: "update connections with invalid channels", - req: wrongData, - id: c.ClientID, - token: validToken, - contentType: contentType, - status: http.StatusNotFound, - err: svcerr.ErrNotFound, - }, - { - desc: "update a config with invalid request format", - req: "}", - id: c.ClientID, - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - err: svcerr.ErrMalformedEntity, - }, - { - desc: "update a config with an empty request", - id: c.ClientID, - req: "", - token: validToken, - contentType: contentType, - status: http.StatusBadRequest, - err: svcerr.ErrMalformedEntity, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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/clients/configs/connections/%s", bs.URL, domainID, tc.id), - contentType: tc.contentType, - token: tc.token, - body: strings.NewReader(tc.req), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - repoCall.Unset() - authCall.Unset() - }) - } -} - -func TestList(t *testing.T) { - configNum := 101 - changedStateNum := 20 - var active, inactive []config - list := make([]config, configNum) - - bs, svc, auth := newBootstrapServer() - defer bs.Close() - 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.ClientSecret = c.ExternalID - c.Name = fmt.Sprintf("%s-%d", addName, i) - c.ExternalKey = fmt.Sprintf("%s%s", addExternalKey, strconv.Itoa(i)) - - var channels []channel - for _, ch := range c.Channels { - channels = append(channels, channel{ID: ch.ID, Name: ch.Name, Metadata: ch.Metadata}) - } - s := config{ - 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 - } - // Change state of first 20 elements for filtering tests. - for i := 0; i < changedStateNum; i++ { - state := bootstrap.Active - if i%2 == 0 { - state = bootstrap.Inactive - } - svcCall := svc.On("ChangeState", context.Background(), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil) - 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() - - list[i].State = state - if state == bootstrap.Inactive { - inactive = append(inactive, list[i]) - continue - } - active = append(active, list[i]) - } - - cases := []struct { - desc string - token string - session smqauthn.Session - url string - status int - res configPage - authenticateErr error - err error - }{ - { - desc: "view list with invalid token", - token: invalidToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d", path, 0, 10), - status: http.StatusUnauthorized, - res: configPage{}, - authenticateErr: svcerr.ErrAuthentication, - err: svcerr.ErrAuthentication, - }, - { - desc: "view list with an empty token", - token: "", - url: fmt.Sprintf("%s?offset=%d&limit=%d", path, 0, 10), - status: http.StatusUnauthorized, - res: configPage{}, - err: apiutil.ErrBearerToken, - }, - { - desc: "view list", - token: validToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d", path, 0, 1), - status: http.StatusOK, - res: configPage{ - Total: uint64(len(list)), - Offset: 0, - Limit: 1, - Configs: list[0:1], - }, - err: nil, - }, - { - desc: "view list searching by name", - token: validToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d&name=%s", path, 0, 100, "95"), - status: http.StatusOK, - res: configPage{ - Total: 1, - Offset: 0, - Limit: 100, - Configs: list[95:96], - }, - err: nil, - }, - { - desc: "view last page", - token: validToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d", path, 100, 10), - status: http.StatusOK, - res: configPage{ - Total: uint64(len(list)), - Offset: 100, - Limit: 10, - Configs: list[100:], - }, - err: nil, - }, - { - desc: "view with limit greater than allowed", - token: validToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d", path, 0, 1000), - status: http.StatusBadRequest, - res: configPage{}, - err: apiutil.ErrInvalidQueryParams, - }, - { - desc: "view list with no specified limit and offset", - token: validToken, - url: path, - status: http.StatusOK, - res: configPage{ - Total: uint64(len(list)), - Offset: 0, - Limit: 10, - Configs: list[0:10], - }, - err: nil, - }, - { - desc: "view list with no specified limit", - token: validToken, - url: fmt.Sprintf("%s?offset=%d", path, 10), - status: http.StatusOK, - res: configPage{ - Total: uint64(len(list)), - Offset: 10, - Limit: 10, - Configs: list[10:20], - }, - err: nil, - }, - { - desc: "view list with no specified offset", - token: validToken, - url: fmt.Sprintf("%s?limit=%d", path, 10), - status: http.StatusOK, - res: configPage{ - Total: uint64(len(list)), - Offset: 0, - Limit: 10, - Configs: list[0:10], - }, - err: nil, - }, - { - desc: "view list with limit < 0", - token: validToken, - url: fmt.Sprintf("%s?limit=%d", path, -10), - status: http.StatusBadRequest, - res: configPage{}, - err: apiutil.ErrInvalidQueryParams, - }, - { - desc: "view list with offset < 0", - token: validToken, - url: fmt.Sprintf("%s?offset=%d", path, -10), - status: http.StatusBadRequest, - res: configPage{}, - err: apiutil.ErrInvalidQueryParams, - }, - { - desc: "view list with invalid query parameters", - token: validToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d&state=%d&key=%%", path, 10, 10, bootstrap.Inactive), - status: http.StatusBadRequest, - res: configPage{}, - err: apiutil.ErrInvalidQueryParams, - }, - { - desc: "view first 10 active", - token: validToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d&state=%d", path, 0, 20, bootstrap.Active), - status: http.StatusOK, - res: configPage{ - Total: uint64(len(active)), - Offset: 0, - Limit: 20, - Configs: active, - }, - err: nil, - }, - { - desc: "view first 10 inactive", - token: validToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d&state=%d", path, 0, 20, bootstrap.Inactive), - status: http.StatusOK, - res: configPage{ - Total: uint64(len(list) - len(inactive)), - Offset: 0, - Limit: 20, - Configs: inactive, - }, - err: nil, - }, - { - desc: "view first 5 active", - token: validToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d&state=%d", path, 0, 10, bootstrap.Active), - status: http.StatusOK, - res: configPage{ - Total: uint64(len(active)), - Offset: 0, - Limit: 10, - Configs: active[:5], - }, - err: nil, - }, - { - desc: "view last 5 inactive", - token: validToken, - url: fmt.Sprintf("%s?offset=%d&limit=%d&state=%d", path, 10, 10, bootstrap.Inactive), - status: http.StatusOK, - res: configPage{ - Total: uint64(len(list) - len(active)), - Offset: 10, - Limit: 10, - Configs: inactive[5:], - }, - err: nil, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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) - req := testRequest{ - client: bs.Client(), - method: http.MethodGet, - url: tc.url, - token: tc.token, - } - - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - var body configPage - - err = json.NewDecoder(res.Body).Decode(&body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding response body: %s", tc.desc, err)) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - assert.Equal(t, tc.res.Total, body.Total, fmt.Sprintf("%s: expected response total '%d' got '%d'", tc.desc, tc.res.Total, body.Total)) - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestRemove(t *testing.T) { - bs, svc, auth := newBootstrapServer() - defer bs.Close() - c := newConfig() - - cases := []struct { - desc string - id string - token string - session smqauthn.Session - status int - authenticateErr error - err error - }{ - { - desc: "remove with invalid token", - id: c.ClientID, - token: invalidToken, - status: http.StatusUnauthorized, - authenticateErr: svcerr.ErrAuthentication, - err: svcerr.ErrAuthentication, - }, - { - desc: "remove with an empty token", - id: c.ClientID, - token: "", - status: http.StatusUnauthorized, - err: apiutil.ErrBearerToken, - }, - { - desc: "remove non-existing config", - id: "non-existing", - token: validToken, - status: http.StatusNoContent, - err: nil, - }, - { - desc: "remove config", - id: c.ClientID, - token: validToken, - status: http.StatusNoContent, - err: nil, - }, - { - desc: "remove removed config", - id: wrongID, - token: validToken, - status: http.StatusNoContent, - err: nil, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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/clients/configs/%s", bs.URL, domainID, tc.id), - token: tc.token, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestBootstrap(t *testing.T) { - bs, svc, _ := newBootstrapServer() - defer bs.Close() - c := newConfig() - - encExternKey, err := enc([]byte(c.ExternalKey)) - assert.Nil(t, err, fmt.Sprintf("Encrypting config expected to succeed: %s.\n", err)) - - var channels []channel - for _, ch := range c.Channels { - channels = append(channels, channel{ID: ch.ID, Name: ch.Name, Metadata: ch.Metadata}) - } - - s := struct { - 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"` - }{ - ClientID: c.ClientID, - ClientSecret: c.ClientSecret, - Channels: channels, - Content: c.Content, - ClientCert: c.ClientCert, - ClientKey: c.ClientKey, - CACert: c.CACert, - } - - data := toJSON(s) - - cases := []struct { - desc string - externalID string - externalKey string - status int - res string - secure bool - err error - }{ - { - desc: "bootstrap a Client with unknown ID", - externalID: unknown, - externalKey: c.ExternalKey, - status: http.StatusNotFound, - res: bsErrorRes, - secure: false, - err: bootstrap.ErrBootstrap, - }, - { - desc: "bootstrap a Client with an empty ID", - externalID: "", - externalKey: c.ExternalKey, - status: http.StatusBadRequest, - res: missingIDRes, - secure: false, - err: errors.Wrap(bootstrap.ErrBootstrap, svcerr.ErrMalformedEntity), - }, - { - desc: "bootstrap a Client with unknown key", - externalID: c.ExternalID, - externalKey: unknown, - status: http.StatusForbidden, - res: extKeyRes, - secure: false, - err: errors.Wrap(bootstrap.ErrExternalKey, errors.New("")), - }, - { - desc: "bootstrap a Client with an empty key", - externalID: c.ExternalID, - externalKey: "", - status: http.StatusBadRequest, - res: missingKeyRes, - secure: false, - err: errors.Wrap(bootstrap.ErrBootstrap, svcerr.ErrAuthentication), - }, - { - desc: "bootstrap known Client", - externalID: c.ExternalID, - externalKey: c.ExternalKey, - status: http.StatusOK, - res: data, - secure: false, - err: nil, - }, - { - desc: "bootstrap secure", - externalID: fmt.Sprintf("secure/%s", c.ExternalID), - externalKey: hex.EncodeToString(encExternKey), - status: http.StatusOK, - res: data, - secure: true, - err: nil, - }, - { - desc: "bootstrap secure with unencrypted key", - externalID: fmt.Sprintf("secure/%s", c.ExternalID), - externalKey: c.ExternalKey, - status: http.StatusForbidden, - res: extSecKeyRes, - secure: true, - err: bootstrap.ErrExternalKeySecure, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - svcCall := svc.On("Bootstrap", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(c, tc.err) - req := testRequest{ - client: bs.Client(), - method: http.MethodGet, - url: fmt.Sprintf("%s/clients/bootstrap/%s", bs.URL, tc.externalID), - key: tc.externalKey, - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - body, err := io.ReadAll(res.Body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - if tc.secure && tc.status == http.StatusOK { - body, err = dec(body) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error while decoding body: %s", tc.desc, err)) - } - data := strings.Trim(string(body), "\n") - assert.Equal(t, tc.res, data, fmt.Sprintf("%s: expected response '%s' got '%s'", tc.desc, tc.res, data)) - svcCall.Unset() - }) - } -} - -func TestChangeState(t *testing.T) { - bs, svc, auth := newBootstrapServer() - defer bs.Close() - c := newConfig() - - inactive := fmt.Sprintf("{\"state\": %d}", bootstrap.Inactive) - active := fmt.Sprintf("{\"state\": %d}", bootstrap.Active) - - cases := []struct { - desc string - id string - token string - session smqauthn.Session - state string - contentType string - status int - authenticateErr error - err error - }{ - { - desc: "change state with invalid token", - id: c.ClientID, - token: invalidToken, - state: active, - contentType: contentType, - status: http.StatusUnauthorized, - authenticateErr: svcerr.ErrAuthentication, - err: svcerr.ErrAuthentication, - }, - { - desc: "change state with an empty token", - id: c.ClientID, - token: "", - state: active, - contentType: contentType, - status: http.StatusUnauthorized, - err: apiutil.ErrBearerToken, - }, - { - desc: "change state with invalid content type", - id: c.ClientID, - token: validToken, - state: active, - contentType: "", - status: http.StatusUnsupportedMediaType, - err: apiutil.ErrUnsupportedContentType, - }, - { - desc: "change state to active", - id: c.ClientID, - token: validToken, - state: active, - contentType: contentType, - status: http.StatusOK, - err: nil, - }, - { - desc: "change state to inactive", - id: c.ClientID, - token: validToken, - state: inactive, - contentType: contentType, - status: http.StatusOK, - err: nil, - }, - { - desc: "change state of non-existing config", - id: wrongID, - token: validToken, - state: active, - contentType: contentType, - status: http.StatusNotFound, - err: svcerr.ErrNotFound, - }, - { - desc: "change state to invalid value", - id: c.ClientID, - token: validToken, - state: fmt.Sprintf("{\"state\": %d}", -3), - contentType: contentType, - status: http.StatusBadRequest, - err: svcerr.ErrMalformedEntity, - }, - { - desc: "change state with invalid data", - id: c.ClientID, - token: validToken, - state: "", - contentType: contentType, - status: http.StatusBadRequest, - err: svcerr.ErrMalformedEntity, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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/clients/state/%s", bs.URL, domainID, tc.id), - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(tc.state), - } - res, err := req.make() - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error %s", tc.desc, err)) - assert.Equal(t, tc.status, res.StatusCode, fmt.Sprintf("%s: expected status code %d got %d", tc.desc, tc.status, res.StatusCode)) - svcCall.Unset() - authCall.Unset() - }) - } -} - -type channel struct { - ID string `json:"id"` - Name string `json:"name,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` -} - -type config struct { - 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 { - Total uint64 `json:"total"` - Offset uint64 `json:"offset"` - Limit uint64 `json:"limit"` - Configs []config `json:"configs"` -} diff --git a/bootstrap/api/requests.go b/bootstrap/api/requests.go deleted file mode 100644 index a83e319045..0000000000 --- a/bootstrap/api/requests.go +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - apiutil "github.com/absmach/supermq/api/http/util" - "github.com/absmach/supermq/bootstrap" -) - -const maxLimitSize = 100 - -type addReq struct { - token string - ClientID string `json:"client_id"` - ExternalID string `json:"external_id"` - ExternalKey string `json:"external_key"` - Channels []string `json:"channels"` - Name string `json:"name"` - Content string `json:"content"` - ClientCert string `json:"client_cert"` - ClientKey string `json:"client_key"` - CACert string `json:"ca_cert"` -} - -func (req addReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.ExternalID == "" { - return apiutil.ErrMissingID - } - - if req.ExternalKey == "" { - return apiutil.ErrBearerKey - } - - if len(req.Channels) == 0 { - return apiutil.ErrEmptyList - } - - for _, channel := range req.Channels { - if channel == "" { - return apiutil.ErrMissingID - } - } - - return nil -} - -type entityReq struct { - id string -} - -func (req entityReq) validate() error { - if req.id == "" { - return apiutil.ErrMissingID - } - - return nil -} - -type updateReq struct { - id string - Name string `json:"name"` - Content string `json:"content"` -} - -func (req updateReq) validate() error { - if req.id == "" { - return apiutil.ErrMissingID - } - - return nil -} - -type updateCertReq struct { - clientID string - ClientCert string `json:"client_cert"` - ClientKey string `json:"client_key"` - CACert string `json:"ca_cert"` -} - -func (req updateCertReq) validate() error { - if req.clientID == "" { - return apiutil.ErrMissingID - } - - return nil -} - -type updateConnReq struct { - token string - id string - Channels []string `json:"channels"` -} - -func (req updateConnReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.id == "" { - return apiutil.ErrMissingID - } - - return nil -} - -type listReq struct { - filter bootstrap.Filter - offset uint64 - limit uint64 -} - -func (req listReq) validate() error { - if req.limit > maxLimitSize { - return apiutil.ErrLimitSize - } - - return nil -} - -type bootstrapReq struct { - key string - id string -} - -func (req bootstrapReq) validate() error { - if req.key == "" { - return apiutil.ErrBearerKey - } - - if req.id == "" { - return apiutil.ErrMissingID - } - - return nil -} - -type changeStateReq struct { - token string - id string - State bootstrap.State `json:"state"` -} - -func (req changeStateReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - - if req.id == "" { - return apiutil.ErrMissingID - } - - if req.State != bootstrap.Inactive && - req.State != bootstrap.Active { - return apiutil.ErrBootstrapState - } - - return nil -} diff --git a/bootstrap/api/requests_test.go b/bootstrap/api/requests_test.go deleted file mode 100644 index 9d8f0668fb..0000000000 --- a/bootstrap/api/requests_test.go +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "fmt" - "testing" - - apiutil "github.com/absmach/supermq/api/http/util" - "github.com/absmach/supermq/bootstrap" - "github.com/absmach/supermq/internal/testsutil" - "github.com/stretchr/testify/assert" -) - -var ( - channel1 = testsutil.GenerateUUID(&testing.T{}) - channel2 = testsutil.GenerateUUID(&testing.T{}) -) - -func TestAddReqValidation(t *testing.T) { - cases := []struct { - desc string - token string - externalID string - externalKey string - channels []string - err error - }{ - { - desc: "valid request", - token: "token", - externalID: "external-id", - externalKey: "external-key", - channels: []string{channel1, channel2}, - err: nil, - }, - { - desc: "empty token", - token: "", - externalID: "external-id", - externalKey: "external-key", - channels: []string{channel1, channel2}, - err: apiutil.ErrBearerToken, - }, - { - desc: "empty external ID", - token: "token", - externalID: "", - externalKey: "external-key", - channels: []string{channel1, channel2}, - err: apiutil.ErrMissingID, - }, - { - desc: "empty external key", - token: "token", - externalID: "external-id", - externalKey: "", - channels: []string{channel1, channel2}, - err: apiutil.ErrBearerKey, - }, - { - desc: "empty external key and external ID", - token: "token", - externalID: "", - externalKey: "", - channels: []string{channel1, channel2}, - err: apiutil.ErrMissingID, - }, - { - desc: "empty channels", - token: "token", - externalID: "external-id", - externalKey: "external-key", - channels: []string{}, - err: apiutil.ErrEmptyList, - }, - { - desc: "empty channel value", - token: "token", - externalID: "external-id", - externalKey: "external-key", - channels: []string{channel1, ""}, - err: apiutil.ErrMissingID, - }, - } - - for _, tc := range cases { - req := addReq{ - token: tc.token, - ExternalID: tc.externalID, - ExternalKey: tc.externalKey, - Channels: tc.channels, - } - - err := req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestEntityReqValidation(t *testing.T) { - cases := []struct { - desc string - id string - err error - }{ - { - desc: "empty id", - id: "", - err: apiutil.ErrMissingID, - }, - } - - for _, tc := range cases { - req := entityReq{ - id: tc.id, - } - - err := req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestUpdateReqValidation(t *testing.T) { - cases := []struct { - desc string - id string - err error - }{ - { - desc: "valid request", - id: "id", - err: nil, - }, - { - desc: "empty id", - id: "", - err: apiutil.ErrMissingID, - }, - } - - for _, tc := range cases { - req := updateReq{ - id: tc.id, - } - - err := req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestUpdateCertReqValidation(t *testing.T) { - cases := []struct { - desc string - clientID string - err error - }{ - { - desc: "empty client id", - clientID: "", - err: apiutil.ErrMissingID, - }, - } - - for _, tc := range cases { - req := updateCertReq{ - clientID: tc.clientID, - } - - err := req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestUpdateConnReqValidation(t *testing.T) { - cases := []struct { - desc string - id string - token string - - err error - }{ - { - desc: "empty token", - token: "", - id: "id", - err: apiutil.ErrBearerToken, - }, - { - desc: "empty id", - token: "token", - id: "", - err: apiutil.ErrMissingID, - }, - } - - for _, tc := range cases { - req := updateConnReq{ - token: tc.token, - id: tc.id, - } - - err := req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestListReqValidation(t *testing.T) { - cases := []struct { - desc string - offset uint64 - limit uint64 - err error - }{ - { - desc: "too large limit", - offset: 0, - limit: maxLimitSize + 1, - err: apiutil.ErrLimitSize, - }, - { - desc: "default limit", - offset: 0, - limit: defLimit, - err: nil, - }, - } - - for _, tc := range cases { - req := listReq{ - offset: tc.offset, - limit: tc.limit, - } - - err := req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestBootstrapReqValidation(t *testing.T) { - cases := []struct { - desc string - externKey string - externID string - err error - }{ - { - desc: "empty external key", - externKey: "", - externID: "id", - err: apiutil.ErrBearerKey, - }, - { - desc: "empty external id", - externKey: "key", - externID: "", - err: apiutil.ErrMissingID, - }, - } - - for _, tc := range cases { - req := bootstrapReq{ - id: tc.externID, - key: tc.externKey, - } - - err := req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestChangeStateReqValidation(t *testing.T) { - cases := []struct { - desc string - token string - id string - state bootstrap.State - err error - }{ - { - desc: "empty token", - token: "", - id: "id", - state: bootstrap.State(1), - err: apiutil.ErrBearerToken, - }, - { - desc: "empty id", - token: "token", - id: "", - state: bootstrap.State(0), - err: apiutil.ErrMissingID, - }, - { - desc: "invalid state", - token: "token", - id: "id", - state: bootstrap.State(14), - err: apiutil.ErrBootstrapState, - }, - } - - for _, tc := range cases { - req := changeStateReq{ - token: tc.token, - id: tc.id, - State: tc.state, - } - - err := req.validate() - assert.Equal(t, tc.err, err, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} diff --git a/bootstrap/api/responses.go b/bootstrap/api/responses.go deleted file mode 100644 index 59d73df747..0000000000 --- a/bootstrap/api/responses.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "fmt" - "net/http" - - "github.com/absmach/supermq" - "github.com/absmach/supermq/bootstrap" -) - -var ( - _ supermq.Response = (*removeRes)(nil) - _ supermq.Response = (*configRes)(nil) - _ supermq.Response = (*stateRes)(nil) - _ supermq.Response = (*viewRes)(nil) - _ supermq.Response = (*listRes)(nil) -) - -type removeRes struct{} - -func (res removeRes) Code() int { - return http.StatusNoContent -} - -func (res removeRes) Headers() map[string]string { - return map[string]string{} -} - -func (res removeRes) Empty() bool { - return true -} - -type configRes struct { - id string - created bool -} - -func (res configRes) Code() int { - if res.created { - return http.StatusCreated - } - - return http.StatusOK -} - -func (res configRes) Headers() map[string]string { - if res.created { - return map[string]string{ - "Location": fmt.Sprintf("/clients/configs/%s", res.id), - } - } - - return map[string]string{} -} - -func (res configRes) Empty() bool { - return true -} - -type channelRes struct { - ID string `json:"id"` - Name string `json:"name,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` -} - -type viewRes struct { - 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 { - return http.StatusOK -} - -func (res viewRes) Headers() map[string]string { - return map[string]string{} -} - -func (res viewRes) Empty() bool { - return false -} - -type listRes struct { - Total uint64 `json:"total"` - Offset uint64 `json:"offset"` - Limit uint64 `json:"limit"` - Configs []viewRes `json:"configs"` -} - -func (res listRes) Code() int { - return http.StatusOK -} - -func (res listRes) Headers() map[string]string { - return map[string]string{} -} - -func (res listRes) Empty() bool { - return false -} - -type stateRes struct{} - -func (res stateRes) Code() int { - return http.StatusOK -} - -func (res stateRes) Headers() map[string]string { - return map[string]string{} -} - -func (res stateRes) Empty() bool { - return true -} - -type updateConfigRes struct { - ClientID string `json:"client_id,omitempty"` - CACert string `json:"ca_cert,omitempty"` - ClientCert string `json:"client_cert,omitempty"` - ClientKey string `json:"client_key,omitempty"` -} - -func (res updateConfigRes) Code() int { - return http.StatusOK -} - -func (res updateConfigRes) Headers() map[string]string { - return map[string]string{} -} - -func (res updateConfigRes) Empty() bool { - return false -} diff --git a/bootstrap/api/transport.go b/bootstrap/api/transport.go deleted file mode 100644 index c5c9baacff..0000000000 --- a/bootstrap/api/transport.go +++ /dev/null @@ -1,284 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "context" - "encoding/json" - "log/slog" - "net/http" - "net/url" - "strings" - - "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" - "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" -) - -const ( - contentType = "application/json" - byteContentType = "application/octet-stream" - offsetKey = "offset" - limitKey = "limit" - defOffset = 0 - defLimit = 10 -) - -var ( - 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 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}/clients", func(r chi.Router) { - r.Group(func(r chi.Router) { - r.Use(api.AuthenticateMiddleware(authn, true)) - - r.Route("/configs", func(r chi.Router) { - r.Post("/", otelhttp.NewHandler(kithttp.NewServer( - addEndpoint(svc), - decodeAddRequest, - api.EncodeResponse, - opts...), "add").ServeHTTP) - - r.Get("/", otelhttp.NewHandler(kithttp.NewServer( - listEndpoint(svc), - decodeListRequest, - api.EncodeResponse, - opts...), "list").ServeHTTP) - - r.Get("/{configID}", otelhttp.NewHandler(kithttp.NewServer( - viewEndpoint(svc), - decodeEntityRequest, - api.EncodeResponse, - opts...), "view").ServeHTTP) - - r.Put("/{configID}", otelhttp.NewHandler(kithttp.NewServer( - updateEndpoint(svc), - decodeUpdateRequest, - api.EncodeResponse, - opts...), "update").ServeHTTP) - - r.Delete("/{configID}", otelhttp.NewHandler(kithttp.NewServer( - removeEndpoint(svc), - decodeEntityRequest, - api.EncodeResponse, - opts...), "remove").ServeHTTP) - - r.Patch("/certs/{certID}", otelhttp.NewHandler(kithttp.NewServer( - updateCertEndpoint(svc), - decodeUpdateCertRequest, - api.EncodeResponse, - opts...), "update_cert").ServeHTTP) - - r.Put("/connections/{connID}", otelhttp.NewHandler(kithttp.NewServer( - updateConnEndpoint(svc), - decodeUpdateConnRequest, - api.EncodeResponse, - opts...), "update_connections").ServeHTTP) - }) - }) - - r.With(api.AuthenticateMiddleware(authn, true)).Put("/state/{clientID}", otelhttp.NewHandler(kithttp.NewServer( - stateEndpoint(svc), - decodeStateRequest, - api.EncodeResponse, - opts...), "update_state").ServeHTTP) - }) - - r.Route("/clients/bootstrap", func(r chi.Router) { - r.Get("/", otelhttp.NewHandler(kithttp.NewServer( - bootstrapEndpoint(svc, reader, false), - decodeBootstrapRequest, - api.EncodeResponse, - opts...), "bootstrap").ServeHTTP) - r.Get("/{externalID}", otelhttp.NewHandler(kithttp.NewServer( - bootstrapEndpoint(svc, reader, false), - decodeBootstrapRequest, - api.EncodeResponse, - opts...), "bootstrap").ServeHTTP) - r.Get("/secure/{externalID}", otelhttp.NewHandler(kithttp.NewServer( - bootstrapEndpoint(svc, reader, true), - decodeBootstrapRequest, - encodeSecureRes, - opts...), "bootstrap_secure").ServeHTTP) - }) - - r.Get("/health", supermq.Health("bootstrap", instanceID)) - r.Handle("/metrics", promhttp.Handler()) - - return r -} - -func decodeAddRequest(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) - } - - req := addReq{ - token: apiutil.ExtractBearerToken(r), - } - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) - } - - return req, nil -} - -func decodeUpdateRequest(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) - } - - req := updateReq{ - id: chi.URLParam(r, "configID"), - } - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) - } - - return req, nil -} - -func decodeUpdateCertRequest(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) - } - - req := updateCertReq{ - 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)) - } - - return req, nil -} - -func decodeUpdateConnRequest(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) - } - - req := updateConnReq{ - token: apiutil.ExtractBearerToken(r), - id: chi.URLParam(r, "connID"), - } - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) - } - - return req, nil -} - -func decodeListRequest(_ context.Context, r *http.Request) (interface{}, error) { - o, err := apiutil.ReadNumQuery[uint64](r, offsetKey, defOffset) - if err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - l, err := apiutil.ReadNumQuery[uint64](r, limitKey, defLimit) - if err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - q, err := url.ParseQuery(r.URL.RawQuery) - if err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrInvalidQueryParams) - } - - req := listReq{ - filter: parseFilter(q), - offset: o, - limit: l, - } - - return req, nil -} - -func decodeBootstrapRequest(_ context.Context, r *http.Request) (interface{}, error) { - req := bootstrapReq{ - id: chi.URLParam(r, "externalID"), - key: apiutil.ExtractClientSecret(r), - } - - return req, nil -} - -func decodeStateRequest(_ context.Context, r *http.Request) (interface{}, error) { - if !strings.Contains(r.Header.Get("Content-Type"), contentType) { - return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) - } - - req := changeStateReq{ - token: apiutil.ExtractBearerToken(r), - 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)) - } - - return req, nil -} - -func decodeEntityRequest(_ context.Context, r *http.Request) (interface{}, error) { - req := entityReq{ - id: chi.URLParam(r, "configID"), - } - - return req, nil -} - -func encodeSecureRes(_ context.Context, w http.ResponseWriter, response interface{}) error { - w.Header().Set("Content-Type", byteContentType) - w.WriteHeader(http.StatusOK) - if b, ok := response.([]byte); ok { - if _, err := w.Write(b); err != nil { - return err - } - } - return nil -} - -func parseFilter(values url.Values) bootstrap.Filter { - ret := bootstrap.Filter{ - FullMatch: make(map[string]string), - PartialMatch: make(map[string]string), - } - for k := range values { - if contains(fullMatch, k) { - ret.FullMatch[k] = values.Get(k) - } - if contains(partialMatch, k) { - ret.PartialMatch[k] = strings.ToLower(values.Get(k)) - } - } - - return ret -} - -func contains(l []string, s string) bool { - for _, v := range l { - if v == s { - return true - } - } - return false -} diff --git a/bootstrap/configs.go b/bootstrap/configs.go deleted file mode 100644 index 2e42d1f28a..0000000000 --- a/bootstrap/configs.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package bootstrap - -import ( - "context" - "time" - - "github.com/absmach/supermq/clients" -) - -// Config represents Configuration entity. It wraps information about external entity -// 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 { - 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 SuperMQ channel corresponding SuperMQ Client is connected to. -type Channel struct { - ID string `json:"id"` - Name string `json:"name,omitempty"` - Metadata map[string]interface{} `json:"metadata,omitempty"` - DomainID string `json:"domain_id"` - Parent string `json:"parent_id,omitempty"` - Description string `json:"description,omitempty"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at,omitempty"` - UpdatedBy string `json:"updated_by,omitempty"` - Status clients.Status `json:"status"` -} - -// Filter is used for the search filters. -type Filter struct { - FullMatch map[string]string - PartialMatch map[string]string -} - -// ConfigsPage contains page related metadata as well as list of Configs that -// belong to this page. -type ConfigsPage struct { - Total uint64 `json:"total"` - Offset uint64 `json:"offset"` - Limit uint64 `json:"limit"` - Configs []Config `json:"configs"` -} - -// ConfigRepository specifies a Config persistence API. -// -//go:generate mockery --name ConfigRepository --output=./mocks --filename configs.go --quiet --note "Copyright (c) Abstract Machines" -type ConfigRepository interface { - // Save persists the Config. Successful operation is indicated by non-nil - // error response. - Save(ctx context.Context, cfg Config, chsConnIDs []string) (string, error) - - // RetrieveByID retrieves the Config having the provided identifier, that is owned - // by the specified user. - RetrieveByID(ctx context.Context, domainID, id string) (Config, error) - - // RetrieveAll retrieves a subset of Configs that are owned - // by the specific user, with given filter parameters. - 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) - - // Update updates an existing Config. A non-nil error is returned - // to indicate operation failure. - Update(ctx context.Context, cfg Config) error - - // 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, clientID, clientCert, clientKey, caCert string) (Config, error) - - // UpdateConnections updates a list of Channels the Config is connected to - // adding new Channels if needed. - UpdateConnections(ctx context.Context, domainID, id string, channels []Channel, connections []string) error - - // Remove removes the Config having the provided identifier, that is owned - // by the specified user. - Remove(ctx context.Context, domainID, id string) error - - // ChangeState changes of the Config, that is owned by the specific user. - ChangeState(ctx context.Context, domainID, id string, state State) error - - // ListExisting retrieves those channels from the given list that exist in DB. - ListExisting(ctx context.Context, domainID string, ids []string) ([]Channel, error) - - // Methods RemoveClient, UpdateChannel, and RemoveChannel are related to - // event sourcing. That's why these methods surpass ownership check. - - // 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 - - // RemoveChannel removes channel with the given ID. - RemoveChannel(ctx context.Context, id 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 - - // DisconnectClient changes state of the Config when the corresponding Client is disconnected from the Channel. - DisconnectClient(ctx context.Context, channelID, clientID string) error -} diff --git a/bootstrap/doc.go b/bootstrap/doc.go deleted file mode 100644 index 2e939673dd..0000000000 --- a/bootstrap/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package bootstrap contains the domain concept definitions needed to support -// SuperMQ bootstrap service functionality. -package bootstrap diff --git a/bootstrap/events/consumer/doc.go b/bootstrap/events/consumer/doc.go deleted file mode 100644 index f3fea76f1e..0000000000 --- a/bootstrap/events/consumer/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package consumer contains events consumer for events -// published by Bootstrap service. -package consumer diff --git a/bootstrap/events/consumer/events.go b/bootstrap/events/consumer/events.go deleted file mode 100644 index 71ded144ac..0000000000 --- a/bootstrap/events/consumer/events.go +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package consumer - -import "time" - -type removeEvent struct { - id string -} - -type updateChannelEvent struct { - id string - name string - metadata map[string]interface{} - updatedAt time.Time - updatedBy string -} - -// Connection event is either connect or disconnect event. -type connectionEvent struct { - clientIDs []string - channelID string -} diff --git a/bootstrap/events/consumer/streams.go b/bootstrap/events/consumer/streams.go deleted file mode 100644 index 1e34e48e28..0000000000 --- a/bootstrap/events/consumer/streams.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package consumer - -import ( - "context" - "time" - - "github.com/absmach/supermq/bootstrap" - svcerr "github.com/absmach/supermq/pkg/errors/service" - "github.com/absmach/supermq/pkg/events" -) - -const ( - clientRemove = "client.remove" - clientConnect = "group.assign" - clientDisconnect = "group.unassign" - - channelPrefix = "channels." - channelUpdate = channelPrefix + "update" - channelRemove = channelPrefix + "remove" - - memberKind = "client" - relation = "group" -) - -type eventHandler struct { - svc bootstrap.Service -} - -// NewEventHandler returns new event store handler. -func NewEventHandler(svc bootstrap.Service) events.EventHandler { - return &eventHandler{ - svc: svc, - } -} - -func (es *eventHandler) Handle(ctx context.Context, event events.Event) error { - msg, err := event.Encode() - if err != nil { - return err - } - - switch msg["operation"] { - case clientRemove: - rte := decodeRemoveClient(msg) - err = es.svc.RemoveConfigHandler(ctx, rte.id) - case clientConnect: - cte := decodeConnectClient(msg) - if cte.channelID == "" || len(cte.clientIDs) == 0 { - return svcerr.ErrMalformedEntity - } - for _, clientID := range cte.clientIDs { - if clientID == "" { - return svcerr.ErrMalformedEntity - } - if err := es.svc.ConnectClientHandler(ctx, cte.channelID, clientID); err != nil { - return err - } - } - case clientDisconnect: - dte := decodeDisconnectClient(msg) - if dte.channelID == "" || len(dte.clientIDs) == 0 { - return svcerr.ErrMalformedEntity - } - for _, clientID := range dte.clientIDs { - if clientID == "" { - return svcerr.ErrMalformedEntity - } - } - - for _, c := range dte.clientIDs { - if err = es.svc.DisconnectClientHandler(ctx, dte.channelID, c); err != nil { - return err - } - } - case channelUpdate: - uce := decodeUpdateChannel(msg) - err = es.handleUpdateChannel(ctx, uce) - case channelRemove: - rce := decodeRemoveChannel(msg) - err = es.svc.RemoveChannelHandler(ctx, rce.id) - } - if err != nil { - return err - } - - return nil -} - -func decodeRemoveClient(event map[string]interface{}) removeEvent { - return removeEvent{ - id: events.Read(event, "id", ""), - } -} - -func decodeUpdateChannel(event map[string]interface{}) updateChannelEvent { - metadata := events.Read(event, "metadata", map[string]interface{}{}) - - return updateChannelEvent{ - id: events.Read(event, "id", ""), - name: events.Read(event, "name", ""), - metadata: metadata, - updatedAt: events.Read(event, "updated_at", time.Now()), - updatedBy: events.Read(event, "updated_by", ""), - } -} - -func decodeRemoveChannel(event map[string]interface{}) removeEvent { - return removeEvent{ - id: events.Read(event, "id", ""), - } -} - -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", ""), - clientIDs: events.ReadStringSlice(event, "member_ids"), - } -} - -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", ""), - clientIDs: events.ReadStringSlice(event, "member_ids"), - } -} - -func (es *eventHandler) handleUpdateChannel(ctx context.Context, uce updateChannelEvent) error { - channel := bootstrap.Channel{ - ID: uce.id, - Name: uce.name, - Metadata: uce.metadata, - UpdatedAt: uce.updatedAt, - UpdatedBy: uce.updatedBy, - } - - return es.svc.UpdateChannelHandler(ctx, channel) -} diff --git a/bootstrap/events/doc.go b/bootstrap/events/doc.go deleted file mode 100644 index fa65f5af29..0000000000 --- a/bootstrap/events/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package events provides the domain concept definitions needed to support -// bootstrap events functionality. -package events diff --git a/bootstrap/events/producer/doc.go b/bootstrap/events/producer/doc.go deleted file mode 100644 index ab1537514a..0000000000 --- a/bootstrap/events/producer/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package producer contains the domain events needed to support -// event sourcing of Bootstrap service actions. -package producer diff --git a/bootstrap/events/producer/events.go b/bootstrap/events/producer/events.go deleted file mode 100644 index dd7ece9c21..0000000000 --- a/bootstrap/events/producer/events.go +++ /dev/null @@ -1,277 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package producer - -import ( - "github.com/absmach/supermq/bootstrap" - "github.com/absmach/supermq/pkg/events" -) - -const ( - configPrefix = "bootstrap.config." - configCreate = configPrefix + "create" - configUpdate = configPrefix + "update" - configRemove = configPrefix + "remove" - configView = configPrefix + "view" - configList = configPrefix + "list" - configHandlerRemove = configPrefix + "remove_handler" - - 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" - channelUpdateHandler = channelPrefix + "update_handler" - - certUpdate = "bootstrap.cert.update" -) - -var ( - _ events.Event = (*configEvent)(nil) - _ events.Event = (*removeConfigEvent)(nil) - _ events.Event = (*bootstrapEvent)(nil) - _ events.Event = (*changeStateEvent)(nil) - _ events.Event = (*updateConnectionsEvent)(nil) - _ events.Event = (*updateCertEvent)(nil) - _ events.Event = (*listConfigsEvent)(nil) - _ events.Event = (*removeHandlerEvent)(nil) -) - -type configEvent struct { - bootstrap.Config - operation string -} - -func (ce configEvent) Encode() (map[string]interface{}, error) { - val := map[string]interface{}{ - "state": ce.State.String(), - "operation": ce.operation, - } - if ce.ClientID != "" { - val["client_id"] = ce.ClientID - } - if ce.Content != "" { - val["content"] = ce.Content - } - if ce.DomainID != "" { - val["domain_id "] = ce.DomainID - } - if ce.Name != "" { - val["name"] = ce.Name - } - if ce.ExternalID != "" { - val["external_id"] = ce.ExternalID - } - if len(ce.Channels) > 0 { - channels := make([]string, len(ce.Channels)) - for i, ch := range ce.Channels { - channels[i] = ch.ID - } - val["channels"] = channels - } - if ce.ClientCert != "" { - val["client_cert"] = ce.ClientCert - } - if ce.ClientKey != "" { - val["client_key"] = ce.ClientKey - } - if ce.CACert != "" { - val["ca_cert"] = ce.CACert - } - if ce.Content != "" { - val["content"] = ce.Content - } - - return val, nil -} - -type removeConfigEvent struct { - client string -} - -func (rce removeConfigEvent) Encode() (map[string]interface{}, error) { - return map[string]interface{}{ - "client_id": rce.client, - "operation": configRemove, - }, nil -} - -type listConfigsEvent struct { - offset uint64 - limit uint64 - fullMatch map[string]string - partialMatch map[string]string -} - -func (rce listConfigsEvent) Encode() (map[string]interface{}, error) { - val := map[string]interface{}{ - "offset": rce.offset, - "limit": rce.limit, - "operation": configList, - } - if len(rce.fullMatch) > 0 { - val["full_match"] = rce.fullMatch - } - - if len(rce.partialMatch) > 0 { - val["full_match"] = rce.partialMatch - } - return val, nil -} - -type bootstrapEvent struct { - bootstrap.Config - externalID string - success bool -} - -func (be bootstrapEvent) Encode() (map[string]interface{}, error) { - val := map[string]interface{}{ - "external_id": be.externalID, - "success": be.success, - "operation": clientBootstrap, - } - - if be.ClientID != "" { - val["client_id"] = be.ClientID - } - if be.Content != "" { - val["content"] = be.Content - } - if be.DomainID != "" { - val["domain_id "] = be.DomainID - } - if be.Name != "" { - val["name"] = be.Name - } - if be.ExternalID != "" { - val["external_id"] = be.ExternalID - } - if len(be.Channels) > 0 { - channels := make([]string, len(be.Channels)) - for i, ch := range be.Channels { - channels[i] = ch.ID - } - val["channels"] = channels - } - if be.ClientCert != "" { - val["client_cert"] = be.ClientCert - } - if be.ClientKey != "" { - val["client_key"] = be.ClientKey - } - if be.CACert != "" { - val["ca_cert"] = be.CACert - } - if be.Content != "" { - val["content"] = be.Content - } - return val, nil -} - -type changeStateEvent struct { - mgClient string - state bootstrap.State -} - -func (cse changeStateEvent) Encode() (map[string]interface{}, error) { - return map[string]interface{}{ - "client_id": cse.mgClient, - "state": cse.state.String(), - "operation": clientStateChange, - }, nil -} - -type updateConnectionsEvent struct { - mgClient string - mgChannels []string -} - -func (uce updateConnectionsEvent) Encode() (map[string]interface{}, error) { - return map[string]interface{}{ - "client_id": uce.mgClient, - "channels": uce.mgChannels, - "operation": clientUpdateConnections, - }, nil -} - -type updateCertEvent struct { - clientID string - clientCert string - clientKey string - caCert string -} - -func (uce updateCertEvent) Encode() (map[string]interface{}, error) { - return map[string]interface{}{ - "client_id": uce.clientID, - "client_cert": uce.clientCert, - "client_key": uce.clientKey, - "ca_cert": uce.caCert, - "operation": certUpdate, - }, nil -} - -type removeHandlerEvent struct { - id string - operation string -} - -func (rhe removeHandlerEvent) Encode() (map[string]interface{}, error) { - return map[string]interface{}{ - "config_id": rhe.id, - "operation": rhe.operation, - }, nil -} - -type updateChannelHandlerEvent struct { - bootstrap.Channel -} - -func (uche updateChannelHandlerEvent) Encode() (map[string]interface{}, error) { - val := map[string]interface{}{ - "operation": channelUpdateHandler, - } - - if uche.ID != "" { - val["channel_id"] = uche.ID - } - if uche.Name != "" { - val["name"] = uche.Name - } - if uche.Metadata != nil { - val["metadata"] = uche.Metadata - } - return val, nil -} - -type connectClientEvent struct { - clientID string - channelID string -} - -func (cte connectClientEvent) Encode() (map[string]interface{}, error) { - return map[string]interface{}{ - "client_id": cte.clientID, - "channel_id": cte.channelID, - "operation": clientConnect, - }, nil -} - -type disconnectClientEvent struct { - clientID string - channelID string -} - -func (dte disconnectClientEvent) Encode() (map[string]interface{}, error) { - return map[string]interface{}{ - "client_id": dte.clientID, - "channel_id": dte.channelID, - "operation": clientDisconnect, - }, nil -} diff --git a/bootstrap/events/producer/setup_test.go b/bootstrap/events/producer/setup_test.go deleted file mode 100644 index 517cd652db..0000000000 --- a/bootstrap/events/producer/setup_test.go +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package producer_test - -import ( - "context" - "fmt" - "log" - "os" - "testing" - - "github.com/ory/dockertest/v3" - "github.com/ory/dockertest/v3/docker" - "github.com/redis/go-redis/v9" -) - -var ( - redisClient *redis.Client - redisURL string -) - -func TestMain(m *testing.M) { - pool, err := dockertest.NewPool("") - if err != nil { - log.Fatalf("Could not connect to docker: %s", err) - } - - container, err := pool.RunWithOptions(&dockertest.RunOptions{ - Repository: "redis", - Tag: "7.2.4-alpine", - }, func(config *docker.HostConfig) { - config.AutoRemove = true - config.RestartPolicy = docker.RestartPolicy{Name: "no"} - }) - if err != nil { - log.Fatalf("Could not start container: %s", err) - } - - redisURL = fmt.Sprintf("redis://localhost:%s/0", container.GetPort("6379/tcp")) - opts, err := redis.ParseURL(redisURL) - if err != nil { - log.Fatalf("Could not parse redis URL: %s", err) - } - - if err := pool.Retry(func() error { - redisClient = redis.NewClient(opts) - - return redisClient.Ping(context.Background()).Err() - }); err != nil { - log.Fatalf("Could not connect to docker: %s", err) - } - - code := m.Run() - - if err := pool.Purge(container); err != nil { - log.Fatalf("Could not purge container: %s", err) - } - - os.Exit(code) -} diff --git a/bootstrap/events/producer/streams.go b/bootstrap/events/producer/streams.go deleted file mode 100644 index 55408e07ea..0000000000 --- a/bootstrap/events/producer/streams.go +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package producer - -import ( - "context" - - "github.com/absmach/supermq/bootstrap" - smqauthn "github.com/absmach/supermq/pkg/authn" - "github.com/absmach/supermq/pkg/events" -) - -var _ bootstrap.Service = (*eventStore)(nil) - -type eventStore struct { - events.Publisher - svc bootstrap.Service -} - -// NewEventStoreMiddleware returns wrapper around bootstrap service that sends -// events to event store. -func NewEventStoreMiddleware(svc bootstrap.Service, publisher events.Publisher) bootstrap.Service { - return &eventStore{ - svc: svc, - Publisher: publisher, - } -} - -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 - } - - ev := configEvent{ - saved, configCreate, - } - - if err := es.Publish(ctx, ev); err != nil { - return saved, err - } - - return saved, err -} - -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 - } - ev := configEvent{ - cfg, configView, - } - - if err := es.Publish(ctx, ev); err != nil { - return cfg, err - } - - return cfg, err -} - -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 - } - - ev := configEvent{ - cfg, configUpdate, - } - - return es.Publish(ctx, ev) -} - -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{ - clientID: clientID, - clientCert: clientCert, - clientKey: clientKey, - caCert: caCert, - } - - if err := es.Publish(ctx, ev); err != nil { - return cfg, err - } - - return cfg, nil -} - -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{ - mgClient: id, - mgChannels: connections, - } - - return es.Publish(ctx, ev) -} - -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 - } - - ev := listConfigsEvent{ - offset: offset, - limit: limit, - fullMatch: filter.FullMatch, - partialMatch: filter.PartialMatch, - } - - if err := es.Publish(ctx, ev); err != nil { - return bp, err - } - - return bp, nil -} - -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{ - client: id, - } - - return es.Publish(ctx, ev) -} - -func (es *eventStore) Bootstrap(ctx context.Context, externalKey, externalID string, secure bool) (bootstrap.Config, error) { - cfg, err := es.svc.Bootstrap(ctx, externalKey, externalID, secure) - - ev := bootstrapEvent{ - cfg, - externalID, - true, - } - - if err != nil { - ev.success = false - } - - if err := es.Publish(ctx, ev); err != nil { - return cfg, err - } - - return cfg, err -} - -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{ - mgClient: id, - state: state, - } - - return es.Publish(ctx, ev) -} - -func (es *eventStore) RemoveConfigHandler(ctx context.Context, id string) error { - if err := es.svc.RemoveConfigHandler(ctx, id); err != nil { - return err - } - - ev := removeHandlerEvent{ - id: id, - operation: configHandlerRemove, - } - - return es.Publish(ctx, ev) -} - -func (es *eventStore) RemoveChannelHandler(ctx context.Context, id string) error { - if err := es.svc.RemoveChannelHandler(ctx, id); err != nil { - return err - } - - ev := removeHandlerEvent{ - id: id, - operation: channelHandlerRemove, - } - - return es.Publish(ctx, ev) -} - -func (es *eventStore) UpdateChannelHandler(ctx context.Context, channel bootstrap.Channel) error { - if err := es.svc.UpdateChannelHandler(ctx, channel); err != nil { - return err - } - - ev := updateChannelHandlerEvent{ - channel, - } - - return es.Publish(ctx, ev) -} - -func (es *eventStore) ConnectClientHandler(ctx context.Context, channelID, clientID string) error { - if err := es.svc.ConnectClientHandler(ctx, channelID, clientID); err != nil { - return err - } - - ev := connectClientEvent{ - clientID: clientID, - channelID: channelID, - } - - return es.Publish(ctx, ev) -} - -func (es *eventStore) DisconnectClientHandler(ctx context.Context, channelID, clientID string) error { - if err := es.svc.DisconnectClientHandler(ctx, channelID, clientID); err != nil { - return err - } - - ev := disconnectClientEvent{ - clientID: clientID, - channelID: channelID, - } - - return es.Publish(ctx, ev) -} diff --git a/bootstrap/events/producer/streams_test.go b/bootstrap/events/producer/streams_test.go deleted file mode 100644 index 372292d73b..0000000000 --- a/bootstrap/events/producer/streams_test.go +++ /dev/null @@ -1,1482 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package producer_test - -import ( - "context" - "fmt" - "strconv" - "strings" - "testing" - "time" - - "github.com/absmach/supermq/bootstrap" - "github.com/absmach/supermq/bootstrap/events/producer" - "github.com/absmach/supermq/bootstrap/mocks" - "github.com/absmach/supermq/internal/testsutil" - "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" - "github.com/stretchr/testify/require" -) - -const ( - streamID = "supermq.bootstrap" - email = "user@example.com" - validToken = "validToken" - invalidToken = "invalid" - unknownClientID = "unknown" - channelsNum = 3 - defaultTimout = 5 - - configPrefix = "config." - configCreate = configPrefix + "create" - configView = configPrefix + "view" - configUpdate = configPrefix + "update" - configRemove = configPrefix + "remove" - configList = configPrefix + "list" - configHandlerRemove = configPrefix + "remove_handler" - - 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" - channelUpdateHandler = channelPrefix + "update_handler" - - certUpdate = "cert.update" - instanceID = "5de9b29a-feb9-11ed-be56-0242ac120002" -) - -var ( - encKey = []byte("1234567891011121") - - domainID = testsutil.GenerateUUID(&testing.T{}) - validID = testsutil.GenerateUUID(&testing.T{}) - - channel = bootstrap.Channel{ - ID: testsutil.GenerateUUID(&testing.T{}), - Name: "name", - Metadata: map[string]interface{}{"name": "value"}, - } - - config = bootstrap.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", - } -) - -type testVariable struct { - svc bootstrap.Service - boot *mocks.ConfigRepository - policies *policymocks.Service - sdk *sdkmocks.SDK -} - -func newTestVariable(t *testing.T, redisURL string) testVariable { - boot := new(mocks.ConfigRepository) - policies := new(policymocks.Service) - sdk := new(sdkmocks.SDK) - idp := uuid.NewMock() - svc := bootstrap.New(policies, boot, sdk, encKey, idp) - publisher, err := store.NewPublisher(context.Background(), redisURL, streamID) - require.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - svc = producer.NewEventStoreMiddleware(svc, publisher) - return testVariable{ - svc: svc, - boot: boot, - policies: policies, - sdk: sdk, - } -} - -func TestAdd(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - var channels []string - for _, ch := range config.Channels { - channels = append(channels, ch.ID) - } - - invalidConfig := config - invalidConfig.Channels = []bootstrap.Channel{{ID: "empty"}} - invalidConfig.Channels = []bootstrap.Channel{{ID: "empty"}} - - cases := []struct { - 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", - config: config, - token: validToken, - id: validID, - domainID: domainID, - channel: config.Channels, - event: map[string]interface{}{ - "client_id": "1", - "domain_id": domainID, - "name": config.Name, - "channels": channels, - "external_id": config.ExternalID, - "content": config.Content, - "timestamp": time.Now().Unix(), - "operation": configCreate, - }, - err: nil, - }, - { - 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", - config: config, - token: validToken, - id: validID, - domainID: domainID, - event: nil, - listErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - }, - { - desc: "create invalid config", - config: invalidConfig, - token: validToken, - id: validID, - domainID: domainID, - event: nil, - listErr: svcerr.ErrMalformedEntity, - err: svcerr.ErrMalformedEntity, - }, - } - - lastID := "0" - for _, tc := range cases { - 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) - - _, err := tv.svc.Add(context.Background(), tc.session, tc.token, tc.config) - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - event := streams[0].Messages - lastID = event[0].ID - } - - test(t, tc.event, event, tc.desc) - - sdkCall.Unset() - repoCall.Unset() - repoCall1.Unset() - } -} - -func TestView(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - nonExisting := config - nonExisting.ClientID = unknownClientID - - cases := []struct { - desc string - config bootstrap.Config - token string - session smqauthn.Session - id string - domainID string - retrieveErr error - err error - event map[string]interface{} - }{ - { - desc: "view successfully", - config: config, - token: validToken, - id: validID, - domainID: domainID, - err: nil, - event: map[string]interface{}{ - "client_id": config.ClientID, - "domain_id": config.DomainID, - "name": config.Name, - "channels": config.Channels, - "external_id": config.ExternalID, - "content": config.Content, - "timestamp": time.Now().Unix(), - "operation": configView, - }, - }, - { - desc: "view with failed retrieve", - config: nonExisting, - token: validToken, - id: validID, - domainID: domainID, - retrieveErr: svcerr.ErrViewEntity, - err: svcerr.ErrViewEntity, - event: nil, - }, - } - - lastID := "0" - for _, tc := range cases { - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - msg := streams[0].Messages[0] - event = msg.Values - event["timestamp"] = msg.ID - lastID = msg.ID - } - - test(t, tc.event, event, tc.desc) - repoCall.Unset() - } -} - -func TestUpdate(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - c := config - - ch1 := channel - ch1.ID = testsutil.GenerateUUID(t) - - ch2 := channel - ch2.ID = testsutil.GenerateUUID(t) - - c.Channels = append(c.Channels, ch1, ch2) - - modified := c - modified.Content = "new-config" - modified.Name = "new name" - - nonExisting := config - nonExisting.ClientID = unknownClientID - - channels := []string{modified.Channels[0].ID, modified.Channels[1].ID} - - cases := []struct { - desc string - config bootstrap.Config - token string - session smqauthn.Session - id string - domainID string - updateErr error - err error - event map[string]interface{} - }{ - { - desc: "update config successfully", - config: modified, - token: validToken, - id: validID, - domainID: domainID, - err: nil, - event: map[string]interface{}{ - "name": modified.Name, - "content": modified.Content, - "timestamp": time.Now().UnixNano(), - "operation": configUpdate, - "channels": channels, - "external_id": modified.ExternalID, - "client_id": modified.ClientID, - "domain_id": domainID, - "state": "0", - "occurred_at": time.Now().UnixNano(), - }, - }, - { - desc: "update with failed update", - config: nonExisting, - token: validToken, - id: validID, - domainID: domainID, - updateErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - event: nil, - }, - } - - lastID := "0" - for _, tc := range cases { - 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)) - - streams := redisClient.XRead(context.Background(), &redis.XReadArgs{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - msg := streams[0].Messages[0] - event = msg.Values - event["timestamp"] = msg.ID - lastID = msg.ID - } - - test(t, tc.event, event, tc.desc) - repoCall.Unset() - } -} - -func TestUpdateConnections(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - cases := []struct { - desc string - configID string - id string - domainID string - token string - session smqauthn.Session - connections []string - clientErr error - channelErr error - retrieveErr error - listErr error - updateErr error - err error - event map[string]interface{} - }{ - { - desc: "update connections successfully", - configID: config.ClientID, - token: validToken, - id: validID, - domainID: domainID, - connections: []string{config.Channels[0].ID}, - err: nil, - event: map[string]interface{}{ - "client_id": config.ClientID, - "channels": "2", - "timestamp": time.Now().Unix(), - "operation": clientUpdateConnections, - }, - }, - { - desc: "update connections with failed channel fetch", - configID: config.ClientID, - token: validToken, - id: validID, - domainID: domainID, - connections: []string{"256"}, - channelErr: errors.NewSDKError(svcerr.ErrNotFound), - err: svcerr.ErrNotFound, - event: nil, - }, - { - desc: "update connections with failed RetrieveByID", - configID: config.ClientID, - token: validToken, - id: validID, - domainID: domainID, - connections: []string{config.Channels[0].ID}, - retrieveErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - event: nil, - }, - { - desc: "update connections with failed ListExisting", - configID: config.ClientID, - token: validToken, - id: validID, - domainID: domainID, - connections: []string{config.Channels[0].ID}, - listErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - event: nil, - }, - { - desc: "update connections with failed UpdateConnections", - configID: config.ClientID, - token: validToken, - id: validID, - domainID: domainID, - connections: []string{config.Channels[0].ID}, - updateErr: svcerr.ErrUpdateEntity, - err: svcerr.ErrUpdateEntity, - event: nil, - }, - } - - lastID := "0" - for _, tc := range cases { - 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) - repoCall2 := tv.boot.On("UpdateConnections", context.Background(), tc.domainID, tc.configID, mock.Anything, tc.connections).Return(tc.updateErr) - err := tv.svc.UpdateConnections(context.Background(), tc.session, tc.token, tc.configID, tc.connections) - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - event := streams[0].Messages - lastID = event[0].ID - } - - test(t, tc.event, event, tc.desc) - sdkCall.Unset() - repoCall.Unset() - repoCall1.Unset() - repoCall2.Unset() - } -} - -func TestUpdateCert(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - cases := []struct { - desc string - configID string - userID string - domainID string - token string - session smqauthn.Session - clientCert string - clientKey string - caCert string - updateErr error - err error - event map[string]interface{} - }{ - { - desc: "update cert successfully", - configID: config.ClientID, - userID: validID, - domainID: domainID, - token: validToken, - clientCert: "clientCert", - clientKey: "clientKey", - caCert: "caCert", - err: nil, - event: map[string]interface{}{ - "client_secret": config.ClientSecret, - "client_cert": "clientCert", - "client_key": "clientKey", - "ca_cert": "caCert", - "operation": certUpdate, - }, - }, - { - desc: "update cert with failed update", - configID: "clientID", - token: validToken, - userID: validID, - domainID: domainID, - clientCert: "clientCert", - clientKey: "clientKey", - caCert: "caCert", - updateErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - event: nil, - }, - { - desc: "update cert with empty client certificate", - configID: config.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - clientCert: "", - clientKey: "clientKey", - caCert: "caCert", - err: nil, - event: nil, - }, - { - desc: "update cert with empty client key", - configID: config.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - clientCert: "clientCert", - clientKey: "", - caCert: "caCert", - err: nil, - event: nil, - }, - { - desc: "update cert with empty CA certificate", - configID: config.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - clientCert: "clientCert", - clientKey: "clientKey", - caCert: "", - err: nil, - event: nil, - }, - { - desc: "successful update without CA certificate", - configID: config.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - clientCert: "clientCert", - clientKey: "clientKey", - caCert: "", - err: nil, - event: map[string]interface{}{ - "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 = 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) - - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - event := streams[0].Messages - lastID = event[0].ID - } - - test(t, tc.event, event, tc.desc) - - repoCall.Unset() - } -} - -func TestList(t *testing.T) { - tv := newTestVariable(t, redisURL) - - numClients := 101 - var c bootstrap.Config - saved := make([]bootstrap.Config, 0) - for i := 0; i < numClients; i++ { - c := config - c.ExternalID = testsutil.GenerateUUID(t) - c.ExternalKey = testsutil.GenerateUUID(t) - c.Name = fmt.Sprintf("%s-%d", config.Name, i) - if i == 41 { - c.State = bootstrap.Active - } - saved = append(saved, c) - } - - cases := []struct { - desc string - token string - session smqauthn.Session - userID string - domainID string - config bootstrap.ConfigsPage - filter bootstrap.Filter - offset uint64 - limit uint64 - listObjectsResponse policysvc.PolicyPage - listObjectsErr error - retrieveErr error - err error - event map[string]interface{} - }{ - { - desc: "list successfully as super admin", - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - config: bootstrap.ConfigsPage{ - Total: uint64(len(saved)), - Offset: 0, - Limit: 10, - Configs: saved[0:10], - }, - filter: bootstrap.Filter{}, - offset: 0, - limit: 10, - listObjectsResponse: policysvc.PolicyPage{}, - err: nil, - event: map[string]interface{}{ - "client_id": c.ClientID, - "domain_id": c.DomainID, - "name": c.Name, - "channels": c.Channels, - "external_id": c.ExternalID, - "content": c.Content, - "timestamp": time.Now().Unix(), - "operation": configList, - }, - }, - { - desc: "list successfully as domain admin", - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - config: bootstrap.ConfigsPage{ - Total: uint64(len(saved)), - Offset: 0, - Limit: 10, - Configs: saved[0:10], - }, - filter: bootstrap.Filter{}, - offset: 0, - limit: 10, - listObjectsResponse: policysvc.PolicyPage{}, - err: nil, - event: map[string]interface{}{ - "client_id": c.ClientID, - "domain_id": c.DomainID, - "name": c.Name, - "channels": c.Channels, - "external_id": c.ExternalID, - "content": c.Content, - "timestamp": time.Now().Unix(), - "operation": configList, - }, - }, - { - desc: "list successfully as non admin", - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, - config: bootstrap.ConfigsPage{ - Total: uint64(len(saved)), - Offset: 0, - Limit: 10, - Configs: saved[0:10], - }, - filter: bootstrap.Filter{}, - offset: 0, - limit: 10, - listObjectsResponse: policysvc.PolicyPage{}, - err: nil, - event: map[string]interface{}{ - "client_id": c.ClientID, - "domain_id": c.DomainID, - "name": c.Name, - "channels": c.Channels, - "external_id": c.ExternalID, - "content": c.Content, - "timestamp": time.Now().Unix(), - "operation": configList, - }, - }, - { - desc: "list as non admin with failed list all objects", - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, - filter: bootstrap.Filter{}, - offset: 0, - limit: 10, - listObjectsResponse: policysvc.PolicyPage{}, - listObjectsErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - event: nil, - }, - - { - desc: "list as super admin with failed retrieve all", - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - filter: bootstrap.Filter{}, - offset: 0, - limit: 10, - listObjectsResponse: policysvc.PolicyPage{}, - retrieveErr: nil, - err: nil, - event: nil, - }, - { - desc: "list as domain admin with failed retrieve all", - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - filter: bootstrap.Filter{}, - offset: 0, - limit: 10, - listObjectsResponse: policysvc.PolicyPage{}, - retrieveErr: nil, - err: nil, - event: nil, - }, - { - desc: "list as non admin with failed retrieve all", - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, - filter: bootstrap.Filter{}, - offset: 0, - limit: 10, - listObjectsResponse: policysvc.PolicyPage{}, - retrieveErr: nil, - err: nil, - event: nil, - }, - } - - lastID := "0" - for _, tc := range cases { - policyCall := tv.policies.On("ListAllObjects", mock.Anything, policysvc.Policy{ - SubjectType: policysvc.UserType, - Subject: tc.userID, - Permission: policysvc.ViewPermission, - 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) - - _, err := tv.svc.List(context.Background(), tc.session, tc.filter, tc.offset, tc.limit) - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - event := streams[0].Messages - lastID = event[0].ID - } - - test(t, tc.event, event, tc.desc) - - policyCall.Unset() - repoCall.Unset() - } -} - -func TestRemove(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - nonExisting := config - nonExisting.ClientID = unknownClientID - - cases := []struct { - desc string - configID string - userID string - domainID string - token string - session smqauthn.Session - removeErr error - err error - event map[string]interface{} - }{ - { - desc: "remove config successfully", - configID: config.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - err: nil, - event: map[string]interface{}{ - "client_id": config.ClientID, - "timestamp": time.Now().Unix(), - "operation": configRemove, - }, - }, - { - desc: "remove config with failed removal", - configID: nonExisting.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - removeErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - event: nil, - }, - } - - lastID := "0" - for _, tc := range cases { - 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)) - - streams := redisClient.XRead(context.Background(), &redis.XReadArgs{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - event := streams[0].Messages - lastID = event[0].ID - } - - test(t, tc.event, event, tc.desc) - repoCall.Unset() - } -} - -func TestBootstrap(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - cases := []struct { - desc string - externalID string - externalKey string - err error - retrieveErr error - event map[string]interface{} - }{ - { - desc: "bootstrap successfully", - externalID: config.ExternalID, - externalKey: config.ExternalKey, - err: nil, - event: map[string]interface{}{ - "external_id": config.ExternalID, - "success": "1", - "timestamp": time.Now().Unix(), - "operation": clientBootstrap, - }, - }, - { - desc: "bootstrap with an error", - externalID: "external_id1", - externalKey: "external_id", - retrieveErr: bootstrap.ErrBootstrap, - err: bootstrap.ErrBootstrap, - event: map[string]interface{}{ - "external_id": "external_id", - "success": "0", - "timestamp": time.Now().Unix(), - "operation": clientBootstrap, - }, - }, - } - - lastID := "0" - for _, tc := range cases { - repoCall := tv.boot.On("RetrieveByExternalID", context.Background(), mock.Anything).Return(config, tc.retrieveErr) - _, err = tv.svc.Bootstrap(context.Background(), tc.externalKey, tc.externalID, false) - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - event := streams[0].Messages - lastID = event[0].ID - } - test(t, tc.event, event, tc.desc) - repoCall.Unset() - } -} - -func TestChangeState(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - cases := []struct { - desc string - id string - userID string - domainID string - token string - session smqauthn.Session - state bootstrap.State - authResponse authn.Session - authorizeErr error - connectErr error - retrieveErr error - stateErr error - authenticateErr error - err error - event map[string]interface{} - }{ - { - desc: "change state to active", - id: config.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - state: bootstrap.Active, - authResponse: authn.Session{}, - err: nil, - event: map[string]interface{}{ - "client_id": config.ClientID, - "state": bootstrap.Active.String(), - "timestamp": time.Now().Unix(), - "operation": clientStateChange, - }, - }, - { - desc: "change state with failed retrieve by ID", - id: "", - token: validToken, - userID: validID, - domainID: domainID, - state: bootstrap.Active, - retrieveErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - event: nil, - }, - { - desc: "change state with failed connect", - id: config.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - state: bootstrap.Active, - connectErr: bootstrap.ErrClients, - err: bootstrap.ErrClients, - event: nil, - }, - { - desc: "change state unsuccessfully", - id: config.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - state: bootstrap.Active, - stateErr: svcerr.ErrUpdateEntity, - err: svcerr.ErrUpdateEntity, - event: nil, - }, - } - - lastID := "0" - for _, tc := range cases { - 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("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)) - - streams := redisClient.XRead(context.Background(), &redis.XReadArgs{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - event := streams[0].Messages - lastID = event[0].ID - } - - test(t, tc.event, event, tc.desc) - sdkCall1.Unset() - repoCall.Unset() - repoCall1.Unset() - } -} - -func TestUpdateChannelHandler(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - cases := []struct { - desc string - channel bootstrap.Channel - err error - event map[string]interface{} - }{ - { - desc: "update channel handler successfully", - channel: channel, - err: nil, - event: map[string]interface{}{ - "channel_id": channel.ID, - "metadata": "{\"name\":\"value\"}", - "name": channel.Name, - "operation": channelUpdateHandler, - "timestamp": time.Now().UnixNano(), - "occurred_at": time.Now().UnixNano(), - }, - }, - { - desc: "update non-existing channel handler", - channel: bootstrap.Channel{ID: "unknown", Name: "NonExistingChannel"}, - err: nil, - event: nil, - }, - { - desc: "update channel handler with empty ID", - channel: bootstrap.Channel{Name: "ChannelWithEmptyID"}, - err: nil, - event: nil, - }, - { - desc: "update channel handler with empty name", - channel: bootstrap.Channel{ID: "3"}, - err: nil, - event: nil, - }, - { - desc: "update channel handler successfully with modified fields", - channel: channel, - err: nil, - event: map[string]interface{}{ - "channel_id": channel.ID, - "metadata": "{\"name\":\"value\"}", - "name": channel.Name, - "operation": channelUpdateHandler, - "timestamp": time.Now().UnixNano(), - "occurred_at": time.Now().UnixNano(), - }, - }, - } - - lastID := "0" - for _, tc := range cases { - repoCall := tv.boot.On("UpdateChannel", context.Background(), mock.Anything).Return(tc.err) - err := tv.svc.UpdateChannelHandler(context.Background(), tc.channel) - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - msg := streams[0].Messages[0] - event = msg.Values - event["timestamp"] = msg.ID - lastID = msg.ID - } - test(t, tc.event, event, tc.desc) - repoCall.Unset() - } -} - -func TestRemoveChannelHandler(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - cases := []struct { - desc string - channelID string - err error - event map[string]interface{} - }{ - { - desc: "remove channel handler successfully", - channelID: channel.ID, - err: nil, - event: map[string]interface{}{ - "config_id": channel.ID, - "operation": channelHandlerRemove, - "timestamp": time.Now().UnixNano(), - "occurred_at": time.Now().UnixNano(), - }, - }, - { - desc: "remove non-existing channel handler", - channelID: "unknown", - err: nil, - event: nil, - }, - { - desc: "remove channel handler with empty ID", - channelID: "", - err: nil, - event: nil, - }, - } - - lastID := "0" - for _, tc := range cases { - repoCall := tv.boot.On("RemoveChannel", context.Background(), mock.Anything).Return(tc.err) - err := tv.svc.RemoveChannelHandler(context.Background(), tc.channelID) - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - msg := streams[0].Messages[0] - event = msg.Values - event["timestamp"] = msg.ID - lastID = msg.ID - } - - test(t, tc.event, event, tc.desc) - repoCall.Unset() - } -} - -func TestRemoveConfigHandler(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - cases := []struct { - desc string - configID string - err error - event map[string]interface{} - }{ - { - desc: "remove config handler successfully", - configID: channel.ID, - err: nil, - event: map[string]interface{}{ - "config_id": channel.ID, - "operation": configHandlerRemove, - "timestamp": time.Now().UnixNano(), - "occurred_at": time.Now().UnixNano(), - }, - }, - { - desc: "remove non-existing config handler", - configID: "unknown", - err: nil, - event: nil, - }, - { - desc: "remove config handler with empty ID", - configID: "", - err: nil, - event: nil, - }, - } - - lastID := "0" - for _, tc := range cases { - 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)) - - streams := redisClient.XRead(context.Background(), &redis.XReadArgs{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - msg := streams[0].Messages[0] - event = msg.Values - event["timestamp"] = msg.ID - lastID = msg.ID - } - - test(t, tc.event, event, tc.desc) - repoCall.Unset() - } -} - -func TestConnectClientHandler(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - cases := []struct { - desc string - channelID string - clientID string - err error - event map[string]interface{} - }{ - { - desc: "connect client handler successfully", - channelID: channel.ID, - clientID: "1", - err: nil, - event: map[string]interface{}{ - "channel_id": channel.ID, - "client_id": "1", - "operation": clientConnect, - "timestamp": time.Now().UnixNano(), - "occurred_at": time.Now().UnixNano(), - }, - }, - { - desc: "connect non-existing client handler", - channelID: channel.ID, - clientID: "unknown", - err: nil, - event: nil, - }, - { - desc: "connect client handler with empty client ID", - channelID: channel.ID, - clientID: "", - err: nil, - event: nil, - }, - { - desc: "connect client handler with empty channel ID", - channelID: "", - clientID: "1", - err: nil, - event: nil, - }, - } - - lastID := "0" - for _, tc := range cases { - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - msg := streams[0].Messages[0] - event = msg.Values - event["timestamp"] = msg.ID - lastID = msg.ID - } - - test(t, tc.event, event, tc.desc) - repoCall.Unset() - } -} - -func TestDisconnectClientHandler(t *testing.T) { - err := redisClient.FlushAll(context.Background()).Err() - assert.Nil(t, err, fmt.Sprintf("got unexpected error: %s", err)) - - tv := newTestVariable(t, redisURL) - - cases := []struct { - desc string - channelID string - clientID string - err error - event map[string]interface{} - }{ - { - desc: "disconnect client handler successfully", - channelID: channel.ID, - clientID: "1", - err: nil, - event: map[string]interface{}{ - "channel_id": channel.ID, - "client_id": "1", - "operation": clientDisconnect, - "timestamp": time.Now().UnixNano(), - "occurred_at": time.Now().UnixNano(), - }, - }, - { - desc: "remove non-existing client handler", - channelID: "unknown", - err: nil, - }, - { - desc: "remove client handler with empty client ID", - channelID: channel.ID, - clientID: "", - err: nil, - event: nil, - }, - { - desc: "remove client handler with empty channel ID", - channelID: "", - err: nil, - event: nil, - }, - { - desc: "remove client handler successfully", - channelID: channel.ID, - clientID: "1", - err: nil, - event: map[string]interface{}{ - "channel_id": channel.ID, - "client_id": "1", - "operation": clientDisconnect, - "timestamp": time.Now().UnixNano(), - "occurred_at": time.Now().UnixNano(), - }, - }, - } - - lastID := "0" - for _, tc := range cases { - 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{ - Streams: []string{streamID, lastID}, - Count: 1, - Block: time.Second, - }).Val() - - var event map[string]interface{} - if len(streams) > 0 && len(streams[0].Messages) > 0 { - msg := streams[0].Messages[0] - event = msg.Values - event["timestamp"] = msg.ID - lastID = msg.ID - } - - test(t, tc.event, event, tc.desc) - repoCall.Unset() - } -} - -func test(t *testing.T, expected, actual map[string]interface{}, description string) { - if expected != nil && actual != nil { - ts1 := expected["timestamp"].(int64) - ats := actual["timestamp"].(string) - ts2, err := strconv.ParseInt(strings.Split(ats, "-")[0], 10, 64) - require.Nil(t, err, fmt.Sprintf("%s: expected to get a valid timestamp, got %s", description, err)) - ts1 = ts1 / 1e9 - ts2 = ts2 / 1e3 - if assert.WithinDuration(t, time.Unix(ts1, 0), time.Unix(ts2, 0), time.Second, fmt.Sprintf("%s: timestamp is not in valid range of 1 second", description)) { - delete(expected, "timestamp") - delete(actual, "timestamp") - } - - oa1 := expected["occurred_at"].(int64) - aoa := actual["occurred_at"].(string) - oa2, err := strconv.ParseInt(aoa, 10, 64) - require.Nil(t, err, fmt.Sprintf("%s: expected to get a valid occurred_at, got %s", description, err)) - oa1 = oa1 / 1e9 - oa2 = oa2 / 1e9 - if assert.WithinDuration(t, time.Unix(oa1, 0), time.Unix(oa2, 0), time.Second, fmt.Sprintf("%s: occurred_at is not in valid range of 1 second", description)) { - delete(expected, "occurred_at") - delete(actual, "occurred_at") - } - - exchs := expected["channels"].([]interface{}) - achs := actual["channels"].([]interface{}) - - if exchs != nil && achs != nil { - if assert.Len(t, exchs, len(achs), fmt.Sprintf("%s: got incorrect number of channels\n", description)) { - for _, exch := range exchs { - assert.Contains(t, achs, exch, fmt.Sprintf("%s: got incorrect channel\n", description)) - } - } - } - - assert.Equal(t, expected, actual, fmt.Sprintf("%s: got incorrect event\n", description)) - } -} diff --git a/bootstrap/middleware/authorization.go b/bootstrap/middleware/authorization.go deleted file mode 100644 index de04f65fb0..0000000000 --- a/bootstrap/middleware/authorization.go +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package middleware - -import ( - "context" - - "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 smqauthz.Authorization -} - -// AuthorizationMiddleware adds authorization to the clients 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 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 - } - - return am.svc.Add(ctx, session, token, cfg) -} - -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 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 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, clientID, clientCert, clientKey, caCert) -} - -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 smqauthn.Session, filter bootstrap.Filter, offset, limit uint64) (bootstrap.ConfigsPage, error) { - if err := am.checkSuperAdmin(ctx, session.DomainUserID); err == nil { - session.SuperAdmin = true - } - if err := am.authorize(ctx, "", policies.UserType, policies.UsersKind, session.DomainUserID, policies.AdminPermission, policies.DomainType, session.DomainID); err == nil { - session.SuperAdmin = true - } - - return am.svc.List(ctx, session, filter, offset, limit) -} - -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 - } - - return am.svc.Remove(ctx, session, id) -} - -func (am *authorizationMiddleware) Bootstrap(ctx context.Context, externalKey, externalID string, secure bool) (bootstrap.Config, error) { - return am.svc.Bootstrap(ctx, externalKey, externalID, secure) -} - -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) -} - -func (am *authorizationMiddleware) UpdateChannelHandler(ctx context.Context, channel bootstrap.Channel) error { - return am.svc.UpdateChannelHandler(ctx, channel) -} - -func (am *authorizationMiddleware) RemoveConfigHandler(ctx context.Context, id string) error { - return am.svc.RemoveConfigHandler(ctx, id) -} - -func (am *authorizationMiddleware) RemoveChannelHandler(ctx context.Context, id string) error { - return am.svc.RemoveChannelHandler(ctx, id) -} - -func (am *authorizationMiddleware) ConnectClientHandler(ctx context.Context, channelID, clientID string) error { - return am.svc.ConnectClientHandler(ctx, channelID, clientID) -} - -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 { - if err := am.authz.Authorize(ctx, authz.PolicyReq{ - SubjectType: policies.UserType, - Subject: adminID, - Permission: policies.AdminPermission, - ObjectType: policies.PlatformType, - Object: policies.SuperMQObject, - }); err != nil { - return err - } - return nil -} - -func (am *authorizationMiddleware) authorize(ctx context.Context, domain, subjType, subjKind, subj, perm, objType, obj string) error { - req := authz.PolicyReq{ - Domain: domain, - SubjectType: subjType, - SubjectKind: subjKind, - Subject: subj, - Permission: perm, - ObjectType: objType, - Object: obj, - } - if err := am.authz.Authorize(ctx, req); err != nil { - return err - } - return nil -} diff --git a/bootstrap/middleware/logging.go b/bootstrap/middleware/logging.go deleted file mode 100644 index a6d23497c2..0000000000 --- a/bootstrap/middleware/logging.go +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -//go:build !test - -package middleware - -import ( - "context" - "log/slog" - "time" - - "github.com/absmach/supermq/bootstrap" - smqauthn "github.com/absmach/supermq/pkg/authn" -) - -var _ bootstrap.Service = (*loggingMiddleware)(nil) - -type loggingMiddleware struct { - logger *slog.Logger - svc bootstrap.Service -} - -// LoggingMiddleware adds logging facilities to the bootstrap service. -func LoggingMiddleware(svc bootstrap.Service, logger *slog.Logger) bootstrap.Service { - return &loggingMiddleware{logger, svc} -} - -// 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 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("client_id", saved.ClientID), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Add new bootstrap failed", args...) - return - } - lm.logger.Info("Add new bootstrap completed successfully", args...) - }(time.Now()) - - return lm.svc.Add(ctx, session, token, cfg) -} - -// 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 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("client_id", id), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("View client config failed", args...) - return - } - 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 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 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("client_id", cfg.ClientID), - slog.String("name", cfg.Name), - ), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Update bootstrap config failed", args...) - return - } - lm.logger.Info("Update bootstrap config completed successfully", args...) - }(time.Now()) - - return lm.svc.Update(ctx, session, cfg) -} - -// 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 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("client_id", cfg.ClientID), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Update bootstrap config certificate failed", args...) - return - } - lm.logger.Info("Update bootstrap config certificate completed successfully", args...) - }(time.Now()) - - 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 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("client_id", id), - slog.Any("connections", connections), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Update config connections failed", args...) - return - } - lm.logger.Info("Update config connections completed successfully", args...) - }(time.Now()) - - return lm.svc.UpdateConnections(ctx, session, token, id, connections) -} - -// 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 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()), - slog.Group("page", - slog.Any("filter", filter), - slog.Uint64("offset", offset), - slog.Uint64("limit", limit), - slog.Uint64("total", res.Total), - ), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("List configs failed", args...) - return - } - lm.logger.Info("List configs completed successfully", args...) - }(time.Now()) - - return lm.svc.List(ctx, session, filter, offset, limit) -} - -// 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 smqauthn.Session, id string) (err error) { - defer func(begin time.Time) { - args := []any{ - slog.String("duration", time.Since(begin).String()), - slog.String("client_id", id), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Remove bootstrap config failed", args...) - return - } - lm.logger.Info("Remove bootstrap config completed successfully", args...) - }(time.Now()) - - return lm.svc.Remove(ctx, session, id) -} - -func (lm *loggingMiddleware) Bootstrap(ctx context.Context, externalKey, externalID string, secure bool) (cfg bootstrap.Config, err error) { - defer func(begin time.Time) { - args := []any{ - slog.String("duration", time.Since(begin).String()), - slog.String("external_id", externalID), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("View bootstrap config failed", args...) - return - } - lm.logger.Info("View bootstrap completed successfully", args...) - }(time.Now()) - - return lm.svc.Bootstrap(ctx, externalKey, externalID, secure) -} - -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()), - slog.String("id", id), - slog.Any("state", state), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Change client state failed", args...) - return - } - lm.logger.Info("Change client state completed successfully", args...) - }(time.Now()) - - return lm.svc.ChangeState(ctx, session, token, id, state) -} - -func (lm *loggingMiddleware) UpdateChannelHandler(ctx context.Context, channel bootstrap.Channel) (err error) { - defer func(begin time.Time) { - args := []any{ - slog.String("duration", time.Since(begin).String()), - slog.Group("channel", - slog.String("id", channel.ID), - slog.String("name", channel.Name), - slog.Any("metadata", channel.Metadata), - ), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Update channel handler failed", args...) - return - } - lm.logger.Info("Update channel handler completed successfully", args...) - }(time.Now()) - - return lm.svc.UpdateChannelHandler(ctx, channel) -} - -func (lm *loggingMiddleware) RemoveConfigHandler(ctx context.Context, id string) (err error) { - defer func(begin time.Time) { - args := []any{ - slog.String("duration", time.Since(begin).String()), - slog.String("config_id", id), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Remove config handler failed", args...) - return - } - lm.logger.Info("Remove config handler completed successfully", args...) - }(time.Now()) - - return lm.svc.RemoveConfigHandler(ctx, id) -} - -func (lm *loggingMiddleware) RemoveChannelHandler(ctx context.Context, id string) (err error) { - defer func(begin time.Time) { - args := []any{ - slog.String("duration", time.Since(begin).String()), - slog.String("channel_id", id), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Remove channel handler failed", args...) - return - } - lm.logger.Info("Remove channel handler completed successfully", args...) - }(time.Now()) - - return lm.svc.RemoveChannelHandler(ctx, id) -} - -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("client_id", clientID), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Connect client handler failed", args...) - return - } - lm.logger.Info("Connect client handler completed successfully", args...) - }(time.Now()) - - return lm.svc.ConnectClientHandler(ctx, channelID, clientID) -} - -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("client_id", clientID), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Disconnect client handler failed", args...) - return - } - lm.logger.Info("Disconnect client handler completed successfully", args...) - }(time.Now()) - - return lm.svc.DisconnectClientHandler(ctx, channelID, clientID) -} diff --git a/bootstrap/middleware/metrics.go b/bootstrap/middleware/metrics.go deleted file mode 100644 index 89f64ecd4c..0000000000 --- a/bootstrap/middleware/metrics.go +++ /dev/null @@ -1,172 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -//go:build !test - -package middleware - -import ( - "context" - "time" - - "github.com/absmach/supermq/bootstrap" - smqauthn "github.com/absmach/supermq/pkg/authn" - "github.com/go-kit/kit/metrics" -) - -var _ bootstrap.Service = (*metricsMiddleware)(nil) - -type metricsMiddleware struct { - counter metrics.Counter - latency metrics.Histogram - svc bootstrap.Service -} - -// MetricsMiddleware instruments core service by tracking request count and latency. -func MetricsMiddleware(svc bootstrap.Service, counter metrics.Counter, latency metrics.Histogram) bootstrap.Service { - return &metricsMiddleware{ - counter: counter, - latency: latency, - svc: svc, - } -} - -// Add instruments Add method with metrics. -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()) - }(time.Now()) - - return mm.svc.Add(ctx, session, token, cfg) -} - -// View instruments View method with metrics. -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()) - }(time.Now()) - - return mm.svc.View(ctx, session, id) -} - -// Update instruments Update method with metrics. -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()) - }(time.Now()) - - return mm.svc.Update(ctx, session, cfg) -} - -// UpdateCert instruments UpdateCert method with metrics. -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, clientID, clientCert, clientKey, caCert) -} - -// UpdateConnections instruments UpdateConnections method with metrics. -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()) - }(time.Now()) - - return mm.svc.UpdateConnections(ctx, session, token, id, connections) -} - -// List instruments List method with metrics. -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()) - }(time.Now()) - - return mm.svc.List(ctx, session, filter, offset, limit) -} - -// Remove instruments Remove method with metrics. -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()) - }(time.Now()) - - return mm.svc.Remove(ctx, session, id) -} - -// Bootstrap instruments Bootstrap method with metrics. -func (mm *metricsMiddleware) Bootstrap(ctx context.Context, externalKey, externalID string, secure bool) (cfg bootstrap.Config, err error) { - defer func(begin time.Time) { - mm.counter.With("method", "bootstrap").Add(1) - mm.latency.With("method", "bootstrap").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return mm.svc.Bootstrap(ctx, externalKey, externalID, secure) -} - -// ChangeState instruments ChangeState method with metrics. -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()) - }(time.Now()) - - return mm.svc.ChangeState(ctx, session, token, id, state) -} - -// UpdateChannelHandler instruments UpdateChannelHandler method with metrics. -func (mm *metricsMiddleware) UpdateChannelHandler(ctx context.Context, channel bootstrap.Channel) (err error) { - defer func(begin time.Time) { - mm.counter.With("method", "update_channel").Add(1) - mm.latency.With("method", "update_channel").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return mm.svc.UpdateChannelHandler(ctx, channel) -} - -// RemoveConfigHandler instruments RemoveConfigHandler method with metrics. -func (mm *metricsMiddleware) RemoveConfigHandler(ctx context.Context, id string) (err error) { - defer func(begin time.Time) { - mm.counter.With("method", "remove_config").Add(1) - mm.latency.With("method", "remove_config").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return mm.svc.RemoveConfigHandler(ctx, id) -} - -// RemoveChannelHandler instruments RemoveChannelHandler method with metrics. -func (mm *metricsMiddleware) RemoveChannelHandler(ctx context.Context, id string) (err error) { - defer func(begin time.Time) { - mm.counter.With("method", "remove_channel").Add(1) - mm.latency.With("method", "remove_channel").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return mm.svc.RemoveChannelHandler(ctx, id) -} - -// 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_client_handler").Add(1) - mm.latency.With("method", "connect_client_handler").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return mm.svc.ConnectClientHandler(ctx, channelID, clientID) -} - -// 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_client_handler").Add(1) - mm.latency.With("method", "disconnect_client_handler").Observe(time.Since(begin).Seconds()) - }(time.Now()) - - return mm.svc.DisconnectClientHandler(ctx, channelID, clientID) -} diff --git a/bootstrap/mocks/config_reader.go b/bootstrap/mocks/config_reader.go deleted file mode 100644 index e4a0d4d9d6..0000000000 --- a/bootstrap/mocks/config_reader.go +++ /dev/null @@ -1,59 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -// Copyright (c) Abstract Machines - -package mocks - -import ( - bootstrap "github.com/absmach/supermq/bootstrap" - mock "github.com/stretchr/testify/mock" -) - -// ConfigReader is an autogenerated mock type for the ConfigReader type -type ConfigReader struct { - mock.Mock -} - -// ReadConfig provides a mock function with given fields: _a0, _a1 -func (_m *ConfigReader) ReadConfig(_a0 bootstrap.Config, _a1 bool) (interface{}, error) { - ret := _m.Called(_a0, _a1) - - if len(ret) == 0 { - panic("no return value specified for ReadConfig") - } - - var r0 interface{} - var r1 error - if rf, ok := ret.Get(0).(func(bootstrap.Config, bool) (interface{}, error)); ok { - return rf(_a0, _a1) - } - if rf, ok := ret.Get(0).(func(bootstrap.Config, bool) interface{}); ok { - r0 = rf(_a0, _a1) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(interface{}) - } - } - - if rf, ok := ret.Get(1).(func(bootstrap.Config, bool) error); ok { - r1 = rf(_a0, _a1) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewConfigReader creates a new instance of ConfigReader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewConfigReader(t interface { - mock.TestingT - Cleanup(func()) -}) *ConfigReader { - mock := &ConfigReader{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/bootstrap/mocks/configs.go b/bootstrap/mocks/configs.go deleted file mode 100644 index 2d80ed0b43..0000000000 --- a/bootstrap/mocks/configs.go +++ /dev/null @@ -1,354 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -// Copyright (c) Abstract Machines - -package mocks - -import ( - context "context" - - bootstrap "github.com/absmach/supermq/bootstrap" - - mock "github.com/stretchr/testify/mock" -) - -// ConfigRepository is an autogenerated mock type for the ConfigRepository type -type ConfigRepository struct { - mock.Mock -} - -// ChangeState provides a mock function with given fields: ctx, domainID, id, state -func (_m *ConfigRepository) ChangeState(ctx context.Context, domainID string, id string, state bootstrap.State) error { - ret := _m.Called(ctx, domainID, id, state) - - if len(ret) == 0 { - panic("no return value specified for ChangeState") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, bootstrap.State) error); ok { - r0 = rf(ctx, domainID, id, state) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// 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 ConnectClient") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { - r0 = rf(ctx, channelID, clientID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// 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 DisconnectClient") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { - r0 = rf(ctx, channelID, clientID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// ListExisting provides a mock function with given fields: ctx, domainID, ids -func (_m *ConfigRepository) ListExisting(ctx context.Context, domainID string, ids []string) ([]bootstrap.Channel, error) { - ret := _m.Called(ctx, domainID, ids) - - if len(ret) == 0 { - panic("no return value specified for ListExisting") - } - - var r0 []bootstrap.Channel - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, []string) ([]bootstrap.Channel, error)); ok { - return rf(ctx, domainID, ids) - } - if rf, ok := ret.Get(0).(func(context.Context, string, []string) []bootstrap.Channel); ok { - r0 = rf(ctx, domainID, ids) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]bootstrap.Channel) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string, []string) error); ok { - r1 = rf(ctx, domainID, ids) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Remove provides a mock function with given fields: ctx, domainID, id -func (_m *ConfigRepository) Remove(ctx context.Context, domainID string, id string) error { - ret := _m.Called(ctx, domainID, id) - - if len(ret) == 0 { - panic("no return value specified for Remove") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { - r0 = rf(ctx, domainID, id) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RemoveChannel provides a mock function with given fields: ctx, id -func (_m *ConfigRepository) RemoveChannel(ctx context.Context, id string) error { - ret := _m.Called(ctx, id) - - if len(ret) == 0 { - panic("no return value specified for RemoveChannel") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { - r0 = rf(ctx, id) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// 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 RemoveClient") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { - r0 = rf(ctx, id) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// 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") - } - - 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, clientIDs, filter, offset, limit) - } else { - r0 = ret.Get(0).(bootstrap.ConfigsPage) - } - - return r0 -} - -// RetrieveByExternalID provides a mock function with given fields: ctx, externalID -func (_m *ConfigRepository) RetrieveByExternalID(ctx context.Context, externalID string) (bootstrap.Config, error) { - ret := _m.Called(ctx, externalID) - - if len(ret) == 0 { - panic("no return value specified for RetrieveByExternalID") - } - - var r0 bootstrap.Config - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) (bootstrap.Config, error)); ok { - return rf(ctx, externalID) - } - if rf, ok := ret.Get(0).(func(context.Context, string) bootstrap.Config); ok { - r0 = rf(ctx, externalID) - } else { - r0 = ret.Get(0).(bootstrap.Config) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, externalID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// RetrieveByID provides a mock function with given fields: ctx, domainID, id -func (_m *ConfigRepository) RetrieveByID(ctx context.Context, domainID string, id string) (bootstrap.Config, error) { - ret := _m.Called(ctx, domainID, id) - - if len(ret) == 0 { - panic("no return value specified for RetrieveByID") - } - - var r0 bootstrap.Config - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) (bootstrap.Config, error)); ok { - return rf(ctx, domainID, id) - } - if rf, ok := ret.Get(0).(func(context.Context, string, string) bootstrap.Config); ok { - r0 = rf(ctx, domainID, id) - } else { - r0 = ret.Get(0).(bootstrap.Config) - } - - if rf, ok := ret.Get(1).(func(context.Context, string, string) error); ok { - r1 = rf(ctx, domainID, id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Save provides a mock function with given fields: ctx, cfg, chsConnIDs -func (_m *ConfigRepository) Save(ctx context.Context, cfg bootstrap.Config, chsConnIDs []string) (string, error) { - ret := _m.Called(ctx, cfg, chsConnIDs) - - if len(ret) == 0 { - panic("no return value specified for Save") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, bootstrap.Config, []string) (string, error)); ok { - return rf(ctx, cfg, chsConnIDs) - } - if rf, ok := ret.Get(0).(func(context.Context, bootstrap.Config, []string) string); ok { - r0 = rf(ctx, cfg, chsConnIDs) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, bootstrap.Config, []string) error); ok { - r1 = rf(ctx, cfg, chsConnIDs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Update provides a mock function with given fields: ctx, cfg -func (_m *ConfigRepository) Update(ctx context.Context, cfg bootstrap.Config) error { - ret := _m.Called(ctx, cfg) - - if len(ret) == 0 { - panic("no return value specified for Update") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, bootstrap.Config) error); ok { - r0 = rf(ctx, cfg) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// 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") - } - - 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, 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, 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, clientID, clientCert, clientKey, caCert) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// UpdateChannel provides a mock function with given fields: ctx, c -func (_m *ConfigRepository) UpdateChannel(ctx context.Context, c bootstrap.Channel) error { - ret := _m.Called(ctx, c) - - if len(ret) == 0 { - panic("no return value specified for UpdateChannel") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, bootstrap.Channel) error); ok { - r0 = rf(ctx, c) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// UpdateConnections provides a mock function with given fields: ctx, domainID, id, channels, connections -func (_m *ConfigRepository) UpdateConnections(ctx context.Context, domainID string, id string, channels []bootstrap.Channel, connections []string) error { - ret := _m.Called(ctx, domainID, id, channels, connections) - - if len(ret) == 0 { - panic("no return value specified for UpdateConnections") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, []bootstrap.Channel, []string) error); ok { - r0 = rf(ctx, domainID, id, channels, connections) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// NewConfigRepository creates a new instance of ConfigRepository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewConfigRepository(t interface { - mock.TestingT - Cleanup(func()) -}) *ConfigRepository { - mock := &ConfigRepository{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/bootstrap/mocks/doc.go b/bootstrap/mocks/doc.go deleted file mode 100644 index 16ed198afd..0000000000 --- a/bootstrap/mocks/doc.go +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package mocks contains mocks for testing purposes. -package mocks diff --git a/bootstrap/mocks/service.go b/bootstrap/mocks/service.go deleted file mode 100644 index b822601c4f..0000000000 --- a/bootstrap/mocks/service.go +++ /dev/null @@ -1,335 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -// Copyright (c) Abstract Machines - -package mocks - -import ( - bootstrap "github.com/absmach/supermq/bootstrap" - authn "github.com/absmach/supermq/pkg/authn" - - context "context" - - mock "github.com/stretchr/testify/mock" -) - -// Service is an autogenerated mock type for the Service type -type Service struct { - mock.Mock -} - -// Add provides a mock function with given fields: ctx, session, token, cfg -func (_m *Service) Add(ctx context.Context, session authn.Session, token string, cfg bootstrap.Config) (bootstrap.Config, error) { - ret := _m.Called(ctx, session, token, cfg) - - if len(ret) == 0 { - panic("no return value specified for Add") - } - - var r0 bootstrap.Config - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, bootstrap.Config) (bootstrap.Config, error)); ok { - return rf(ctx, session, token, cfg) - } - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, bootstrap.Config) bootstrap.Config); ok { - r0 = rf(ctx, session, token, cfg) - } else { - r0 = ret.Get(0).(bootstrap.Config) - } - - if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string, bootstrap.Config) error); ok { - r1 = rf(ctx, session, token, cfg) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Bootstrap provides a mock function with given fields: ctx, externalKey, externalID, secure -func (_m *Service) Bootstrap(ctx context.Context, externalKey string, externalID string, secure bool) (bootstrap.Config, error) { - ret := _m.Called(ctx, externalKey, externalID, secure) - - if len(ret) == 0 { - panic("no return value specified for Bootstrap") - } - - var r0 bootstrap.Config - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string, string, bool) (bootstrap.Config, error)); ok { - return rf(ctx, externalKey, externalID, secure) - } - if rf, ok := ret.Get(0).(func(context.Context, string, string, bool) bootstrap.Config); ok { - r0 = rf(ctx, externalKey, externalID, secure) - } else { - r0 = ret.Get(0).(bootstrap.Config) - } - - if rf, ok := ret.Get(1).(func(context.Context, string, string, bool) error); ok { - r1 = rf(ctx, externalKey, externalID, secure) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// ChangeState provides a mock function with given fields: ctx, session, token, id, state -func (_m *Service) ChangeState(ctx context.Context, session authn.Session, token string, id string, state bootstrap.State) error { - ret := _m.Called(ctx, session, token, id, state) - - if len(ret) == 0 { - panic("no return value specified for ChangeState") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string, bootstrap.State) error); ok { - r0 = rf(ctx, session, token, id, state) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// 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 ConnectClientHandler") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { - r0 = rf(ctx, channelID, clientID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// 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 DisconnectClientHandler") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, string) error); ok { - r0 = rf(ctx, channelID, clientID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// List provides a mock function with given fields: ctx, session, filter, offset, limit -func (_m *Service) List(ctx context.Context, session authn.Session, filter bootstrap.Filter, offset uint64, limit uint64) (bootstrap.ConfigsPage, error) { - ret := _m.Called(ctx, session, filter, offset, limit) - - if len(ret) == 0 { - panic("no return value specified for List") - } - - var r0 bootstrap.ConfigsPage - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, bootstrap.Filter, uint64, uint64) (bootstrap.ConfigsPage, error)); ok { - return rf(ctx, session, filter, offset, limit) - } - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, bootstrap.Filter, uint64, uint64) bootstrap.ConfigsPage); ok { - r0 = rf(ctx, session, filter, offset, limit) - } else { - r0 = ret.Get(0).(bootstrap.ConfigsPage) - } - - if rf, ok := ret.Get(1).(func(context.Context, authn.Session, bootstrap.Filter, uint64, uint64) error); ok { - r1 = rf(ctx, session, filter, offset, limit) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Remove provides a mock function with given fields: ctx, session, id -func (_m *Service) Remove(ctx context.Context, session authn.Session, id string) error { - ret := _m.Called(ctx, session, id) - - if len(ret) == 0 { - panic("no return value specified for Remove") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) error); ok { - r0 = rf(ctx, session, id) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RemoveChannelHandler provides a mock function with given fields: ctx, id -func (_m *Service) RemoveChannelHandler(ctx context.Context, id string) error { - ret := _m.Called(ctx, id) - - if len(ret) == 0 { - panic("no return value specified for RemoveChannelHandler") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { - r0 = rf(ctx, id) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// RemoveConfigHandler provides a mock function with given fields: ctx, id -func (_m *Service) RemoveConfigHandler(ctx context.Context, id string) error { - ret := _m.Called(ctx, id) - - if len(ret) == 0 { - panic("no return value specified for RemoveConfigHandler") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { - r0 = rf(ctx, id) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// Update provides a mock function with given fields: ctx, session, cfg -func (_m *Service) Update(ctx context.Context, session authn.Session, cfg bootstrap.Config) error { - ret := _m.Called(ctx, session, cfg) - - if len(ret) == 0 { - panic("no return value specified for Update") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, bootstrap.Config) error); ok { - r0 = rf(ctx, session, cfg) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// 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") - } - - 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, 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, 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, clientID, clientCert, clientKey, caCert) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// UpdateChannelHandler provides a mock function with given fields: ctx, channel -func (_m *Service) UpdateChannelHandler(ctx context.Context, channel bootstrap.Channel) error { - ret := _m.Called(ctx, channel) - - if len(ret) == 0 { - panic("no return value specified for UpdateChannelHandler") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, bootstrap.Channel) error); ok { - r0 = rf(ctx, channel) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// UpdateConnections provides a mock function with given fields: ctx, session, token, id, connections -func (_m *Service) UpdateConnections(ctx context.Context, session authn.Session, token string, id string, connections []string) error { - ret := _m.Called(ctx, session, token, id, connections) - - if len(ret) == 0 { - panic("no return value specified for UpdateConnections") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string, string, []string) error); ok { - r0 = rf(ctx, session, token, id, connections) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// View provides a mock function with given fields: ctx, session, id -func (_m *Service) View(ctx context.Context, session authn.Session, id string) (bootstrap.Config, error) { - ret := _m.Called(ctx, session, id) - - if len(ret) == 0 { - panic("no return value specified for View") - } - - var r0 bootstrap.Config - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) (bootstrap.Config, error)); ok { - return rf(ctx, session, id) - } - if rf, ok := ret.Get(0).(func(context.Context, authn.Session, string) bootstrap.Config); ok { - r0 = rf(ctx, session, id) - } else { - r0 = ret.Get(0).(bootstrap.Config) - } - - if rf, ok := ret.Get(1).(func(context.Context, authn.Session, string) error); ok { - r1 = rf(ctx, session, id) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewService creates a new instance of Service. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewService(t interface { - mock.TestingT - Cleanup(func()) -}) *Service { - mock := &Service{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/bootstrap/postgres/configs.go b/bootstrap/postgres/configs.go deleted file mode 100644 index 5bc6f3b59e..0000000000 --- a/bootstrap/postgres/configs.go +++ /dev/null @@ -1,778 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package postgres - -import ( - "context" - "database/sql" - "encoding/json" - "fmt" - "log/slog" - "strings" - "time" - - "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" - "github.com/jmoiron/sqlx" -) - -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") - 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 ( - SELECT channel_id FROM connections c WHERE ch.magistrala_channel = c.channel_id);` - -var _ bootstrap.ConfigRepository = (*configRepository)(nil) - -type configRepository struct { - db postgres.Database - log *slog.Logger -} - -// NewConfigRepository instantiates a PostgreSQL implementation of config -// repository. -func NewConfigRepository(db postgres.Database, log *slog.Logger) bootstrap.ConfigRepository { - return &configRepository{db: db, log: log} -} - -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 { - return "", errors.Wrap(repoerr.ErrCreateEntity, err) - } - dbcfg := toDBConfig(cfg) - - defer func() { - if err != nil { - err = cr.rollback("Save method", err, tx) - } - }() - - if _, err := tx.NamedExec(q, dbcfg); err != nil { - switch pgErr := err.(type) { - case *pgconn.PgError: - if pgErr.Code == pgerrcode.UniqueViolation { - err = repoerr.ErrConflict - } - } - return "", err - } - - if err := insertChannels(cfg.DomainID, cfg.Channels, tx); err != nil { - return "", errors.Wrap(errSaveChannels, err) - } - - if err := insertConnections(ctx, cfg, chsConnIDs, tx); err != nil { - return "", errors.Wrap(errSaveConnections, err) - } - - if commitErr := tx.Commit(); commitErr != nil { - return "", commitErr - } - - return cfg.ClientID, nil -} - -func (cr configRepository) RetrieveByID(ctx context.Context, domainID, id string) (bootstrap.Config, error) { - q := `SELECT magistrala_client, magistrala_secret, external_id, external_key, name, content, state, client_cert, ca_cert - FROM configs - WHERE magistrala_client = :magistrala_client AND domain_id = :domain_id` - - dbcfg := dbConfig{ - ClientID: id, - DomainID: domainID, - } - row, err := cr.db.NamedQueryContext(ctx, q, dbcfg) - if err != nil { - if err == sql.ErrNoRows { - return bootstrap.Config{}, errors.Wrap(repoerr.ErrNotFound, err) - } - - return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - - if ok := row.Next(); !ok { - return bootstrap.Config{}, errors.Wrap(repoerr.ErrNotFound, row.Err()) - } - - if err := row.StructScan(&dbcfg); err != nil { - return bootstrap.Config{}, err - } - - 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_client AND conn.domain_id = :domain_id` - - rows, err := cr.db.NamedQueryContext(ctx, q, dbcfg) - if err != nil { - cr.log.Error(fmt.Sprintf("Failed to retrieve connected due to %s", err)) - return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - defer rows.Close() - - chans := []bootstrap.Channel{} - for rows.Next() { - dbch := dbChannel{} - if err := rows.StructScan(&dbch); err != nil { - 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) - - ch, err := toChannel(dbch) - if err != nil { - return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - chans = append(chans, ch) - } - - cfg := toConfig(dbcfg) - cfg.Channels = chans - - return cfg, nil -} - -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_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)...) - if err != nil { - cr.log.Error(fmt.Sprintf("Failed to retrieve configs due to %s", err)) - return bootstrap.ConfigsPage{} - } - defer rows.Close() - - var name, content sql.NullString - configs := []bootstrap.Config{} - - for rows.Next() { - c := bootstrap.Config{DomainID: domainID} - 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{} - } - - c.Name = name.String - c.Content = content.String - configs = append(configs, c) - } - - q = fmt.Sprintf(`SELECT COUNT(*) FROM configs %s`, search) - - var total uint64 - if err := cr.db.QueryRowxContext(ctx, q, params...).Scan(&total); err != nil { - cr.log.Error(fmt.Sprintf("Failed to count configs due to %s", err)) - return bootstrap.ConfigsPage{} - } - - return bootstrap.ConfigsPage{ - Total: total, - Limit: limit, - Offset: offset, - Configs: configs, - } -} - -func (cr configRepository) RetrieveByExternalID(ctx context.Context, externalID string) (bootstrap.Config, error) { - 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{ - ExternalID: externalID, - } - - row, err := cr.db.NamedQueryContext(ctx, q, dbcfg) - if err != nil { - if err == sql.ErrNoRows { - return bootstrap.Config{}, errors.Wrap(repoerr.ErrNotFound, err) - } - return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - - if ok := row.Next(); !ok { - return bootstrap.Config{}, errors.Wrap(repoerr.ErrNotFound, row.Err()) - } - - if err := row.StructScan(&dbcfg); err != nil { - return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - - 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_client AND conn.domain_id = :domain_id` - - rows, err := cr.db.NamedQueryContext(ctx, q, dbcfg) - if err != nil { - cr.log.Error(fmt.Sprintf("Failed to retrieve connected due to %s", err)) - return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - defer rows.Close() - - channels := []bootstrap.Channel{} - for rows.Next() { - dbch := dbChannel{} - if err := rows.StructScan(&dbch); err != nil { - cr.log.Error(fmt.Sprintf("Failed to read connected client due to %s", err)) - return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - - ch, err := toChannel(dbch) - if err != nil { - cr.log.Error(fmt.Sprintf("Failed to deserialize channel due to %s", err)) - return bootstrap.Config{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - - channels = append(channels, ch) - } - - cfg := toConfig(dbcfg) - cfg.Channels = channels - - return cfg, nil -} - -func (cr configRepository) Update(ctx context.Context, cfg bootstrap.Config) error { - 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), - ClientID: cfg.ClientID, - DomainID: cfg.DomainID, - } - - res, err := cr.db.NamedExecContext(ctx, q, dbcfg) - if err != nil { - return errors.Wrap(repoerr.ErrUpdateEntity, err) - } - - cnt, err := res.RowsAffected() - if err != nil { - return errors.Wrap(repoerr.ErrUpdateEntity, err) - } - - if cnt == 0 { - return repoerr.ErrNotFound - } - - return nil -} - -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{ - ClientID: clientID, - ClientCert: nullString(clientCert), - DomainID: domainID, - ClientKey: nullString(clientKey), - CaCert: nullString(caCert), - } - - row, err := cr.db.NamedQueryContext(ctx, q, dbcfg) - if err != nil { - return bootstrap.Config{}, errors.Wrap(repoerr.ErrUpdateEntity, err) - } - defer row.Close() - - if ok := row.Next(); !ok { - return bootstrap.Config{}, errors.Wrap(repoerr.ErrNotFound, row.Err()) - } - - if err := row.StructScan(&dbcfg); err != nil { - return bootstrap.Config{}, err - } - - return toConfig(dbcfg), nil -} - -func (cr configRepository) UpdateConnections(ctx context.Context, domainID, id string, channels []bootstrap.Channel, connections []string) (err error) { - tx, err := cr.db.BeginTxx(ctx, nil) - if err != nil { - return errors.Wrap(repoerr.ErrUpdateEntity, err) - } - - defer func() { - if err != nil { - err = cr.rollback("UpdateConnections method", err, tx) - } else { - if commitErr := tx.Commit(); commitErr != nil { - err = commitErr - } - } - }() - - if err = insertChannels(domainID, channels, tx); err != nil { - err = errors.Wrap(repoerr.ErrUpdateEntity, err) - return err - } - - if err = updateConnections(domainID, id, connections, tx); err != nil { - if e, ok := err.(*pgconn.PgError); ok { - if e.Code == pgerrcode.ForeignKeyViolation { - err = repoerr.ErrNotFound - } - } - err = errors.Wrap(repoerr.ErrUpdateEntity, err) - return err - } - - return nil -} - -func (cr configRepository) Remove(ctx context.Context, domainID, id string) error { - q := `DELETE FROM configs WHERE magistrala_client = :magistrala_client AND domain_id = :domain_id` - dbcfg := dbConfig{ - ClientID: id, - DomainID: domainID, - } - - if _, err := cr.db.NamedExecContext(ctx, q, dbcfg); err != nil { - return errors.Wrap(repoerr.ErrRemoveEntity, err) - } - - if _, err := cr.db.ExecContext(ctx, cleanupQuery); err != nil { - cr.log.Warn("Failed to clean dangling channels after removal") - } - - return nil -} - -func (cr configRepository) ChangeState(ctx context.Context, domainID, id string, state bootstrap.State) error { - q := `UPDATE configs SET state = :state WHERE magistrala_client = :magistrala_client AND domain_id = :domain_id;` - - dbcfg := dbConfig{ - ClientID: id, - State: state, - DomainID: domainID, - } - - res, err := cr.db.NamedExecContext(ctx, q, dbcfg) - if err != nil { - return errors.Wrap(repoerr.ErrUpdateEntity, err) - } - - cnt, err := res.RowsAffected() - if err != nil { - return errors.Wrap(repoerr.ErrUpdateEntity, err) - } - - if cnt == 0 { - return repoerr.ErrNotFound - } - - return nil -} - -func (cr configRepository) ListExisting(ctx context.Context, domainID string, ids []string) ([]bootstrap.Channel, error) { - var channels []bootstrap.Channel - if len(ids) == 0 { - return channels, nil - } - - var chans pgtype.TextArray - if err := chans.Set(ids); err != nil { - return []bootstrap.Channel{}, err - } - - q := "SELECT magistrala_channel, name, metadata FROM channels WHERE domain_id = $1 AND magistrala_channel = ANY ($2)" - rows, err := cr.db.QueryxContext(ctx, q, domainID, chans) - if err != nil { - return []bootstrap.Channel{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - - for rows.Next() { - var dbch dbChannel - if err := rows.StructScan(&dbch); err != nil { - cr.log.Error(fmt.Sprintf("Failed to read retrieved channels due to %s", err)) - return []bootstrap.Channel{}, errors.Wrap(repoerr.ErrViewEntity, err) - } - - ch, err := toChannel(dbch) - if err != nil { - cr.log.Error(fmt.Sprintf("Failed to deserialize channel due to %s", err)) - return []bootstrap.Channel{}, err - } - - channels = append(channels, ch) - } - - return channels, nil -} - -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 { - cr.log.Warn("Failed to clean dangling channels after removal") - } - if err != nil { - return errors.Wrap(repoerr.ErrRemoveEntity, err) - } - return nil -} - -func (cr configRepository) UpdateChannel(ctx context.Context, c bootstrap.Channel) error { - dbch, err := toDBChannel("", c) - if err != nil { - return errors.Wrap(repoerr.ErrUpdateEntity, err) - } - - q := `UPDATE channels SET name = :name, metadata = :metadata, updated_at = :updated_at, updated_by = :updated_by - WHERE magistrala_channel = :magistrala_channel` - if _, err = cr.db.NamedExecContext(ctx, q, dbch); err != nil { - return errors.Wrap(errUpdateChannels, err) - } - return nil -} - -func (cr configRepository) RemoveChannel(ctx context.Context, id string) error { - q := `DELETE FROM channels WHERE magistrala_channel = $1` - if _, err := cr.db.ExecContext(ctx, q, id); err != nil { - return errors.Wrap(errRemoveChannels, err) - } - return nil -} - -func (cr configRepository) ConnectClient(ctx context.Context, channelID, clientID string) error { - q := `UPDATE configs SET state = $1 - 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, clientID, channelID) - if err != nil { - return errors.Wrap(errConnectClient, err) - } - if rows, _ := result.RowsAffected(); rows == 0 { - return repoerr.ErrNotFound - } - return nil -} - -func (cr configRepository) DisconnectClient(ctx context.Context, channelID, clientID string) error { - q := `UPDATE configs SET state = $1 - 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, clientID, channelID) - if err != nil { - return errors.Wrap(errDisconnectClient, err) - } - return nil -} - -func buildRetrieveQueryParams(domainID string, clientIDs []string, filter bootstrap.Filter) (string, []interface{}) { - params := []interface{}{} - queries := []string{} - - 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))) - } - - // Adjust the starting point for placeholders based on the current length of params - counter := len(params) + 1 - for k, v := range filter.FullMatch { - params = append(params, v) - queries = append(queries, fmt.Sprintf("%s = $%d", k, counter)) - counter++ - } - for k, v := range filter.PartialMatch { - params = append(params, v) - queries = append(queries, fmt.Sprintf("LOWER(%s) LIKE '%%' || $%d || '%%'", k, counter)) - counter++ - } - - if len(queries) > 0 { - return "WHERE " + strings.Join(queries, " AND "), params - } - return "", params -} - -func (cr configRepository) rollback(content string, defErr error, tx *sqlx.Tx) error { - if err := tx.Rollback(); err != nil { - return errors.Wrap(defErr, errors.Wrap(errors.New("failed to rollback at "+content), err)) - } - - return defErr -} - -func insertChannels(domainID string, channels []bootstrap.Channel, tx *sqlx.Tx) error { - if len(channels) == 0 { - return nil - } - - var chans []dbChannel - for _, ch := range channels { - dbch, err := toDBChannel(domainID, ch) - if err != nil { - return err - } - chans = append(chans, dbch) - } - q := `INSERT INTO channels (magistrala_channel, domain_id, name, metadata, parent_id, description, created_at, updated_at, updated_by, status) - VALUES (:magistrala_channel, :domain_id, :name, :metadata, :parent_id, :description, :created_at, :updated_at, :updated_by, :status)` - if _, err := tx.NamedExec(q, chans); err != nil { - e := err - if pqErr, ok := err.(*pgconn.PgError); ok && pqErr.Code == pgerrcode.UniqueViolation { - e = repoerr.ErrConflict - } - return e - } - - return nil -} - -func insertConnections(_ context.Context, cfg bootstrap.Config, connections []string, tx *sqlx.Tx) error { - if len(connections) == 0 { - return nil - } - - q := `INSERT INTO connections (config_id, channel_id, domain_id) - VALUES (:config_id, :channel_id, :domain_id)` - - conns := []dbConnection{} - for _, conn := range connections { - dbconn := dbConnection{ - Config: cfg.ClientID, - Channel: conn, - DomainID: cfg.DomainID, - } - conns = append(conns, dbconn) - } - _, err := tx.NamedExec(q, conns) - - return err -} - -func updateConnections(domainID, id string, connections []string, tx *sqlx.Tx) error { - if len(connections) == 0 { - return nil - } - - q := `DELETE FROM connections - WHERE config_id = $1 AND domain_id = $2 - AND channel_id NOT IN ($3)` - - var conn pgtype.TextArray - if err := conn.Set(connections); err != nil { - return err - } - - res, err := tx.Exec(q, id, domainID, conn) - if err != nil { - return err - } - - cnt, err := res.RowsAffected() - if err != nil { - return err - } - - q = `INSERT INTO connections (config_id, channel_id, domain_id) - VALUES (:config_id, :channel_id, :domain_id)` - - conns := []dbConnection{} - for _, conn := range connections { - dbconn := dbConnection{ - Config: id, - Channel: conn, - DomainID: domainID, - } - conns = append(conns, dbconn) - } - - if _, err := tx.NamedExec(q, conns); err != nil { - return err - } - - if cnt == 0 { - return nil - } - - _, err = tx.Exec(cleanupQuery) - - return err -} - -func nullString(s string) sql.NullString { - if s == "" { - return sql.NullString{} - } - - return sql.NullString{ - String: s, - Valid: true, - } -} - -func nullTime(t time.Time) sql.NullTime { - if t.IsZero() { - return sql.NullTime{} - } - - return sql.NullTime{ - Time: t, - Valid: true, - } -} - -type dbConfig struct { - 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{ - 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{ - ClientID: dbcfg.ClientID, - ClientSecret: dbcfg.ClientSecret, - DomainID: dbcfg.DomainID, - ExternalID: dbcfg.ExternalID, - ExternalKey: dbcfg.ExternalKey, - State: dbcfg.State, - } - - if dbcfg.Name.Valid { - cfg.Name = dbcfg.Name.String - } - - if dbcfg.Content.Valid { - cfg.Content = dbcfg.Content.String - } - - if dbcfg.ClientCert.Valid { - cfg.ClientCert = dbcfg.ClientCert.String - } - - if dbcfg.ClientKey.Valid { - cfg.ClientKey = dbcfg.ClientKey.String - } - - if dbcfg.CaCert.Valid { - cfg.CACert = dbcfg.CaCert.String - } - return cfg -} - -type dbChannel struct { - ID string `db:"magistrala_channel"` - Name sql.NullString `db:"name"` - DomainID sql.NullString `db:"domain_id"` - Metadata string `db:"metadata"` - Parent sql.NullString `db:"parent_id,omitempty"` - Description string `db:"description,omitempty"` - CreatedAt time.Time `db:"created_at"` - UpdatedAt sql.NullTime `db:"updated_at,omitempty"` - UpdatedBy sql.NullString `db:"updated_by,omitempty"` - Status clients.Status `db:"status"` -} - -func toDBChannel(domainID string, ch bootstrap.Channel) (dbChannel, error) { - dbch := dbChannel{ - ID: ch.ID, - Name: nullString(ch.Name), - DomainID: nullString(domainID), - Parent: nullString(ch.Parent), - Description: ch.Description, - CreatedAt: ch.CreatedAt, - UpdatedAt: nullTime(ch.UpdatedAt), - UpdatedBy: nullString(ch.UpdatedBy), - Status: ch.Status, - } - - metadata, err := json.Marshal(ch.Metadata) - if err != nil { - return dbChannel{}, errors.Wrap(errors.ErrMalformedEntity, err) - } - - dbch.Metadata = string(metadata) - return dbch, nil -} - -func toChannel(dbch dbChannel) (bootstrap.Channel, error) { - ch := bootstrap.Channel{ - ID: dbch.ID, - Description: dbch.Description, - CreatedAt: dbch.CreatedAt, - Status: dbch.Status, - } - - if dbch.Name.Valid { - ch.Name = dbch.Name.String - } - if dbch.DomainID.Valid { - ch.DomainID = dbch.DomainID.String - } - if dbch.Parent.Valid { - ch.Parent = dbch.Parent.String - } - if dbch.UpdatedBy.Valid { - ch.UpdatedBy = dbch.UpdatedBy.String - } - if dbch.UpdatedAt.Valid { - ch.UpdatedAt = dbch.UpdatedAt.Time - } - - if err := json.Unmarshal([]byte(dbch.Metadata), &ch.Metadata); err != nil { - return bootstrap.Channel{}, errors.Wrap(errors.ErrMalformedEntity, err) - } - - return ch, nil -} - -type dbConnection struct { - Config string `db:"config_id"` - Channel string `db:"channel_id"` - DomainID string `db:"domain_id"` -} diff --git a/bootstrap/postgres/configs_test.go b/bootstrap/postgres/configs_test.go deleted file mode 100644 index dfeab45853..0000000000 --- a/bootstrap/postgres/configs_test.go +++ /dev/null @@ -1,913 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package postgres_test - -import ( - "context" - "fmt" - "strconv" - "testing" - - "github.com/absmach/supermq/bootstrap" - "github.com/absmach/supermq/bootstrap/postgres" - "github.com/absmach/supermq/internal/testsutil" - "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" -) - -const numConfigs = 10 - -var ( - config = bootstrap.Config{ - 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}}, - }, - Content: "content", - State: bootstrap.Inactive, - } - - channels = []string{"1", "2"} -) - -func TestSave(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - diff := "different" - - duplicateClient := config - duplicateClient.ExternalID = diff - duplicateClient.ClientSecret = diff - duplicateClient.Channels = []bootstrap.Channel{} - - duplicateExternal := config - duplicateExternal.ClientID = diff - duplicateExternal.ClientSecret = diff - duplicateExternal.Channels = []bootstrap.Channel{} - - duplicateChannels := config - duplicateChannels.ExternalID = diff - duplicateChannels.ClientSecret = diff - duplicateChannels.ClientID = diff - - cases := []struct { - desc string - config bootstrap.Config - connections []string - err error - }{ - { - desc: "save a config", - config: config, - connections: channels, - err: nil, - }, - { - desc: "save config with same Client ID", - config: duplicateClient, - connections: nil, - err: repoerr.ErrConflict, - }, - { - desc: "save config with same external ID", - config: duplicateExternal, - connections: nil, - err: repoerr.ErrConflict, - }, - { - desc: "save config with same Channels", - config: duplicateChannels, - connections: channels, - err: repoerr.ErrConflict, - }, - } - for _, tc := range cases { - 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.ClientID, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.config.ClientID, id)) - } - } -} - -func TestRetrieveByID(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - require.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - id, err := repo.Save(context.Background(), c, channels) - require.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - nonexistentConfID, err := uuid.NewV4() - require.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - - cases := []struct { - desc string - domainID string - id string - err error - }{ - { - desc: "retrieve config", - domainID: c.DomainID, - id: id, - err: nil, - }, - { - desc: "retrieve config with wrong domain ID ", - domainID: "2", - id: id, - err: repoerr.ErrNotFound, - }, - { - desc: "retrieve a non-existing config", - domainID: c.DomainID, - id: nonexistentConfID.String(), - err: repoerr.ErrNotFound, - }, - { - desc: "retrieve a config with invalid ID", - domainID: c.DomainID, - id: "invalid", - err: repoerr.ErrNotFound, - }, - } - for _, tc := range cases { - _, err := repo.RetrieveByID(context.Background(), tc.domainID, tc.id) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestRetrieveAll(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - clientIDs := make([]string, numConfigs) - - for i := 0; i < numConfigs; i++ { - c := config - - // Use UUID to prevent conflict errors. - uid, err := uuid.NewV4() - require.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ExternalID = uid.String() - c.Name = fmt.Sprintf("name %d", i) - c.ClientID = uid.String() - c.ClientSecret = uid.String() - - clientIDs[i] = c.ClientID - - if i%2 == 0 { - c.State = bootstrap.Active - } - - if i > 0 { - c.Channels = nil - } - - _, err = repo.Save(context.Background(), c, channels) - require.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - } - cases := []struct { - desc string - domainID string - clientID []string - offset uint64 - limit uint64 - filter bootstrap.Filter - size int - }{ - { - desc: "retrieve all configs", - domainID: config.DomainID, - clientID: []string{}, - offset: 0, - limit: uint64(numConfigs), - size: numConfigs, - }, - { - desc: "retrieve a subset of configs", - domainID: config.DomainID, - clientID: []string{}, - offset: 5, - limit: uint64(numConfigs - 5), - size: numConfigs - 5, - }, - { - desc: "retrieve with wrong domain ID ", - domainID: "2", - clientID: []string{}, - offset: 0, - limit: uint64(numConfigs), - size: 0, - }, - { - desc: "retrieve all active configs ", - domainID: config.DomainID, - clientID: []string{}, - offset: 0, - limit: uint64(numConfigs), - filter: bootstrap.Filter{FullMatch: map[string]string{"state": bootstrap.Active.String()}}, - size: numConfigs / 2, - }, - { - desc: "retrieve all with partial match filter", - domainID: config.DomainID, - clientID: []string{}, - offset: 0, - limit: uint64(numConfigs), - filter: bootstrap.Filter{PartialMatch: map[string]string{"name": "1"}}, - size: 1, - }, - { - desc: "retrieve search by name", - domainID: config.DomainID, - clientID: []string{}, - offset: 0, - limit: uint64(numConfigs), - filter: bootstrap.Filter{PartialMatch: map[string]string{"name": "1"}}, - size: 1, - }, - { - desc: "retrieve by valid clientIDs", - domainID: config.DomainID, - clientID: clientIDs, - offset: 0, - limit: uint64(numConfigs), - size: 10, - }, - { - desc: "retrieve by non-existing clientID", - domainID: config.DomainID, - clientID: []string{"non-existing"}, - offset: 0, - limit: uint64(numConfigs), - size: 0, - }, - } - for _, tc := range cases { - 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)) - } -} - -func TestRetrieveByExternalID(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - _, err = repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - cases := []struct { - desc string - externalID string - err error - }{ - { - desc: "retrieve with invalid external ID", - externalID: strconv.Itoa(numConfigs + 1), - err: repoerr.ErrNotFound, - }, - { - desc: "retrieve with external key", - externalID: c.ExternalID, - err: nil, - }, - } - for _, tc := range cases { - _, err := repo.RetrieveByExternalID(context.Background(), tc.externalID) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestUpdate(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - _, err = repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - c.Content = "new content" - c.Name = "new name" - - wrongDomainID := c - wrongDomainID.DomainID = "3" - - cases := []struct { - desc string - id string - config bootstrap.Config - err error - }{ - { - desc: "update with wrong domainID ", - config: wrongDomainID, - err: repoerr.ErrNotFound, - }, - { - desc: "update a config", - config: c, - err: nil, - }, - } - for _, tc := range cases { - err := repo.Update(context.Background(), tc.config) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestUpdateCert(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - _, err = repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - c.Content = "new content" - c.Name = "new name" - - wrongDomainID := c - wrongDomainID.DomainID = "3" - - cases := []struct { - desc string - clientID string - domainID string - cert string - certKey string - ca string - expectedConfig bootstrap.Config - err error - }{ - { - desc: "update with wrong domain ID ", - clientID: "", - cert: "cert", - certKey: "certKey", - ca: "", - domainID: wrongDomainID.DomainID, - expectedConfig: bootstrap.Config{}, - err: repoerr.ErrNotFound, - }, - { - desc: "update a config", - clientID: c.ClientID, - cert: "cert", - certKey: "certKey", - ca: "ca", - domainID: c.DomainID, - expectedConfig: bootstrap.Config{ - ClientID: c.ClientID, - ClientCert: "cert", - CACert: "ca", - ClientKey: "certKey", - DomainID: c.DomainID, - }, - err: nil, - }, - } - for _, tc := range cases { - 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)) - } -} - -func TestUpdateConnections(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - _, err = repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - // Use UUID to prevent conflicts. - uid, err = uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - c.Channels = []bootstrap.Channel{} - c2, err := repo.Save(context.Background(), c, []string{channels[0]}) - assert.Nil(t, err, fmt.Sprintf("Saving a config expected to succeed: %s.\n", err)) - - cases := []struct { - desc string - domainID string - id string - channels []bootstrap.Channel - connections []string - err error - }{ - { - desc: "update connections of non-existing config", - domainID: config.DomainID, - id: "unknown", - channels: nil, - connections: []string{channels[1]}, - err: repoerr.ErrNotFound, - }, - { - desc: "update connections", - domainID: config.DomainID, - id: c.ClientID, - channels: nil, - connections: []string{channels[1]}, - err: nil, - }, - { - desc: "update connections with existing channels", - domainID: config.DomainID, - id: c2, - channels: nil, - connections: channels, - err: nil, - }, - { - desc: "update connections no channels", - domainID: config.DomainID, - id: c.ClientID, - channels: nil, - connections: nil, - err: nil, - }, - } - for _, tc := range cases { - err := repo.UpdateConnections(context.Background(), tc.domainID, tc.id, tc.channels, tc.connections) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - } -} - -func TestRemove(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - id, err := repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - // Removal works the same for both existing and non-existing - // (removed) config - for i := 0; i < 2; i++ { - err := repo.Remove(context.Background(), c.DomainID, id) - assert.Nil(t, err, fmt.Sprintf("%d: failed to remove config due to: %s", i, err)) - - _, err = repo.RetrieveByID(context.Background(), c.DomainID, id) - assert.True(t, errors.Contains(err, repoerr.ErrNotFound), fmt.Sprintf("%d: expected %s got %s", i, repoerr.ErrNotFound, err)) - } -} - -func TestChangeState(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - 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)) - - cases := []struct { - desc string - domainID string - id string - state bootstrap.State - err error - }{ - { - desc: "change state with wrong domain ID ", - id: saved, - domainID: "2", - err: repoerr.ErrNotFound, - }, - { - desc: "change state with wrong id", - id: "wrong", - domainID: c.DomainID, - err: repoerr.ErrNotFound, - }, - { - desc: "change state to Active", - id: saved, - domainID: c.DomainID, - state: bootstrap.Active, - err: nil, - }, - { - desc: "change state to Inactive", - id: saved, - domainID: c.DomainID, - state: bootstrap.Inactive, - err: nil, - }, - } - for _, tc := range cases { - err := repo.ChangeState(context.Background(), tc.domainID, 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)) - } -} - -func TestListExisting(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - _, err = repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - var chs []bootstrap.Channel - chs = append(chs, config.Channels...) - - cases := []struct { - desc string - domainID string - connections []string - existing []bootstrap.Channel - }{ - { - desc: "list all existing channels", - domainID: c.DomainID, - connections: channels, - existing: chs, - }, - { - desc: "list a subset of existing channels", - domainID: c.DomainID, - connections: []string{channels[0], "5"}, - existing: []bootstrap.Channel{chs[0]}, - }, - { - desc: "list a subset of existing channels empty", - domainID: c.DomainID, - connections: []string{"5", "6"}, - existing: []bootstrap.Channel{}, - }, - } - for _, tc := range cases { - existing, err := repo.ListExisting(context.Background(), tc.domainID, tc.connections) - assert.Nil(t, err, fmt.Sprintf("%s: unexpected error: %s", tc.desc, err)) - assert.ElementsMatch(t, tc.existing, existing, fmt.Sprintf("%s: Got non-matching elements.", tc.desc)) - } -} - -func TestRemoveClient(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - 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.RemoveClient(context.Background(), saved) - assert.Nil(t, err, fmt.Sprintf("an unexpected error occurred: %s\n", err)) - } -} - -func TestUpdateChannel(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - _, err = repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - id := c.Channels[0].ID - update := bootstrap.Channel{ - ID: id, - Name: "update name", - Metadata: map[string]interface{}{"update": "metadata update"}, - } - 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.ClientID) - assert.Nil(t, err, fmt.Sprintf("Retrieving config expected to succeed: %s.\n", err)) - var retreved bootstrap.Channel - for _, c := range cfg.Channels { - if c.ID == id { - retreved = c - break - } - } - update.DomainID = retreved.DomainID - assert.Equal(t, update, retreved, fmt.Sprintf("expected %s, go %s", update, retreved)) -} - -func TestRemoveChannel(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - _, err = repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - 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.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 TestConnectClient(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - c.State = bootstrap.Inactive - saved, err := repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - wrongID := testsutil.GenerateUUID(&testing.T{}) - - connectedClient := c - - randomClient := c - randomClientID, _ := uuid.NewV4() - randomClient.ClientID = randomClientID.String() - - emptyClient := c - emptyClient.ClientID = "" - - cases := []struct { - desc string - domainID string - id string - state bootstrap.State - channels []bootstrap.Channel - connections []string - err error - }{ - { - desc: "connect disconnected client", - domainID: c.DomainID, - id: saved, - state: bootstrap.Inactive, - channels: c.Channels, - connections: channels, - err: nil, - }, - { - desc: "connect already connected client", - domainID: c.DomainID, - id: connectedClient.ClientID, - state: connectedClient.State, - channels: c.Channels, - connections: channels, - err: nil, - }, - { - desc: "connect non-existent client", - domainID: c.DomainID, - id: wrongID, - channels: c.Channels, - connections: channels, - err: repoerr.ErrNotFound, - }, - { - desc: "connect random client", - domainID: c.DomainID, - id: randomClient.ClientID, - channels: c.Channels, - connections: channels, - err: repoerr.ErrNotFound, - }, - { - desc: "connect empty client", - domainID: c.DomainID, - id: emptyClient.ClientID, - channels: c.Channels, - connections: channels, - err: repoerr.ErrNotFound, - }, - } - for _, tc := range cases { - for i, ch := range tc.channels { - if i == 0 { - 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.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.ConnectClient(context.Background(), ch.ID, tc.id) - } - } - - 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 TestDisconnectClient(t *testing.T) { - repo := postgres.NewConfigRepository(db, testLog) - err := deleteChannels(context.Background(), repo) - require.Nil(t, err, "Channels cleanup expected to succeed.") - - c := config - // Use UUID to prevent conflicts. - uid, err := uuid.NewV4() - assert.Nil(t, err, fmt.Sprintf("Got unexpected error: %s.\n", err)) - c.ClientSecret = uid.String() - c.ClientID = uid.String() - c.ExternalID = uid.String() - c.ExternalKey = uid.String() - c.State = bootstrap.Inactive - saved, err := repo.Save(context.Background(), c, channels) - assert.Nil(t, err, fmt.Sprintf("Saving config expected to succeed: %s.\n", err)) - - wrongID := testsutil.GenerateUUID(&testing.T{}) - - connectedClient := c - - randomClient := c - randomClientID, _ := uuid.NewV4() - randomClient.ClientID = randomClientID.String() - - emptyClient := c - emptyClient.ClientID = "" - - cases := []struct { - desc string - domainID string - id string - state bootstrap.State - channels []bootstrap.Channel - connections []string - err error - }{ - { - desc: "disconnect connected client", - domainID: c.DomainID, - id: connectedClient.ClientID, - state: connectedClient.State, - channels: c.Channels, - connections: channels, - err: nil, - }, - { - desc: "disconnect already disconnected client", - domainID: c.DomainID, - id: saved, - state: bootstrap.Inactive, - channels: c.Channels, - connections: channels, - err: nil, - }, - { - desc: "disconnect invalid client", - domainID: c.DomainID, - id: wrongID, - channels: c.Channels, - connections: channels, - err: nil, - }, - { - desc: "disconnect random client", - domainID: c.DomainID, - id: randomClient.ClientID, - channels: c.Channels, - connections: channels, - err: nil, - }, - { - desc: "disconnect empty client", - domainID: c.DomainID, - id: emptyClient.ClientID, - channels: c.Channels, - connections: channels, - err: nil, - }, - } - - for _, tc := range cases { - for _, ch := range tc.channels { - 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.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)) - } -} - -func deleteChannels(ctx context.Context, repo bootstrap.ConfigRepository) error { - for _, ch := range channels { - if err := repo.RemoveChannel(ctx, ch); err != nil { - return err - } - } - - return nil -} diff --git a/bootstrap/postgres/doc.go b/bootstrap/postgres/doc.go deleted file mode 100644 index 73a6784776..0000000000 --- a/bootstrap/postgres/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package postgres contains repository implementations using PostgreSQL as -// the underlying database. -package postgres diff --git a/bootstrap/postgres/init.go b/bootstrap/postgres/init.go deleted file mode 100644 index 5ab55938d7..0000000000 --- a/bootstrap/postgres/init.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package postgres - -import migrate "github.com/rubenv/sql-migrate" - -// Migration of bootstrap service. -func Migration() *migrate.MemoryMigrationSource { - return &migrate.MemoryMigrationSource{ - Migrations: []*migrate.Migration{ - { - Id: "configs_1", - Up: []string{ - `CREATE TABLE IF NOT EXISTS configs ( - mainflux_client TEXT UNIQUE NOT NULL, - owner VARCHAR(254), - name TEXT, - mainflux_key CHAR(36) UNIQUE NOT NULL, - external_id TEXT UNIQUE NOT NULL, - external_key TEXT NOT NULL, - content TEXT, - client_cert TEXT, - client_key TEXT, - ca_cert TEXT, - state BIGINT NOT NULL, - PRIMARY KEY (mainflux_client, owner) - )`, - `CREATE TABLE IF NOT EXISTS unknown_configs ( - external_id TEXT UNIQUE NOT NULL, - external_key TEXT NOT NULL, - PRIMARY KEY (external_id, external_key) - )`, - `CREATE TABLE IF NOT EXISTS channels ( - mainflux_channel TEXT UNIQUE NOT NULL, - owner VARCHAR(254), - name TEXT, - metadata JSON, - PRIMARY KEY (mainflux_channel, owner) - )`, - `CREATE TABLE IF NOT EXISTS connections ( - channel_id TEXT, - channel_owner VARCHAR(256), - 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_client, owner) ON DELETE CASCADE ON UPDATE CASCADE, - PRIMARY KEY (channel_id, channel_owner, config_id, config_owner) - )`, - }, - Down: []string{ - "DROP TABLE connections", - "DROP TABLE configs", - "DROP TABLE channels", - "DROP TABLE unknown_configs", - }, - }, - { - Id: "configs_2", - Up: []string{ - "DROP TABLE IF EXISTS unknown_configs", - }, - Down: []string{ - "CREATE TABLE IF NOT EXISTS unknown_configs", - }, - }, - { - Id: "configs_3", - Up: []string{ - `ALTER TABLE IF EXISTS channels ADD COLUMN IF NOT EXISTS parent_id VARCHAR(36)`, - `ALTER TABLE IF EXISTS channels ADD COLUMN IF NOT EXISTS description VARCHAR(1024)`, - `ALTER TABLE IF EXISTS channels ADD COLUMN IF NOT EXISTS created_at TIMESTAMP`, - `ALTER TABLE IF EXISTS channels ADD COLUMN IF NOT EXISTS updated_at TIMESTAMP`, - `ALTER TABLE IF EXISTS channels ADD COLUMN IF NOT EXISTS updated_by VARCHAR(254)`, - `ALTER TABLE IF EXISTS channels ADD COLUMN IF NOT EXISTS status SMALLINT NOT NULL DEFAULT 0 CHECK (status >= 0)`, - }, - }, - { - Id: "configs_4", - Up: []string{ - `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`, - }, - }, - { - Id: "configs_5", - Up: []string{ - `ALTER TABLE IF EXISTS configs RENAME COLUMN owner TO domain_id`, - `ALTER TABLE IF EXISTS channels RENAME COLUMN owner TO domain_id`, - `ALTER TABLE IF EXISTS configs ADD CONSTRAINT configs_name_domain_id_key UNIQUE (name, domain_id)`, - }, - }, - { - Id: "configs_6", - Up: []string{ - `ALTER TABLE IF EXISTS connections DROP CONSTRAINT IF EXISTS connections_pkey`, - `ALTER TABLE IF EXISTS connections DROP COLUMN IF EXISTS channel_owner`, - `ALTER TABLE IF EXISTS connections DROP COLUMN IF EXISTS config_owner`, - `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_client, domain_id) ON DELETE CASCADE ON UPDATE CASCADE`, - }, - }, - }, - } -} diff --git a/bootstrap/postgres/setup_test.go b/bootstrap/postgres/setup_test.go deleted file mode 100644 index 4151768d90..0000000000 --- a/bootstrap/postgres/setup_test.go +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package postgres_test - -import ( - "fmt" - "log" - "os" - "testing" - - "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, _ = smqlog.New(os.Stdout, "info") - db *sqlx.DB -) - -func TestMain(m *testing.M) { - pool, err := dockertest.NewPool("") - if err != nil { - testLog.Error(fmt.Sprintf("Could not connect to docker: %s", err)) - } - - container, err := pool.RunWithOptions(&dockertest.RunOptions{ - Repository: "postgres", - Tag: "16.2-alpine", - Env: []string{ - "POSTGRES_USER=test", - "POSTGRES_PASSWORD=test", - "POSTGRES_DB=test", - "listen_addresses = '*'", - }, - }, func(config *docker.HostConfig) { - config.AutoRemove = true - config.RestartPolicy = docker.RestartPolicy{Name: "no"} - }) - if err != nil { - log.Fatalf("Could not start container: %s", err) - } - - port := container.GetPort("5432/tcp") - - if err := pool.Retry(func() error { - url := fmt.Sprintf("host=localhost port=%s user=test dbname=test password=test sslmode=disable", port) - db, err = sqlx.Open("pgx", url) - if err != nil { - return err - } - return db.Ping() - }); err != nil { - testLog.Error(fmt.Sprintf("Could not connect to docker: %s", err)) - } - - dbConfig := pgclient.Config{ - Host: "localhost", - Port: port, - User: "test", - Pass: "test", - Name: "test", - SSLMode: "disable", - SSLCert: "", - SSLKey: "", - SSLRootCert: "", - } - - if db, err = pgclient.Setup(dbConfig, *postgres.Migration()); err != nil { - testLog.Error(fmt.Sprintf("Could not setup test DB connection: %s", err)) - } - - code := m.Run() - - // Defers will not be run when using os.Exit - db.Close() - if err := pool.Purge(container); err != nil { - testLog.Error(fmt.Sprintf("Could not purge container: %s", err)) - } - - os.Exit(code) -} diff --git a/bootstrap/reader.go b/bootstrap/reader.go deleted file mode 100644 index 84fa1ef2c8..0000000000 --- a/bootstrap/reader.go +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package bootstrap - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/json" - "io" - "net/http" -) - -// 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 { - 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 { - ID string `json:"id"` - Name string `json:"name,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` -} - -func (res bootstrapRes) Code() int { - return http.StatusOK -} - -func (res bootstrapRes) Headers() map[string]string { - return map[string]string{} -} - -func (res bootstrapRes) Empty() bool { - return false -} - -type reader struct { - encKey []byte -} - -// NewConfigReader return new reader which is used to generate response -// from the config. -func NewConfigReader(encKey []byte) ConfigReader { - return reader{encKey: encKey} -} - -func (r reader) ReadConfig(cfg Config, secure bool) (interface{}, error) { - var channels []channelRes - for _, ch := range cfg.Channels { - channels = append(channels, channelRes{ID: ch.ID, Name: ch.Name, Metadata: ch.Metadata}) - } - - res := bootstrapRes{ - 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) - if err != nil { - return nil, err - } - return r.encrypt(b) - } - - return res, nil -} - -func (r reader) encrypt(in []byte) ([]byte, error) { - block, err := aes.NewCipher(r.encKey) - if err != nil { - return nil, err - } - ciphertext := make([]byte, aes.BlockSize+len(in)) - iv := ciphertext[:aes.BlockSize] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return nil, err - } - stream := cipher.NewCFBEncrypter(block, iv) - stream.XORKeyStream(ciphertext[aes.BlockSize:], in) - return ciphertext, nil -} diff --git a/bootstrap/reader_test.go b/bootstrap/reader_test.go deleted file mode 100644 index 28a36bd421..0000000000 --- a/bootstrap/reader_test.go +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package bootstrap_test - -import ( - "crypto/aes" - "crypto/cipher" - "encoding/json" - "fmt" - "net/http" - "testing" - - "github.com/absmach/supermq" - "github.com/absmach/supermq/bootstrap" - "github.com/absmach/supermq/pkg/errors" - "github.com/stretchr/testify/assert" -) - -type readChan struct { - ID string `json:"id"` - Name string `json:"name,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` -} - -type readResp struct { - 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) { - block, err := aes.NewCipher(encKey) - if err != nil { - return nil, err - } - if len(in) < aes.BlockSize { - return nil, errors.ErrMalformedEntity - } - iv := in[:aes.BlockSize] - in = in[aes.BlockSize:] - stream := cipher.NewCFBDecrypter(block, iv) - stream.XORKeyStream(in, in) - return in, nil -} - -func TestReadConfig(t *testing.T) { - cfg := bootstrap.Config{ - ClientID: "smq_id", - ClientCert: "client_cert", - ClientKey: "client_key", - CACert: "ca_cert", - ClientSecret: "smq_key", - Channels: []bootstrap.Channel{ - { - ID: "smq_id", - Name: "smq_name", - Metadata: map[string]interface{}{"key": "value}"}, - }, - }, - Content: "content", - } - ret := readResp{ - ClientID: "smq_id", - ClientSecret: "smq_key", - Channels: []readChan{ - { - ID: "smq_id", - Name: "smq_name", - Metadata: map[string]interface{}{"key": "value}"}, - }, - }, - Content: "content", - ClientCert: "client_cert", - ClientKey: "client_key", - CACert: "ca_cert", - } - - bin, err := json.Marshal(ret) - assert.Nil(t, err, fmt.Sprintf("Marshalling expected to succeed: %s.\n", err)) - - reader := bootstrap.NewConfigReader(encKey) - cases := []struct { - desc string - config bootstrap.Config - enc []byte - secret bool - err error - }{ - { - desc: "read a config", - config: cfg, - enc: bin, - secret: false, - }, - { - desc: "read encrypted config", - config: cfg, - enc: bin, - secret: true, - }, - } - - for _, tc := range cases { - res, err := reader.ReadConfig(tc.config, tc.secret) - assert.Nil(t, err, fmt.Sprintf("Reading config to succeed: %s.\n", err)) - - if tc.secret { - d, err := dec(res.([]byte)) - assert.Nil(t, err, fmt.Sprintf("Decrypting expected to succeed: %s.\n", err)) - assert.Equal(t, tc.enc, d, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.enc, d)) - continue - } - 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.(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.") - } -} diff --git a/bootstrap/service.go b/bootstrap/service.go deleted file mode 100644 index 566483b075..0000000000 --- a/bootstrap/service.go +++ /dev/null @@ -1,505 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package bootstrap - -import ( - "context" - "crypto/aes" - "crypto/cipher" - "encoding/hex" - - "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 ( - // ErrClients indicates failure to communicate with SuperMQ Clients service. - // It can be due to networking error or invalid/unauthenticated request. - 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") - - // ErrExternalKeySecure indicates error in getting bootstrap configuration for given encrypted external key. - ErrExternalKeySecure = errors.New("failed to get bootstrap configuration for given encrypted external key") - - // ErrBootstrap indicates error in getting bootstrap configuration. - ErrBootstrap = errors.New("failed to read bootstrap configuration") - - // ErrAddBootstrap indicates error in adding bootstrap configuration. - ErrAddBootstrap = errors.New("failed to add bootstrap configuration") - - // ErrNotInSameDomain indicates entities are not in the same domain. - errNotInSameDomain = errors.New("entities are not in the same domain") - - errUpdateConnections = errors.New("failed to update connections") - errRemoveBootstrap = errors.New("failed to remove bootstrap configuration") - errChangeState = errors.New("failed to change state of bootstrap configuration") - errUpdateChannel = errors.New("failed to update channel") - errRemoveConfig = errors.New("failed to remove bootstrap configuration") - errRemoveChannel = errors.New("failed to remove channel") - 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") - errClientNotFound = errors.New("failed to find client") - errUpdateCert = errors.New("failed to update cert") -) - -var _ Service = (*bootstrapService)(nil) - -// Service specifies an API that must be fulfilled by the domain service -// implementation, and all of its decorators (e.g. logging & metrics). -// -//go:generate mockery --name Service --output=./mocks --filename service.go --quiet --note "Copyright (c) Abstract Machines" -type Service interface { - // 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 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 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 smqauthn.Session, clientID, clientCert, clientKey, caCert string) (Config, error) - - // UpdateConnections updates list of Channels related to given Config. - 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 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 smqauthn.Session, id string) error - - // 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 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. - - // UpdateChannelHandler updates Channel with data received from an event. - UpdateChannelHandler(ctx context.Context, channel Channel) error - - // RemoveConfigHandler removes Configuration with id received from an event. - RemoveConfigHandler(ctx context.Context, id string) error - - // RemoveChannelHandler removes Channel with id received from an event. - RemoveChannelHandler(ctx context.Context, id string) error - - // ConnectClientHandler changes state of the Config to active when connect event occurs. - ConnectClientHandler(ctx context.Context, channelID, clientID 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 -// as a JSON and consumed from the client side. The purpose of this interface -// is to provide convenient way to generate custom configuration response -// based on the specific Config which will be consumed by the client. -// -//go:generate mockery --name ConfigReader --output=./mocks --filename config_reader.go --quiet --note "Copyright (c) Abstract Machines" -type ConfigReader interface { - ReadConfig(Config, bool) (interface{}, error) -} - -type bootstrapService struct { - policies policies.Service - configs ConfigRepository - sdk mgsdk.SDK - encKey []byte - idProvider supermq.IDProvider -} - -// New returns new Bootstrap service. -func New(policyService policies.Service, configs ConfigRepository, sdk mgsdk.SDK, encKey []byte, idp supermq.IDProvider) Service { - return &bootstrapService{ - configs: configs, - sdk: sdk, - policies: policyService, - encKey: encKey, - idProvider: idp, - } -} - -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. - existing, err := bs.configs.ListExisting(ctx, session.DomainID, toConnect) - if err != nil { - return Config{}, errors.Wrap(errCheckChannels, err) - } - - cfg.Channels, err = bs.connectionChannels(toConnect, bs.toIDList(existing), session.DomainID, token) - if err != nil { - return Config{}, errors.Wrap(errConnectionChannels, err) - } - - id := cfg.ClientID - mgClient, err := bs.client(session.DomainID, id, token) - if err != nil { - return Config{}, errors.Wrap(errClientNotFound, err) - } - - for _, channel := range cfg.Channels { - if channel.DomainID != mgClient.DomainID { - return Config{}, errors.Wrap(svcerr.ErrMalformedEntity, errNotInSameDomain) - } - } - - cfg.ClientID = mgClient.ID - cfg.DomainID = session.DomainID - cfg.State = Inactive - cfg.ClientSecret = mgClient.Credentials.Secret - - saved, err := bs.configs.Save(ctx, cfg, toConnect) - if err != nil { - // 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.DeleteClient(cfg.ClientID, cfg.DomainID, token); errT != nil { - err = errors.Wrap(err, errT) - } - } - return Config{}, errors.Wrap(ErrAddBootstrap, err) - } - - cfg.ClientID = saved - cfg.Channels = append(cfg.Channels, existing...) - - return cfg, nil -} - -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) - } - return cfg, nil -} - -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) - } - return nil -} - -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 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) - } - - add, remove := bs.updateList(cfg, connections) - - // Check if channels exist. This is the way to prevent fetching channels that already exist. - existing, err := bs.configs.ListExisting(ctx, session.DomainID, connections) - if err != nil { - return errors.Wrap(errUpdateConnections, err) - } - - channels, err := bs.connectionChannels(connections, bs.toIDList(existing), session.DomainID, token) - if err != nil { - return errors.Wrap(errUpdateConnections, err) - } - - cfg.Channels = channels - var connect, disconnect []string - - if cfg.State == Active { - connect = add - disconnect = remove - } - - for _, c := range disconnect { - if err := bs.sdk.DisconnectClients(c, []string{id}, []string{"Publish", "Subscribe"}, session.DomainID, token); err != nil { - if errors.Contains(err, repoerr.ErrNotFound) { - continue - } - return ErrClients - } - } - - for _, c := range connect { - conIDs := mgsdk.Connection{ - ChannelIDs: []string{c}, - ClientIDs: []string{id}, - Types: []string{"Publish", "Subscribe"}, - } - if err := bs.sdk.Connect(conIDs, session.DomainID, token); err != nil { - return ErrClients - } - } - if err := bs.configs.UpdateConnections(ctx, session.DomainID, id, channels, connections); err != nil { - return errors.Wrap(errUpdateConnections, err) - } - return nil -} - -func (bs bootstrapService) listClientIDs(ctx context.Context, userID string) ([]string, error) { - tids, err := bs.policies.ListAllObjects(ctx, policies.Policy{ - SubjectType: policies.UserType, - Subject: userID, - Permission: policies.ViewPermission, - ObjectType: policies.ClientType, - }) - if err != nil { - return nil, errors.Wrap(svcerr.ErrNotFound, err) - } - return tids.Policies, nil -} - -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 - clientIDs, err := bs.listClientIDs(ctx, session.DomainUserID) - if err != nil { - return ConfigsPage{}, errors.Wrap(svcerr.ErrNotFound, err) - } - - if len(clientIDs) == 0 { - return ConfigsPage{ - Total: 0, - Offset: offset, - Limit: limit, - Configs: []Config{}, - }, nil - } - - return bs.configs.RetrieveAll(ctx, session.DomainID, clientIDs, filter, offset, limit), nil -} - -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) - } - return nil -} - -func (bs bootstrapService) Bootstrap(ctx context.Context, externalKey, externalID string, secure bool) (Config, error) { - cfg, err := bs.configs.RetrieveByExternalID(ctx, externalID) - if err != nil { - return cfg, errors.Wrap(ErrBootstrap, err) - } - if secure { - dec, err := bs.dec(externalKey) - if err != nil { - return Config{}, errors.Wrap(ErrExternalKeySecure, err) - } - externalKey = dec - } - if cfg.ExternalKey != externalKey { - return Config{}, ErrExternalKey - } - - return cfg, nil -} - -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) - } - - if cfg.State == state { - return nil - } - - switch state { - case Active: - for _, c := range cfg.Channels { - 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 ErrClients - } - } - case Inactive: - for _, c := range cfg.Channels { - 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 ErrClients - } - } - } - if err := bs.configs.ChangeState(ctx, session.DomainID, id, state); err != nil { - return errors.Wrap(errChangeState, err) - } - return nil -} - -func (bs bootstrapService) UpdateChannelHandler(ctx context.Context, channel Channel) error { - if err := bs.configs.UpdateChannel(ctx, channel); err != nil { - return errors.Wrap(errUpdateChannel, err) - } - return nil -} - -func (bs bootstrapService) RemoveConfigHandler(ctx context.Context, id string) error { - if err := bs.configs.RemoveClient(ctx, id); err != nil { - return errors.Wrap(errRemoveConfig, err) - } - return nil -} - -func (bs bootstrapService) RemoveChannelHandler(ctx context.Context, id string) error { - if err := bs.configs.RemoveChannel(ctx, id); err != nil { - return errors.Wrap(errRemoveChannel, err) - } - return nil -} - -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) 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 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.Client{}, errors.Wrap(errCreateClient, err) - } - client, sdkErr := bs.sdk.CreateClient(mgsdk.Client{ID: id, Name: "Bootstrapped Client " + id}, domainID, token) - if sdkErr != nil { - return mgsdk.Client{}, errors.Wrap(errCreateClient, sdkErr) - } - return client, nil - } - - // If Client ID is provided, then retrieve client - client, sdkErr := bs.sdk.Client(id, domainID, token) - if sdkErr != nil { - return mgsdk.Client{}, errors.Wrap(ErrClients, sdkErr) - } - return client, nil -} - -func (bs bootstrapService) connectionChannels(channels, existing []string, domainID, token string) ([]Channel, error) { - add := make(map[string]bool, len(channels)) - for _, ch := range channels { - add[ch] = true - } - - for _, ch := range existing { - if add[ch] { - delete(add, ch) - } - } - - var ret []Channel - for id := range add { - ch, err := bs.sdk.Channel(id, domainID, token) - if err != nil { - return nil, errors.Wrap(errors.ErrMalformedEntity, err) - } - - ret = append(ret, Channel{ - ID: ch.ID, - Name: ch.Name, - Metadata: ch.Metadata, - DomainID: ch.DomainID, - }) - } - - return ret, nil -} - -// Method updateList accepts config and channel IDs and returns three lists: -// 1) IDs of Channels to be added -// 2) IDs of Channels to be removed -// 3) IDs of common Channels for these two configs. -func (bs bootstrapService) updateList(cfg Config, connections []string) (add, remove []string) { - disconnect := make(map[string]bool, len(cfg.Channels)) - for _, c := range cfg.Channels { - disconnect[c.ID] = true - } - - for _, c := range connections { - if disconnect[c] { - // Don't disconnect common elements. - delete(disconnect, c) - continue - } - // Connect new elements. - add = append(add, c) - } - - for v := range disconnect { - remove = append(remove, v) - } - - return -} - -func (bs bootstrapService) toIDList(channels []Channel) []string { - var ret []string - for _, ch := range channels { - ret = append(ret, ch.ID) - } - - return ret -} - -func (bs bootstrapService) dec(in string) (string, error) { - ciphertext, err := hex.DecodeString(in) - if err != nil { - return "", err - } - block, err := aes.NewCipher(bs.encKey) - if err != nil { - return "", err - } - if len(ciphertext) < aes.BlockSize { - return "", err - } - iv := ciphertext[:aes.BlockSize] - ciphertext = ciphertext[aes.BlockSize:] - stream := cipher.NewCFBDecrypter(block, iv) - stream.XORKeyStream(ciphertext, ciphertext) - return string(ciphertext), nil -} diff --git a/bootstrap/service_test.go b/bootstrap/service_test.go deleted file mode 100644 index 65ce4043b0..0000000000 --- a/bootstrap/service_test.go +++ /dev/null @@ -1,1113 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package bootstrap_test - -import ( - "context" - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/hex" - "fmt" - "io" - "sort" - "testing" - - "github.com/absmach/supermq/bootstrap" - "github.com/absmach/supermq/bootstrap/mocks" - "github.com/absmach/supermq/internal/testsutil" - 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" -) - -const ( - validToken = "validToken" - invalidToken = "invalid" - invalidDomainID = "invalid" - email = "test@example.com" - unknown = "unknown" - channelsNum = 3 - instanceID = "5de9b29a-feb9-11ed-be56-0242ac120002" - validID = "d4ebb847-5d0e-4e46-bdd9-b6aceaaa3a22" -) - -var ( - encKey = []byte("1234567891011121") - domainID = testsutil.GenerateUUID(&testing.T{}) - channel = bootstrap.Channel{ - ID: testsutil.GenerateUUID(&testing.T{}), - Name: "name", - Metadata: map[string]interface{}{"name": "value"}, - } - - config = bootstrap.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", - } -) - -var ( - boot *mocks.ConfigRepository - policies *policymocks.Service - sdk *sdkmocks.SDK -) - -func newService() bootstrap.Service { - boot = new(mocks.ConfigRepository) - policies = new(policymocks.Service) - sdk = new(sdkmocks.SDK) - idp := uuid.NewMock() - return bootstrap.New(policies, boot, sdk, encKey, idp) -} - -func enc(in []byte) ([]byte, error) { - block, err := aes.NewCipher(encKey) - if err != nil { - return nil, err - } - ciphertext := make([]byte, aes.BlockSize+len(in)) - iv := ciphertext[:aes.BlockSize] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return nil, err - } - stream := cipher.NewCFBEncrypter(block, iv) - stream.XORKeyStream(ciphertext[aes.BlockSize:], in) - return ciphertext, nil -} - -func TestAdd(t *testing.T) { - svc := newService() - - neID := config - neID.ClientID = "non-existent" - - wrongChannels := config - ch := channel - ch.ID = "invalid" - wrongChannels.Channels = append(wrongChannels.Channels, ch) - - cases := []struct { - desc string - config bootstrap.Config - token string - session smqauthn.Session - userID string - domainID string - clientErr error - createClientErr error - channelErr error - listExistingErr error - saveErr error - deleteClientErr error - err error - }{ - { - desc: "add a new config", - config: config, - token: validToken, - userID: validID, - domainID: domainID, - err: nil, - }, - { - 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", - config: wrongChannels, - token: validToken, - userID: validID, - domainID: domainID, - listExistingErr: svcerr.ErrMalformedEntity, - err: svcerr.ErrMalformedEntity, - }, - { - desc: "add empty config", - config: bootstrap.Config{}, - token: validToken, - userID: validID, - domainID: domainID, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - 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) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() - repoCall1.Unset() - repoCall2.Unset() - repoCall3.Unset() - repoCall4.Unset() - }) - } -} - -func TestView(t *testing.T) { - svc := newService() - - cases := []struct { - 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.ClientID, - userID: validID, - clientDomain: domainID, - domain: domainID, - token: validToken, - err: nil, - }, - { - 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.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 = 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() - }) - } -} - -func TestUpdate(t *testing.T) { - svc := newService() - - c := config - ch := channel - ch.ID = "2" - c.Channels = append(c.Channels, ch) - - modifiedCreated := c - modifiedCreated.Content = "new-config" - modifiedCreated.Name = "new name" - - nonExisting := c - nonExisting.ClientID = unknown - - cases := []struct { - desc string - config bootstrap.Config - token string - session smqauthn.Session - userID string - domainID string - updateErr error - err error - }{ - { - desc: "update a config with state Created", - config: modifiedCreated, - token: validToken, - userID: validID, - domainID: domainID, - err: nil, - }, - { - desc: "update a non-existing config", - config: nonExisting, - token: validToken, - userID: validID, - domainID: domainID, - updateErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - }, - { - desc: "update a config with update error", - config: c, - token: validToken, - userID: validID, - domainID: domainID, - updateErr: svcerr.ErrUpdateEntity, - err: svcerr.ErrUpdateEntity, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - 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)) - repoCall.Unset() - }) - } -} - -func TestUpdateCert(t *testing.T) { - svc := newService() - - c := config - ch := channel - ch.ID = "2" - c.Channels = append(c.Channels, ch) - - cases := []struct { - desc string - token string - session smqauthn.Session - userID string - domainID string - clientID string - clientCert string - clientKey string - caCert string - expectedConfig bootstrap.Config - authorizeErr error - authenticateErr error - updateErr error - err error - }{ - { - desc: "update certs for the valid config", - userID: validID, - domainID: domainID, - clientID: c.ClientID, - clientCert: "newCert", - clientKey: "newKey", - caCert: "newCert", - token: validToken, - expectedConfig: bootstrap.Config{ - 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, - }, - { - desc: "update cert for a non-existing config", - userID: validID, - domainID: domainID, - clientID: "empty", - clientCert: "newCert", - clientKey: "newKey", - caCert: "newCert", - token: validToken, - expectedConfig: bootstrap.Config{}, - updateErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - 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.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 - }) - sort.Slice(tc.expectedConfig.Channels, func(i, j int) bool { - return tc.expectedConfig.Channels[i].ID < tc.expectedConfig.Channels[j].ID - }) - assert.Equal(t, tc.expectedConfig, cfg, fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.expectedConfig, cfg)) - repoCall.Unset() - }) - } -} - -func TestUpdateConnections(t *testing.T) { - svc := newService() - - c := config - c.State = bootstrap.Inactive - - activeConf := config - activeConf.State = bootstrap.Active - - ch := channel - - cases := []struct { - desc string - token string - session smqauthn.Session - id string - state bootstrap.State - userID string - domainID string - connections []string - updateErr error - clientErr error - channelErr error - retrieveErr error - listErr error - err error - }{ - { - desc: "update connections for config with state Inactive", - token: validToken, - userID: validID, - domainID: domainID, - id: c.ClientID, - state: c.State, - connections: []string{ch.ID}, - err: nil, - }, - { - desc: "update connections for config with state Active", - token: validToken, - userID: validID, - domainID: domainID, - id: activeConf.ClientID, - state: activeConf.State, - connections: []string{ch.ID}, - err: nil, - }, - { - desc: "update connections with invalid channels", - token: validToken, - userID: validID, - domainID: domainID, - id: c.ClientID, - connections: []string{"wrong"}, - channelErr: errors.NewSDKError(svcerr.ErrNotFound), - err: svcerr.ErrNotFound, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - 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) - repoCall2 := boot.On("UpdateConnections", context.Background(), mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.updateErr) - err := svc.UpdateConnections(context.Background(), tc.session, tc.token, tc.id, tc.connections) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - sdkCall.Unset() - repoCall.Unset() - repoCall1.Unset() - repoCall2.Unset() - }) - } -} - -func TestList(t *testing.T) { - svc := newService() - - numClients := 101 - var saved []bootstrap.Config - for i := 0; i < numClients; i++ { - c := config - c.ExternalID = testsutil.GenerateUUID(t) - c.ExternalKey = testsutil.GenerateUUID(t) - c.Name = fmt.Sprintf("%s-%d", config.Name, i) - if i == 41 { - c.State = bootstrap.Active - } - saved = append(saved, c) - } - cases := []struct { - desc string - config bootstrap.ConfigsPage - filter bootstrap.Filter - offset uint64 - limit uint64 - token string - session smqauthn.Session - userID string - domainID string - listObjectsResponse policysvc.PolicyPage - listObjectsErr error - retrieveErr error - err error - }{ - { - desc: "list configs successfully as super admin", - config: bootstrap.ConfigsPage{ - Total: uint64(len(saved)), - Offset: 0, - Limit: 10, - Configs: saved[0:10], - }, - filter: bootstrap.Filter{}, - token: validToken, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - userID: validID, - domainID: domainID, - offset: 0, - limit: 10, - err: nil, - }, - { - desc: "list configs with failed super admin check", - config: bootstrap.ConfigsPage{}, - filter: bootstrap.Filter{}, - token: validID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, - userID: validID, - domainID: domainID, - listObjectsResponse: policysvc.PolicyPage{}, - offset: 0, - limit: 10, - err: nil, - }, - { - desc: "list configs successfully as domain admin", - config: bootstrap.ConfigsPage{ - Total: uint64(len(saved)), - Offset: 0, - Limit: 10, - Configs: saved[0:10], - }, - filter: bootstrap.Filter{}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - listObjectsResponse: policysvc.PolicyPage{}, - offset: 0, - limit: 10, - err: nil, - }, - { - desc: "list configs successfully as non admin", - config: bootstrap.ConfigsPage{ - Total: uint64(len(saved)), - Offset: 0, - Limit: 10, - Configs: saved[0:10], - }, - filter: bootstrap.Filter{}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, - listObjectsResponse: policysvc.PolicyPage{Policies: []string{"test", "test"}}, - offset: 0, - limit: 10, - err: nil, - }, - { - desc: "list configs with specified name as super admin", - config: bootstrap.ConfigsPage{ - Total: 1, - Offset: 0, - Limit: 100, - Configs: saved[95:96], - }, - filter: bootstrap.Filter{PartialMatch: map[string]string{"name": "95"}}, - token: validToken, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - userID: validID, - domainID: domainID, - offset: 0, - limit: 100, - err: nil, - }, - { - desc: "list configs with specified name as domain admin", - config: bootstrap.ConfigsPage{ - Total: 1, - Offset: 0, - Limit: 100, - Configs: saved[95:96], - }, - filter: bootstrap.Filter{PartialMatch: map[string]string{"name": "95"}}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - offset: 0, - limit: 100, - err: nil, - }, - { - desc: "list configs with specified name as non admin", - config: bootstrap.ConfigsPage{ - Total: 1, - Offset: 0, - Limit: 100, - Configs: saved[95:96], - }, - filter: bootstrap.Filter{PartialMatch: map[string]string{"name": "95"}}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, - listObjectsResponse: policysvc.PolicyPage{Policies: []string{"test", "test"}}, - offset: 0, - limit: 100, - err: nil, - }, - { - desc: "list last page as super admin", - config: bootstrap.ConfigsPage{ - Total: uint64(len(saved)), - Offset: 95, - Limit: 10, - Configs: saved[95:], - }, - filter: bootstrap.Filter{}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - offset: 95, - limit: 10, - err: nil, - }, - { - desc: "list last page as domain admin", - config: bootstrap.ConfigsPage{ - Total: uint64(len(saved)), - Offset: 95, - Limit: 10, - Configs: saved[95:], - }, - filter: bootstrap.Filter{}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - offset: 95, - limit: 10, - err: nil, - }, - { - desc: "list last page as non admin", - config: bootstrap.ConfigsPage{ - Total: uint64(len(saved)), - Offset: 95, - Limit: 10, - Configs: saved[95:], - }, - filter: bootstrap.Filter{}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, - listObjectsResponse: policysvc.PolicyPage{Policies: []string{"test", "test"}}, - offset: 95, - limit: 10, - err: nil, - }, - { - desc: "list configs with Active state as super admin", - config: bootstrap.ConfigsPage{ - Total: 1, - Offset: 35, - Limit: 20, - Configs: []bootstrap.Config{saved[41]}, - }, - filter: bootstrap.Filter{FullMatch: map[string]string{"state": bootstrap.Active.String()}}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - offset: 35, - limit: 20, - err: nil, - }, - { - desc: "list configs with Active state as domain admin", - config: bootstrap.ConfigsPage{ - Total: 1, - Offset: 35, - Limit: 20, - Configs: []bootstrap.Config{saved[41]}, - }, - filter: bootstrap.Filter{FullMatch: map[string]string{"state": bootstrap.Active.String()}}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID, SuperAdmin: true}, - offset: 35, - limit: 20, - err: nil, - }, - { - desc: "list configs with Active state as non admin", - config: bootstrap.ConfigsPage{ - Total: 1, - Offset: 35, - Limit: 20, - Configs: []bootstrap.Config{saved[41]}, - }, - filter: bootstrap.Filter{FullMatch: map[string]string{"state": bootstrap.Active.String()}}, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, - listObjectsResponse: policysvc.PolicyPage{Policies: []string{"test", "test"}}, - offset: 35, - limit: 20, - err: nil, - }, - { - desc: "list configs with failed to list objects", - config: bootstrap.ConfigsPage{}, - filter: bootstrap.Filter{}, - offset: 0, - limit: 10, - token: validToken, - userID: validID, - domainID: domainID, - session: smqauthn.Session{UserID: validID, DomainID: domainID, DomainUserID: validID}, - listObjectsResponse: policysvc.PolicyPage{}, - listObjectsErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - policyCall := policies.On("ListAllObjects", mock.Anything, policysvc.Policy{ - SubjectType: policysvc.UserType, - Subject: tc.userID, - Permission: policysvc.ViewPermission, - 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) - - result, err := svc.List(context.Background(), tc.session, tc.filter, tc.offset, tc.limit) - assert.ElementsMatch(t, tc.config.Configs, result.Configs, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.config.Configs, result.Configs)) - assert.Equal(t, tc.config.Total, result.Total, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.config.Total, result.Total)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - policyCall.Unset() - repoCall.Unset() - }) - } -} - -func TestRemove(t *testing.T) { - svc := newService() - - c := config - cases := []struct { - desc string - id string - token string - session smqauthn.Session - userID string - domainID string - removeErr error - err error - }{ - { - desc: "remove an existing config", - id: c.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - err: nil, - }, - { - desc: "remove removed config", - id: c.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - err: nil, - }, - { - desc: "remove a config with failed remove", - id: c.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - removeErr: svcerr.ErrRemoveEntity, - err: svcerr.ErrRemoveEntity, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - 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)) - repoCall.Unset() - }) - } -} - -func TestBootstrap(t *testing.T) { - svc := newService() - - c := config - e, err := enc([]byte(c.ExternalKey)) - assert.Nil(t, err, fmt.Sprintf("Encrypting external key expected to succeed: %s.\n", err)) - - cases := []struct { - desc string - config bootstrap.Config - externalKey string - externalID string - userID string - domainID string - err error - encrypted bool - }{ - { - desc: "bootstrap using invalid external id", - config: bootstrap.Config{}, - externalID: "invalid", - externalKey: c.ExternalKey, - userID: validID, - domainID: invalidDomainID, - err: svcerr.ErrNotFound, - encrypted: false, - }, - { - desc: "bootstrap using invalid external key", - config: bootstrap.Config{}, - externalID: c.ExternalID, - externalKey: "invalid", - userID: validID, - domainID: domainID, - err: bootstrap.ErrExternalKey, - encrypted: false, - }, - { - desc: "bootstrap an existing config", - config: c, - externalID: c.ExternalID, - externalKey: c.ExternalKey, - userID: validID, - domainID: domainID, - err: nil, - encrypted: false, - }, - { - desc: "bootstrap encrypted", - config: c, - externalID: c.ExternalID, - externalKey: hex.EncodeToString(e), - userID: validID, - domainID: domainID, - err: nil, - encrypted: true, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - repoCall := boot.On("RetrieveByExternalID", context.Background(), mock.Anything).Return(tc.config, tc.err) - config, err := svc.Bootstrap(context.Background(), tc.externalKey, tc.externalID, tc.encrypted) - assert.Equal(t, tc.config, config, fmt.Sprintf("%s: expected %v got %v\n", tc.desc, tc.config, config)) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() - }) - } -} - -func TestChangeState(t *testing.T) { - svc := newService() - - c := config - cases := []struct { - desc string - state bootstrap.State - id string - token string - session smqauthn.Session - userID string - domainID string - retrieveErr error - connectErr errors.SDKError - disconenctErr error - stateErr error - err error - }{ - { - desc: "change state of non-existing config", - state: bootstrap.Active, - id: unknown, - token: validToken, - userID: validID, - domainID: domainID, - retrieveErr: svcerr.ErrNotFound, - err: svcerr.ErrNotFound, - }, - { - desc: "change state to Active", - state: bootstrap.Active, - id: c.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - err: nil, - }, - { - desc: "change state to current state", - state: bootstrap.Active, - id: c.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - err: nil, - }, - { - desc: "change state to Inactive", - state: bootstrap.Inactive, - id: c.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - err: nil, - }, - { - desc: "change state with failed Connect", - state: bootstrap.Active, - id: c.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - connectErr: errors.NewSDKError(bootstrap.ErrClients), - err: bootstrap.ErrClients, - }, - { - desc: "change state with invalid state", - state: bootstrap.State(2), - id: c.ClientID, - token: validToken, - userID: validID, - domainID: domainID, - stateErr: svcerr.ErrMalformedEntity, - err: svcerr.ErrMalformedEntity, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - 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("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)) - sdkCall.Unset() - repoCall.Unset() - repoCall1.Unset() - }) - } -} - -func TestUpdateChannelHandler(t *testing.T) { - svc := newService() - - ch := bootstrap.Channel{ - ID: channel.ID, - Name: "new name", - Metadata: map[string]interface{}{"meta": "new"}, - } - - cases := []struct { - desc string - channel bootstrap.Channel - err error - }{ - { - desc: "update an existing channel", - channel: ch, - err: nil, - }, - { - desc: "update a non-existing channel", - channel: bootstrap.Channel{ID: ""}, - err: nil, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - repoCall := boot.On("UpdateChannel", context.Background(), mock.Anything).Return(tc.err) - err := svc.UpdateChannelHandler(context.Background(), tc.channel) - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err)) - repoCall.Unset() - }) - } -} - -func TestRemoveChannelHandler(t *testing.T) { - svc := newService() - - cases := []struct { - desc string - id string - err error - }{ - { - desc: "remove an existing channel", - id: config.Channels[0].ID, - err: nil, - }, - { - desc: "remove a non-existing channel", - id: "unknown", - err: nil, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - repoCall := boot.On("RemoveChannel", context.Background(), mock.Anything).Return(tc.err) - err := svc.RemoveChannelHandler(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() - }) - } -} - -func TestRemoveConfigHandler(t *testing.T) { - svc := newService() - - cases := []struct { - desc string - id string - err error - }{ - { - desc: "remove an existing config", - id: config.ClientID, - err: nil, - }, - { - desc: "remove a non-existing channel", - id: "unknown", - err: nil, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - 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() - }) - } -} - -func TestConnectClientHandler(t *testing.T) { - svc := newService() - - cases := []struct { - desc string - clientID string - channelID string - err error - }{ - { - desc: "connect", - channelID: channel.ID, - clientID: config.ClientID, - err: nil, - }, - { - desc: "connect connected", - channelID: channel.ID, - clientID: config.ClientID, - err: svcerr.ErrAddPolicies, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - 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 TestDisconnectClientsHandler(t *testing.T) { - svc := newService() - - cases := []struct { - desc string - clientID string - channelID string - err error - }{ - { - desc: "disconnect", - channelID: channel.ID, - clientID: config.ClientID, - err: nil, - }, - { - desc: "disconnect disconnected", - channelID: channel.ID, - clientID: config.ClientID, - err: nil, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - 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() - }) - } -} diff --git a/bootstrap/state.go b/bootstrap/state.go deleted file mode 100644 index e97aedb0c7..0000000000 --- a/bootstrap/state.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package bootstrap - -import "strconv" - -const ( - // Inactive Client is created, but not able to exchange messages using SuperMQ. - Inactive State = iota - // Active Client is created, configured, and whitelisted. - Active -) - -// 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 | 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. -func (s State) String() string { - return strconv.Itoa(int(s)) -} diff --git a/bootstrap/tracing/doc.go b/bootstrap/tracing/doc.go deleted file mode 100644 index aa43565e46..0000000000 --- a/bootstrap/tracing/doc.go +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package tracing provides tracing instrumentation for SuperMQ Users service. -// -// This package provides tracing middleware for SuperMQ Users service. -// It can be used to trace incoming requests and add tracing capabilities to -// SuperMQ Users service. -// -// For more details about tracing instrumentation for SuperMQ messaging refer -// to the documentation at https://docs.supermq.abstractmachines.fr/tracing/. -package tracing diff --git a/bootstrap/tracing/tracing.go b/bootstrap/tracing/tracing.go deleted file mode 100644 index c18530e03e..0000000000 --- a/bootstrap/tracing/tracing.go +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package tracing - -import ( - "context" - - "github.com/absmach/supermq/bootstrap" - smqauthn "github.com/absmach/supermq/pkg/authn" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" -) - -var _ bootstrap.Service = (*tracingMiddleware)(nil) - -type tracingMiddleware struct { - tracer trace.Tracer - svc bootstrap.Service -} - -// New returns a new bootstrap service with tracing capabilities. -func New(svc bootstrap.Service, tracer trace.Tracer) bootstrap.Service { - return &tracingMiddleware{tracer, svc} -} - -// Add traces the "Add" operation of the wrapped bootstrap.Service. -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("client_id", cfg.ClientID), - attribute.String("domain_id ", cfg.DomainID), - attribute.String("name", cfg.Name), - attribute.String("external_id", cfg.ExternalID), - attribute.String("content", cfg.Content), - attribute.String("state", cfg.State.String()), - )) - defer span.End() - - return tm.svc.Add(ctx, session, token, cfg) -} - -// View traces the "View" operation of the wrapped bootstrap.Service. -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), - )) - defer span.End() - - return tm.svc.View(ctx, session, id) -} - -// Update traces the "Update" operation of the wrapped bootstrap.Service. -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("client_id", cfg.ClientID), - attribute.String("domain_id ", cfg.DomainID), - )) - defer span.End() - - return tm.svc.Update(ctx, session, cfg) -} - -// UpdateCert traces the "UpdateCert" operation of the wrapped bootstrap.Service. -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("client_id", clientID), - )) - defer span.End() - - 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 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), - )) - defer span.End() - - return tm.svc.UpdateConnections(ctx, session, token, id, connections) -} - -// List traces the "List" operation of the wrapped bootstrap.Service. -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)), - )) - defer span.End() - - return tm.svc.List(ctx, session, filter, offset, limit) -} - -// Remove traces the "Remove" operation of the wrapped bootstrap.Service. -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), - )) - defer span.End() - - return tm.svc.Remove(ctx, session, id) -} - -// Bootstrap traces the "Bootstrap" operation of the wrapped bootstrap.Service. -func (tm *tracingMiddleware) Bootstrap(ctx context.Context, externalKey, externalID string, secure bool) (bootstrap.Config, error) { - ctx, span := tm.tracer.Start(ctx, "svc_bootstrap_user", trace.WithAttributes( - attribute.String("external_key", externalKey), - attribute.String("external_id", externalID), - attribute.Bool("secure", secure), - )) - defer span.End() - - return tm.svc.Bootstrap(ctx, externalKey, externalID, secure) -} - -// ChangeState traces the "ChangeState" operation of the wrapped bootstrap.Service. -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()), - )) - defer span.End() - - return tm.svc.ChangeState(ctx, session, token, id, state) -} - -// UpdateChannelHandler traces the "UpdateChannelHandler" operation of the wrapped bootstrap.Service. -func (tm *tracingMiddleware) UpdateChannelHandler(ctx context.Context, channel bootstrap.Channel) error { - ctx, span := tm.tracer.Start(ctx, "svc_update_channel_handler", trace.WithAttributes( - attribute.String("id", channel.ID), - attribute.String("name", channel.Name), - attribute.String("description", channel.Description), - )) - defer span.End() - - return tm.svc.UpdateChannelHandler(ctx, channel) -} - -// RemoveConfigHandler traces the "RemoveConfigHandler" operation of the wrapped bootstrap.Service. -func (tm *tracingMiddleware) RemoveConfigHandler(ctx context.Context, id string) error { - ctx, span := tm.tracer.Start(ctx, "svc_remove_config_handler", trace.WithAttributes( - attribute.String("id", id), - )) - defer span.End() - - return tm.svc.RemoveConfigHandler(ctx, id) -} - -// RemoveChannelHandler traces the "RemoveChannelHandler" operation of the wrapped bootstrap.Service. -func (tm *tracingMiddleware) RemoveChannelHandler(ctx context.Context, id string) error { - ctx, span := tm.tracer.Start(ctx, "svc_remove_channel_handler", trace.WithAttributes( - attribute.String("id", id), - )) - defer span.End() - - return tm.svc.RemoveChannelHandler(ctx, id) -} - -// 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("client_id", clientID), - )) - defer span.End() - - return tm.svc.ConnectClientHandler(ctx, channelID, clientID) -} - -// 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("client_id", clientID), - )) - defer span.End() - - return tm.svc.DisconnectClientHandler(ctx, channelID, clientID) -} diff --git a/certs/api/logging.go b/certs/api/logging.go index 8291ed02c4..90af0a0ad5 100644 --- a/certs/api/logging.go +++ b/certs/api/logging.go @@ -20,7 +20,7 @@ type loggingMiddleware struct { svc certs.Service } -// LoggingMiddleware adds logging facilities to the bootstrap service. +// LoggingMiddleware adds logging facilities to the certs service. func LoggingMiddleware(svc certs.Service, logger *slog.Logger) certs.Service { return &loggingMiddleware{logger, svc} } diff --git a/cli/README.md b/cli/README.md index 339a3e53f8..0dadf0d99d 100644 --- a/cli/README.md +++ b/cli/README.md @@ -84,50 +84,6 @@ supermq-cli clients create '{"name":"myClient"}' supermq-cli clients create '{"name":"myClient", "metadata": {"key1":"value1"}}' ``` -#### Bulk Provision Clients - -```bash -supermq-cli provision clients -``` - -- `file` - A CSV or JSON file containing client names (must have extension `.csv` or `.json`) -- `user_token` - A valid user auth token for the current system - -An example CSV file might be: - -```csv -client1, -client2, -client3, -``` - -in which the first column is the client's name. - -A comparable JSON file would be - -```json -[ - { - "name": "", - "status": "enabled" - }, - { - "name": "", - "status": "disabled" - }, - { - "name": "", - "status": "enabled", - "credentials": { - "identity": "", - "secret": "" - } - } -] -``` - -With JSON you can be able to specify more fields of the channels you want to create - #### Update Client ```bash @@ -322,38 +278,6 @@ supermq-cli messages send '[{"bn":"Dev1","n":"temp","v":20}, {"n":" supermq-cli messages read -R ``` -### Bootstrap - -#### Add configuration - -```bash -supermq-cli bootstrap create '{"external_id": "myExtID", "external_key": "myExtKey", "name": "myName", "content": "myContent"}' -b -``` - -#### View configuration - -```bash -supermq-cli bootstrap get -b -``` - -#### Update configuration - -```bash -supermq-cli bootstrap update '{"client_id":"", "name": "newName", "content": "newContent"}' -b -``` - -#### Remove configuration - -```bash -supermq-cli bootstrap remove -b -``` - -#### Bootstrap configuration - -```bash -supermq-cli bootstrap bootstrap -b -``` - ### Groups #### Create Group diff --git a/cli/bootstrap.go b/cli/bootstrap.go deleted file mode 100644 index 94c06be210..0000000000 --- a/cli/bootstrap.go +++ /dev/null @@ -1,216 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package cli - -import ( - "encoding/json" - - smqsdk "github.com/absmach/supermq/pkg/sdk" - "github.com/spf13/cobra" -) - -var cmdBootstrap = []cobra.Command{ - { - Use: "create ", - Short: "Create config", - Long: `Create new Client Bootstrap Config to the user identified by the provided key`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { - logUsageCmd(*cmd, cmd.Use) - return - } - - var cfg smqsdk.BootstrapConfig - if err := json.Unmarshal([]byte(args[0]), &cfg); err != nil { - logErrorCmd(*cmd, err) - return - } - - id, err := sdk.AddBootstrap(cfg, args[1], args[2]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - logCreatedCmd(*cmd, id) - }, - }, - { - Use: "get [all | ] ", - Short: "Get config", - Long: `Get Client Config with given ID belonging to the user identified by the given key. - all - lists all config - - view config of `, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { - logUsageCmd(*cmd, cmd.Use) - return - } - pageMetadata := smqsdk.PageMetadata{ - Offset: Offset, - Limit: Limit, - State: State, - Name: Name, - } - if args[0] == "all" { - l, err := sdk.Bootstraps(pageMetadata, args[1], args[2]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - logJSONCmd(*cmd, l) - return - } - - c, err := sdk.ViewBootstrap(args[0], args[1], args[2]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - logJSONCmd(*cmd, c) - }, - }, - { - Use: "update [config | connection | certs ] ", - Short: "Update config", - Long: `Updates editable fields of the provided Config. - config - Updates editable fields of the provided Config. - connection - Updates connections performs update of the channel list corresponding Client is connected to. - channel_ids - '["channel_id1", ...]' - certs - Update bootstrap config certificates.`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) < 4 { - logUsageCmd(*cmd, cmd.Use) - return - } - if args[0] == "config" { - var cfg smqsdk.BootstrapConfig - if err := json.Unmarshal([]byte(args[1]), &cfg); err != nil { - logErrorCmd(*cmd, err) - return - } - - if err := sdk.UpdateBootstrap(cfg, args[1], args[2]); err != nil { - logErrorCmd(*cmd, err) - return - } - - logOKCmd(*cmd) - return - } - if args[0] == "connection" { - var ids []string - if err := json.Unmarshal([]byte(args[2]), &ids); err != nil { - logErrorCmd(*cmd, err) - return - } - if err := sdk.UpdateBootstrapConnection(args[1], ids, args[3], args[4]); err != nil { - logErrorCmd(*cmd, err) - return - } - - logOKCmd(*cmd) - return - } - if args[0] == "certs" { - cfg, err := sdk.UpdateBootstrapCerts(args[0], args[1], args[2], args[3], args[4], args[5]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - logJSONCmd(*cmd, cfg) - return - } - logUsageCmd(*cmd, cmd.Use) - }, - }, - { - Use: "remove ", - Short: "Remove config", - Long: `Removes Config with specified key that belongs to the user identified by the given key`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { - logUsageCmd(*cmd, cmd.Use) - return - } - - if err := sdk.RemoveBootstrap(args[0], args[1], args[2]); err != nil { - logErrorCmd(*cmd, err) - return - } - - logOKCmd(*cmd) - }, - }, - { - Use: "bootstrap [ | secure ]", - Short: "Bootstrap config", - Long: `Returns Config to the Client with provided external ID using external key. - secure - Retrieves a configuration with given external ID and encrypted external key.`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) < 2 { - logUsageCmd(*cmd, cmd.Use) - return - } - if args[0] == "secure" { - c, err := sdk.BootstrapSecure(args[1], args[2], args[3]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - logJSONCmd(*cmd, c) - return - } - c, err := sdk.Bootstrap(args[0], args[1]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - logJSONCmd(*cmd, c) - }, - }, - { - Use: "whitelist ", - Short: "Whitelist config", - Long: `Whitelist updates client state config with given id from the authenticated user`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { - logUsageCmd(*cmd, cmd.Use) - return - } - - var cfg smqsdk.BootstrapConfig - if err := json.Unmarshal([]byte(args[0]), &cfg); err != nil { - logErrorCmd(*cmd, err) - return - } - - if err := sdk.Whitelist(cfg.ClientID, cfg.State, args[1], args[2]); err != nil { - logErrorCmd(*cmd, err) - return - } - - logOKCmd(*cmd) - }, - }, -} - -// NewBootstrapCmd returns bootstrap command. -func NewBootstrapCmd() *cobra.Command { - cmd := cobra.Command{ - Use: "bootstrap [create | get | update | remove | bootstrap | whitelist]", - Short: "Bootstrap management", - Long: `Bootstrap management: create, get, update, delete or whitelist Bootstrap config`, - } - - for i := range cmdBootstrap { - cmd.AddCommand(&cmdBootstrap[i]) - } - - return &cmd -} diff --git a/cli/bootstrap_test.go b/cli/bootstrap_test.go deleted file mode 100644 index d64117b111..0000000000 --- a/cli/bootstrap_test.go +++ /dev/null @@ -1,622 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package cli_test - -import ( - "encoding/json" - "fmt" - "net/http" - "strings" - "testing" - - "github.com/absmach/supermq/cli" - "github.com/absmach/supermq/pkg/errors" - svcerr "github.com/absmach/supermq/pkg/errors/service" - mgsdk "github.com/absmach/supermq/pkg/sdk" - sdkmocks "github.com/absmach/supermq/pkg/sdk/mocks" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -var bootConfig = mgsdk.BootstrapConfig{ - ClientID: client.ID, - Channels: []string{channel.ID}, - Name: "Test Bootstrap", - ExternalID: "09:6:0:sb:sa", - ExternalKey: "key", -} - -func TestCreateBootstrapConfigCmd(t *testing.T) { - sdkMock := new(sdkmocks.SDK) - cli.SetSDK(sdkMock) - bootCmd := cli.NewBootstrapCmd() - rootCmd := setFlags(bootCmd) - - jsonConfig := fmt.Sprintf("{\"external_id\":\"09:6:0:sb:sa\", \"client_id\": \"%s\", \"external_key\":\"key\", \"name\": \"%s\", \"channels\":[\"%s\"]}", client.ID, "Test Bootstrap", channel.ID) - invalidJson := fmt.Sprintf("{\"external_id\":\"09:6:0:sb:sa\", \"client_id\": \"%s\", \"external_key\":\"key\", \"name\": \"%s\", \"channels\":[\"%s\"]", client.ID, "Test Bootdtrap", channel.ID) - cases := []struct { - desc string - args []string - logType outputLog - response string - sdkErr errors.SDKError - errLogMessage string - id string - }{ - { - desc: "create bootstrap config successfully", - args: []string{ - jsonConfig, - domainID, - validToken, - }, - logType: createLog, - id: client.ID, - response: fmt.Sprintf("\ncreated: %s\n\n", client.ID), - }, - { - desc: "create bootstrap config with invald args", - args: []string{ - jsonConfig, - domainID, - validToken, - extraArg, - }, - logType: usageLog, - }, - { - desc: "create bootstrap config with invald json", - args: []string{ - invalidJson, - domainID, - validToken, - }, - sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.New("unexpected end of JSON input")), - logType: errLog, - }, - { - desc: "create bootstrap config with invald token", - args: []string{ - jsonConfig, - domainID, - invalidToken, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized)), - logType: errLog, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("AddBootstrap", mock.Anything, mock.Anything, mock.Anything).Return(tc.id, tc.sdkErr) - out := executeCommand(t, rootCmd, append([]string{createCmd}, tc.args...)...) - - switch tc.logType { - case createLog: - assert.Equal(t, tc.response, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.response, out)) - case errLog: - assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) - case usageLog: - assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) - } - sdkCall.Unset() - }) - } -} - -func TestGetBootstrapConfigCmd(t *testing.T) { - sdkMock := new(sdkmocks.SDK) - cli.SetSDK(sdkMock) - bootCmd := cli.NewBootstrapCmd() - rootCmd := setFlags(bootCmd) - - var boot mgsdk.BootstrapConfig - var page mgsdk.BootstrapPage - - cases := []struct { - desc string - args []string - sdkErr errors.SDKError - page mgsdk.BootstrapPage - boot mgsdk.BootstrapConfig - logType outputLog - errLogMessage string - }{ - { - desc: "get all bootstrap config successfully", - args: []string{ - all, - domainID, - token, - }, - page: mgsdk.BootstrapPage{ - PageRes: mgsdk.PageRes{ - Total: 1, - Offset: 0, - Limit: 10, - }, - Configs: []mgsdk.BootstrapConfig{bootConfig}, - }, - logType: entityLog, - }, - { - desc: "get bootstrap config with id", - args: []string{ - channel.ID, - domainID, - token, - }, - logType: entityLog, - boot: bootConfig, - }, - { - desc: "get bootstrap config with invalid args", - args: []string{ - all, - domainID, - token, - extraArg, - }, - logType: usageLog, - }, - { - desc: "get all bootstrap config with invalid token", - args: []string{ - all, - domainID, - invalidToken, - }, - logType: errLog, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), - }, - { - desc: "get bootstrap config with invalid id", - args: []string{ - invalidID, - domainID, - token, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), - logType: errLog, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("ViewBootstrap", tc.args[0], tc.args[1], tc.args[2]).Return(tc.boot, tc.sdkErr) - sdkCall1 := sdkMock.On("Bootstraps", mock.Anything, tc.args[1], tc.args[2]).Return(tc.page, tc.sdkErr) - - out := executeCommand(t, rootCmd, append([]string{getCmd}, tc.args...)...) - - switch tc.logType { - case entityLog: - if tc.args[0] == all { - err := json.Unmarshal([]byte(out), &page) - assert.Nil(t, err) - assert.Equal(t, tc.page, page, fmt.Sprintf("%v unexpected response, expected: %v, got: %v", tc.desc, tc.page, page)) - } else { - err := json.Unmarshal([]byte(out), &boot) - assert.Nil(t, err) - assert.Equal(t, tc.boot, boot, fmt.Sprintf("%v unexpected response, expected: %v, got: %v", tc.desc, tc.boot, boot)) - } - case errLog: - assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) - case usageLog: - assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) - } - sdkCall.Unset() - sdkCall1.Unset() - }) - } -} - -func TestRemoveBootstrapConfigCmd(t *testing.T) { - sdkMock := new(sdkmocks.SDK) - cli.SetSDK(sdkMock) - bootCmd := cli.NewBootstrapCmd() - rootCmd := setFlags(bootCmd) - - cases := []struct { - desc string - args []string - sdkErr errors.SDKError - logType outputLog - errLogMessage string - }{ - { - desc: "remove bootstrap config successfully", - args: []string{ - client.ID, - domainID, - token, - }, - logType: okLog, - }, - { - desc: "remove bootstrap config with invalid args", - args: []string{ - client.ID, - domainID, - token, - extraArg, - }, - logType: usageLog, - }, - { - desc: "remove bootstrap config with invalid client id", - args: []string{ - invalidID, - domainID, - token, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), - logType: errLog, - }, - { - desc: "remove bootstrap config with invalid token", - args: []string{ - client.ID, - domainID, - invalidToken, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), - logType: errLog, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("RemoveBootstrap", tc.args[0], tc.args[1], tc.args[2]).Return(tc.sdkErr) - out := executeCommand(t, rootCmd, append([]string{rmCmd}, tc.args...)...) - - switch tc.logType { - case okLog: - assert.True(t, strings.Contains(out, "ok"), fmt.Sprintf("%s unexpected response: expected success message, got: %v", tc.desc, out)) - case errLog: - assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) - case usageLog: - assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) - } - sdkCall.Unset() - }) - } -} - -func TestUpdateBootstrapConfigCmd(t *testing.T) { - sdkMock := new(sdkmocks.SDK) - cli.SetSDK(sdkMock) - bootCmd := cli.NewBootstrapCmd() - rootCmd := setFlags(bootCmd) - - config := "config" - connection := "connection" - - newConfigJson := "{\"name\" : \"New Bootstrap\"}" - chanIDsJson := fmt.Sprintf("[\"%s\"]", channel.ID) - cases := []struct { - desc string - args []string - boot mgsdk.BootstrapConfig - sdkErr errors.SDKError - errLogMessage string - logType outputLog - }{ - { - desc: "update bootstrap config successfully", - args: []string{ - config, - newConfigJson, - domainID, - token, - }, - logType: okLog, - }, - { - desc: "update bootstrap config with invalid token", - args: []string{ - config, - newConfigJson, - domainID, - invalidToken, - }, - logType: errLog, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), - }, - { - desc: "update bootstrap connections successfully", - args: []string{ - connection, - client.ID, - chanIDsJson, - domainID, - token, - }, - logType: okLog, - }, - { - desc: "update bootstrap connections with invalid json", - args: []string{ - connection, - client.ID, - fmt.Sprintf("[\"%s\"", client.ID), - domainID, - token, - }, - sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.New("unexpected end of JSON input")), - logType: errLog, - }, - { - desc: "update bootstrap connections with invalid token", - args: []string{ - connection, - client.ID, - chanIDsJson, - domainID, - invalidToken, - }, - logType: errLog, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), - }, - { - desc: "update bootstrap certs successfully", - args: []string{ - "certs", - client.ID, - "client cert", - "client key", - "ca", - domainID, - token, - }, - boot: bootConfig, - logType: entityLog, - }, - { - desc: "update bootstrap certs with invalid token", - args: []string{ - "certs", - client.ID, - "client cert", - "client key", - "ca", - domainID, - invalidToken, - }, - logType: errLog, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusForbidden)), - }, - { - desc: "update bootstrap config with invalid args", - args: []string{ - newConfigJson, - domainID, - token, - }, - logType: usageLog, - }, - { - desc: "update bootstrap config with invalid json", - args: []string{ - config, - "{\"name\" : \"New Bootstrap\"", - domainID, - token, - }, - sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.New("unexpected end of JSON input")), - logType: errLog, - }, - { - desc: "update bootstrap with invalid args", - args: []string{ - extraArg, - extraArg, - extraArg, - extraArg, - extraArg, - }, - logType: usageLog, - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - var boot mgsdk.BootstrapConfig - sdkCall := sdkMock.On("UpdateBootstrap", mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) - sdkCall1 := sdkMock.On("UpdateBootstrapConnection", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.sdkErr) - sdkCall2 := sdkMock.On("UpdateBootstrapCerts", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.boot, tc.sdkErr) - out := executeCommand(t, rootCmd, append([]string{updCmd}, tc.args...)...) - - switch tc.logType { - case entityLog: - err := json.Unmarshal([]byte(out), &boot) - assert.Nil(t, err) - assert.Equal(t, tc.boot, boot, fmt.Sprintf("%s unexpected response: expected: %v, got: %v", tc.desc, tc.boot, boot)) - case okLog: - assert.True(t, strings.Contains(out, "ok"), fmt.Sprintf("%s unexpected response: expected success message, got: %v", tc.desc, out)) - case usageLog: - assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) - case errLog: - assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) - } - sdkCall.Unset() - sdkCall1.Unset() - sdkCall2.Unset() - }) - } -} - -func TestWhitelistConfigCmd(t *testing.T) { - sdkMock := new(sdkmocks.SDK) - cli.SetSDK(sdkMock) - bootCmd := cli.NewBootstrapCmd() - rootCmd := setFlags(bootCmd) - - jsonConfig := fmt.Sprintf("{\"client_id\": \"%s\", \"state\":%d}", client.ID, 1) - - cases := []struct { - desc string - args []string - logType outputLog - errLogMessage string - sdkErr errors.SDKError - }{ - { - desc: "whitelist config successfully", - args: []string{ - jsonConfig, - domainID, - validToken, - }, - logType: okLog, - }, - { - desc: "whitelist config with invalid args", - args: []string{ - jsonConfig, - domainID, - validToken, - extraArg, - }, - logType: usageLog, - }, - { - desc: "whitelist config with invalid json", - args: []string{ - fmt.Sprintf("{\"client_id\": \"%s\", \"state\":%d", client.ID, 1), - domainID, - validToken, - }, - sdkErr: errors.NewSDKError(errors.New("unexpected end of JSON input")), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.New("unexpected end of JSON input")), - logType: errLog, - }, - { - desc: "whitelist config with invalid token", - args: []string{ - jsonConfig, - domainID, - invalidToken, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized)), - logType: errLog, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("Whitelist", mock.Anything, mock.Anything, tc.args[1], tc.args[2]).Return(tc.sdkErr) - out := executeCommand(t, rootCmd, append([]string{whitelistCmd}, tc.args...)...) - switch tc.logType { - case okLog: - assert.True(t, strings.Contains(out, "ok"), fmt.Sprintf("%s unexpected response: expected success message, got: %v", tc.desc, out)) - case usageLog: - assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) - case errLog: - assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) - } - sdkCall.Unset() - }) - } -} - -func TestBootstrapConfigCmd(t *testing.T) { - sdkMock := new(sdkmocks.SDK) - cli.SetSDK(sdkMock) - bootCmd := cli.NewBootstrapCmd() - rootCmd := setFlags(bootCmd) - - var boot mgsdk.BootstrapConfig - crptoKey := "v7aT0HGxJxt2gULzr3RHwf4WIf6DusPp" - invalidKey := "invalid key" - cases := []struct { - desc string - args []string - logType outputLog - errLogMessage string - sdkErr errors.SDKError - boot mgsdk.BootstrapConfig - }{ - { - desc: "bootstrap secure config successfully", - args: []string{ - "secure", - bootConfig.ExternalID, - bootConfig.ExternalKey, - crptoKey, - }, - boot: bootConfig, - logType: entityLog, - }, - { - desc: "bootstrap config successfully", - args: []string{ - bootConfig.ExternalID, - bootConfig.ExternalKey, - }, - boot: bootConfig, - logType: entityLog, - }, - { - desc: "bootstrap secure config with invalid args", - args: []string{ - crptoKey, - }, - - logType: usageLog, - }, - { - desc: "bootstrap secure config with invalid key", - args: []string{ - "secure", - bootConfig.ExternalID, - invalidKey, - crptoKey, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized)), - logType: errLog, - }, - { - desc: "bootstrap config with invalid key", - args: []string{ - bootConfig.ExternalID, - invalidKey, - }, - sdkErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized), - errLogMessage: fmt.Sprintf("\nerror: %s\n\n", errors.NewSDKErrorWithStatus(svcerr.ErrAuthorization, http.StatusUnauthorized)), - logType: errLog, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - sdkCall := sdkMock.On("BootstrapSecure", mock.Anything, mock.Anything, mock.Anything).Return(tc.boot, tc.sdkErr) - sdkCall1 := sdkMock.On("Bootstrap", mock.Anything, mock.Anything).Return(tc.boot, tc.sdkErr) - out := executeCommand(t, rootCmd, append([]string{bootStrapCmd}, tc.args...)...) - switch tc.logType { - case entityLog: - err := json.Unmarshal([]byte(out), &boot) - assert.Nil(t, err) - assert.Equal(t, tc.boot, boot, fmt.Sprintf("%s unexpected response: expected: %v, got: %v", tc.desc, tc.boot, boot)) - case usageLog: - assert.False(t, strings.Contains(out, rootCmd.Use), fmt.Sprintf("%s invalid usage: %s", tc.desc, out)) - case errLog: - assert.Equal(t, tc.errLogMessage, out, fmt.Sprintf("%s unexpected error response: expected %s got errLogMessage:%s", tc.desc, tc.errLogMessage, out)) - } - sdkCall.Unset() - sdkCall1.Unset() - }) - } -} diff --git a/cli/commands_test.go b/cli/commands_test.go index 04cf2d75de..2842c041a3 100644 --- a/cli/commands_test.go +++ b/cli/commands_test.go @@ -59,12 +59,6 @@ const ( readCmd = "read" ) -// Bootstrap commands -const ( - whitelistCmd = "whitelist" - bootStrapCmd = "bootstrap" -) - // Invitations commands const ( acceptCmd = "accept" diff --git a/cli/config.go b/cli/config.go index 7a42a4eb0f..c7adab3305 100644 --- a/cli/config.go +++ b/cli/config.go @@ -22,7 +22,6 @@ const ( defUsersURL string = defURL + ":9002" defCLientsURL string = defURL + ":9000" defReaderURL string = defURL + ":9011" - defBootstrapURL string = defURL + ":9013" defDomainsURL string = defURL + ":8189" defCertsURL string = defURL + ":9019" defInvitationsURL string = defURL + ":9020" @@ -41,7 +40,6 @@ type remotes struct { ReaderURL string `toml:"reader_url"` DomainsURL string `toml:"domains_url"` HTTPAdapterURL string `toml:"http_adapter_url"` - BootstrapURL string `toml:"bootstrap_url"` CertsURL string `toml:"certs_url"` InvitationsURL string `toml:"invitations_url"` JournalURL string `toml:"journal_url"` @@ -112,7 +110,6 @@ func ParseConfig(sdkConf smqsdk.Config) (smqsdk.Config, error) { ReaderURL: defReaderURL, DomainsURL: defDomainsURL, HTTPAdapterURL: defHTTPURL, - BootstrapURL: defBootstrapURL, CertsURL: defCertsURL, InvitationsURL: defInvitationsURL, JournalURL: defJournalURL, @@ -191,10 +188,6 @@ func ParseConfig(sdkConf smqsdk.Config) (smqsdk.Config, error) { sdkConf.HTTPAdapterURL = config.Remotes.HTTPAdapterURL } - if sdkConf.BootstrapURL == "" && config.Remotes.BootstrapURL != "" { - sdkConf.BootstrapURL = config.Remotes.BootstrapURL - } - if sdkConf.CertsURL == "" && config.Remotes.CertsURL != "" { sdkConf.CertsURL = config.Remotes.CertsURL } @@ -262,7 +255,6 @@ func setConfigValue(key, value string) error { "users_url": &config.Remotes.UsersURL, "reader_url": &config.Remotes.ReaderURL, "http_adapter_url": &config.Remotes.HTTPAdapterURL, - "bootstrap_url": &config.Remotes.BootstrapURL, "certs_url": &config.Remotes.CertsURL, "tls_verification": &config.Remotes.TLSVerification, "offset": &config.Filter.Offset, diff --git a/cli/provision.go b/cli/provision.go deleted file mode 100644 index e1956753d6..0000000000 --- a/cli/provision.go +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package cli - -import ( - "encoding/csv" - "encoding/json" - "errors" - "fmt" - "io" - "math/rand" - "os" - "path/filepath" - "time" - - "github.com/0x6flab/namegenerator" - smqsdk "github.com/absmach/supermq/pkg/sdk" - "github.com/spf13/cobra" -) - -const ( - jsonExt = ".json" - csvExt = ".csv" - PublishType = "publish" - SubscribeType = "subscribe" -) - -var ( - msgFormat = `[{"bn":"provision:", "bu":"V", "t": %d, "bver":5, "n":"voltage", "u":"V", "v":%d}]` - namesgenerator = namegenerator.NewGenerator() -) - -var cmdProvision = []cobra.Command{ - { - Use: "clients ", - Short: "Provision clients", - Long: `Bulk create clients`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { - logUsageCmd(*cmd, cmd.Use) - return - } - - if _, err := os.Stat(args[0]); os.IsNotExist(err) { - logErrorCmd(*cmd, err) - return - } - - clients, err := clientsFromFile(args[0]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - clients, err = sdk.CreateClients(clients, args[1], args[2]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - logJSONCmd(*cmd, clients) - }, - }, - { - Use: "channels ", - Short: "Provision channels", - Long: `Bulk create channels`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { - logUsageCmd(*cmd, cmd.Use) - return - } - - channels, err := channelsFromFile(args[0]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - var chs []smqsdk.Channel - for _, c := range channels { - c, err = sdk.CreateChannel(c, args[1], args[2]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - chs = append(chs, c) - } - channels = chs - - logJSONCmd(*cmd, channels) - }, - }, - { - Use: "connect ", - Short: "Provision connections", - Long: `Bulk connect clients to channels`, - Run: func(cmd *cobra.Command, args []string) { - if len(args) != 3 { - logUsageCmd(*cmd, cmd.Use) - return - } - - connIDs, err := connectionsFromFile(args[0]) - if err != nil { - logErrorCmd(*cmd, err) - return - } - for _, conn := range connIDs { - if err := sdk.Connect(conn, args[1], args[2]); err != nil { - logErrorCmd(*cmd, err) - return - } - } - - logOKCmd(*cmd) - }, - }, - { - Use: "test", - Short: "test", - Long: `Provisions test setup: one test user, two clients and two channels. \ - Connect both clients to one of the channels, \ - and only on client to other channel.`, - Run: func(cmd *cobra.Command, args []string) { - numClients := 2 - numChan := 2 - clients := []smqsdk.Client{} - channels := []smqsdk.Channel{} - - if len(args) != 0 { - logUsageCmd(*cmd, cmd.Use) - return - } - - // Create test user - name := namesgenerator.Generate() - user := smqsdk.User{ - FirstName: name, - Email: fmt.Sprintf("%s@email.com", name), - Credentials: smqsdk.Credentials{ - Username: name, - Secret: "12345678", - }, - Status: smqsdk.EnabledStatus, - } - user, err := sdk.CreateUser(user, "") - if err != nil { - logErrorCmd(*cmd, err) - return - } - - ut, err := sdk.CreateToken(smqsdk.Login{Username: user.Credentials.Username, Password: user.Credentials.Secret}) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - // create domain - domain := smqsdk.Domain{ - Name: fmt.Sprintf("%s-domain", name), - Status: smqsdk.EnabledStatus, - } - domain, err = sdk.CreateDomain(domain, ut.AccessToken) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - ut, err = sdk.CreateToken(smqsdk.Login{Username: user.Email, Password: user.Credentials.Secret}) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - // Create clients - for i := 0; i < numClients; i++ { - t := smqsdk.Client{ - Name: fmt.Sprintf("%s-client-%d", name, i), - Status: smqsdk.EnabledStatus, - } - - clients = append(clients, t) - } - clients, err = sdk.CreateClients(clients, domain.ID, ut.AccessToken) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - // Create channels - for i := 0; i < numChan; i++ { - c := smqsdk.Channel{ - Name: fmt.Sprintf("%s-channel-%d", name, i), - Status: smqsdk.EnabledStatus, - } - c, err = sdk.CreateChannel(c, domain.ID, ut.AccessToken) - if err != nil { - logErrorCmd(*cmd, err) - return - } - - channels = append(channels, c) - } - - // Connect clients to channels - first client to both channels, second only to first - conIDs := smqsdk.Connection{ - ChannelIDs: []string{channels[0].ID}, - ClientIDs: []string{clients[0].ID}, - Types: []string{PublishType, SubscribeType}, - } - if err := sdk.Connect(conIDs, domain.ID, ut.AccessToken); err != nil { - logErrorCmd(*cmd, err) - return - } - - conIDs = smqsdk.Connection{ - ChannelIDs: []string{channels[1].ID}, - ClientIDs: []string{clients[0].ID}, - Types: []string{PublishType, SubscribeType}, - } - if err := sdk.Connect(conIDs, domain.ID, ut.AccessToken); err != nil { - logErrorCmd(*cmd, err) - return - } - - conIDs = smqsdk.Connection{ - ChannelIDs: []string{channels[0].ID}, - ClientIDs: []string{clients[1].ID}, - Types: []string{PublishType, SubscribeType}, - } - if err := sdk.Connect(conIDs, domain.ID, ut.AccessToken); err != nil { - logErrorCmd(*cmd, err) - return - } - - // send message to test connectivity - if err := sdk.SendMessage(channels[0].ID, fmt.Sprintf(msgFormat, time.Now().Unix(), rand.Int()), clients[0].Credentials.Secret); err != nil { - logErrorCmd(*cmd, err) - return - } - if err := sdk.SendMessage(channels[0].ID, fmt.Sprintf(msgFormat, time.Now().Unix(), rand.Int()), clients[1].Credentials.Secret); err != nil { - logErrorCmd(*cmd, err) - return - } - if err := sdk.SendMessage(channels[1].ID, fmt.Sprintf(msgFormat, time.Now().Unix(), rand.Int()), clients[0].Credentials.Secret); err != nil { - logErrorCmd(*cmd, err) - return - } - - logJSONCmd(*cmd, user, ut, clients, channels) - }, - }, -} - -// NewProvisionCmd returns provision command. -func NewProvisionCmd() *cobra.Command { - cmd := cobra.Command{ - Use: "provision [clients | channels | connect | test]", - Short: "Provision clients and channels from a config file", - Long: `Provision clients and channels: use json or csv file to bulk provision clients and channels`, - } - - for i := range cmdProvision { - cmd.AddCommand(&cmdProvision[i]) - } - - return &cmd -} - -func clientsFromFile(path string) ([]smqsdk.Client, error) { - if _, err := os.Stat(path); os.IsNotExist(err) { - return []smqsdk.Client{}, err - } - - file, err := os.OpenFile(path, os.O_RDONLY, os.ModePerm) - if err != nil { - return []smqsdk.Client{}, err - } - defer file.Close() - - clients := []smqsdk.Client{} - switch filepath.Ext(path) { - case csvExt: - reader := csv.NewReader(file) - - for { - l, err := reader.Read() - if err == io.EOF { - break - } - if err != nil { - return []smqsdk.Client{}, err - } - - if len(l) < 1 { - return []smqsdk.Client{}, errors.New("empty line found in file") - } - - client := smqsdk.Client{ - Name: l[0], - } - - clients = append(clients, client) - } - case jsonExt: - err := json.NewDecoder(file).Decode(&clients) - if err != nil { - return []smqsdk.Client{}, err - } - default: - return []smqsdk.Client{}, err - } - - return clients, nil -} - -func channelsFromFile(path string) ([]smqsdk.Channel, error) { - if _, err := os.Stat(path); os.IsNotExist(err) { - return []smqsdk.Channel{}, err - } - - file, err := os.OpenFile(path, os.O_RDONLY, os.ModePerm) - if err != nil { - return []smqsdk.Channel{}, err - } - defer file.Close() - - channels := []smqsdk.Channel{} - switch filepath.Ext(path) { - case csvExt: - reader := csv.NewReader(file) - - for { - l, err := reader.Read() - if err == io.EOF { - break - } - if err != nil { - return []smqsdk.Channel{}, err - } - - if len(l) < 1 { - return []smqsdk.Channel{}, errors.New("empty line found in file") - } - - channel := smqsdk.Channel{ - Name: l[0], - } - - channels = append(channels, channel) - } - case jsonExt: - err := json.NewDecoder(file).Decode(&channels) - if err != nil { - return []smqsdk.Channel{}, err - } - default: - return []smqsdk.Channel{}, err - } - - return channels, nil -} - -func connectionsFromFile(path string) ([]smqsdk.Connection, error) { - if _, err := os.Stat(path); os.IsNotExist(err) { - return []smqsdk.Connection{}, err - } - - file, err := os.OpenFile(path, os.O_RDONLY, os.ModePerm) - if err != nil { - return []smqsdk.Connection{}, err - } - defer file.Close() - - connections := []smqsdk.Connection{} - switch filepath.Ext(path) { - case csvExt: - reader := csv.NewReader(file) - - for { - l, err := reader.Read() - if err == io.EOF { - break - } - if err != nil { - return []smqsdk.Connection{}, err - } - - if len(l) < 1 { - return []smqsdk.Connection{}, errors.New("empty line found in file") - } - connections = append(connections, smqsdk.Connection{ - ClientIDs: []string{l[0]}, - ChannelIDs: []string{l[1]}, - Types: []string{PublishType, SubscribeType}, - }) - } - case jsonExt: - err := json.NewDecoder(file).Decode(&connections) - if err != nil { - return []smqsdk.Connection{}, err - } - default: - return []smqsdk.Connection{}, err - } - - return connections, nil -} diff --git a/cli/setup_test.go b/cli/setup_test.go index a34218f805..cfc73d232b 100644 --- a/cli/setup_test.go +++ b/cli/setup_test.go @@ -92,14 +92,6 @@ func setFlags(rootCmd *cobra.Command) *cobra.Command { "User status query parameter", ) - rootCmd.PersistentFlags().StringVarP( - &cli.State, - "state", - "z", - "", - "Bootstrap state query parameter", - ) - rootCmd.PersistentFlags().StringVarP( &cli.Topic, "topic", diff --git a/cmd/bootstrap/main.go b/cmd/bootstrap/main.go deleted file mode 100644 index 2476aab73c..0000000000 --- a/cmd/bootstrap/main.go +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package main contains bootstrap main function to start the bootstrap service. -package main - -import ( - "context" - "fmt" - "log" - "log/slog" - "net/url" - "os" - - chclient "github.com/absmach/callhome/pkg/client" - "github.com/absmach/supermq" - "github.com/absmach/supermq/bootstrap" - httpapi "github.com/absmach/supermq/bootstrap/api" - "github.com/absmach/supermq/bootstrap/events/consumer" - "github.com/absmach/supermq/bootstrap/events/producer" - "github.com/absmach/supermq/bootstrap/middleware" - bootstrappg "github.com/absmach/supermq/bootstrap/postgres" - "github.com/absmach/supermq/bootstrap/tracing" - smqlog "github.com/absmach/supermq/logger" - authsvcAuthn "github.com/absmach/supermq/pkg/authn/authsvc" - smqauthz "github.com/absmach/supermq/pkg/authz" - authsvcAuthz "github.com/absmach/supermq/pkg/authz/authsvc" - domainsAuthz "github.com/absmach/supermq/pkg/domains/grpcclient" - "github.com/absmach/supermq/pkg/events" - "github.com/absmach/supermq/pkg/events/store" - "github.com/absmach/supermq/pkg/grpcclient" - "github.com/absmach/supermq/pkg/jaeger" - "github.com/absmach/supermq/pkg/policies" - "github.com/absmach/supermq/pkg/policies/spicedb" - pgclient "github.com/absmach/supermq/pkg/postgres" - "github.com/absmach/supermq/pkg/prometheus" - mgsdk "github.com/absmach/supermq/pkg/sdk" - "github.com/absmach/supermq/pkg/server" - httpserver "github.com/absmach/supermq/pkg/server/http" - "github.com/absmach/supermq/pkg/uuid" - "github.com/authzed/authzed-go/v1" - "github.com/authzed/grpcutil" - "github.com/caarlos0/env/v11" - "github.com/jmoiron/sqlx" - "go.opentelemetry.io/otel/trace" - "golang.org/x/sync/errgroup" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" -) - -const ( - svcName = "bootstrap" - envPrefixDB = "SMQ_BOOTSTRAP_DB_" - envPrefixHTTP = "SMQ_BOOTSTRAP_HTTP_" - envPrefixAuth = "SMQ_AUTH_GRPC_" - envPrefixDomains = "SMQ_DOMAINS_GRPC_" - defDB = "bootstrap" - defSvcHTTPPort = "9013" - - stream = "events.supermq.clients" - streamID = "supermq.bootstrap" -) - -type config struct { - LogLevel string `env:"SMQ_BOOTSTRAP_LOG_LEVEL" envDefault:"info"` - EncKey string `env:"SMQ_BOOTSTRAP_ENCRYPT_KEY" envDefault:"12345678910111213141516171819202"` - ESConsumerName string `env:"SMQ_BOOTSTRAP_EVENT_CONSUMER" envDefault:"bootstrap"` - ClientsURL string `env:"SMQ_CLIENTS_URL" envDefault:"http://localhost:9000"` - JaegerURL url.URL `env:"SMQ_JAEGER_URL" envDefault:"http://localhost:4318/v1/traces"` - SendTelemetry bool `env:"SMQ_SEND_TELEMETRY" envDefault:"true"` - InstanceID string `env:"SMQ_BOOTSTRAP_INSTANCE_ID" envDefault:""` - ESURL string `env:"SMQ_ES_URL" envDefault:"nats://localhost:4222"` - TraceRatio float64 `env:"SMQ_JAEGER_TRACE_RATIO" envDefault:"1.0"` - SpicedbHost string `env:"SMQ_SPICEDB_HOST" envDefault:"localhost"` - SpicedbPort string `env:"SMQ_SPICEDB_PORT" envDefault:"50051"` - SpicedbPreSharedKey string `env:"SMQ_SPICEDB_PRE_SHARED_KEY" envDefault:"12345678"` -} - -func main() { - ctx, cancel := context.WithCancel(context.Background()) - g, ctx := errgroup.WithContext(ctx) - - cfg := config{} - if err := env.Parse(&cfg); err != nil { - log.Fatalf("failed to load %s configuration : %s", svcName, err) - } - - logger, err := smqlog.New(os.Stdout, cfg.LogLevel) - if err != nil { - log.Fatalf("failed to init logger: %s", err.Error()) - } - - var exitCode int - defer smqlog.ExitWithError(&exitCode) - - if cfg.InstanceID == "" { - if cfg.InstanceID, err = uuid.New().ID(); err != nil { - logger.Error(fmt.Sprintf("failed to generate instanceID: %s", err)) - exitCode = 1 - return - } - } - - // Create new postgres client - dbConfig := pgclient.Config{Name: defDB} - if err := env.ParseWithOptions(&dbConfig, env.Options{Prefix: envPrefixDB}); err != nil { - logger.Error(err.Error()) - } - db, err := pgclient.Setup(dbConfig, *bootstrappg.Migration()) - if err != nil { - logger.Error(err.Error()) - exitCode = 1 - return - } - defer db.Close() - - policySvc, err := newPolicyService(cfg, logger) - if err != nil { - logger.Error(err.Error()) - exitCode = 1 - return - } - logger.Info("Policy client successfully connected to spicedb gRPC server") - - tp, err := jaeger.NewProvider(ctx, svcName, cfg.JaegerURL, cfg.InstanceID, cfg.TraceRatio) - if err != nil { - logger.Error(fmt.Sprintf("failed to init Jaeger: %s", err)) - exitCode = 1 - return - } - defer func() { - if err := tp.Shutdown(ctx); err != nil { - logger.Error(fmt.Sprintf("error shutting down tracer provider: %v", err)) - } - }() - tracer := tp.Tracer(svcName) - - grpcCfg := grpcclient.Config{} - if err := env.ParseWithOptions(&grpcCfg, env.Options{Prefix: envPrefixAuth}); err != nil { - logger.Error(fmt.Sprintf("failed to load auth gRPC client configuration : %s", err)) - exitCode = 1 - return - } - authn, authnClient, err := authsvcAuthn.NewAuthentication(ctx, grpcCfg) - if err != nil { - logger.Error(err.Error()) - exitCode = 1 - return - } - logger.Info("AuthN successfully connected to auth gRPC server " + authnClient.Secure()) - defer authnClient.Close() - - domsGrpcCfg := grpcclient.Config{} - if err := env.ParseWithOptions(&domsGrpcCfg, env.Options{Prefix: envPrefixDomains}); err != nil { - logger.Error(fmt.Sprintf("failed to load domains gRPC client configuration : %s", err)) - exitCode = 1 - return - } - domainsAuthz, _, domainsHandler, err := domainsAuthz.NewAuthorization(ctx, domsGrpcCfg) - if err != nil { - logger.Error(err.Error()) - exitCode = 1 - return - } - defer domainsHandler.Close() - - authz, authzClient, err := authsvcAuthz.NewAuthorization(ctx, grpcCfg, domainsAuthz) - if err != nil { - logger.Error(err.Error()) - exitCode = 1 - return - } - defer authzClient.Close() - logger.Info("AuthZ successfully connected to auth gRPC server " + authzClient.Secure()) - - // Create new service - svc, err := newService(ctx, authz, policySvc, db, tracer, logger, cfg, dbConfig) - if err != nil { - logger.Error(fmt.Sprintf("failed to create %s service: %s", svcName, err)) - exitCode = 1 - return - } - - if err = subscribeToClientsES(ctx, svc, cfg, logger); err != nil { - logger.Error(fmt.Sprintf("failed to subscribe to clients event store: %s", err)) - exitCode = 1 - return - } - - logger.Info("Subscribed to Event Store") - - httpServerConfig := server.Config{Port: defSvcHTTPPort} - if err := env.ParseWithOptions(&httpServerConfig, env.Options{Prefix: envPrefixHTTP}); err != nil { - logger.Error(fmt.Sprintf("failed to load %s HTTP server configuration : %s", svcName, err)) - exitCode = 1 - return - } - hs := httpserver.NewServer(ctx, cancel, svcName, httpServerConfig, httpapi.MakeHandler(svc, authn, bootstrap.NewConfigReader([]byte(cfg.EncKey)), logger, cfg.InstanceID), logger) - - if cfg.SendTelemetry { - chc := chclient.New(svcName, supermq.Version, logger, cancel) - go chc.CallHome(ctx) - } - - // Start servers - g.Go(func() error { - return hs.Start() - }) - g.Go(func() error { - return server.StopSignalHandler(ctx, cancel, logger, svcName, hs) - }) - - if err := g.Wait(); err != nil { - logger.Error(fmt.Sprintf("Bootstrap service terminated: %s", err)) - } -} - -func newService(ctx context.Context, authz smqauthz.Authorization, policySvc policies.Service, db *sqlx.DB, tracer trace.Tracer, logger *slog.Logger, cfg config, dbConfig pgclient.Config) (bootstrap.Service, error) { - database := pgclient.NewDatabase(db, dbConfig, tracer) - - repoConfig := bootstrappg.NewConfigRepository(database, logger) - - config := mgsdk.Config{ - ClientsURL: cfg.ClientsURL, - } - - sdk := mgsdk.NewSDK(config) - idp := uuid.New() - - svc := bootstrap.New(policySvc, repoConfig, sdk, []byte(cfg.EncKey), idp) - - publisher, err := store.NewPublisher(ctx, cfg.ESURL, streamID) - if err != nil { - return nil, err - } - - svc = middleware.AuthorizationMiddleware(svc, authz) - svc = producer.NewEventStoreMiddleware(svc, publisher) - svc = middleware.LoggingMiddleware(svc, logger) - counter, latency := prometheus.MakeMetrics(svcName, "api") - svc = middleware.MetricsMiddleware(svc, counter, latency) - svc = tracing.New(svc, tracer) - - return svc, nil -} - -func subscribeToClientsES(ctx context.Context, svc bootstrap.Service, cfg config, logger *slog.Logger) error { - subscriber, err := store.NewSubscriber(ctx, cfg.ESURL, logger) - if err != nil { - return err - } - - subConfig := events.SubscriberConfig{ - Stream: stream, - Consumer: cfg.ESConsumerName, - Handler: consumer.NewEventHandler(svc), - } - return subscriber.Subscribe(ctx, subConfig) -} - -func newPolicyService(cfg config, logger *slog.Logger) (policies.Service, error) { - client, err := authzed.NewClientWithExperimentalAPIs( - fmt.Sprintf("%s:%s", cfg.SpicedbHost, cfg.SpicedbPort), - grpc.WithTransportCredentials(insecure.NewCredentials()), - grpcutil.WithInsecureBearerToken(cfg.SpicedbPreSharedKey), - ) - if err != nil { - return nil, err - } - policySvc := spicedb.NewPolicyService(client, logger) - - return policySvc, nil -} diff --git a/cmd/cli/main.go b/cmd/cli/main.go index a261527887..d7b6526fa8 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -41,8 +41,6 @@ func main() { groupsCmd := cli.NewGroupsCmd() channelsCmd := cli.NewChannelsCmd() messagesCmd := cli.NewMessagesCmd() - provisionCmd := cli.NewProvisionCmd() - bootstrapCmd := cli.NewBootstrapCmd() certsCmd := cli.NewCertsCmd() subscriptionsCmd := cli.NewSubscriptionCmd() configCmd := cli.NewConfigCmd() @@ -57,8 +55,6 @@ func main() { rootCmd.AddCommand(clientsCmd) rootCmd.AddCommand(channelsCmd) rootCmd.AddCommand(messagesCmd) - rootCmd.AddCommand(provisionCmd) - rootCmd.AddCommand(bootstrapCmd) rootCmd.AddCommand(certsCmd) rootCmd.AddCommand(subscriptionsCmd) rootCmd.AddCommand(configCmd) @@ -66,14 +62,6 @@ func main() { rootCmd.AddCommand(journalCmd) // Root Flags - rootCmd.PersistentFlags().StringVarP( - &sdkConf.BootstrapURL, - "bootstrap-url", - "b", - sdkConf.BootstrapURL, - "Bootstrap service URL", - ) - rootCmd.PersistentFlags().StringVarP( &sdkConf.CertsURL, "certs-url", @@ -234,14 +222,6 @@ func main() { "User status query parameter", ) - rootCmd.PersistentFlags().StringVarP( - &cli.State, - "state", - "z", - "", - "Bootstrap state query parameter", - ) - rootCmd.PersistentFlags().StringVarP( &cli.Topic, "topic", diff --git a/cmd/provision/main.go b/cmd/provision/main.go deleted file mode 100644 index 6c126a83bf..0000000000 --- a/cmd/provision/main.go +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package main contains provision main function to start the provision service. -package main - -import ( - "context" - "encoding/json" - "fmt" - "log" - "os" - "reflect" - - chclient "github.com/absmach/callhome/pkg/client" - "github.com/absmach/supermq" - "github.com/absmach/supermq/channels" - "github.com/absmach/supermq/clients" - smqlog "github.com/absmach/supermq/logger" - "github.com/absmach/supermq/pkg/errors" - mgsdk "github.com/absmach/supermq/pkg/sdk" - "github.com/absmach/supermq/pkg/server" - httpserver "github.com/absmach/supermq/pkg/server/http" - "github.com/absmach/supermq/pkg/uuid" - "github.com/absmach/supermq/provision" - httpapi "github.com/absmach/supermq/provision/api" - "github.com/caarlos0/env/v11" - "golang.org/x/sync/errgroup" -) - -const ( - svcName = "provision" - contentType = "application/json" -) - -var ( - errMissingConfigFile = errors.New("missing config file setting") - errFailLoadingConfigFile = errors.New("failed to load config from file") - errFailedToReadBootstrapContent = errors.New("failed to read bootstrap content from envs") -) - -func main() { - ctx, cancel := context.WithCancel(context.Background()) - g, ctx := errgroup.WithContext(ctx) - - cfg, err := loadConfig() - if err != nil { - log.Fatalf("failed to load %s configuration : %s", svcName, err) - } - - logger, err := smqlog.New(os.Stdout, cfg.Server.LogLevel) - if err != nil { - log.Fatalf("failed to init logger: %s", err.Error()) - } - - var exitCode int - defer smqlog.ExitWithError(&exitCode) - - if cfg.InstanceID == "" { - if cfg.InstanceID, err = uuid.New().ID(); err != nil { - logger.Error(fmt.Sprintf("failed to generate instanceID: %s", err)) - exitCode = 1 - return - } - } - - if cfgFromFile, err := loadConfigFromFile(cfg.File); err != nil { - logger.Warn(fmt.Sprintf("Continue with settings from env, failed to load from: %s: %s", cfg.File, err)) - } else { - // Merge environment variables and file settings. - mergeConfigs(&cfgFromFile, &cfg) - cfg = cfgFromFile - logger.Info("Continue with settings from file: " + cfg.File) - } - - SDKCfg := mgsdk.Config{ - UsersURL: cfg.Server.UsersURL, - ClientsURL: cfg.Server.ClientsURL, - BootstrapURL: cfg.Server.MgBSURL, - CertsURL: cfg.Server.MgCertsURL, - MsgContentType: contentType, - TLSVerification: cfg.Server.TLS, - } - SDK := mgsdk.NewSDK(SDKCfg) - - svc := provision.New(cfg, SDK, logger) - svc = httpapi.NewLoggingMiddleware(svc, logger) - - httpServerConfig := server.Config{Host: "", Port: cfg.Server.HTTPPort, KeyFile: cfg.Server.ServerKey, CertFile: cfg.Server.ServerCert} - hs := httpserver.NewServer(ctx, cancel, svcName, httpServerConfig, httpapi.MakeHandler(svc, logger, cfg.InstanceID), logger) - - if cfg.SendTelemetry { - chc := chclient.New(svcName, supermq.Version, logger, cancel) - go chc.CallHome(ctx) - } - - g.Go(func() error { - return hs.Start() - }) - - g.Go(func() error { - return server.StopSignalHandler(ctx, cancel, logger, svcName, hs) - }) - - if err := g.Wait(); err != nil { - logger.Error(fmt.Sprintf("Provision service terminated: %s", err)) - } -} - -func loadConfigFromFile(file string) (provision.Config, error) { - _, err := os.Stat(file) - if os.IsNotExist(err) { - return provision.Config{}, errors.Wrap(errMissingConfigFile, err) - } - c, err := provision.Read(file) - if err != nil { - return provision.Config{}, errors.Wrap(errFailLoadingConfigFile, err) - } - return c, nil -} - -func loadConfig() (provision.Config, error) { - cfg := provision.Config{} - if err := env.Parse(&cfg); err != nil { - return provision.Config{}, err - } - - if cfg.Bootstrap.AutoWhiteList && !cfg.Bootstrap.Provision { - return provision.Config{}, errors.New("Can't auto whitelist if auto config save is off") - } - - var content map[string]interface{} - if cfg.BSContent != "" { - if err := json.Unmarshal([]byte(cfg.BSContent), &content); err != nil { - return provision.Config{}, errFailedToReadBootstrapContent - } - } - - cfg.Bootstrap.Content = content - // This is default conf for provision if there is no config file - cfg.Channels = []channels.Channel{ - { - Name: "control-channel", - Metadata: map[string]interface{}{"type": "control"}, - }, { - Name: "data-channel", - Metadata: map[string]interface{}{"type": "data"}, - }, - } - cfg.Clients = []clients.Client{ - { - Name: "client", - Metadata: map[string]interface{}{"external_id": "xxxxxx"}, - }, - } - - return cfg, nil -} - -func mergeConfigs(dst, src interface{}) interface{} { - d := reflect.ValueOf(dst).Elem() - s := reflect.ValueOf(src).Elem() - - for i := 0; i < d.NumField(); i++ { - dField := d.Field(i) - sField := s.Field(i) - switch dField.Kind() { - case reflect.Struct: - dst := dField.Addr().Interface() - src := sField.Addr().Interface() - m := mergeConfigs(dst, src) - val := reflect.ValueOf(m).Elem().Interface() - dField.Set(reflect.ValueOf(val)) - case reflect.Slice: - case reflect.Bool: - if dField.Interface() == false { - dField.Set(reflect.ValueOf(sField.Interface())) - } - case reflect.Int: - if dField.Interface() == 0 { - dField.Set(reflect.ValueOf(sField.Interface())) - } - case reflect.String: - if dField.Interface() == "" { - dField.Set(reflect.ValueOf(sField.Interface())) - } - } - } - return dst -} diff --git a/config.toml b/config.toml index cd96a917f8..5b66d5a4dc 100644 --- a/config.toml +++ b/config.toml @@ -11,7 +11,6 @@ user_token = "" [remotes] journal_url = "http://localhost:9021" - bootstrap_url = "http://localhost:9013" certs_url = "http://localhost:9019" domains_url = "http://localhost:8189" host_url = "http://localhost" diff --git a/docker/.env b/docker/.env index 769bf6299b..1717d2f173 100644 --- a/docker/.env +++ b/docker/.env @@ -381,48 +381,6 @@ SMQ_WS_ADAPTER_HTTP_SERVER_KEY= SMQ_WS_ADAPTER_INSTANCE_ID= ## Addons Services -### Bootstrap -SMQ_BOOTSTRAP_LOG_LEVEL=debug -SMQ_BOOTSTRAP_ENCRYPT_KEY=v7aT0HGxJxt2gULzr3RHwf4WIf6DusPp -SMQ_BOOTSTRAP_EVENT_CONSUMER=bootstrap -SMQ_BOOTSTRAP_HTTP_HOST=bootstrap -SMQ_BOOTSTRAP_HTTP_PORT=9013 -SMQ_BOOTSTRAP_HTTP_SERVER_CERT= -SMQ_BOOTSTRAP_HTTP_SERVER_KEY= -SMQ_BOOTSTRAP_DB_HOST=bootstrap-db -SMQ_BOOTSTRAP_DB_PORT=5432 -SMQ_BOOTSTRAP_DB_USER=supermq -SMQ_BOOTSTRAP_DB_PASS=supermq -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_INSTANCE_ID= - -### Provision -SMQ_PROVISION_CONFIG_FILE=/configs/config.toml -SMQ_PROVISION_LOG_LEVEL=debug -SMQ_PROVISION_HTTP_PORT=9016 -SMQ_PROVISION_ENV_CLIENTS_TLS=false -SMQ_PROVISION_SERVER_CERT= -SMQ_PROVISION_SERVER_KEY= -SMQ_PROVISION_USERS_LOCATION=http://users:9002 -SMQ_PROVISION_CLIENTS_LOCATION=http://clients:9006 -SMQ_PROVISION_USER= -SMQ_PROVISION_USERNAME= -SMQ_PROVISION_PASS= -SMQ_PROVISION_API_KEY= -SMQ_PROVISION_CERTS_SVC_URL=http://certs:9019 -SMQ_PROVISION_X509_PROVISIONING=false -SMQ_PROVISION_BS_SVC_URL=http://bootstrap:9013 -SMQ_PROVISION_BS_CONFIG_PROVISIONING=true -SMQ_PROVISION_BS_AUTO_WHITELIST=true -SMQ_PROVISION_BS_CONTENT= -SMQ_PROVISION_CERTS_HOURS_VALID=2400h -SMQ_PROVISION_CERTS_RSA_BITS=2048 -SMQ_PROVISION_INSTANCE_ID= - ### Vault SMQ_VAULT_HOST=vault SMQ_VAULT_PORT=8200 diff --git a/docker/addons/bootstrap/docker-compose.yml b/docker/addons/bootstrap/docker-compose.yml deleted file mode 100644 index 1065a2f2c7..0000000000 --- a/docker/addons/bootstrap/docker-compose.yml +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (c) Abstract Machines -# SPDX-License-Identifier: Apache-2.0 - -# This docker-compose file contains optional bootstrap services. Since it's optional, this file is -# dependent of docker-compose file from /docker. In order to run this services, execute command: -# docker compose -f docker/docker-compose.yml -f docker/addons/bootstrap/docker-compose.yml up -# from project root. - -networks: - supermq-base-net: - -volumes: - supermq-bootstrap-db-volume: - -services: - bootstrap-db: - image: postgres:16.2-alpine - container_name: supermq-bootstrap-db - restart: on-failure - environment: - POSTGRES_USER: ${SMQ_BOOTSTRAP_DB_USER} - POSTGRES_PASSWORD: ${SMQ_BOOTSTRAP_DB_PASS} - POSTGRES_DB: ${SMQ_BOOTSTRAP_DB_NAME} - networks: - - supermq-base-net - volumes: - - supermq-bootstrap-db-volume:/var/lib/postgresql/data - - bootstrap: - image: supermq/bootstrap:${SMQ_RELEASE_TAG} - container_name: supermq-bootstrap - depends_on: - - bootstrap-db - restart: on-failure - ports: - - ${SMQ_BOOTSTRAP_HTTP_PORT}:${SMQ_BOOTSTRAP_HTTP_PORT} - environment: - SMQ_BOOTSTRAP_LOG_LEVEL: ${SMQ_BOOTSTRAP_LOG_LEVEL} - SMQ_BOOTSTRAP_ENCRYPT_KEY: ${SMQ_BOOTSTRAP_ENCRYPT_KEY} - SMQ_BOOTSTRAP_EVENT_CONSUMER: ${SMQ_BOOTSTRAP_EVENT_CONSUMER} - SMQ_ES_URL: ${SMQ_ES_URL} - SMQ_BOOTSTRAP_HTTP_HOST: ${SMQ_BOOTSTRAP_HTTP_HOST} - SMQ_BOOTSTRAP_HTTP_PORT: ${SMQ_BOOTSTRAP_HTTP_PORT} - SMQ_BOOTSTRAP_HTTP_SERVER_CERT: ${SMQ_BOOTSTRAP_HTTP_SERVER_CERT} - SMQ_BOOTSTRAP_HTTP_SERVER_KEY: ${SMQ_BOOTSTRAP_HTTP_SERVER_KEY} - SMQ_BOOTSTRAP_DB_HOST: ${SMQ_BOOTSTRAP_DB_HOST} - SMQ_BOOTSTRAP_DB_PORT: ${SMQ_BOOTSTRAP_DB_PORT} - SMQ_BOOTSTRAP_DB_USER: ${SMQ_BOOTSTRAP_DB_USER} - SMQ_BOOTSTRAP_DB_PASS: ${SMQ_BOOTSTRAP_DB_PASS} - SMQ_BOOTSTRAP_DB_NAME: ${SMQ_BOOTSTRAP_DB_NAME} - SMQ_BOOTSTRAP_DB_SSL_MODE: ${SMQ_BOOTSTRAP_DB_SSL_MODE} - SMQ_BOOTSTRAP_DB_SSL_CERT: ${SMQ_BOOTSTRAP_DB_SSL_CERT} - SMQ_BOOTSTRAP_DB_SSL_KEY: ${SMQ_BOOTSTRAP_DB_SSL_KEY} - SMQ_BOOTSTRAP_DB_SSL_ROOT_CERT: ${SMQ_BOOTSTRAP_DB_SSL_ROOT_CERT} - SMQ_AUTH_GRPC_URL: ${SMQ_AUTH_GRPC_URL} - SMQ_AUTH_GRPC_TIMEOUT: ${SMQ_AUTH_GRPC_TIMEOUT} - SMQ_AUTH_GRPC_CLIENT_CERT: ${SMQ_AUTH_GRPC_CLIENT_CERT:+/auth-grpc-client.crt} - SMQ_AUTH_GRPC_CLIENT_KEY: ${SMQ_AUTH_GRPC_CLIENT_KEY:+/auth-grpc-client.key} - SMQ_AUTH_GRPC_SERVER_CA_CERTS: ${SMQ_AUTH_GRPC_SERVER_CA_CERTS:+/auth-grpc-server-ca.crt} - SMQ_CLIENTS_URL: ${SMQ_CLIENTS_URL} - SMQ_JAEGER_URL: ${SMQ_JAEGER_URL} - SMQ_JAEGER_TRACE_RATIO: ${SMQ_JAEGER_TRACE_RATIO} - SMQ_SEND_TELEMETRY: ${SMQ_SEND_TELEMETRY} - SMQ_BOOTSTRAP_INSTANCE_ID: ${SMQ_BOOTSTRAP_INSTANCE_ID} - SMQ_SPICEDB_PRE_SHARED_KEY: ${SMQ_SPICEDB_PRE_SHARED_KEY} - SMQ_SPICEDB_HOST: ${SMQ_SPICEDB_HOST} - SMQ_SPICEDB_PORT: ${SMQ_SPICEDB_PORT} - SMQ_DOMAINS_GRPC_URL: ${SMQ_DOMAINS_GRPC_URL} - SMQ_DOMAINS_GRPC_TIMEOUT: ${SMQ_DOMAINS_GRPC_TIMEOUT} - SMQ_DOMAINS_GRPC_CLIENT_CERT: ${SMQ_DOMAINS_GRPC_CLIENT_CERT:+/domains-grpc-client.crt} - SMQ_DOMAINS_GRPC_CLIENT_KEY: ${SMQ_DOMAINS_GRPC_CLIENT_KEY:+/domains-grpc-client.key} - SMQ_DOMAINS_GRPC_SERVER_CA_CERTS: ${SMQ_DOMAINS_GRPC_SERVER_CA_CERTS:+/domains-grpc-server-ca.crt} - networks: - - supermq-base-net - volumes: - - type: bind - source: ${SMQ_ADDONS_CERTS_PATH_PREFIX}${SMQ_AUTH_GRPC_CLIENT_CERT:-./ssl/certs/dummy/client_cert} - target: /auth-grpc-client${SMQ_AUTH_GRPC_CLIENT_CERT:+.crt} - bind: - create_host_path: true - - type: bind - source: ${SMQ_ADDONS_CERTS_PATH_PREFIX}${SMQ_AUTH_GRPC_CLIENT_KEY:-./ssl/certs/dummy/client_key} - target: /auth-grpc-client${SMQ_AUTH_GRPC_CLIENT_KEY:+.key} - bind: - create_host_path: true - - type: bind - source: ${SMQ_ADDONS_CERTS_PATH_PREFIX}${SMQ_AUTH_GRPC_SERVER_CA_CERTS:-./ssl/certs/dummy/server_ca} - target: /auth-grpc-server-ca${SMQ_AUTH_GRPC_SERVER_CA_CERTS:+.crt} - bind: - create_host_path: true diff --git a/docker/addons/provision/configs/config.toml b/docker/addons/provision/configs/config.toml deleted file mode 100644 index 70e3114951..0000000000 --- a/docker/addons/provision/configs/config.toml +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (c) Abstract Machines -# SPDX-License-Identifier: Apache-2.0 - -[bootstrap] - [bootstrap.content] - [bootstrap.content.agent.edgex] - url = "http://localhost:48090/api/v1/" - - [bootstrap.content.agent.log] - level = "info" - - [bootstrap.content.agent.mqtt] - mtls = false - qos = 0 - retain = false - skip_tls_ver = true - url = "localhost:1883" - - [bootstrap.content.agent.server] - nats_url = "localhost:4222" - port = "9000" - - [bootstrap.content.agent.heartbeat] - interval = "30s" - - [bootstrap.content.agent.terminal] - session_timeout = "30s" - - - [bootstrap.content.export.exp] - log_level = "debug" - nats = "nats://localhost:4222" - port = "8172" - cache_url = "localhost:6379" - cache_pass = "" - cache_db = "0" - - [bootstrap.content.export.mqtt] - ca_path = "ca.crt" - cert_path = "client.crt" - channel = "" - host = "tcp://localhost:1883" - mtls = false - password = "" - priv_key_path = "client.key" - qos = 0 - retain = false - skip_tls_ver = false - username = "" - - [[bootstrap.content.export.routes]] - mqtt_topic = "" - nats_topic = ">" - subtopic = "" - type = "plain" - workers = 10 - -[[clients]] - name = "client" - - [clients.metadata] - external_id = "xxxxxx" - -[[channels]] - name = "control-channel" - - [channels.metadata] - type = "control" - -[[channels]] - name = "data-channel" - - [channels.metadata] - type = "data" diff --git a/docker/addons/provision/docker-compose.yml b/docker/addons/provision/docker-compose.yml deleted file mode 100644 index 58198977a0..0000000000 --- a/docker/addons/provision/docker-compose.yml +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright (c) Abstract Machines -# SPDX-License-Identifier: Apache-2.0 - -# This docker-compose file contains optional provision services. Since it's optional, this file is -# dependent of docker-compose file from /docker. In order to run this services, execute command: -# docker compose -f docker/docker-compose.yml -f docker/addons/provision/docker-compose.yml up -# from project root. - -networks: - supermq-base-net: - -services: - provision: - image: supermq/provision:${SMQ_RELEASE_TAG} - container_name: supermq-provision - restart: on-failure - networks: - - supermq-base-net - ports: - - ${SMQ_PROVISION_HTTP_PORT}:${SMQ_PROVISION_HTTP_PORT} - environment: - SMQ_PROVISION_LOG_LEVEL: ${SMQ_PROVISION_LOG_LEVEL} - SMQ_PROVISION_HTTP_PORT: ${SMQ_PROVISION_HTTP_PORT} - SMQ_PROVISION_CONFIG_FILE: ${SMQ_PROVISION_CONFIG_FILE} - SMQ_PROVISION_ENV_CLIENTS_TLS: ${SMQ_PROVISION_ENV_CLIENTS_TLS} - SMQ_PROVISION_SERVER_CERT: ${SMQ_PROVISION_SERVER_CERT} - SMQ_PROVISION_SERVER_KEY: ${SMQ_PROVISION_SERVER_KEY} - SMQ_PROVISION_USERS_LOCATION: ${SMQ_PROVISION_USERS_LOCATION} - SMQ_PROVISION_CLIENTS_LOCATION: ${SMQ_PROVISION_CLIENTS_LOCATION} - SMQ_PROVISION_USER: ${SMQ_PROVISION_USER} - SMQ_PROVISION_USERNAME: ${SMQ_PROVISION_USERNAME} - SMQ_PROVISION_PASS: ${SMQ_PROVISION_PASS} - SMQ_PROVISION_API_KEY: ${SMQ_PROVISION_API_KEY} - SMQ_PROVISION_CERTS_SVC_URL: ${SMQ_PROVISION_CERTS_SVC_URL} - SMQ_PROVISION_X509_PROVISIONING: ${SMQ_PROVISION_X509_PROVISIONING} - SMQ_PROVISION_BS_SVC_URL: ${SMQ_PROVISION_BS_SVC_URL} - SMQ_PROVISION_BS_CONFIG_PROVISIONING: ${SMQ_PROVISION_BS_CONFIG_PROVISIONING} - SMQ_PROVISION_BS_AUTO_WHITELIST: ${SMQ_PROVISION_BS_AUTO_WHITELIST} - SMQ_PROVISION_BS_CONTENT: ${SMQ_PROVISION_BS_CONTENT} - SMQ_PROVISION_CERTS_HOURS_VALID: ${SMQ_PROVISION_CERTS_HOURS_VALID} - SMQ_SEND_TELEMETRY: ${SMQ_SEND_TELEMETRY} - SMQ_PROVISION_INSTANCE_ID: ${SMQ_PROVISION_INSTANCE_ID} - volumes: - - ./configs:/configs - - ../../ssl/certs/ca.key:/etc/ssl/certs/ca.key - - ../../ssl/certs/ca.crt:/etc/ssl/certs/ca.crt diff --git a/pkg/sdk/bootstrap.go b/pkg/sdk/bootstrap.go deleted file mode 100644 index 8a21e0437b..0000000000 --- a/pkg/sdk/bootstrap.go +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package sdk - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/hex" - "encoding/json" - "fmt" - "io" - "net/http" - "strings" - - apiutil "github.com/absmach/supermq/api/http/util" - "github.com/absmach/supermq/pkg/errors" -) - -const ( - configsEndpoint = "clients/configs" - bootstrapEndpoint = "clients/bootstrap" - whitelistEndpoint = "clients/state" - bootstrapCertsEndpoint = "clients/configs/certs" - bootstrapConnEndpoint = "clients/configs/connections" - secureEndpoint = "secure" -) - -// BootstrapConfig represents Configuration entity. It wraps information about external entity -// 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 BootstrapConfig struct { - Channels interface{} `json:"channels,omitempty"` - ExternalID string `json:"external_id,omitempty"` - ExternalKey string `json:"external_key,omitempty"` - ClientID string `json:"client_id,omitempty"` - ClientSecret string `json:"client_secret,omitempty"` - Name string `json:"name,omitempty"` - ClientCert string `json:"client_cert,omitempty"` - ClientKey string `json:"client_key,omitempty"` - CACert string `json:"ca_cert,omitempty"` - Content string `json:"content,omitempty"` - State int `json:"state,omitempty"` -} - -func (ts *BootstrapConfig) UnmarshalJSON(data []byte) error { - var rawData map[string]json.RawMessage - if err := json.Unmarshal(data, &rawData); err != nil { - return err - } - - if channelData, ok := rawData["channels"]; ok { - var stringData []string - if err := json.Unmarshal(channelData, &stringData); err == nil { - ts.Channels = stringData - } else { - var channels []Channel - if err := json.Unmarshal(channelData, &channels); err == nil { - ts.Channels = channels - } else { - return fmt.Errorf("unsupported channel data type") - } - } - } - - if err := json.Unmarshal(data, &struct { - ExternalID *string `json:"external_id,omitempty"` - ExternalKey *string `json:"external_key,omitempty"` - ClientID *string `json:"client_id,omitempty"` - ClientSecret *string `json:"client_secret,omitempty"` - Name *string `json:"name,omitempty"` - ClientCert *string `json:"client_cert,omitempty"` - ClientKey *string `json:"client_key,omitempty"` - CACert *string `json:"ca_cert,omitempty"` - Content *string `json:"content,omitempty"` - State *int `json:"state,omitempty"` - }{ - ExternalID: &ts.ExternalID, - ExternalKey: &ts.ExternalKey, - ClientID: &ts.ClientID, - ClientSecret: &ts.ClientSecret, - Name: &ts.Name, - ClientCert: &ts.ClientCert, - ClientKey: &ts.ClientKey, - CACert: &ts.CACert, - Content: &ts.Content, - State: &ts.State, - }); err != nil { - return err - } - - return nil -} - -func (sdk mgSDK) AddBootstrap(cfg BootstrapConfig, domainID, token string) (string, errors.SDKError) { - data, err := json.Marshal(cfg) - if err != nil { - return "", errors.NewSDKError(err) - } - - url := fmt.Sprintf("%s/%s/%s", sdk.bootstrapURL, domainID, configsEndpoint) - - headers, _, sdkerr := sdk.processRequest(http.MethodPost, url, token, data, nil, http.StatusOK, http.StatusCreated) - if sdkerr != nil { - return "", sdkerr - } - - id := strings.TrimPrefix(headers.Get("Location"), "/clients/configs/") - - return id, nil -} - -func (sdk mgSDK) Bootstraps(pm PageMetadata, domainID, token string) (BootstrapPage, errors.SDKError) { - endpoint := fmt.Sprintf("%s/%s", domainID, configsEndpoint) - url, err := sdk.withQueryParams(sdk.bootstrapURL, endpoint, pm) - if err != nil { - return BootstrapPage{}, errors.NewSDKError(err) - } - - _, body, sdkerr := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) - if sdkerr != nil { - return BootstrapPage{}, sdkerr - } - - var bb BootstrapPage - if err = json.Unmarshal(body, &bb); err != nil { - return BootstrapPage{}, errors.NewSDKError(err) - } - - return bb, nil -} - -func (sdk mgSDK) Whitelist(clientID string, state int, domainID, token string) errors.SDKError { - if clientID == "" { - return errors.NewSDKError(apiutil.ErrMissingID) - } - - data, err := json.Marshal(BootstrapConfig{State: state}) - if err != nil { - return errors.NewSDKError(err) - } - - url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, whitelistEndpoint, clientID) - - _, _, sdkerr := sdk.processRequest(http.MethodPut, url, token, data, nil, http.StatusCreated, http.StatusOK) - - return sdkerr -} - -func (sdk mgSDK) ViewBootstrap(id, domainID, token string) (BootstrapConfig, errors.SDKError) { - if id == "" { - return BootstrapConfig{}, errors.NewSDKError(apiutil.ErrMissingID) - } - url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, configsEndpoint, id) - - _, body, err := sdk.processRequest(http.MethodGet, url, token, nil, nil, http.StatusOK) - if err != nil { - return BootstrapConfig{}, err - } - - var bc BootstrapConfig - if err := json.Unmarshal(body, &bc); err != nil { - return BootstrapConfig{}, errors.NewSDKError(err) - } - - return bc, nil -} - -func (sdk mgSDK) UpdateBootstrap(cfg BootstrapConfig, domainID, token string) errors.SDKError { - if cfg.ClientID == "" { - return errors.NewSDKError(apiutil.ErrMissingID) - } - url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, configsEndpoint, cfg.ClientID) - - data, err := json.Marshal(cfg) - if err != nil { - return errors.NewSDKError(err) - } - - _, _, sdkerr := sdk.processRequest(http.MethodPut, url, token, data, nil, http.StatusOK) - - return sdkerr -} - -func (sdk mgSDK) UpdateBootstrapCerts(id, clientCert, clientKey, ca, domainID, token string) (BootstrapConfig, errors.SDKError) { - if id == "" { - return BootstrapConfig{}, errors.NewSDKError(apiutil.ErrMissingID) - } - url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, bootstrapCertsEndpoint, id) - request := BootstrapConfig{ - ClientCert: clientCert, - ClientKey: clientKey, - CACert: ca, - } - - data, err := json.Marshal(request) - if err != nil { - return BootstrapConfig{}, errors.NewSDKError(err) - } - - _, body, sdkerr := sdk.processRequest(http.MethodPatch, url, token, data, nil, http.StatusOK) - if sdkerr != nil { - return BootstrapConfig{}, sdkerr - } - - var bc BootstrapConfig - if err := json.Unmarshal(body, &bc); err != nil { - return BootstrapConfig{}, errors.NewSDKError(err) - } - - return bc, nil -} - -func (sdk mgSDK) UpdateBootstrapConnection(id string, channels []string, domainID, token string) errors.SDKError { - if id == "" { - return errors.NewSDKError(apiutil.ErrMissingID) - } - url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, bootstrapConnEndpoint, id) - request := map[string][]string{ - "channels": channels, - } - data, err := json.Marshal(request) - if err != nil { - return errors.NewSDKError(err) - } - - _, _, sdkerr := sdk.processRequest(http.MethodPut, url, token, data, nil, http.StatusOK) - return sdkerr -} - -func (sdk mgSDK) RemoveBootstrap(id, domainID, token string) errors.SDKError { - if id == "" { - return errors.NewSDKError(apiutil.ErrMissingID) - } - url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, domainID, configsEndpoint, id) - - _, _, err := sdk.processRequest(http.MethodDelete, url, token, nil, nil, http.StatusNoContent) - return err -} - -func (sdk mgSDK) Bootstrap(externalID, externalKey string) (BootstrapConfig, errors.SDKError) { - if externalID == "" { - return BootstrapConfig{}, errors.NewSDKError(apiutil.ErrMissingID) - } - url := fmt.Sprintf("%s/%s/%s", sdk.bootstrapURL, bootstrapEndpoint, externalID) - - _, body, err := sdk.processRequest(http.MethodGet, url, ClientPrefix+externalKey, nil, nil, http.StatusOK) - if err != nil { - return BootstrapConfig{}, err - } - - var bc BootstrapConfig - if err := json.Unmarshal(body, &bc); err != nil { - return BootstrapConfig{}, errors.NewSDKError(err) - } - - return bc, nil -} - -func (sdk mgSDK) BootstrapSecure(externalID, externalKey, cryptoKey string) (BootstrapConfig, errors.SDKError) { - if externalID == "" { - return BootstrapConfig{}, errors.NewSDKError(apiutil.ErrMissingID) - } - url := fmt.Sprintf("%s/%s/%s/%s", sdk.bootstrapURL, bootstrapEndpoint, secureEndpoint, externalID) - - encExtKey, err := bootstrapEncrypt([]byte(externalKey), cryptoKey) - if err != nil { - return BootstrapConfig{}, errors.NewSDKError(err) - } - - _, body, sdkErr := sdk.processRequest(http.MethodGet, url, ClientPrefix+encExtKey, nil, nil, http.StatusOK) - if sdkErr != nil { - return BootstrapConfig{}, sdkErr - } - - decBody, decErr := bootstrapDecrypt(body, cryptoKey) - if decErr != nil { - return BootstrapConfig{}, errors.NewSDKError(decErr) - } - var bc BootstrapConfig - if err := json.Unmarshal(decBody, &bc); err != nil { - return BootstrapConfig{}, errors.NewSDKError(err) - } - - return bc, nil -} - -func bootstrapEncrypt(in []byte, cryptoKey string) (string, error) { - block, err := aes.NewCipher([]byte(cryptoKey)) - if err != nil { - return "", err - } - ciphertext := make([]byte, aes.BlockSize+len(in)) - iv := ciphertext[:aes.BlockSize] - - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return "", err - } - stream := cipher.NewCFBEncrypter(block, iv) - stream.XORKeyStream(ciphertext[aes.BlockSize:], in) - return hex.EncodeToString(ciphertext), nil -} - -func bootstrapDecrypt(in []byte, cryptoKey string) ([]byte, error) { - ciphertext := in - - block, err := aes.NewCipher([]byte(cryptoKey)) - if err != nil { - return nil, err - } - if len(ciphertext) < aes.BlockSize { - return nil, err - } - iv := ciphertext[:aes.BlockSize] - ciphertext = ciphertext[aes.BlockSize:] - stream := cipher.NewCFBDecrypter(block, iv) - stream.XORKeyStream(ciphertext, ciphertext) - return ciphertext, nil -} diff --git a/pkg/sdk/bootstrap_test.go b/pkg/sdk/bootstrap_test.go deleted file mode 100644 index 361d4f3f76..0000000000 --- a/pkg/sdk/bootstrap_test.go +++ /dev/null @@ -1,1347 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package sdk_test - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httptest" - "testing" - - apiutil "github.com/absmach/supermq/api/http/util" - "github.com/absmach/supermq/bootstrap" - "github.com/absmach/supermq/bootstrap/api" - bmocks "github.com/absmach/supermq/bootstrap/mocks" - "github.com/absmach/supermq/internal/testsutil" - 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" - sdk "github.com/absmach/supermq/pkg/sdk" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -var ( - externalId = testsutil.GenerateUUID(&testing.T{}) - externalKey = testsutil.GenerateUUID(&testing.T{}) - clientId = testsutil.GenerateUUID(&testing.T{}) - clientSecret = testsutil.GenerateUUID(&testing.T{}) - channel1Id = testsutil.GenerateUUID(&testing.T{}) - channel2Id = testsutil.GenerateUUID(&testing.T{}) - clientCert = "newcert" - clientKey = "newkey" - caCert = "newca" - content = "newcontent" - state = 1 - bsName = "test" - encKey = []byte("1234567891011121") - bootstrapConfig = bootstrap.Config{ - ClientID: clientId, - Name: "test", - ClientCert: clientCert, - ClientKey: clientKey, - CACert: caCert, - Channels: []bootstrap.Channel{ - { - ID: channel1Id, - }, - { - ID: channel2Id, - }, - }, - ExternalID: externalId, - ExternalKey: externalKey, - Content: content, - State: bootstrap.Inactive, - } - sdkBootstrapConfig = sdk.BootstrapConfig{ - Channels: []string{channel1Id, channel2Id}, - ExternalID: externalId, - ExternalKey: externalKey, - ClientID: clientId, - ClientSecret: clientSecret, - Name: bsName, - ClientCert: clientCert, - ClientKey: clientKey, - CACert: caCert, - Content: content, - State: state, - } - sdkBootsrapConfigRes = sdk.BootstrapConfig{ - ClientID: clientId, - ClientSecret: clientSecret, - Channels: []sdk.Channel{ - { - ID: channel1Id, - }, - { - ID: channel2Id, - }, - }, - ClientCert: clientCert, - ClientKey: clientKey, - CACert: caCert, - } - readConfigResponse = struct { - ClientID string `json:"client_id"` - ClientSecret string `json:"client_secret"` - Channels []readerChannelRes `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: clientId, - ClientSecret: clientSecret, - Channels: []readerChannelRes{ - { - ID: channel1Id, - }, - { - ID: channel2Id, - }, - }, - ClientCert: clientCert, - ClientKey: clientKey, - CACert: caCert, - } -) - -var ( - errMarshalChan = errors.New("json: unsupported type: chan int") - errJsonEOF = errors.New("unexpected end of JSON input") -) - -type readerChannelRes struct { - ID string `json:"id"` - Name string `json:"name,omitempty"` - Metadata interface{} `json:"metadata,omitempty"` -} - -func setupBootstrap() (*httptest.Server, *bmocks.Service, *bmocks.ConfigReader, *authnmocks.Authentication) { - bsvc := new(bmocks.Service) - reader := new(bmocks.ConfigReader) - logger := smqlog.NewMock() - authn := new(authnmocks.Authentication) - mux := api.MakeHandler(bsvc, authn, reader, logger, "") - - return httptest.NewServer(mux), bsvc, reader, authn -} - -func TestAddBootstrap(t *testing.T) { - bs, bsvc, _, auth := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - neID := sdkBootstrapConfig - neID.ClientID = "non-existent" - - neReqId := bootstrapConfig - neReqId.ClientID = "non-existent" - - cases := []struct { - desc string - domainID string - token string - session smqauthn.Session - cfg sdk.BootstrapConfig - svcReq bootstrap.Config - svcRes bootstrap.Config - svcErr error - authenticateErr error - response string - err errors.SDKError - }{ - { - desc: "add successfully", - domainID: domainID, - token: validToken, - cfg: sdkBootstrapConfig, - svcReq: bootstrapConfig, - svcRes: bootstrapConfig, - svcErr: nil, - err: nil, - }, - { - desc: "add with invalid token", - domainID: domainID, - token: invalidToken, - cfg: sdkBootstrapConfig, - svcReq: bootstrapConfig, - svcRes: bootstrap.Config{}, - authenticateErr: svcerr.ErrAuthentication, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "add with config that cannot be marshalled", - domainID: domainID, - token: validToken, - cfg: sdk.BootstrapConfig{ - Channels: map[string]interface{}{ - "channel1": make(chan int), - }, - ExternalID: externalId, - ExternalKey: externalKey, - ClientID: clientId, - ClientSecret: clientSecret, - Name: bsName, - ClientCert: clientCert, - ClientKey: clientKey, - CACert: caCert, - Content: content, - }, - svcReq: bootstrap.Config{}, - svcRes: bootstrap.Config{}, - svcErr: nil, - err: errors.NewSDKError(errMarshalChan), - }, - { - desc: "add an existing config", - domainID: domainID, - token: validToken, - cfg: sdkBootstrapConfig, - svcReq: bootstrapConfig, - svcRes: bootstrap.Config{}, - svcErr: svcerr.ErrConflict, - err: errors.NewSDKErrorWithStatus(svcerr.ErrConflict, http.StatusConflict), - }, - { - desc: "add empty config", - domainID: domainID, - token: validToken, - cfg: sdk.BootstrapConfig{}, - svcReq: bootstrap.Config{}, - svcRes: bootstrap.Config{}, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrMissingID), http.StatusBadRequest), - }, - { - desc: "add with non-existent client Id", - domainID: domainID, - token: validToken, - cfg: neID, - svcReq: neReqId, - svcRes: bootstrap.Config{}, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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 := bsvc.On("Add", mock.Anything, tc.session, tc.token, tc.svcReq).Return(tc.svcRes, tc.svcErr) - resp, err := mgsdk.AddBootstrap(tc.cfg, tc.domainID, tc.token) - assert.Equal(t, tc.err, err) - if err == nil { - assert.Equal(t, bootstrapConfig.ClientID, resp) - ok := svcCall.Parent.AssertCalled(t, "Add", mock.Anything, tc.session, tc.token, tc.svcReq) - assert.True(t, ok) - } - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestListBootstraps(t *testing.T) { - bs, bsvc, _, auth := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - configRes := sdk.BootstrapConfig{ - Channels: []sdk.Channel{ - { - ID: channel1Id, - }, - { - ID: channel2Id, - }, - }, - ClientID: clientId, - Name: bsName, - ExternalID: externalId, - ExternalKey: externalKey, - Content: content, - } - unmarshalableConfig := bootstrapConfig - unmarshalableConfig.Channels = []bootstrap.Channel{ - { - ID: channel1Id, - Metadata: map[string]interface{}{ - "test": make(chan int), - }, - }, - } - - cases := []struct { - desc string - domainID string - token string - session smqauthn.Session - pageMeta sdk.PageMetadata - svcResp bootstrap.ConfigsPage - svcErr error - authenticateErr error - response sdk.BootstrapPage - err errors.SDKError - }{ - { - desc: "list successfully", - domainID: domainID, - token: validToken, - pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, - }, - svcResp: bootstrap.ConfigsPage{ - Total: 1, - Offset: 0, - Configs: []bootstrap.Config{bootstrapConfig}, - }, - response: sdk.BootstrapPage{ - PageRes: sdk.PageRes{ - Total: 1, - }, - Configs: []sdk.BootstrapConfig{configRes}, - }, - err: nil, - }, - { - desc: "list with invalid token", - domainID: domainID, - token: invalidToken, - pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, - }, - svcResp: bootstrap.ConfigsPage{}, - authenticateErr: svcerr.ErrAuthentication, - response: sdk.BootstrapPage{}, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "list with empty token", - domainID: domainID, - token: "", - pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, - }, - svcResp: bootstrap.ConfigsPage{}, - svcErr: nil, - response: sdk.BootstrapPage{}, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - }, - { - desc: "list with invalid query params", - domainID: domainID, - token: validToken, - pageMeta: sdk.PageMetadata{ - Offset: 1, - Limit: 10, - Metadata: map[string]interface{}{ - "test": make(chan int), - }, - }, - svcResp: bootstrap.ConfigsPage{}, - svcErr: nil, - response: sdk.BootstrapPage{}, - err: errors.NewSDKError(errMarshalChan), - }, - { - desc: "list with response that cannot be unmarshalled", - domainID: domainID, - token: validToken, - pageMeta: sdk.PageMetadata{ - Offset: 0, - Limit: 10, - }, - svcResp: bootstrap.ConfigsPage{ - Total: 1, - Offset: 0, - Configs: []bootstrap.Config{unmarshalableConfig}, - }, - svcErr: nil, - response: sdk.BootstrapPage{}, - err: errors.NewSDKError(errJsonEOF), - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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 := bsvc.On("List", mock.Anything, tc.session, mock.Anything, tc.pageMeta.Offset, tc.pageMeta.Limit).Return(tc.svcResp, tc.svcErr) - resp, err := mgsdk.Bootstraps(tc.pageMeta, tc.domainID, tc.token) - assert.Equal(t, tc.err, err) - assert.Equal(t, tc.response, resp) - if err == nil { - ok := svcCall.Parent.AssertCalled(t, "List", mock.Anything, tc.session, mock.Anything, tc.pageMeta.Offset, tc.pageMeta.Limit) - assert.True(t, ok) - } - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestWhiteList(t *testing.T) { - bs, bsvc, _, auth := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - active := 1 - inactive := 0 - - cases := []struct { - desc string - domainID string - token string - session smqauthn.Session - clientID string - state int - svcReq bootstrap.State - svcErr error - authenticateErr error - err errors.SDKError - }{ - { - desc: "whitelist to active state successfully", - domainID: domainID, - token: validToken, - clientID: clientId, - state: active, - svcReq: bootstrap.Active, - svcErr: nil, - err: nil, - }, - { - desc: "whitelist to inactive state successfully", - domainID: domainID, - token: validToken, - clientID: clientId, - state: inactive, - svcReq: bootstrap.Inactive, - svcErr: nil, - err: nil, - }, - { - desc: "whitelist with invalid token", - domainID: domainID, - token: invalidToken, - clientID: clientId, - state: active, - svcReq: bootstrap.Active, - authenticateErr: svcerr.ErrAuthentication, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "whitelist with empty token", - domainID: domainID, - token: "", - clientID: clientId, - state: active, - svcReq: bootstrap.Active, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - }, - { - desc: "whitelist with invalid state", - domainID: domainID, - token: validToken, - clientID: clientId, - state: -1, - svcReq: bootstrap.Active, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrBootstrapState), http.StatusBadRequest), - }, - { - desc: "whitelist with empty client Id", - domainID: domainID, - token: validToken, - clientID: "", - state: 1, - svcReq: bootstrap.Active, - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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 := bsvc.On("ChangeState", mock.Anything, tc.session, tc.token, tc.clientID, tc.svcReq).Return(tc.svcErr) - err := mgsdk.Whitelist(tc.clientID, tc.state, tc.domainID, tc.token) - assert.Equal(t, tc.err, err) - if tc.err == nil { - ok := svcCall.Parent.AssertCalled(t, "ChangeState", mock.Anything, tc.session, tc.token, tc.clientID, tc.svcReq) - assert.True(t, ok) - } - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestViewBootstrap(t *testing.T) { - bs, bsvc, _, auth := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - viewBoostrapRes := sdk.BootstrapConfig{ - ClientID: clientId, - Channels: sdkBootsrapConfigRes.Channels, - ExternalID: externalId, - ExternalKey: externalKey, - Name: bsName, - Content: content, - State: 0, - } - - cases := []struct { - desc string - domainID string - token string - session smqauthn.Session - id string - svcResp bootstrap.Config - svcErr error - authenticateErr error - response sdk.BootstrapConfig - err errors.SDKError - }{ - { - desc: "view successfully", - domainID: domainID, - token: validToken, - id: clientId, - svcResp: bootstrapConfig, - svcErr: nil, - response: viewBoostrapRes, - err: nil, - }, - { - desc: "view with invalid token", - domainID: domainID, - token: invalidToken, - id: clientId, - svcResp: bootstrap.Config{}, - authenticateErr: svcerr.ErrAuthentication, - response: sdk.BootstrapConfig{}, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "view with empty token", - domainID: domainID, - token: "", - id: clientId, - svcResp: bootstrap.Config{}, - svcErr: nil, - response: sdk.BootstrapConfig{}, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - }, - { - desc: "view with non-existent client Id", - domainID: domainID, - token: validToken, - id: invalid, - svcResp: bootstrap.Config{}, - svcErr: svcerr.ErrViewEntity, - response: sdk.BootstrapConfig{}, - err: errors.NewSDKErrorWithStatus(svcerr.ErrViewEntity, http.StatusBadRequest), - }, - { - desc: "view with response that cannot be unmarshalled", - domainID: domainID, - token: validToken, - id: clientId, - svcResp: bootstrap.Config{ - ClientID: clientId, - Channels: []bootstrap.Channel{ - { - ID: channel1Id, - Metadata: map[string]interface{}{ - "test": make(chan int), - }, - }, - }, - }, - svcErr: nil, - response: sdk.BootstrapConfig{}, - err: errors.NewSDKError(errJsonEOF), - }, - { - desc: "view with empty client Id", - domainID: domainID, - token: validToken, - id: "", - svcResp: bootstrap.Config{}, - svcErr: nil, - response: sdk.BootstrapConfig{}, - err: errors.NewSDKError(apiutil.ErrMissingID), - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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 := bsvc.On("View", mock.Anything, tc.session, tc.id).Return(tc.svcResp, tc.svcErr) - resp, err := mgsdk.ViewBootstrap(tc.id, tc.domainID, tc.token) - assert.Equal(t, tc.err, err) - assert.Equal(t, tc.response, resp) - if err == nil { - ok := svcCall.Parent.AssertCalled(t, "View", mock.Anything, tc.session, tc.id) - assert.True(t, ok) - } - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestUpdateBootstrap(t *testing.T) { - bs, bsvc, _, auth := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - cases := []struct { - desc string - domainID string - token string - session smqauthn.Session - cfg sdk.BootstrapConfig - svcReq bootstrap.Config - svcErr error - authenticationErr error - err errors.SDKError - }{ - { - desc: "update successfully", - domainID: domainID, - token: validToken, - cfg: sdkBootstrapConfig, - svcReq: bootstrap.Config{ - ClientID: clientId, - Name: bsName, - Content: content, - }, - svcErr: nil, - err: nil, - }, - { - desc: "update with invalid token", - domainID: domainID, - token: invalidToken, - cfg: sdkBootstrapConfig, - svcReq: bootstrap.Config{ - ClientID: clientId, - Name: bsName, - Content: content, - }, - authenticationErr: svcerr.ErrAuthentication, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "update with empty token", - domainID: domainID, - token: "", - cfg: sdkBootstrapConfig, - svcReq: bootstrap.Config{}, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - }, - { - desc: "update with config that cannot be marshalled", - domainID: domainID, - token: validToken, - cfg: sdk.BootstrapConfig{ - Channels: map[string]interface{}{ - "channel1": make(chan int), - }, - ExternalID: externalId, - ExternalKey: externalKey, - ClientID: clientId, - ClientSecret: clientSecret, - Name: bsName, - ClientCert: clientCert, - ClientKey: clientKey, - CACert: caCert, - Content: content, - }, - svcReq: bootstrap.Config{ - ClientID: clientId, - Name: bsName, - Content: content, - }, - svcErr: nil, - err: errors.NewSDKError(errMarshalChan), - }, - { - desc: "update with non-existent client Id", - domainID: domainID, - token: validToken, - cfg: sdk.BootstrapConfig{ - ClientID: invalid, - Channels: []sdk.Channel{ - { - ID: channel1Id, - }, - }, - ExternalID: externalId, - ExternalKey: externalKey, - Content: content, - Name: bsName, - }, - svcReq: bootstrap.Config{ - ClientID: invalid, - Name: bsName, - Content: content, - }, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), - }, - { - desc: "update with empty client Id", - domainID: domainID, - token: validToken, - cfg: sdk.BootstrapConfig{ - ClientID: "", - Channels: []sdk.Channel{ - { - ID: channel1Id, - }, - }, - ExternalID: externalId, - ExternalKey: externalKey, - Content: content, - Name: bsName, - }, - svcReq: bootstrap.Config{ - ClientID: "", - Name: bsName, - Content: content, - }, - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), - }, - { - desc: "update with config with only client Id", - domainID: domainID, - token: validToken, - cfg: sdk.BootstrapConfig{ - ClientID: clientId, - }, - svcReq: bootstrap.Config{ - ClientID: clientId, - }, - svcErr: nil, - err: nil, - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - tc.session = smqauthn.Session{DomainUserID: domainID + "_" + validID, UserID: validID, DomainID: domainID} - } - authCall := auth.On("Authenticate", mock.Anything, tc.token).Return(tc.session, tc.authenticationErr) - svcCall := bsvc.On("Update", mock.Anything, tc.session, tc.svcReq).Return(tc.svcErr) - err := mgsdk.UpdateBootstrap(tc.cfg, tc.domainID, tc.token) - assert.Equal(t, tc.err, err) - if tc.err == nil { - ok := svcCall.Parent.AssertCalled(t, "Update", mock.Anything, tc.session, tc.svcReq) - assert.True(t, ok) - } - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestUpdateBootstrapCerts(t *testing.T) { - bs, bsvc, _, auth := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - updateconfigRes := sdk.BootstrapConfig{ - ClientID: clientId, - ClientCert: clientCert, - CACert: caCert, - ClientKey: clientKey, - } - - cases := []struct { - desc string - domainID string - token string - session smqauthn.Session - id string - clientCert string - clientKey string - caCert string - svcResp bootstrap.Config - svcErr error - authenticateErr error - response sdk.BootstrapConfig - err errors.SDKError - }{ - { - desc: "update certs successfully", - domainID: domainID, - token: validToken, - id: clientId, - clientCert: clientCert, - clientKey: clientKey, - caCert: caCert, - svcResp: bootstrapConfig, - svcErr: nil, - response: updateconfigRes, - err: nil, - }, - { - desc: "update certs with invalid token", - domainID: domainID, - token: validToken, - id: clientId, - clientCert: clientCert, - clientKey: clientKey, - caCert: caCert, - svcResp: bootstrap.Config{}, - authenticateErr: svcerr.ErrAuthentication, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "update certs with empty token", - domainID: domainID, - token: "", - id: clientId, - clientCert: clientCert, - clientKey: clientKey, - caCert: caCert, - svcResp: bootstrap.Config{}, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - }, - { - desc: "update certs with non-existent client Id", - domainID: domainID, - token: validToken, - id: invalid, - clientCert: clientCert, - clientKey: clientKey, - caCert: caCert, - svcResp: bootstrap.Config{}, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), - }, - { - desc: "update certs with empty certs", - domainID: domainID, - token: validToken, - id: clientId, - clientCert: "", - clientKey: "", - caCert: "", - svcResp: bootstrap.Config{}, - svcErr: nil, - err: nil, - }, - { - desc: "update certs with empty id", - domainID: domainID, - token: validToken, - id: "", - clientCert: clientCert, - clientKey: clientKey, - caCert: caCert, - svcResp: bootstrap.Config{}, - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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 := bsvc.On("UpdateCert", mock.Anything, tc.session, tc.id, tc.clientCert, tc.clientKey, tc.caCert).Return(tc.svcResp, tc.svcErr) - resp, err := mgsdk.UpdateBootstrapCerts(tc.id, tc.clientCert, tc.clientKey, tc.caCert, tc.domainID, tc.token) - assert.Equal(t, tc.err, err) - if err == nil { - assert.Equal(t, tc.response, resp) - } - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestUpdateBootstrapConnection(t *testing.T) { - bs, bsvc, _, auth := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - cases := []struct { - desc string - domainID string - token string - session smqauthn.Session - id string - channels []string - svcRes bootstrap.Config - svcErr error - authenticateErr error - err errors.SDKError - }{ - { - desc: "update connection successfully", - domainID: domainID, - token: validToken, - id: clientId, - channels: []string{channel1Id, channel2Id}, - svcErr: nil, - err: nil, - }, - { - desc: "update connection with invalid token", - domainID: domainID, - token: invalidToken, - id: clientId, - channels: []string{channel1Id, channel2Id}, - authenticateErr: svcerr.ErrAuthentication, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "update connection with empty token", - domainID: domainID, - token: "", - id: clientId, - channels: []string{channel1Id, channel2Id}, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - }, - { - desc: "update connection with non-existent client Id", - domainID: domainID, - token: validToken, - id: invalid, - channels: []string{channel1Id, channel2Id}, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), - }, - { - desc: "update connection with non-existent channel Id", - domainID: domainID, - token: validToken, - id: clientId, - channels: []string{invalid}, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), - }, - { - desc: "update connection with empty channels", - domainID: domainID, - token: validToken, - id: clientId, - channels: []string{}, - svcErr: svcerr.ErrUpdateEntity, - err: errors.NewSDKErrorWithStatus(svcerr.ErrUpdateEntity, http.StatusUnprocessableEntity), - }, - { - desc: "update connection with empty id", - domainID: domainID, - token: validToken, - id: "", - channels: []string{channel1Id, channel2Id}, - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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 := bsvc.On("UpdateConnections", mock.Anything, tc.session, tc.token, tc.id, tc.channels).Return(tc.svcErr) - err := mgsdk.UpdateBootstrapConnection(tc.id, tc.channels, tc.domainID, tc.token) - assert.Equal(t, tc.err, err) - if tc.err == nil { - ok := svcCall.Parent.AssertCalled(t, "UpdateConnections", mock.Anything, tc.session, tc.token, tc.id, tc.channels) - assert.True(t, ok) - } - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestRemoveBootstrap(t *testing.T) { - bs, bsvc, _, auth := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - cases := []struct { - desc string - domainID string - token string - session smqauthn.Session - id string - svcErr error - authenticateErr error - err errors.SDKError - }{ - { - desc: "remove successfully", - domainID: domainID, - token: validToken, - id: clientId, - svcErr: nil, - err: nil, - }, - { - desc: "remove with invalid token", - domainID: domainID, - token: invalidToken, - id: clientId, - authenticateErr: svcerr.ErrAuthentication, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "remove with non-existent client Id", - domainID: domainID, - token: validToken, - id: invalid, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), - }, - { - desc: "remove removed bootstrap", - domainID: domainID, - token: validToken, - id: clientId, - svcErr: svcerr.ErrNotFound, - err: errors.NewSDKErrorWithStatus(svcerr.ErrNotFound, http.StatusNotFound), - }, - { - desc: "remove with empty token", - domainID: domainID, - token: "", - id: clientId, - svcErr: nil, - err: errors.NewSDKErrorWithStatus(apiutil.ErrBearerToken, http.StatusUnauthorized), - }, - { - desc: "remove with empty id", - domainID: domainID, - token: validToken, - id: "", - svcErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - if tc.token == validToken { - 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 := bsvc.On("Remove", mock.Anything, tc.session, tc.id).Return(tc.svcErr) - err := mgsdk.RemoveBootstrap(tc.id, tc.domainID, tc.token) - assert.Equal(t, tc.err, err) - if tc.err == nil { - ok := svcCall.Parent.AssertCalled(t, "Remove", mock.Anything, tc.session, tc.id) - assert.True(t, ok) - } - svcCall.Unset() - authCall.Unset() - }) - } -} - -func TestBoostrap(t *testing.T) { - bs, bsvc, reader, _ := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - cases := []struct { - desc string - token string - externalID string - externalKey string - svcResp bootstrap.Config - svcErr error - readerResp interface{} - readerErr error - response sdk.BootstrapConfig - err errors.SDKError - }{ - { - desc: "bootstrap successfully", - token: validToken, - externalID: externalId, - externalKey: externalKey, - svcResp: bootstrapConfig, - svcErr: nil, - readerResp: readConfigResponse, - readerErr: nil, - response: sdkBootsrapConfigRes, - err: nil, - }, - { - desc: "bootstrap with invalid token", - token: invalidToken, - externalID: externalId, - externalKey: externalKey, - svcResp: bootstrap.Config{}, - svcErr: svcerr.ErrAuthentication, - readerResp: bootstrap.Config{}, - readerErr: nil, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "bootstrap with error in reader", - token: validToken, - externalID: externalId, - externalKey: externalKey, - svcResp: bootstrapConfig, - svcErr: nil, - readerResp: []byte{0}, - readerErr: errJsonEOF, - err: errors.NewSDKErrorWithStatus(errJsonEOF, http.StatusInternalServerError), - }, - { - desc: "boostrap with response that cannot be unmarshalled", - token: validToken, - externalID: externalId, - externalKey: externalKey, - svcResp: bootstrapConfig, - svcErr: nil, - readerResp: []byte{0}, - readerErr: nil, - err: errors.NewSDKError(errors.New("json: cannot unmarshal string into Go value of type map[string]json.RawMessage")), - }, - { - desc: "bootstrap with empty id", - token: validToken, - externalID: "", - externalKey: externalKey, - svcResp: bootstrap.Config{}, - svcErr: nil, - readerResp: bootstrap.Config{}, - readerErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), - }, - { - desc: "boostrap with empty key", - token: validToken, - externalID: externalId, - externalKey: "", - svcResp: bootstrap.Config{}, - svcErr: nil, - readerResp: bootstrap.Config{}, - readerErr: nil, - err: errors.NewSDKErrorWithStatus(errors.Wrap(apiutil.ErrValidation, apiutil.ErrBearerKey), http.StatusBadRequest), - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - svcCall := bsvc.On("Bootstrap", mock.Anything, tc.externalKey, tc.externalID, false).Return(tc.svcResp, tc.svcErr) - readerCall := reader.On("ReadConfig", tc.svcResp, false).Return(tc.readerResp, tc.readerErr) - resp, err := mgsdk.Bootstrap(tc.externalID, tc.externalKey) - assert.Equal(t, tc.err, err) - if err == nil { - assert.Equal(t, tc.response, resp) - ok := svcCall.Parent.AssertCalled(t, "Bootstrap", mock.Anything, tc.externalKey, tc.externalID, false) - assert.True(t, ok) - } - svcCall.Unset() - readerCall.Unset() - }) - } -} - -func TestBootstrapSecure(t *testing.T) { - bs, bsvc, reader, _ := setupBootstrap() - defer bs.Close() - - conf := sdk.Config{ - BootstrapURL: bs.URL, - } - mgsdk := sdk.NewSDK(conf) - - b, err := json.Marshal(readConfigResponse) - assert.Nil(t, err, fmt.Sprintf("Marshalling bootstrap response expected to succeed: %s.\n", err)) - encResponse, err := encrypt(b, encKey) - assert.Nil(t, err, fmt.Sprintf("Encrypting bootstrap response expected to succeed: %s.\n", err)) - - cases := []struct { - desc string - token string - externalID string - externalKey string - cryptoKey string - svcResp bootstrap.Config - svcErr error - readerResp []byte - readerErr error - response sdk.BootstrapConfig - err errors.SDKError - }{ - { - desc: "bootstrap successfully", - token: validToken, - externalID: externalId, - externalKey: externalKey, - cryptoKey: string(encKey), - svcResp: bootstrapConfig, - svcErr: nil, - readerResp: encResponse, - readerErr: nil, - response: sdkBootsrapConfigRes, - err: nil, - }, - { - desc: "bootstrap with invalid token", - token: invalidToken, - externalID: externalId, - externalKey: externalKey, - cryptoKey: string(encKey), - svcResp: bootstrap.Config{}, - svcErr: svcerr.ErrAuthentication, - readerResp: []byte{0}, - readerErr: nil, - err: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, http.StatusUnauthorized), - }, - { - desc: "booostrap with invalid crypto key", - token: validToken, - externalID: externalId, - externalKey: externalKey, - cryptoKey: invalid, - svcResp: bootstrap.Config{}, - svcErr: nil, - readerResp: []byte{0}, - readerErr: nil, - err: errors.NewSDKError(errors.New("crypto/aes: invalid key size 7")), - }, - { - desc: "bootstrap with error in reader", - token: validToken, - externalID: externalId, - externalKey: externalKey, - cryptoKey: string(encKey), - svcResp: bootstrapConfig, - svcErr: nil, - readerResp: []byte{0}, - readerErr: errJsonEOF, - err: errors.NewSDKErrorWithStatus(errJsonEOF, http.StatusInternalServerError), - }, - { - desc: "bootstrap with response that cannot be unmarshalled", - token: validToken, - externalID: externalId, - externalKey: externalKey, - cryptoKey: string(encKey), - svcResp: bootstrapConfig, - svcErr: nil, - readerResp: []byte{0}, - readerErr: nil, - err: errors.NewSDKError(errJsonEOF), - }, - { - desc: "bootstrap with empty id", - token: validToken, - externalID: "", - externalKey: externalKey, - svcResp: bootstrap.Config{}, - svcErr: nil, - readerResp: []byte{0}, - readerErr: nil, - err: errors.NewSDKError(apiutil.ErrMissingID), - }, - } - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - svcCall := bsvc.On("Bootstrap", mock.Anything, mock.Anything, tc.externalID, true).Return(tc.svcResp, tc.svcErr) - readerCall := reader.On("ReadConfig", tc.svcResp, true).Return(tc.readerResp, tc.readerErr) - resp, err := mgsdk.BootstrapSecure(tc.externalID, tc.externalKey, tc.cryptoKey) - assert.Equal(t, tc.err, err) - if err == nil { - assert.Equal(t, sdkBootsrapConfigRes, resp) - ok := svcCall.Parent.AssertCalled(t, "Bootstrap", mock.Anything, mock.Anything, tc.externalID, true) - assert.True(t, ok) - } - svcCall.Unset() - readerCall.Unset() - }) - } -} - -func encrypt(in, encKey []byte) ([]byte, error) { - block, err := aes.NewCipher(encKey) - if err != nil { - return nil, err - } - ciphertext := make([]byte, aes.BlockSize+len(in)) - iv := ciphertext[:aes.BlockSize] - if _, err := io.ReadFull(rand.Reader, iv); err != nil { - return nil, err - } - stream := cipher.NewCFBEncrypter(block, iv) - stream.XORKeyStream(ciphertext[aes.BlockSize:], in) - return ciphertext, nil -} diff --git a/pkg/sdk/health.go b/pkg/sdk/health.go index 1906cf0c07..f944eb960f 100644 --- a/pkg/sdk/health.go +++ b/pkg/sdk/health.go @@ -36,8 +36,6 @@ func (sdk mgSDK) Health(service string) (HealthInfo, errors.SDKError) { url = fmt.Sprintf("%s/health", sdk.clientsURL) case "users": url = fmt.Sprintf("%s/health", sdk.usersURL) - case "bootstrap": - url = fmt.Sprintf("%s/health", sdk.bootstrapURL) case "certs": url = fmt.Sprintf("%s/health", sdk.certsURL) case "reader": diff --git a/pkg/sdk/health_test.go b/pkg/sdk/health_test.go index 25087bc548..74b6a7f6d4 100644 --- a/pkg/sdk/health_test.go +++ b/pkg/sdk/health_test.go @@ -9,11 +9,8 @@ import ( "testing" "github.com/absmach/supermq" - "github.com/absmach/supermq/bootstrap/api" - bmocks "github.com/absmach/supermq/bootstrap/mocks" chmocks "github.com/absmach/supermq/channels/mocks" climocks "github.com/absmach/supermq/clients/mocks" - smqlog "github.com/absmach/supermq/logger" authnmocks "github.com/absmach/supermq/pkg/authn/mocks" "github.com/absmach/supermq/pkg/errors" sdk "github.com/absmach/supermq/pkg/sdk" @@ -32,9 +29,6 @@ func TestHealth(t *testing.T) { certsTs, _, _ := setupCerts() defer certsTs.Close() - bootstrapTs := setupMinimalBootstrap() - defer bootstrapTs.Close() - readerTs := setupMinimalReader() defer readerTs.Close() @@ -45,7 +39,6 @@ func TestHealth(t *testing.T) { ClientsURL: clientsTs.URL, UsersURL: usersTs.URL, CertsURL: certsTs.URL, - BootstrapURL: bootstrapTs.URL, ReaderURL: readerTs.URL, HTTPAdapterURL: httpAdapterTs.URL, MsgContentType: contentType, @@ -85,14 +78,6 @@ func TestHealth(t *testing.T) { description: "certs service", status: "pass", }, - { - desc: "get bootstrap service health check", - service: "bootstrap", - empty: false, - err: nil, - description: "bootstrap service", - status: "pass", - }, { desc: "get reader service health check", service: "reader", @@ -123,16 +108,6 @@ func TestHealth(t *testing.T) { } } -func setupMinimalBootstrap() *httptest.Server { - bsvc := new(bmocks.Service) - reader := new(bmocks.ConfigReader) - logger := smqlog.NewMock() - authn := new(authnmocks.Authentication) - mux := api.MakeHandler(bsvc, authn, reader, logger, "") - - return httptest.NewServer(mux) -} - func setupMinimalReader() *httptest.Server { repo := new(readersmocks.MessageRepository) channels := new(chmocks.ChannelsServiceClient) diff --git a/pkg/sdk/mocks/sdk.go b/pkg/sdk/mocks/sdk.go index 962f44bd55..038cf4c24b 100644 --- a/pkg/sdk/mocks/sdk.go +++ b/pkg/sdk/mocks/sdk.go @@ -1,9 +1,7 @@ -// Copyright (c) Abstract Machines - -// SPDX-License-Identifier: Apache-2.0 - // Code generated by mockery v2.43.2. DO NOT EDIT. +// Copyright (c) Abstract Machines + package mocks import ( @@ -20,14 +18,6 @@ type SDK struct { mock.Mock } -type SDK_Expecter struct { - mock *mock.Mock -} - -func (_m *SDK) EXPECT() *SDK_Expecter { - return &SDK_Expecter{mock: &_m.Mock} -} - // AcceptInvitation provides a mock function with given fields: domainID, token func (_m *SDK) AcceptInvitation(domainID string, token string) error { ret := _m.Called(domainID, token) @@ -46,95 +36,6 @@ func (_m *SDK) AcceptInvitation(domainID string, token string) error { return r0 } -// SDK_AcceptInvitation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AcceptInvitation' -type SDK_AcceptInvitation_Call struct { - *mock.Call -} - -// AcceptInvitation is a helper method to define mock.On call -// - domainID string -// - token string -func (_e *SDK_Expecter) AcceptInvitation(domainID interface{}, token interface{}) *SDK_AcceptInvitation_Call { - return &SDK_AcceptInvitation_Call{Call: _e.mock.On("AcceptInvitation", domainID, token)} -} - -func (_c *SDK_AcceptInvitation_Call) Run(run func(domainID string, token string)) *SDK_AcceptInvitation_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_AcceptInvitation_Call) Return(err error) *SDK_AcceptInvitation_Call { - _c.Call.Return(err) - return _c -} - -func (_c *SDK_AcceptInvitation_Call) RunAndReturn(run func(string, string) error) *SDK_AcceptInvitation_Call { - _c.Call.Return(run) - return _c -} - -// AddBootstrap provides a mock function with given fields: cfg, domainID, token -func (_m *SDK) AddBootstrap(cfg sdk.BootstrapConfig, domainID string, token string) (string, errors.SDKError) { - ret := _m.Called(cfg, domainID, token) - - if len(ret) == 0 { - panic("no return value specified for AddBootstrap") - } - - var r0 string - var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.BootstrapConfig, string, string) (string, errors.SDKError)); ok { - return rf(cfg, domainID, token) - } - if rf, ok := ret.Get(0).(func(sdk.BootstrapConfig, string, string) string); ok { - r0 = rf(cfg, domainID, token) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(sdk.BootstrapConfig, string, string) errors.SDKError); ok { - r1 = rf(cfg, domainID, token) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(errors.SDKError) - } - } - - return r0, r1 -} - -// SDK_AddBootstrap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddBootstrap' -type SDK_AddBootstrap_Call struct { - *mock.Call -} - -// AddBootstrap is a helper method to define mock.On call -// - cfg sdk.BootstrapConfig -// - domainID string -// - token string -func (_e *SDK_Expecter) AddBootstrap(cfg interface{}, domainID interface{}, token interface{}) *SDK_AddBootstrap_Call { - return &SDK_AddBootstrap_Call{Call: _e.mock.On("AddBootstrap", cfg, domainID, token)} -} - -func (_c *SDK_AddBootstrap_Call) Run(run func(cfg sdk.BootstrapConfig, domainID string, token string)) *SDK_AddBootstrap_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.BootstrapConfig), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_AddBootstrap_Call) Return(_a0 string, _a1 errors.SDKError) *SDK_AddBootstrap_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AddBootstrap_Call) RunAndReturn(run func(sdk.BootstrapConfig, string, string) (string, errors.SDKError)) *SDK_AddBootstrap_Call { - _c.Call.Return(run) - return _c -} - // AddChildren provides a mock function with given fields: id, domainID, groupIDs, token func (_m *SDK) AddChildren(id string, domainID string, groupIDs []string, token string) errors.SDKError { ret := _m.Called(id, domainID, groupIDs, token) @@ -155,37 +56,6 @@ func (_m *SDK) AddChildren(id string, domainID string, groupIDs []string, token return r0 } -// SDK_AddChildren_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddChildren' -type SDK_AddChildren_Call struct { - *mock.Call -} - -// AddChildren is a helper method to define mock.On call -// - id string -// - domainID string -// - groupIDs []string -// - token string -func (_e *SDK_Expecter) AddChildren(id interface{}, domainID interface{}, groupIDs interface{}, token interface{}) *SDK_AddChildren_Call { - return &SDK_AddChildren_Call{Call: _e.mock.On("AddChildren", id, domainID, groupIDs, token)} -} - -func (_c *SDK_AddChildren_Call) Run(run func(id string, domainID string, groupIDs []string, token string)) *SDK_AddChildren_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].([]string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_AddChildren_Call) Return(_a0 errors.SDKError) *SDK_AddChildren_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_AddChildren_Call) RunAndReturn(run func(string, string, []string, string) errors.SDKError) *SDK_AddChildren_Call { - _c.Call.Return(run) - return _c -} - // AddClientRoleActions provides a mock function with given fields: id, roleID, domainID, actions, token func (_m *SDK) AddClientRoleActions(id string, roleID string, domainID string, actions []string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, roleID, domainID, actions, token) @@ -218,38 +88,6 @@ func (_m *SDK) AddClientRoleActions(id string, roleID string, domainID string, a return r0, r1 } -// SDK_AddClientRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddClientRoleActions' -type SDK_AddClientRoleActions_Call struct { - *mock.Call -} - -// AddClientRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - actions []string -// - token string -func (_e *SDK_Expecter) AddClientRoleActions(id interface{}, roleID interface{}, domainID interface{}, actions interface{}, token interface{}) *SDK_AddClientRoleActions_Call { - return &SDK_AddClientRoleActions_Call{Call: _e.mock.On("AddClientRoleActions", id, roleID, domainID, actions, token)} -} - -func (_c *SDK_AddClientRoleActions_Call) Run(run func(id string, roleID string, domainID string, actions []string, token string)) *SDK_AddClientRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].([]string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_AddClientRoleActions_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_AddClientRoleActions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AddClientRoleActions_Call) RunAndReturn(run func(string, string, string, []string, string) ([]string, errors.SDKError)) *SDK_AddClientRoleActions_Call { - _c.Call.Return(run) - return _c -} - // AddClientRoleMembers provides a mock function with given fields: id, roleID, domainID, members, token func (_m *SDK) AddClientRoleMembers(id string, roleID string, domainID string, members []string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, roleID, domainID, members, token) @@ -282,38 +120,6 @@ func (_m *SDK) AddClientRoleMembers(id string, roleID string, domainID string, m return r0, r1 } -// SDK_AddClientRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddClientRoleMembers' -type SDK_AddClientRoleMembers_Call struct { - *mock.Call -} - -// AddClientRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - members []string -// - token string -func (_e *SDK_Expecter) AddClientRoleMembers(id interface{}, roleID interface{}, domainID interface{}, members interface{}, token interface{}) *SDK_AddClientRoleMembers_Call { - return &SDK_AddClientRoleMembers_Call{Call: _e.mock.On("AddClientRoleMembers", id, roleID, domainID, members, token)} -} - -func (_c *SDK_AddClientRoleMembers_Call) Run(run func(id string, roleID string, domainID string, members []string, token string)) *SDK_AddClientRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].([]string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_AddClientRoleMembers_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_AddClientRoleMembers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AddClientRoleMembers_Call) RunAndReturn(run func(string, string, string, []string, string) ([]string, errors.SDKError)) *SDK_AddClientRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // AddDomainRoleActions provides a mock function with given fields: id, roleID, actions, token func (_m *SDK) AddDomainRoleActions(id string, roleID string, actions []string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, roleID, actions, token) @@ -346,37 +152,6 @@ func (_m *SDK) AddDomainRoleActions(id string, roleID string, actions []string, return r0, r1 } -// SDK_AddDomainRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddDomainRoleActions' -type SDK_AddDomainRoleActions_Call struct { - *mock.Call -} - -// AddDomainRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - actions []string -// - token string -func (_e *SDK_Expecter) AddDomainRoleActions(id interface{}, roleID interface{}, actions interface{}, token interface{}) *SDK_AddDomainRoleActions_Call { - return &SDK_AddDomainRoleActions_Call{Call: _e.mock.On("AddDomainRoleActions", id, roleID, actions, token)} -} - -func (_c *SDK_AddDomainRoleActions_Call) Run(run func(id string, roleID string, actions []string, token string)) *SDK_AddDomainRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].([]string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_AddDomainRoleActions_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_AddDomainRoleActions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AddDomainRoleActions_Call) RunAndReturn(run func(string, string, []string, string) ([]string, errors.SDKError)) *SDK_AddDomainRoleActions_Call { - _c.Call.Return(run) - return _c -} - // AddDomainRoleMembers provides a mock function with given fields: id, roleID, members, token func (_m *SDK) AddDomainRoleMembers(id string, roleID string, members []string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, roleID, members, token) @@ -409,37 +184,6 @@ func (_m *SDK) AddDomainRoleMembers(id string, roleID string, members []string, return r0, r1 } -// SDK_AddDomainRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddDomainRoleMembers' -type SDK_AddDomainRoleMembers_Call struct { - *mock.Call -} - -// AddDomainRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - members []string -// - token string -func (_e *SDK_Expecter) AddDomainRoleMembers(id interface{}, roleID interface{}, members interface{}, token interface{}) *SDK_AddDomainRoleMembers_Call { - return &SDK_AddDomainRoleMembers_Call{Call: _e.mock.On("AddDomainRoleMembers", id, roleID, members, token)} -} - -func (_c *SDK_AddDomainRoleMembers_Call) Run(run func(id string, roleID string, members []string, token string)) *SDK_AddDomainRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].([]string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_AddDomainRoleMembers_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_AddDomainRoleMembers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AddDomainRoleMembers_Call) RunAndReturn(run func(string, string, []string, string) ([]string, errors.SDKError)) *SDK_AddDomainRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // AddGroupRoleActions provides a mock function with given fields: id, roleID, domainID, actions, token func (_m *SDK) AddGroupRoleActions(id string, roleID string, domainID string, actions []string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, roleID, domainID, actions, token) @@ -472,38 +216,6 @@ func (_m *SDK) AddGroupRoleActions(id string, roleID string, domainID string, ac return r0, r1 } -// SDK_AddGroupRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddGroupRoleActions' -type SDK_AddGroupRoleActions_Call struct { - *mock.Call -} - -// AddGroupRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - actions []string -// - token string -func (_e *SDK_Expecter) AddGroupRoleActions(id interface{}, roleID interface{}, domainID interface{}, actions interface{}, token interface{}) *SDK_AddGroupRoleActions_Call { - return &SDK_AddGroupRoleActions_Call{Call: _e.mock.On("AddGroupRoleActions", id, roleID, domainID, actions, token)} -} - -func (_c *SDK_AddGroupRoleActions_Call) Run(run func(id string, roleID string, domainID string, actions []string, token string)) *SDK_AddGroupRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].([]string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_AddGroupRoleActions_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_AddGroupRoleActions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AddGroupRoleActions_Call) RunAndReturn(run func(string, string, string, []string, string) ([]string, errors.SDKError)) *SDK_AddGroupRoleActions_Call { - _c.Call.Return(run) - return _c -} - // AddGroupRoleMembers provides a mock function with given fields: id, roleID, domainID, members, token func (_m *SDK) AddGroupRoleMembers(id string, roleID string, domainID string, members []string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, roleID, domainID, members, token) @@ -536,38 +248,6 @@ func (_m *SDK) AddGroupRoleMembers(id string, roleID string, domainID string, me return r0, r1 } -// SDK_AddGroupRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AddGroupRoleMembers' -type SDK_AddGroupRoleMembers_Call struct { - *mock.Call -} - -// AddGroupRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - members []string -// - token string -func (_e *SDK_Expecter) AddGroupRoleMembers(id interface{}, roleID interface{}, domainID interface{}, members interface{}, token interface{}) *SDK_AddGroupRoleMembers_Call { - return &SDK_AddGroupRoleMembers_Call{Call: _e.mock.On("AddGroupRoleMembers", id, roleID, domainID, members, token)} -} - -func (_c *SDK_AddGroupRoleMembers_Call) Run(run func(id string, roleID string, domainID string, members []string, token string)) *SDK_AddGroupRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].([]string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_AddGroupRoleMembers_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_AddGroupRoleMembers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AddGroupRoleMembers_Call) RunAndReturn(run func(string, string, string, []string, string) ([]string, errors.SDKError)) *SDK_AddGroupRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // AvailableClientRoleActions provides a mock function with given fields: domainID, token func (_m *SDK) AvailableClientRoleActions(domainID string, token string) ([]string, errors.SDKError) { ret := _m.Called(domainID, token) @@ -600,35 +280,6 @@ func (_m *SDK) AvailableClientRoleActions(domainID string, token string) ([]stri return r0, r1 } -// SDK_AvailableClientRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AvailableClientRoleActions' -type SDK_AvailableClientRoleActions_Call struct { - *mock.Call -} - -// AvailableClientRoleActions is a helper method to define mock.On call -// - domainID string -// - token string -func (_e *SDK_Expecter) AvailableClientRoleActions(domainID interface{}, token interface{}) *SDK_AvailableClientRoleActions_Call { - return &SDK_AvailableClientRoleActions_Call{Call: _e.mock.On("AvailableClientRoleActions", domainID, token)} -} - -func (_c *SDK_AvailableClientRoleActions_Call) Run(run func(domainID string, token string)) *SDK_AvailableClientRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_AvailableClientRoleActions_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_AvailableClientRoleActions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AvailableClientRoleActions_Call) RunAndReturn(run func(string, string) ([]string, errors.SDKError)) *SDK_AvailableClientRoleActions_Call { - _c.Call.Return(run) - return _c -} - // AvailableDomainRoleActions provides a mock function with given fields: token func (_m *SDK) AvailableDomainRoleActions(token string) ([]string, errors.SDKError) { ret := _m.Called(token) @@ -661,34 +312,6 @@ func (_m *SDK) AvailableDomainRoleActions(token string) ([]string, errors.SDKErr return r0, r1 } -// SDK_AvailableDomainRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AvailableDomainRoleActions' -type SDK_AvailableDomainRoleActions_Call struct { - *mock.Call -} - -// AvailableDomainRoleActions is a helper method to define mock.On call -// - token string -func (_e *SDK_Expecter) AvailableDomainRoleActions(token interface{}) *SDK_AvailableDomainRoleActions_Call { - return &SDK_AvailableDomainRoleActions_Call{Call: _e.mock.On("AvailableDomainRoleActions", token)} -} - -func (_c *SDK_AvailableDomainRoleActions_Call) Run(run func(token string)) *SDK_AvailableDomainRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string)) - }) - return _c -} - -func (_c *SDK_AvailableDomainRoleActions_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_AvailableDomainRoleActions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AvailableDomainRoleActions_Call) RunAndReturn(run func(string) ([]string, errors.SDKError)) *SDK_AvailableDomainRoleActions_Call { - _c.Call.Return(run) - return _c -} - // AvailableGroupRoleActions provides a mock function with given fields: id, token func (_m *SDK) AvailableGroupRoleActions(id string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, token) @@ -721,56 +344,27 @@ func (_m *SDK) AvailableGroupRoleActions(id string, token string) ([]string, err return r0, r1 } -// SDK_AvailableGroupRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AvailableGroupRoleActions' -type SDK_AvailableGroupRoleActions_Call struct { - *mock.Call -} - -// AvailableGroupRoleActions is a helper method to define mock.On call -// - id string -// - token string -func (_e *SDK_Expecter) AvailableGroupRoleActions(id interface{}, token interface{}) *SDK_AvailableGroupRoleActions_Call { - return &SDK_AvailableGroupRoleActions_Call{Call: _e.mock.On("AvailableGroupRoleActions", id, token)} -} - -func (_c *SDK_AvailableGroupRoleActions_Call) Run(run func(id string, token string)) *SDK_AvailableGroupRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_AvailableGroupRoleActions_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_AvailableGroupRoleActions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_AvailableGroupRoleActions_Call) RunAndReturn(run func(string, string) ([]string, errors.SDKError)) *SDK_AvailableGroupRoleActions_Call { - _c.Call.Return(run) - return _c -} - -// Bootstrap provides a mock function with given fields: externalID, externalKey -func (_m *SDK) Bootstrap(externalID string, externalKey string) (sdk.BootstrapConfig, errors.SDKError) { - ret := _m.Called(externalID, externalKey) +// Channel provides a mock function with given fields: id, domainID, token +func (_m *SDK) Channel(id string, domainID string, token string) (sdk.Channel, errors.SDKError) { + ret := _m.Called(id, domainID, token) if len(ret) == 0 { - panic("no return value specified for Bootstrap") + panic("no return value specified for Channel") } - var r0 sdk.BootstrapConfig + var r0 sdk.Channel var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string) (sdk.BootstrapConfig, errors.SDKError)); ok { - return rf(externalID, externalKey) + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Channel, errors.SDKError)); ok { + return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string) sdk.BootstrapConfig); ok { - r0 = rf(externalID, externalKey) + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Channel); ok { + r0 = rf(id, domainID, token) } else { - r0 = ret.Get(0).(sdk.BootstrapConfig) + r0 = ret.Get(0).(sdk.Channel) } - if rf, ok := ret.Get(1).(func(string, string) errors.SDKError); ok { - r1 = rf(externalID, externalKey) + if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { + r1 = rf(id, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -780,56 +374,27 @@ func (_m *SDK) Bootstrap(externalID string, externalKey string) (sdk.BootstrapCo return r0, r1 } -// SDK_Bootstrap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Bootstrap' -type SDK_Bootstrap_Call struct { - *mock.Call -} - -// Bootstrap is a helper method to define mock.On call -// - externalID string -// - externalKey string -func (_e *SDK_Expecter) Bootstrap(externalID interface{}, externalKey interface{}) *SDK_Bootstrap_Call { - return &SDK_Bootstrap_Call{Call: _e.mock.On("Bootstrap", externalID, externalKey)} -} - -func (_c *SDK_Bootstrap_Call) Run(run func(externalID string, externalKey string)) *SDK_Bootstrap_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_Bootstrap_Call) Return(_a0 sdk.BootstrapConfig, _a1 errors.SDKError) *SDK_Bootstrap_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Bootstrap_Call) RunAndReturn(run func(string, string) (sdk.BootstrapConfig, errors.SDKError)) *SDK_Bootstrap_Call { - _c.Call.Return(run) - return _c -} - -// BootstrapSecure provides a mock function with given fields: externalID, externalKey, cryptoKey -func (_m *SDK) BootstrapSecure(externalID string, externalKey string, cryptoKey string) (sdk.BootstrapConfig, errors.SDKError) { - ret := _m.Called(externalID, externalKey, cryptoKey) +// Channels provides a mock function with given fields: pm, domainID, token +func (_m *SDK) Channels(pm sdk.PageMetadata, domainID string, token string) (sdk.ChannelsPage, errors.SDKError) { + ret := _m.Called(pm, domainID, token) if len(ret) == 0 { - panic("no return value specified for BootstrapSecure") + panic("no return value specified for Channels") } - var r0 sdk.BootstrapConfig + var r0 sdk.ChannelsPage var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string) (sdk.BootstrapConfig, errors.SDKError)); ok { - return rf(externalID, externalKey, cryptoKey) + if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string, string) (sdk.ChannelsPage, errors.SDKError)); ok { + return rf(pm, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string, string) sdk.BootstrapConfig); ok { - r0 = rf(externalID, externalKey, cryptoKey) + if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string, string) sdk.ChannelsPage); ok { + r0 = rf(pm, domainID, token) } else { - r0 = ret.Get(0).(sdk.BootstrapConfig) + r0 = ret.Get(0).(sdk.ChannelsPage) } - if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { - r1 = rf(externalID, externalKey, cryptoKey) + if rf, ok := ret.Get(1).(func(sdk.PageMetadata, string, string) errors.SDKError); ok { + r1 = rf(pm, domainID, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -839,57 +404,27 @@ func (_m *SDK) BootstrapSecure(externalID string, externalKey string, cryptoKey return r0, r1 } -// SDK_BootstrapSecure_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BootstrapSecure' -type SDK_BootstrapSecure_Call struct { - *mock.Call -} - -// BootstrapSecure is a helper method to define mock.On call -// - externalID string -// - externalKey string -// - cryptoKey string -func (_e *SDK_Expecter) BootstrapSecure(externalID interface{}, externalKey interface{}, cryptoKey interface{}) *SDK_BootstrapSecure_Call { - return &SDK_BootstrapSecure_Call{Call: _e.mock.On("BootstrapSecure", externalID, externalKey, cryptoKey)} -} - -func (_c *SDK_BootstrapSecure_Call) Run(run func(externalID string, externalKey string, cryptoKey string)) *SDK_BootstrapSecure_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_BootstrapSecure_Call) Return(_a0 sdk.BootstrapConfig, _a1 errors.SDKError) *SDK_BootstrapSecure_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_BootstrapSecure_Call) RunAndReturn(run func(string, string, string) (sdk.BootstrapConfig, errors.SDKError)) *SDK_BootstrapSecure_Call { - _c.Call.Return(run) - return _c -} - -// Bootstraps provides a mock function with given fields: pm, domainID, token -func (_m *SDK) Bootstraps(pm sdk.PageMetadata, domainID string, token string) (sdk.BootstrapPage, errors.SDKError) { - ret := _m.Called(pm, domainID, token) +// Children provides a mock function with given fields: id, domainID, pm, token +func (_m *SDK) Children(id string, domainID string, pm sdk.PageMetadata, token string) (sdk.GroupsPage, errors.SDKError) { + ret := _m.Called(id, domainID, pm, token) if len(ret) == 0 { - panic("no return value specified for Bootstraps") + panic("no return value specified for Children") } - var r0 sdk.BootstrapPage + var r0 sdk.GroupsPage var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string, string) (sdk.BootstrapPage, errors.SDKError)); ok { - return rf(pm, domainID, token) + if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) (sdk.GroupsPage, errors.SDKError)); ok { + return rf(id, domainID, pm, token) } - if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string, string) sdk.BootstrapPage); ok { - r0 = rf(pm, domainID, token) + if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) sdk.GroupsPage); ok { + r0 = rf(id, domainID, pm, token) } else { - r0 = ret.Get(0).(sdk.BootstrapPage) + r0 = ret.Get(0).(sdk.GroupsPage) } - if rf, ok := ret.Get(1).(func(sdk.PageMetadata, string, string) errors.SDKError); ok { - r1 = rf(pm, domainID, token) + if rf, ok := ret.Get(1).(func(string, string, sdk.PageMetadata, string) errors.SDKError); ok { + r1 = rf(id, domainID, pm, token) } else { if ret.Get(1) != nil { r1 = ret.Get(1).(errors.SDKError) @@ -899,53 +434,23 @@ func (_m *SDK) Bootstraps(pm sdk.PageMetadata, domainID string, token string) (s return r0, r1 } -// SDK_Bootstraps_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Bootstraps' -type SDK_Bootstraps_Call struct { - *mock.Call -} - -// Bootstraps is a helper method to define mock.On call -// - pm sdk.PageMetadata -// - domainID string -// - token string -func (_e *SDK_Expecter) Bootstraps(pm interface{}, domainID interface{}, token interface{}) *SDK_Bootstraps_Call { - return &SDK_Bootstraps_Call{Call: _e.mock.On("Bootstraps", pm, domainID, token)} -} - -func (_c *SDK_Bootstraps_Call) Run(run func(pm sdk.PageMetadata, domainID string, token string)) *SDK_Bootstraps_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.PageMetadata), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Bootstraps_Call) Return(_a0 sdk.BootstrapPage, _a1 errors.SDKError) *SDK_Bootstraps_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Bootstraps_Call) RunAndReturn(run func(sdk.PageMetadata, string, string) (sdk.BootstrapPage, errors.SDKError)) *SDK_Bootstraps_Call { - _c.Call.Return(run) - return _c -} - -// Channel provides a mock function with given fields: id, domainID, token -func (_m *SDK) Channel(id string, domainID string, token string) (sdk.Channel, errors.SDKError) { +// Client provides a mock function with given fields: id, domainID, token +func (_m *SDK) Client(id string, domainID string, token string) (sdk.Client, errors.SDKError) { ret := _m.Called(id, domainID, token) if len(ret) == 0 { - panic("no return value specified for Channel") + panic("no return value specified for Client") } - var r0 sdk.Channel + var r0 sdk.Client var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Channel, errors.SDKError)); ok { + if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Client, errors.SDKError)); ok { return rf(id, domainID, token) } - if rf, ok := ret.Get(0).(func(string, string, string) sdk.Channel); ok { + if rf, ok := ret.Get(0).(func(string, string, string) sdk.Client); ok { r0 = rf(id, domainID, token) } else { - r0 = ret.Get(0).(sdk.Channel) + r0 = ret.Get(0).(sdk.Client) } if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { @@ -959,226 +464,15 @@ func (_m *SDK) Channel(id string, domainID string, token string) (sdk.Channel, e return r0, r1 } -// SDK_Channel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Channel' -type SDK_Channel_Call struct { - *mock.Call -} - -// Channel is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) Channel(id interface{}, domainID interface{}, token interface{}) *SDK_Channel_Call { - return &SDK_Channel_Call{Call: _e.mock.On("Channel", id, domainID, token)} -} - -func (_c *SDK_Channel_Call) Run(run func(id string, domainID string, token string)) *SDK_Channel_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Channel_Call) Return(_a0 sdk.Channel, _a1 errors.SDKError) *SDK_Channel_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Channel_Call) RunAndReturn(run func(string, string, string) (sdk.Channel, errors.SDKError)) *SDK_Channel_Call { - _c.Call.Return(run) - return _c -} - -// Channels provides a mock function with given fields: pm, domainID, token -func (_m *SDK) Channels(pm sdk.PageMetadata, domainID string, token string) (sdk.ChannelsPage, errors.SDKError) { - ret := _m.Called(pm, domainID, token) +// ClientRole provides a mock function with given fields: id, roleID, domainID, token +func (_m *SDK) ClientRole(id string, roleID string, domainID string, token string) (sdk.Role, errors.SDKError) { + ret := _m.Called(id, roleID, domainID, token) if len(ret) == 0 { - panic("no return value specified for Channels") + panic("no return value specified for ClientRole") } - var r0 sdk.ChannelsPage - var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string, string) (sdk.ChannelsPage, errors.SDKError)); ok { - return rf(pm, domainID, token) - } - if rf, ok := ret.Get(0).(func(sdk.PageMetadata, string, string) sdk.ChannelsPage); ok { - r0 = rf(pm, domainID, token) - } else { - r0 = ret.Get(0).(sdk.ChannelsPage) - } - - if rf, ok := ret.Get(1).(func(sdk.PageMetadata, string, string) errors.SDKError); ok { - r1 = rf(pm, domainID, token) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(errors.SDKError) - } - } - - return r0, r1 -} - -// SDK_Channels_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Channels' -type SDK_Channels_Call struct { - *mock.Call -} - -// Channels is a helper method to define mock.On call -// - pm sdk.PageMetadata -// - domainID string -// - token string -func (_e *SDK_Expecter) Channels(pm interface{}, domainID interface{}, token interface{}) *SDK_Channels_Call { - return &SDK_Channels_Call{Call: _e.mock.On("Channels", pm, domainID, token)} -} - -func (_c *SDK_Channels_Call) Run(run func(pm sdk.PageMetadata, domainID string, token string)) *SDK_Channels_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.PageMetadata), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Channels_Call) Return(_a0 sdk.ChannelsPage, _a1 errors.SDKError) *SDK_Channels_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Channels_Call) RunAndReturn(run func(sdk.PageMetadata, string, string) (sdk.ChannelsPage, errors.SDKError)) *SDK_Channels_Call { - _c.Call.Return(run) - return _c -} - -// Children provides a mock function with given fields: id, domainID, pm, token -func (_m *SDK) Children(id string, domainID string, pm sdk.PageMetadata, token string) (sdk.GroupsPage, errors.SDKError) { - ret := _m.Called(id, domainID, pm, token) - - if len(ret) == 0 { - panic("no return value specified for Children") - } - - var r0 sdk.GroupsPage - var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) (sdk.GroupsPage, errors.SDKError)); ok { - return rf(id, domainID, pm, token) - } - if rf, ok := ret.Get(0).(func(string, string, sdk.PageMetadata, string) sdk.GroupsPage); ok { - r0 = rf(id, domainID, pm, token) - } else { - r0 = ret.Get(0).(sdk.GroupsPage) - } - - if rf, ok := ret.Get(1).(func(string, string, sdk.PageMetadata, string) errors.SDKError); ok { - r1 = rf(id, domainID, pm, token) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(errors.SDKError) - } - } - - return r0, r1 -} - -// SDK_Children_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Children' -type SDK_Children_Call struct { - *mock.Call -} - -// Children is a helper method to define mock.On call -// - id string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) Children(id interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_Children_Call { - return &SDK_Children_Call{Call: _e.mock.On("Children", id, domainID, pm, token)} -} - -func (_c *SDK_Children_Call) Run(run func(id string, domainID string, pm sdk.PageMetadata, token string)) *SDK_Children_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string)) - }) - return _c -} - -func (_c *SDK_Children_Call) Return(_a0 sdk.GroupsPage, _a1 errors.SDKError) *SDK_Children_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Children_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.GroupsPage, errors.SDKError)) *SDK_Children_Call { - _c.Call.Return(run) - return _c -} - -// Client provides a mock function with given fields: id, domainID, token -func (_m *SDK) Client(id string, domainID string, token string) (sdk.Client, errors.SDKError) { - ret := _m.Called(id, domainID, token) - - if len(ret) == 0 { - panic("no return value specified for Client") - } - - var r0 sdk.Client - var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string) (sdk.Client, errors.SDKError)); ok { - return rf(id, domainID, token) - } - if rf, ok := ret.Get(0).(func(string, string, string) sdk.Client); ok { - r0 = rf(id, domainID, token) - } else { - r0 = ret.Get(0).(sdk.Client) - } - - if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { - r1 = rf(id, domainID, token) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(errors.SDKError) - } - } - - return r0, r1 -} - -// SDK_Client_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Client' -type SDK_Client_Call struct { - *mock.Call -} - -// Client is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) Client(id interface{}, domainID interface{}, token interface{}) *SDK_Client_Call { - return &SDK_Client_Call{Call: _e.mock.On("Client", id, domainID, token)} -} - -func (_c *SDK_Client_Call) Run(run func(id string, domainID string, token string)) *SDK_Client_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Client_Call) Return(_a0 sdk.Client, _a1 errors.SDKError) *SDK_Client_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Client_Call) RunAndReturn(run func(string, string, string) (sdk.Client, errors.SDKError)) *SDK_Client_Call { - _c.Call.Return(run) - return _c -} - -// ClientRole provides a mock function with given fields: id, roleID, domainID, token -func (_m *SDK) ClientRole(id string, roleID string, domainID string, token string) (sdk.Role, errors.SDKError) { - ret := _m.Called(id, roleID, domainID, token) - - if len(ret) == 0 { - panic("no return value specified for ClientRole") - } - - var r0 sdk.Role + var r0 sdk.Role var r1 errors.SDKError if rf, ok := ret.Get(0).(func(string, string, string, string) (sdk.Role, errors.SDKError)); ok { return rf(id, roleID, domainID, token) @@ -1200,37 +494,6 @@ func (_m *SDK) ClientRole(id string, roleID string, domainID string, token strin return r0, r1 } -// SDK_ClientRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClientRole' -type SDK_ClientRole_Call struct { - *mock.Call -} - -// ClientRole is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) ClientRole(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_ClientRole_Call { - return &SDK_ClientRole_Call{Call: _e.mock.On("ClientRole", id, roleID, domainID, token)} -} - -func (_c *SDK_ClientRole_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_ClientRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_ClientRole_Call) Return(_a0 sdk.Role, _a1 errors.SDKError) *SDK_ClientRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ClientRole_Call) RunAndReturn(run func(string, string, string, string) (sdk.Role, errors.SDKError)) *SDK_ClientRole_Call { - _c.Call.Return(run) - return _c -} - // ClientRoleActions provides a mock function with given fields: id, roleID, domainID, token func (_m *SDK) ClientRoleActions(id string, roleID string, domainID string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, roleID, domainID, token) @@ -1263,37 +526,6 @@ func (_m *SDK) ClientRoleActions(id string, roleID string, domainID string, toke return r0, r1 } -// SDK_ClientRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClientRoleActions' -type SDK_ClientRoleActions_Call struct { - *mock.Call -} - -// ClientRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) ClientRoleActions(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_ClientRoleActions_Call { - return &SDK_ClientRoleActions_Call{Call: _e.mock.On("ClientRoleActions", id, roleID, domainID, token)} -} - -func (_c *SDK_ClientRoleActions_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_ClientRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_ClientRoleActions_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_ClientRoleActions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ClientRoleActions_Call) RunAndReturn(run func(string, string, string, string) ([]string, errors.SDKError)) *SDK_ClientRoleActions_Call { - _c.Call.Return(run) - return _c -} - // ClientRoleMembers provides a mock function with given fields: id, roleID, domainID, pm, token func (_m *SDK) ClientRoleMembers(id string, roleID string, domainID string, pm sdk.PageMetadata, token string) (sdk.RoleMembersPage, errors.SDKError) { ret := _m.Called(id, roleID, domainID, pm, token) @@ -1324,38 +556,6 @@ func (_m *SDK) ClientRoleMembers(id string, roleID string, domainID string, pm s return r0, r1 } -// SDK_ClientRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClientRoleMembers' -type SDK_ClientRoleMembers_Call struct { - *mock.Call -} - -// ClientRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) ClientRoleMembers(id interface{}, roleID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ClientRoleMembers_Call { - return &SDK_ClientRoleMembers_Call{Call: _e.mock.On("ClientRoleMembers", id, roleID, domainID, pm, token)} -} - -func (_c *SDK_ClientRoleMembers_Call) Run(run func(id string, roleID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ClientRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(sdk.PageMetadata), args[4].(string)) - }) - return _c -} - -func (_c *SDK_ClientRoleMembers_Call) Return(_a0 sdk.RoleMembersPage, _a1 errors.SDKError) *SDK_ClientRoleMembers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ClientRoleMembers_Call) RunAndReturn(run func(string, string, string, sdk.PageMetadata, string) (sdk.RoleMembersPage, errors.SDKError)) *SDK_ClientRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // ClientRoles provides a mock function with given fields: id, domainID, pm, token func (_m *SDK) ClientRoles(id string, domainID string, pm sdk.PageMetadata, token string) (sdk.RolesPage, errors.SDKError) { ret := _m.Called(id, domainID, pm, token) @@ -1386,37 +586,6 @@ func (_m *SDK) ClientRoles(id string, domainID string, pm sdk.PageMetadata, toke return r0, r1 } -// SDK_ClientRoles_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ClientRoles' -type SDK_ClientRoles_Call struct { - *mock.Call -} - -// ClientRoles is a helper method to define mock.On call -// - id string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) ClientRoles(id interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ClientRoles_Call { - return &SDK_ClientRoles_Call{Call: _e.mock.On("ClientRoles", id, domainID, pm, token)} -} - -func (_c *SDK_ClientRoles_Call) Run(run func(id string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ClientRoles_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string)) - }) - return _c -} - -func (_c *SDK_ClientRoles_Call) Return(_a0 sdk.RolesPage, _a1 errors.SDKError) *SDK_ClientRoles_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ClientRoles_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.RolesPage, errors.SDKError)) *SDK_ClientRoles_Call { - _c.Call.Return(run) - return _c -} - // Clients provides a mock function with given fields: pm, domainID, token func (_m *SDK) Clients(pm sdk.PageMetadata, domainID string, token string) (sdk.ClientsPage, errors.SDKError) { ret := _m.Called(pm, domainID, token) @@ -1447,36 +616,6 @@ func (_m *SDK) Clients(pm sdk.PageMetadata, domainID string, token string) (sdk. return r0, r1 } -// SDK_Clients_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Clients' -type SDK_Clients_Call struct { - *mock.Call -} - -// Clients is a helper method to define mock.On call -// - pm sdk.PageMetadata -// - domainID string -// - token string -func (_e *SDK_Expecter) Clients(pm interface{}, domainID interface{}, token interface{}) *SDK_Clients_Call { - return &SDK_Clients_Call{Call: _e.mock.On("Clients", pm, domainID, token)} -} - -func (_c *SDK_Clients_Call) Run(run func(pm sdk.PageMetadata, domainID string, token string)) *SDK_Clients_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.PageMetadata), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Clients_Call) Return(_a0 sdk.ClientsPage, _a1 errors.SDKError) *SDK_Clients_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Clients_Call) RunAndReturn(run func(sdk.PageMetadata, string, string) (sdk.ClientsPage, errors.SDKError)) *SDK_Clients_Call { - _c.Call.Return(run) - return _c -} - // Connect provides a mock function with given fields: conn, domainID, token func (_m *SDK) Connect(conn sdk.Connection, domainID string, token string) errors.SDKError { ret := _m.Called(conn, domainID, token) @@ -1497,36 +636,6 @@ func (_m *SDK) Connect(conn sdk.Connection, domainID string, token string) error return r0 } -// SDK_Connect_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Connect' -type SDK_Connect_Call struct { - *mock.Call -} - -// Connect is a helper method to define mock.On call -// - conn sdk.Connection -// - domainID string -// - token string -func (_e *SDK_Expecter) Connect(conn interface{}, domainID interface{}, token interface{}) *SDK_Connect_Call { - return &SDK_Connect_Call{Call: _e.mock.On("Connect", conn, domainID, token)} -} - -func (_c *SDK_Connect_Call) Run(run func(conn sdk.Connection, domainID string, token string)) *SDK_Connect_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Connection), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Connect_Call) Return(_a0 errors.SDKError) *SDK_Connect_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_Connect_Call) RunAndReturn(run func(sdk.Connection, string, string) errors.SDKError) *SDK_Connect_Call { - _c.Call.Return(run) - return _c -} - // ConnectClients provides a mock function with given fields: channelID, clientIDs, connTypes, domainID, token func (_m *SDK) ConnectClients(channelID string, clientIDs []string, connTypes []string, domainID string, token string) errors.SDKError { ret := _m.Called(channelID, clientIDs, connTypes, domainID, token) @@ -1547,38 +656,6 @@ func (_m *SDK) ConnectClients(channelID string, clientIDs []string, connTypes [] return r0 } -// SDK_ConnectClients_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConnectClients' -type SDK_ConnectClients_Call struct { - *mock.Call -} - -// ConnectClients is a helper method to define mock.On call -// - channelID string -// - clientIDs []string -// - connTypes []string -// - domainID string -// - token string -func (_e *SDK_Expecter) ConnectClients(channelID interface{}, clientIDs interface{}, connTypes interface{}, domainID interface{}, token interface{}) *SDK_ConnectClients_Call { - return &SDK_ConnectClients_Call{Call: _e.mock.On("ConnectClients", channelID, clientIDs, connTypes, domainID, token)} -} - -func (_c *SDK_ConnectClients_Call) Run(run func(channelID string, clientIDs []string, connTypes []string, domainID string, token string)) *SDK_ConnectClients_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].([]string), args[2].([]string), args[3].(string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_ConnectClients_Call) Return(_a0 errors.SDKError) *SDK_ConnectClients_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_ConnectClients_Call) RunAndReturn(run func(string, []string, []string, string, string) errors.SDKError) *SDK_ConnectClients_Call { - _c.Call.Return(run) - return _c -} - // CreateChannel provides a mock function with given fields: channel, domainID, token func (_m *SDK) CreateChannel(channel sdk.Channel, domainID string, token string) (sdk.Channel, errors.SDKError) { ret := _m.Called(channel, domainID, token) @@ -1609,36 +686,6 @@ func (_m *SDK) CreateChannel(channel sdk.Channel, domainID string, token string) return r0, r1 } -// SDK_CreateChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateChannel' -type SDK_CreateChannel_Call struct { - *mock.Call -} - -// CreateChannel is a helper method to define mock.On call -// - channel sdk.Channel -// - domainID string -// - token string -func (_e *SDK_Expecter) CreateChannel(channel interface{}, domainID interface{}, token interface{}) *SDK_CreateChannel_Call { - return &SDK_CreateChannel_Call{Call: _e.mock.On("CreateChannel", channel, domainID, token)} -} - -func (_c *SDK_CreateChannel_Call) Run(run func(channel sdk.Channel, domainID string, token string)) *SDK_CreateChannel_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Channel), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_CreateChannel_Call) Return(_a0 sdk.Channel, _a1 errors.SDKError) *SDK_CreateChannel_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateChannel_Call) RunAndReturn(run func(sdk.Channel, string, string) (sdk.Channel, errors.SDKError)) *SDK_CreateChannel_Call { - _c.Call.Return(run) - return _c -} - // CreateChannels provides a mock function with given fields: channels, domainID, token func (_m *SDK) CreateChannels(channels []sdk.Channel, domainID string, token string) ([]sdk.Channel, errors.SDKError) { ret := _m.Called(channels, domainID, token) @@ -1671,36 +718,6 @@ func (_m *SDK) CreateChannels(channels []sdk.Channel, domainID string, token str return r0, r1 } -// SDK_CreateChannels_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateChannels' -type SDK_CreateChannels_Call struct { - *mock.Call -} - -// CreateChannels is a helper method to define mock.On call -// - channels []sdk.Channel -// - domainID string -// - token string -func (_e *SDK_Expecter) CreateChannels(channels interface{}, domainID interface{}, token interface{}) *SDK_CreateChannels_Call { - return &SDK_CreateChannels_Call{Call: _e.mock.On("CreateChannels", channels, domainID, token)} -} - -func (_c *SDK_CreateChannels_Call) Run(run func(channels []sdk.Channel, domainID string, token string)) *SDK_CreateChannels_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]sdk.Channel), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_CreateChannels_Call) Return(_a0 []sdk.Channel, _a1 errors.SDKError) *SDK_CreateChannels_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateChannels_Call) RunAndReturn(run func([]sdk.Channel, string, string) ([]sdk.Channel, errors.SDKError)) *SDK_CreateChannels_Call { - _c.Call.Return(run) - return _c -} - // CreateClient provides a mock function with given fields: client, domainID, token func (_m *SDK) CreateClient(client sdk.Client, domainID string, token string) (sdk.Client, errors.SDKError) { ret := _m.Called(client, domainID, token) @@ -1731,36 +748,6 @@ func (_m *SDK) CreateClient(client sdk.Client, domainID string, token string) (s return r0, r1 } -// SDK_CreateClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateClient' -type SDK_CreateClient_Call struct { - *mock.Call -} - -// CreateClient is a helper method to define mock.On call -// - client sdk.Client -// - domainID string -// - token string -func (_e *SDK_Expecter) CreateClient(client interface{}, domainID interface{}, token interface{}) *SDK_CreateClient_Call { - return &SDK_CreateClient_Call{Call: _e.mock.On("CreateClient", client, domainID, token)} -} - -func (_c *SDK_CreateClient_Call) Run(run func(client sdk.Client, domainID string, token string)) *SDK_CreateClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Client), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_CreateClient_Call) Return(_a0 sdk.Client, _a1 errors.SDKError) *SDK_CreateClient_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateClient_Call) RunAndReturn(run func(sdk.Client, string, string) (sdk.Client, errors.SDKError)) *SDK_CreateClient_Call { - _c.Call.Return(run) - return _c -} - // CreateClientRole provides a mock function with given fields: id, domainID, rq, token func (_m *SDK) CreateClientRole(id string, domainID string, rq sdk.RoleReq, token string) (sdk.Role, errors.SDKError) { ret := _m.Called(id, domainID, rq, token) @@ -1791,37 +778,6 @@ func (_m *SDK) CreateClientRole(id string, domainID string, rq sdk.RoleReq, toke return r0, r1 } -// SDK_CreateClientRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateClientRole' -type SDK_CreateClientRole_Call struct { - *mock.Call -} - -// CreateClientRole is a helper method to define mock.On call -// - id string -// - domainID string -// - rq sdk.RoleReq -// - token string -func (_e *SDK_Expecter) CreateClientRole(id interface{}, domainID interface{}, rq interface{}, token interface{}) *SDK_CreateClientRole_Call { - return &SDK_CreateClientRole_Call{Call: _e.mock.On("CreateClientRole", id, domainID, rq, token)} -} - -func (_c *SDK_CreateClientRole_Call) Run(run func(id string, domainID string, rq sdk.RoleReq, token string)) *SDK_CreateClientRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.RoleReq), args[3].(string)) - }) - return _c -} - -func (_c *SDK_CreateClientRole_Call) Return(_a0 sdk.Role, _a1 errors.SDKError) *SDK_CreateClientRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateClientRole_Call) RunAndReturn(run func(string, string, sdk.RoleReq, string) (sdk.Role, errors.SDKError)) *SDK_CreateClientRole_Call { - _c.Call.Return(run) - return _c -} - // CreateClients provides a mock function with given fields: client, domainID, token func (_m *SDK) CreateClients(client []sdk.Client, domainID string, token string) ([]sdk.Client, errors.SDKError) { ret := _m.Called(client, domainID, token) @@ -1854,36 +810,6 @@ func (_m *SDK) CreateClients(client []sdk.Client, domainID string, token string) return r0, r1 } -// SDK_CreateClients_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateClients' -type SDK_CreateClients_Call struct { - *mock.Call -} - -// CreateClients is a helper method to define mock.On call -// - client []sdk.Client -// - domainID string -// - token string -func (_e *SDK_Expecter) CreateClients(client interface{}, domainID interface{}, token interface{}) *SDK_CreateClients_Call { - return &SDK_CreateClients_Call{Call: _e.mock.On("CreateClients", client, domainID, token)} -} - -func (_c *SDK_CreateClients_Call) Run(run func(client []sdk.Client, domainID string, token string)) *SDK_CreateClients_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].([]sdk.Client), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_CreateClients_Call) Return(_a0 []sdk.Client, _a1 errors.SDKError) *SDK_CreateClients_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateClients_Call) RunAndReturn(run func([]sdk.Client, string, string) ([]sdk.Client, errors.SDKError)) *SDK_CreateClients_Call { - _c.Call.Return(run) - return _c -} - // CreateDomain provides a mock function with given fields: d, token func (_m *SDK) CreateDomain(d sdk.Domain, token string) (sdk.Domain, errors.SDKError) { ret := _m.Called(d, token) @@ -1914,35 +840,6 @@ func (_m *SDK) CreateDomain(d sdk.Domain, token string) (sdk.Domain, errors.SDKE return r0, r1 } -// SDK_CreateDomain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateDomain' -type SDK_CreateDomain_Call struct { - *mock.Call -} - -// CreateDomain is a helper method to define mock.On call -// - d sdk.Domain -// - token string -func (_e *SDK_Expecter) CreateDomain(d interface{}, token interface{}) *SDK_CreateDomain_Call { - return &SDK_CreateDomain_Call{Call: _e.mock.On("CreateDomain", d, token)} -} - -func (_c *SDK_CreateDomain_Call) Run(run func(d sdk.Domain, token string)) *SDK_CreateDomain_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Domain), args[1].(string)) - }) - return _c -} - -func (_c *SDK_CreateDomain_Call) Return(_a0 sdk.Domain, _a1 errors.SDKError) *SDK_CreateDomain_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateDomain_Call) RunAndReturn(run func(sdk.Domain, string) (sdk.Domain, errors.SDKError)) *SDK_CreateDomain_Call { - _c.Call.Return(run) - return _c -} - // CreateDomainRole provides a mock function with given fields: id, rq, token func (_m *SDK) CreateDomainRole(id string, rq sdk.RoleReq, token string) (sdk.Role, errors.SDKError) { ret := _m.Called(id, rq, token) @@ -1973,39 +870,9 @@ func (_m *SDK) CreateDomainRole(id string, rq sdk.RoleReq, token string) (sdk.Ro return r0, r1 } -// SDK_CreateDomainRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateDomainRole' -type SDK_CreateDomainRole_Call struct { - *mock.Call -} - -// CreateDomainRole is a helper method to define mock.On call -// - id string -// - rq sdk.RoleReq -// - token string -func (_e *SDK_Expecter) CreateDomainRole(id interface{}, rq interface{}, token interface{}) *SDK_CreateDomainRole_Call { - return &SDK_CreateDomainRole_Call{Call: _e.mock.On("CreateDomainRole", id, rq, token)} -} - -func (_c *SDK_CreateDomainRole_Call) Run(run func(id string, rq sdk.RoleReq, token string)) *SDK_CreateDomainRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(sdk.RoleReq), args[2].(string)) - }) - return _c -} - -func (_c *SDK_CreateDomainRole_Call) Return(_a0 sdk.Role, _a1 errors.SDKError) *SDK_CreateDomainRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateDomainRole_Call) RunAndReturn(run func(string, sdk.RoleReq, string) (sdk.Role, errors.SDKError)) *SDK_CreateDomainRole_Call { - _c.Call.Return(run) - return _c -} - -// CreateGroup provides a mock function with given fields: group, domainID, token -func (_m *SDK) CreateGroup(group sdk.Group, domainID string, token string) (sdk.Group, errors.SDKError) { - ret := _m.Called(group, domainID, token) +// CreateGroup provides a mock function with given fields: group, domainID, token +func (_m *SDK) CreateGroup(group sdk.Group, domainID string, token string) (sdk.Group, errors.SDKError) { + ret := _m.Called(group, domainID, token) if len(ret) == 0 { panic("no return value specified for CreateGroup") @@ -2033,36 +900,6 @@ func (_m *SDK) CreateGroup(group sdk.Group, domainID string, token string) (sdk. return r0, r1 } -// SDK_CreateGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateGroup' -type SDK_CreateGroup_Call struct { - *mock.Call -} - -// CreateGroup is a helper method to define mock.On call -// - group sdk.Group -// - domainID string -// - token string -func (_e *SDK_Expecter) CreateGroup(group interface{}, domainID interface{}, token interface{}) *SDK_CreateGroup_Call { - return &SDK_CreateGroup_Call{Call: _e.mock.On("CreateGroup", group, domainID, token)} -} - -func (_c *SDK_CreateGroup_Call) Run(run func(group sdk.Group, domainID string, token string)) *SDK_CreateGroup_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Group), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_CreateGroup_Call) Return(_a0 sdk.Group, _a1 errors.SDKError) *SDK_CreateGroup_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateGroup_Call) RunAndReturn(run func(sdk.Group, string, string) (sdk.Group, errors.SDKError)) *SDK_CreateGroup_Call { - _c.Call.Return(run) - return _c -} - // CreateGroupRole provides a mock function with given fields: id, domainID, rq, token func (_m *SDK) CreateGroupRole(id string, domainID string, rq sdk.RoleReq, token string) (sdk.Role, errors.SDKError) { ret := _m.Called(id, domainID, rq, token) @@ -2093,37 +930,6 @@ func (_m *SDK) CreateGroupRole(id string, domainID string, rq sdk.RoleReq, token return r0, r1 } -// SDK_CreateGroupRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateGroupRole' -type SDK_CreateGroupRole_Call struct { - *mock.Call -} - -// CreateGroupRole is a helper method to define mock.On call -// - id string -// - domainID string -// - rq sdk.RoleReq -// - token string -func (_e *SDK_Expecter) CreateGroupRole(id interface{}, domainID interface{}, rq interface{}, token interface{}) *SDK_CreateGroupRole_Call { - return &SDK_CreateGroupRole_Call{Call: _e.mock.On("CreateGroupRole", id, domainID, rq, token)} -} - -func (_c *SDK_CreateGroupRole_Call) Run(run func(id string, domainID string, rq sdk.RoleReq, token string)) *SDK_CreateGroupRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.RoleReq), args[3].(string)) - }) - return _c -} - -func (_c *SDK_CreateGroupRole_Call) Return(_a0 sdk.Role, _a1 errors.SDKError) *SDK_CreateGroupRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateGroupRole_Call) RunAndReturn(run func(string, string, sdk.RoleReq, string) (sdk.Role, errors.SDKError)) *SDK_CreateGroupRole_Call { - _c.Call.Return(run) - return _c -} - // CreateSubscription provides a mock function with given fields: topic, contact, token func (_m *SDK) CreateSubscription(topic string, contact string, token string) (string, errors.SDKError) { ret := _m.Called(topic, contact, token) @@ -2154,36 +960,6 @@ func (_m *SDK) CreateSubscription(topic string, contact string, token string) (s return r0, r1 } -// SDK_CreateSubscription_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateSubscription' -type SDK_CreateSubscription_Call struct { - *mock.Call -} - -// CreateSubscription is a helper method to define mock.On call -// - topic string -// - contact string -// - token string -func (_e *SDK_Expecter) CreateSubscription(topic interface{}, contact interface{}, token interface{}) *SDK_CreateSubscription_Call { - return &SDK_CreateSubscription_Call{Call: _e.mock.On("CreateSubscription", topic, contact, token)} -} - -func (_c *SDK_CreateSubscription_Call) Run(run func(topic string, contact string, token string)) *SDK_CreateSubscription_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_CreateSubscription_Call) Return(_a0 string, _a1 errors.SDKError) *SDK_CreateSubscription_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateSubscription_Call) RunAndReturn(run func(string, string, string) (string, errors.SDKError)) *SDK_CreateSubscription_Call { - _c.Call.Return(run) - return _c -} - // CreateToken provides a mock function with given fields: lt func (_m *SDK) CreateToken(lt sdk.Login) (sdk.Token, errors.SDKError) { ret := _m.Called(lt) @@ -2214,34 +990,6 @@ func (_m *SDK) CreateToken(lt sdk.Login) (sdk.Token, errors.SDKError) { return r0, r1 } -// SDK_CreateToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateToken' -type SDK_CreateToken_Call struct { - *mock.Call -} - -// CreateToken is a helper method to define mock.On call -// - lt sdk.Login -func (_e *SDK_Expecter) CreateToken(lt interface{}) *SDK_CreateToken_Call { - return &SDK_CreateToken_Call{Call: _e.mock.On("CreateToken", lt)} -} - -func (_c *SDK_CreateToken_Call) Run(run func(lt sdk.Login)) *SDK_CreateToken_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Login)) - }) - return _c -} - -func (_c *SDK_CreateToken_Call) Return(_a0 sdk.Token, _a1 errors.SDKError) *SDK_CreateToken_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateToken_Call) RunAndReturn(run func(sdk.Login) (sdk.Token, errors.SDKError)) *SDK_CreateToken_Call { - _c.Call.Return(run) - return _c -} - // CreateUser provides a mock function with given fields: user, token func (_m *SDK) CreateUser(user sdk.User, token string) (sdk.User, errors.SDKError) { ret := _m.Called(user, token) @@ -2272,35 +1020,6 @@ func (_m *SDK) CreateUser(user sdk.User, token string) (sdk.User, errors.SDKErro return r0, r1 } -// SDK_CreateUser_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateUser' -type SDK_CreateUser_Call struct { - *mock.Call -} - -// CreateUser is a helper method to define mock.On call -// - user sdk.User -// - token string -func (_e *SDK_Expecter) CreateUser(user interface{}, token interface{}) *SDK_CreateUser_Call { - return &SDK_CreateUser_Call{Call: _e.mock.On("CreateUser", user, token)} -} - -func (_c *SDK_CreateUser_Call) Run(run func(user sdk.User, token string)) *SDK_CreateUser_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.User), args[1].(string)) - }) - return _c -} - -func (_c *SDK_CreateUser_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_CreateUser_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_CreateUser_Call) RunAndReturn(run func(sdk.User, string) (sdk.User, errors.SDKError)) *SDK_CreateUser_Call { - _c.Call.Return(run) - return _c -} - // DeleteChannel provides a mock function with given fields: id, domainID, token func (_m *SDK) DeleteChannel(id string, domainID string, token string) errors.SDKError { ret := _m.Called(id, domainID, token) @@ -2321,36 +1040,6 @@ func (_m *SDK) DeleteChannel(id string, domainID string, token string) errors.SD return r0 } -// SDK_DeleteChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteChannel' -type SDK_DeleteChannel_Call struct { - *mock.Call -} - -// DeleteChannel is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) DeleteChannel(id interface{}, domainID interface{}, token interface{}) *SDK_DeleteChannel_Call { - return &SDK_DeleteChannel_Call{Call: _e.mock.On("DeleteChannel", id, domainID, token)} -} - -func (_c *SDK_DeleteChannel_Call) Run(run func(id string, domainID string, token string)) *SDK_DeleteChannel_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DeleteChannel_Call) Return(_a0 errors.SDKError) *SDK_DeleteChannel_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DeleteChannel_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_DeleteChannel_Call { - _c.Call.Return(run) - return _c -} - // DeleteClient provides a mock function with given fields: id, domainID, token func (_m *SDK) DeleteClient(id string, domainID string, token string) errors.SDKError { ret := _m.Called(id, domainID, token) @@ -2371,36 +1060,6 @@ func (_m *SDK) DeleteClient(id string, domainID string, token string) errors.SDK return r0 } -// SDK_DeleteClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteClient' -type SDK_DeleteClient_Call struct { - *mock.Call -} - -// DeleteClient is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) DeleteClient(id interface{}, domainID interface{}, token interface{}) *SDK_DeleteClient_Call { - return &SDK_DeleteClient_Call{Call: _e.mock.On("DeleteClient", id, domainID, token)} -} - -func (_c *SDK_DeleteClient_Call) Run(run func(id string, domainID string, token string)) *SDK_DeleteClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DeleteClient_Call) Return(_a0 errors.SDKError) *SDK_DeleteClient_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DeleteClient_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_DeleteClient_Call { - _c.Call.Return(run) - return _c -} - // DeleteClientRole provides a mock function with given fields: id, roleID, domainID, token func (_m *SDK) DeleteClientRole(id string, roleID string, domainID string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, token) @@ -2421,37 +1080,6 @@ func (_m *SDK) DeleteClientRole(id string, roleID string, domainID string, token return r0 } -// SDK_DeleteClientRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteClientRole' -type SDK_DeleteClientRole_Call struct { - *mock.Call -} - -// DeleteClientRole is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) DeleteClientRole(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_DeleteClientRole_Call { - return &SDK_DeleteClientRole_Call{Call: _e.mock.On("DeleteClientRole", id, roleID, domainID, token)} -} - -func (_c *SDK_DeleteClientRole_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_DeleteClientRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_DeleteClientRole_Call) Return(_a0 errors.SDKError) *SDK_DeleteClientRole_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DeleteClientRole_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_DeleteClientRole_Call { - _c.Call.Return(run) - return _c -} - // DeleteDomainRole provides a mock function with given fields: id, roleID, token func (_m *SDK) DeleteDomainRole(id string, roleID string, token string) errors.SDKError { ret := _m.Called(id, roleID, token) @@ -2472,36 +1100,6 @@ func (_m *SDK) DeleteDomainRole(id string, roleID string, token string) errors.S return r0 } -// SDK_DeleteDomainRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteDomainRole' -type SDK_DeleteDomainRole_Call struct { - *mock.Call -} - -// DeleteDomainRole is a helper method to define mock.On call -// - id string -// - roleID string -// - token string -func (_e *SDK_Expecter) DeleteDomainRole(id interface{}, roleID interface{}, token interface{}) *SDK_DeleteDomainRole_Call { - return &SDK_DeleteDomainRole_Call{Call: _e.mock.On("DeleteDomainRole", id, roleID, token)} -} - -func (_c *SDK_DeleteDomainRole_Call) Run(run func(id string, roleID string, token string)) *SDK_DeleteDomainRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DeleteDomainRole_Call) Return(_a0 errors.SDKError) *SDK_DeleteDomainRole_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DeleteDomainRole_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_DeleteDomainRole_Call { - _c.Call.Return(run) - return _c -} - // DeleteGroup provides a mock function with given fields: id, domainID, token func (_m *SDK) DeleteGroup(id string, domainID string, token string) errors.SDKError { ret := _m.Called(id, domainID, token) @@ -2522,36 +1120,6 @@ func (_m *SDK) DeleteGroup(id string, domainID string, token string) errors.SDKE return r0 } -// SDK_DeleteGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteGroup' -type SDK_DeleteGroup_Call struct { - *mock.Call -} - -// DeleteGroup is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) DeleteGroup(id interface{}, domainID interface{}, token interface{}) *SDK_DeleteGroup_Call { - return &SDK_DeleteGroup_Call{Call: _e.mock.On("DeleteGroup", id, domainID, token)} -} - -func (_c *SDK_DeleteGroup_Call) Run(run func(id string, domainID string, token string)) *SDK_DeleteGroup_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DeleteGroup_Call) Return(_a0 errors.SDKError) *SDK_DeleteGroup_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DeleteGroup_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_DeleteGroup_Call { - _c.Call.Return(run) - return _c -} - // DeleteGroupRole provides a mock function with given fields: id, roleID, domainID, token func (_m *SDK) DeleteGroupRole(id string, roleID string, domainID string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, token) @@ -2572,37 +1140,6 @@ func (_m *SDK) DeleteGroupRole(id string, roleID string, domainID string, token return r0 } -// SDK_DeleteGroupRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteGroupRole' -type SDK_DeleteGroupRole_Call struct { - *mock.Call -} - -// DeleteGroupRole is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) DeleteGroupRole(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_DeleteGroupRole_Call { - return &SDK_DeleteGroupRole_Call{Call: _e.mock.On("DeleteGroupRole", id, roleID, domainID, token)} -} - -func (_c *SDK_DeleteGroupRole_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_DeleteGroupRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_DeleteGroupRole_Call) Return(_a0 errors.SDKError) *SDK_DeleteGroupRole_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DeleteGroupRole_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_DeleteGroupRole_Call { - _c.Call.Return(run) - return _c -} - // DeleteInvitation provides a mock function with given fields: userID, domainID, token func (_m *SDK) DeleteInvitation(userID string, domainID string, token string) error { ret := _m.Called(userID, domainID, token) @@ -2621,36 +1158,6 @@ func (_m *SDK) DeleteInvitation(userID string, domainID string, token string) er return r0 } -// SDK_DeleteInvitation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteInvitation' -type SDK_DeleteInvitation_Call struct { - *mock.Call -} - -// DeleteInvitation is a helper method to define mock.On call -// - userID string -// - domainID string -// - token string -func (_e *SDK_Expecter) DeleteInvitation(userID interface{}, domainID interface{}, token interface{}) *SDK_DeleteInvitation_Call { - return &SDK_DeleteInvitation_Call{Call: _e.mock.On("DeleteInvitation", userID, domainID, token)} -} - -func (_c *SDK_DeleteInvitation_Call) Run(run func(userID string, domainID string, token string)) *SDK_DeleteInvitation_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DeleteInvitation_Call) Return(err error) *SDK_DeleteInvitation_Call { - _c.Call.Return(err) - return _c -} - -func (_c *SDK_DeleteInvitation_Call) RunAndReturn(run func(string, string, string) error) *SDK_DeleteInvitation_Call { - _c.Call.Return(run) - return _c -} - // DeleteSubscription provides a mock function with given fields: id, token func (_m *SDK) DeleteSubscription(id string, token string) errors.SDKError { ret := _m.Called(id, token) @@ -2671,35 +1178,6 @@ func (_m *SDK) DeleteSubscription(id string, token string) errors.SDKError { return r0 } -// SDK_DeleteSubscription_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteSubscription' -type SDK_DeleteSubscription_Call struct { - *mock.Call -} - -// DeleteSubscription is a helper method to define mock.On call -// - id string -// - token string -func (_e *SDK_Expecter) DeleteSubscription(id interface{}, token interface{}) *SDK_DeleteSubscription_Call { - return &SDK_DeleteSubscription_Call{Call: _e.mock.On("DeleteSubscription", id, token)} -} - -func (_c *SDK_DeleteSubscription_Call) Run(run func(id string, token string)) *SDK_DeleteSubscription_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_DeleteSubscription_Call) Return(_a0 errors.SDKError) *SDK_DeleteSubscription_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DeleteSubscription_Call) RunAndReturn(run func(string, string) errors.SDKError) *SDK_DeleteSubscription_Call { - _c.Call.Return(run) - return _c -} - // DeleteUser provides a mock function with given fields: id, token func (_m *SDK) DeleteUser(id string, token string) errors.SDKError { ret := _m.Called(id, token) @@ -2720,35 +1198,6 @@ func (_m *SDK) DeleteUser(id string, token string) errors.SDKError { return r0 } -// SDK_DeleteUser_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteUser' -type SDK_DeleteUser_Call struct { - *mock.Call -} - -// DeleteUser is a helper method to define mock.On call -// - id string -// - token string -func (_e *SDK_Expecter) DeleteUser(id interface{}, token interface{}) *SDK_DeleteUser_Call { - return &SDK_DeleteUser_Call{Call: _e.mock.On("DeleteUser", id, token)} -} - -func (_c *SDK_DeleteUser_Call) Run(run func(id string, token string)) *SDK_DeleteUser_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_DeleteUser_Call) Return(_a0 errors.SDKError) *SDK_DeleteUser_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DeleteUser_Call) RunAndReturn(run func(string, string) errors.SDKError) *SDK_DeleteUser_Call { - _c.Call.Return(run) - return _c -} - // DisableChannel provides a mock function with given fields: id, domainID, token func (_m *SDK) DisableChannel(id string, domainID string, token string) (sdk.Channel, errors.SDKError) { ret := _m.Called(id, domainID, token) @@ -2779,36 +1228,6 @@ func (_m *SDK) DisableChannel(id string, domainID string, token string) (sdk.Cha return r0, r1 } -// SDK_DisableChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisableChannel' -type SDK_DisableChannel_Call struct { - *mock.Call -} - -// DisableChannel is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) DisableChannel(id interface{}, domainID interface{}, token interface{}) *SDK_DisableChannel_Call { - return &SDK_DisableChannel_Call{Call: _e.mock.On("DisableChannel", id, domainID, token)} -} - -func (_c *SDK_DisableChannel_Call) Run(run func(id string, domainID string, token string)) *SDK_DisableChannel_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DisableChannel_Call) Return(_a0 sdk.Channel, _a1 errors.SDKError) *SDK_DisableChannel_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_DisableChannel_Call) RunAndReturn(run func(string, string, string) (sdk.Channel, errors.SDKError)) *SDK_DisableChannel_Call { - _c.Call.Return(run) - return _c -} - // DisableClient provides a mock function with given fields: id, domainID, token func (_m *SDK) DisableClient(id string, domainID string, token string) (sdk.Client, errors.SDKError) { ret := _m.Called(id, domainID, token) @@ -2839,36 +1258,6 @@ func (_m *SDK) DisableClient(id string, domainID string, token string) (sdk.Clie return r0, r1 } -// SDK_DisableClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisableClient' -type SDK_DisableClient_Call struct { - *mock.Call -} - -// DisableClient is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) DisableClient(id interface{}, domainID interface{}, token interface{}) *SDK_DisableClient_Call { - return &SDK_DisableClient_Call{Call: _e.mock.On("DisableClient", id, domainID, token)} -} - -func (_c *SDK_DisableClient_Call) Run(run func(id string, domainID string, token string)) *SDK_DisableClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DisableClient_Call) Return(_a0 sdk.Client, _a1 errors.SDKError) *SDK_DisableClient_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_DisableClient_Call) RunAndReturn(run func(string, string, string) (sdk.Client, errors.SDKError)) *SDK_DisableClient_Call { - _c.Call.Return(run) - return _c -} - // DisableDomain provides a mock function with given fields: domainID, token func (_m *SDK) DisableDomain(domainID string, token string) errors.SDKError { ret := _m.Called(domainID, token) @@ -2889,35 +1278,6 @@ func (_m *SDK) DisableDomain(domainID string, token string) errors.SDKError { return r0 } -// SDK_DisableDomain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisableDomain' -type SDK_DisableDomain_Call struct { - *mock.Call -} - -// DisableDomain is a helper method to define mock.On call -// - domainID string -// - token string -func (_e *SDK_Expecter) DisableDomain(domainID interface{}, token interface{}) *SDK_DisableDomain_Call { - return &SDK_DisableDomain_Call{Call: _e.mock.On("DisableDomain", domainID, token)} -} - -func (_c *SDK_DisableDomain_Call) Run(run func(domainID string, token string)) *SDK_DisableDomain_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_DisableDomain_Call) Return(_a0 errors.SDKError) *SDK_DisableDomain_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DisableDomain_Call) RunAndReturn(run func(string, string) errors.SDKError) *SDK_DisableDomain_Call { - _c.Call.Return(run) - return _c -} - // DisableGroup provides a mock function with given fields: id, domainID, token func (_m *SDK) DisableGroup(id string, domainID string, token string) (sdk.Group, errors.SDKError) { ret := _m.Called(id, domainID, token) @@ -2948,36 +1308,6 @@ func (_m *SDK) DisableGroup(id string, domainID string, token string) (sdk.Group return r0, r1 } -// SDK_DisableGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisableGroup' -type SDK_DisableGroup_Call struct { - *mock.Call -} - -// DisableGroup is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) DisableGroup(id interface{}, domainID interface{}, token interface{}) *SDK_DisableGroup_Call { - return &SDK_DisableGroup_Call{Call: _e.mock.On("DisableGroup", id, domainID, token)} -} - -func (_c *SDK_DisableGroup_Call) Run(run func(id string, domainID string, token string)) *SDK_DisableGroup_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DisableGroup_Call) Return(_a0 sdk.Group, _a1 errors.SDKError) *SDK_DisableGroup_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_DisableGroup_Call) RunAndReturn(run func(string, string, string) (sdk.Group, errors.SDKError)) *SDK_DisableGroup_Call { - _c.Call.Return(run) - return _c -} - // DisableUser provides a mock function with given fields: id, token func (_m *SDK) DisableUser(id string, token string) (sdk.User, errors.SDKError) { ret := _m.Called(id, token) @@ -3008,35 +1338,6 @@ func (_m *SDK) DisableUser(id string, token string) (sdk.User, errors.SDKError) return r0, r1 } -// SDK_DisableUser_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisableUser' -type SDK_DisableUser_Call struct { - *mock.Call -} - -// DisableUser is a helper method to define mock.On call -// - id string -// - token string -func (_e *SDK_Expecter) DisableUser(id interface{}, token interface{}) *SDK_DisableUser_Call { - return &SDK_DisableUser_Call{Call: _e.mock.On("DisableUser", id, token)} -} - -func (_c *SDK_DisableUser_Call) Run(run func(id string, token string)) *SDK_DisableUser_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_DisableUser_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_DisableUser_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_DisableUser_Call) RunAndReturn(run func(string, string) (sdk.User, errors.SDKError)) *SDK_DisableUser_Call { - _c.Call.Return(run) - return _c -} - // Disconnect provides a mock function with given fields: conn, domainID, token func (_m *SDK) Disconnect(conn sdk.Connection, domainID string, token string) errors.SDKError { ret := _m.Called(conn, domainID, token) @@ -3057,36 +1358,6 @@ func (_m *SDK) Disconnect(conn sdk.Connection, domainID string, token string) er return r0 } -// SDK_Disconnect_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Disconnect' -type SDK_Disconnect_Call struct { - *mock.Call -} - -// Disconnect is a helper method to define mock.On call -// - conn sdk.Connection -// - domainID string -// - token string -func (_e *SDK_Expecter) Disconnect(conn interface{}, domainID interface{}, token interface{}) *SDK_Disconnect_Call { - return &SDK_Disconnect_Call{Call: _e.mock.On("Disconnect", conn, domainID, token)} -} - -func (_c *SDK_Disconnect_Call) Run(run func(conn sdk.Connection, domainID string, token string)) *SDK_Disconnect_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Connection), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Disconnect_Call) Return(_a0 errors.SDKError) *SDK_Disconnect_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_Disconnect_Call) RunAndReturn(run func(sdk.Connection, string, string) errors.SDKError) *SDK_Disconnect_Call { - _c.Call.Return(run) - return _c -} - // DisconnectClients provides a mock function with given fields: channelID, clientIDs, connTypes, domainID, token func (_m *SDK) DisconnectClients(channelID string, clientIDs []string, connTypes []string, domainID string, token string) errors.SDKError { ret := _m.Called(channelID, clientIDs, connTypes, domainID, token) @@ -3107,38 +1378,6 @@ func (_m *SDK) DisconnectClients(channelID string, clientIDs []string, connTypes return r0 } -// SDK_DisconnectClients_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DisconnectClients' -type SDK_DisconnectClients_Call struct { - *mock.Call -} - -// DisconnectClients is a helper method to define mock.On call -// - channelID string -// - clientIDs []string -// - connTypes []string -// - domainID string -// - token string -func (_e *SDK_Expecter) DisconnectClients(channelID interface{}, clientIDs interface{}, connTypes interface{}, domainID interface{}, token interface{}) *SDK_DisconnectClients_Call { - return &SDK_DisconnectClients_Call{Call: _e.mock.On("DisconnectClients", channelID, clientIDs, connTypes, domainID, token)} -} - -func (_c *SDK_DisconnectClients_Call) Run(run func(channelID string, clientIDs []string, connTypes []string, domainID string, token string)) *SDK_DisconnectClients_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].([]string), args[2].([]string), args[3].(string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_DisconnectClients_Call) Return(_a0 errors.SDKError) *SDK_DisconnectClients_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_DisconnectClients_Call) RunAndReturn(run func(string, []string, []string, string, string) errors.SDKError) *SDK_DisconnectClients_Call { - _c.Call.Return(run) - return _c -} - // Domain provides a mock function with given fields: domainID, token func (_m *SDK) Domain(domainID string, token string) (sdk.Domain, errors.SDKError) { ret := _m.Called(domainID, token) @@ -3169,35 +1408,6 @@ func (_m *SDK) Domain(domainID string, token string) (sdk.Domain, errors.SDKErro return r0, r1 } -// SDK_Domain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Domain' -type SDK_Domain_Call struct { - *mock.Call -} - -// Domain is a helper method to define mock.On call -// - domainID string -// - token string -func (_e *SDK_Expecter) Domain(domainID interface{}, token interface{}) *SDK_Domain_Call { - return &SDK_Domain_Call{Call: _e.mock.On("Domain", domainID, token)} -} - -func (_c *SDK_Domain_Call) Run(run func(domainID string, token string)) *SDK_Domain_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_Domain_Call) Return(_a0 sdk.Domain, _a1 errors.SDKError) *SDK_Domain_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Domain_Call) RunAndReturn(run func(string, string) (sdk.Domain, errors.SDKError)) *SDK_Domain_Call { - _c.Call.Return(run) - return _c -} - // DomainRole provides a mock function with given fields: id, roleID, token func (_m *SDK) DomainRole(id string, roleID string, token string) (sdk.Role, errors.SDKError) { ret := _m.Called(id, roleID, token) @@ -3228,36 +1438,6 @@ func (_m *SDK) DomainRole(id string, roleID string, token string) (sdk.Role, err return r0, r1 } -// SDK_DomainRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DomainRole' -type SDK_DomainRole_Call struct { - *mock.Call -} - -// DomainRole is a helper method to define mock.On call -// - id string -// - roleID string -// - token string -func (_e *SDK_Expecter) DomainRole(id interface{}, roleID interface{}, token interface{}) *SDK_DomainRole_Call { - return &SDK_DomainRole_Call{Call: _e.mock.On("DomainRole", id, roleID, token)} -} - -func (_c *SDK_DomainRole_Call) Run(run func(id string, roleID string, token string)) *SDK_DomainRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DomainRole_Call) Return(_a0 sdk.Role, _a1 errors.SDKError) *SDK_DomainRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_DomainRole_Call) RunAndReturn(run func(string, string, string) (sdk.Role, errors.SDKError)) *SDK_DomainRole_Call { - _c.Call.Return(run) - return _c -} - // DomainRoleActions provides a mock function with given fields: id, roleID, token func (_m *SDK) DomainRoleActions(id string, roleID string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, roleID, token) @@ -3290,36 +1470,6 @@ func (_m *SDK) DomainRoleActions(id string, roleID string, token string) ([]stri return r0, r1 } -// SDK_DomainRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DomainRoleActions' -type SDK_DomainRoleActions_Call struct { - *mock.Call -} - -// DomainRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - token string -func (_e *SDK_Expecter) DomainRoleActions(id interface{}, roleID interface{}, token interface{}) *SDK_DomainRoleActions_Call { - return &SDK_DomainRoleActions_Call{Call: _e.mock.On("DomainRoleActions", id, roleID, token)} -} - -func (_c *SDK_DomainRoleActions_Call) Run(run func(id string, roleID string, token string)) *SDK_DomainRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DomainRoleActions_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_DomainRoleActions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_DomainRoleActions_Call) RunAndReturn(run func(string, string, string) ([]string, errors.SDKError)) *SDK_DomainRoleActions_Call { - _c.Call.Return(run) - return _c -} - // DomainRoleMembers provides a mock function with given fields: id, roleID, pm, token func (_m *SDK) DomainRoleMembers(id string, roleID string, pm sdk.PageMetadata, token string) (sdk.RoleMembersPage, errors.SDKError) { ret := _m.Called(id, roleID, pm, token) @@ -3350,40 +1500,9 @@ func (_m *SDK) DomainRoleMembers(id string, roleID string, pm sdk.PageMetadata, return r0, r1 } -// SDK_DomainRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DomainRoleMembers' -type SDK_DomainRoleMembers_Call struct { - *mock.Call -} - -// DomainRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) DomainRoleMembers(id interface{}, roleID interface{}, pm interface{}, token interface{}) *SDK_DomainRoleMembers_Call { - return &SDK_DomainRoleMembers_Call{Call: _e.mock.On("DomainRoleMembers", id, roleID, pm, token)} -} - -func (_c *SDK_DomainRoleMembers_Call) Run(run func(id string, roleID string, pm sdk.PageMetadata, token string)) *SDK_DomainRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string)) - }) - return _c -} - -func (_c *SDK_DomainRoleMembers_Call) Return(_a0 sdk.RoleMembersPage, _a1 errors.SDKError) *SDK_DomainRoleMembers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_DomainRoleMembers_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.RoleMembersPage, errors.SDKError)) *SDK_DomainRoleMembers_Call { - _c.Call.Return(run) - return _c -} - -// DomainRoles provides a mock function with given fields: id, pm, token -func (_m *SDK) DomainRoles(id string, pm sdk.PageMetadata, token string) (sdk.RolesPage, errors.SDKError) { - ret := _m.Called(id, pm, token) +// DomainRoles provides a mock function with given fields: id, pm, token +func (_m *SDK) DomainRoles(id string, pm sdk.PageMetadata, token string) (sdk.RolesPage, errors.SDKError) { + ret := _m.Called(id, pm, token) if len(ret) == 0 { panic("no return value specified for DomainRoles") @@ -3411,36 +1530,6 @@ func (_m *SDK) DomainRoles(id string, pm sdk.PageMetadata, token string) (sdk.Ro return r0, r1 } -// SDK_DomainRoles_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DomainRoles' -type SDK_DomainRoles_Call struct { - *mock.Call -} - -// DomainRoles is a helper method to define mock.On call -// - id string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) DomainRoles(id interface{}, pm interface{}, token interface{}) *SDK_DomainRoles_Call { - return &SDK_DomainRoles_Call{Call: _e.mock.On("DomainRoles", id, pm, token)} -} - -func (_c *SDK_DomainRoles_Call) Run(run func(id string, pm sdk.PageMetadata, token string)) *SDK_DomainRoles_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(sdk.PageMetadata), args[2].(string)) - }) - return _c -} - -func (_c *SDK_DomainRoles_Call) Return(_a0 sdk.RolesPage, _a1 errors.SDKError) *SDK_DomainRoles_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_DomainRoles_Call) RunAndReturn(run func(string, sdk.PageMetadata, string) (sdk.RolesPage, errors.SDKError)) *SDK_DomainRoles_Call { - _c.Call.Return(run) - return _c -} - // Domains provides a mock function with given fields: pm, token func (_m *SDK) Domains(pm sdk.PageMetadata, token string) (sdk.DomainsPage, errors.SDKError) { ret := _m.Called(pm, token) @@ -3471,35 +1560,6 @@ func (_m *SDK) Domains(pm sdk.PageMetadata, token string) (sdk.DomainsPage, erro return r0, r1 } -// SDK_Domains_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Domains' -type SDK_Domains_Call struct { - *mock.Call -} - -// Domains is a helper method to define mock.On call -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) Domains(pm interface{}, token interface{}) *SDK_Domains_Call { - return &SDK_Domains_Call{Call: _e.mock.On("Domains", pm, token)} -} - -func (_c *SDK_Domains_Call) Run(run func(pm sdk.PageMetadata, token string)) *SDK_Domains_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.PageMetadata), args[1].(string)) - }) - return _c -} - -func (_c *SDK_Domains_Call) Return(_a0 sdk.DomainsPage, _a1 errors.SDKError) *SDK_Domains_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Domains_Call) RunAndReturn(run func(sdk.PageMetadata, string) (sdk.DomainsPage, errors.SDKError)) *SDK_Domains_Call { - _c.Call.Return(run) - return _c -} - // EnableChannel provides a mock function with given fields: id, domainID, token func (_m *SDK) EnableChannel(id string, domainID string, token string) (sdk.Channel, errors.SDKError) { ret := _m.Called(id, domainID, token) @@ -3530,36 +1590,6 @@ func (_m *SDK) EnableChannel(id string, domainID string, token string) (sdk.Chan return r0, r1 } -// SDK_EnableChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnableChannel' -type SDK_EnableChannel_Call struct { - *mock.Call -} - -// EnableChannel is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) EnableChannel(id interface{}, domainID interface{}, token interface{}) *SDK_EnableChannel_Call { - return &SDK_EnableChannel_Call{Call: _e.mock.On("EnableChannel", id, domainID, token)} -} - -func (_c *SDK_EnableChannel_Call) Run(run func(id string, domainID string, token string)) *SDK_EnableChannel_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_EnableChannel_Call) Return(_a0 sdk.Channel, _a1 errors.SDKError) *SDK_EnableChannel_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_EnableChannel_Call) RunAndReturn(run func(string, string, string) (sdk.Channel, errors.SDKError)) *SDK_EnableChannel_Call { - _c.Call.Return(run) - return _c -} - // EnableClient provides a mock function with given fields: id, domainID, token func (_m *SDK) EnableClient(id string, domainID string, token string) (sdk.Client, errors.SDKError) { ret := _m.Called(id, domainID, token) @@ -3590,36 +1620,6 @@ func (_m *SDK) EnableClient(id string, domainID string, token string) (sdk.Clien return r0, r1 } -// SDK_EnableClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnableClient' -type SDK_EnableClient_Call struct { - *mock.Call -} - -// EnableClient is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) EnableClient(id interface{}, domainID interface{}, token interface{}) *SDK_EnableClient_Call { - return &SDK_EnableClient_Call{Call: _e.mock.On("EnableClient", id, domainID, token)} -} - -func (_c *SDK_EnableClient_Call) Run(run func(id string, domainID string, token string)) *SDK_EnableClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_EnableClient_Call) Return(_a0 sdk.Client, _a1 errors.SDKError) *SDK_EnableClient_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_EnableClient_Call) RunAndReturn(run func(string, string, string) (sdk.Client, errors.SDKError)) *SDK_EnableClient_Call { - _c.Call.Return(run) - return _c -} - // EnableDomain provides a mock function with given fields: domainID, token func (_m *SDK) EnableDomain(domainID string, token string) errors.SDKError { ret := _m.Called(domainID, token) @@ -3640,35 +1640,6 @@ func (_m *SDK) EnableDomain(domainID string, token string) errors.SDKError { return r0 } -// SDK_EnableDomain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnableDomain' -type SDK_EnableDomain_Call struct { - *mock.Call -} - -// EnableDomain is a helper method to define mock.On call -// - domainID string -// - token string -func (_e *SDK_Expecter) EnableDomain(domainID interface{}, token interface{}) *SDK_EnableDomain_Call { - return &SDK_EnableDomain_Call{Call: _e.mock.On("EnableDomain", domainID, token)} -} - -func (_c *SDK_EnableDomain_Call) Run(run func(domainID string, token string)) *SDK_EnableDomain_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_EnableDomain_Call) Return(_a0 errors.SDKError) *SDK_EnableDomain_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_EnableDomain_Call) RunAndReturn(run func(string, string) errors.SDKError) *SDK_EnableDomain_Call { - _c.Call.Return(run) - return _c -} - // EnableGroup provides a mock function with given fields: id, domainID, token func (_m *SDK) EnableGroup(id string, domainID string, token string) (sdk.Group, errors.SDKError) { ret := _m.Called(id, domainID, token) @@ -3699,36 +1670,6 @@ func (_m *SDK) EnableGroup(id string, domainID string, token string) (sdk.Group, return r0, r1 } -// SDK_EnableGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnableGroup' -type SDK_EnableGroup_Call struct { - *mock.Call -} - -// EnableGroup is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) EnableGroup(id interface{}, domainID interface{}, token interface{}) *SDK_EnableGroup_Call { - return &SDK_EnableGroup_Call{Call: _e.mock.On("EnableGroup", id, domainID, token)} -} - -func (_c *SDK_EnableGroup_Call) Run(run func(id string, domainID string, token string)) *SDK_EnableGroup_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_EnableGroup_Call) Return(_a0 sdk.Group, _a1 errors.SDKError) *SDK_EnableGroup_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_EnableGroup_Call) RunAndReturn(run func(string, string, string) (sdk.Group, errors.SDKError)) *SDK_EnableGroup_Call { - _c.Call.Return(run) - return _c -} - // EnableUser provides a mock function with given fields: id, token func (_m *SDK) EnableUser(id string, token string) (sdk.User, errors.SDKError) { ret := _m.Called(id, token) @@ -3759,35 +1700,6 @@ func (_m *SDK) EnableUser(id string, token string) (sdk.User, errors.SDKError) { return r0, r1 } -// SDK_EnableUser_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EnableUser' -type SDK_EnableUser_Call struct { - *mock.Call -} - -// EnableUser is a helper method to define mock.On call -// - id string -// - token string -func (_e *SDK_Expecter) EnableUser(id interface{}, token interface{}) *SDK_EnableUser_Call { - return &SDK_EnableUser_Call{Call: _e.mock.On("EnableUser", id, token)} -} - -func (_c *SDK_EnableUser_Call) Run(run func(id string, token string)) *SDK_EnableUser_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_EnableUser_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_EnableUser_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_EnableUser_Call) RunAndReturn(run func(string, string) (sdk.User, errors.SDKError)) *SDK_EnableUser_Call { - _c.Call.Return(run) - return _c -} - // FreezeDomain provides a mock function with given fields: domainID, token func (_m *SDK) FreezeDomain(domainID string, token string) errors.SDKError { ret := _m.Called(domainID, token) @@ -3808,35 +1720,6 @@ func (_m *SDK) FreezeDomain(domainID string, token string) errors.SDKError { return r0 } -// SDK_FreezeDomain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FreezeDomain' -type SDK_FreezeDomain_Call struct { - *mock.Call -} - -// FreezeDomain is a helper method to define mock.On call -// - domainID string -// - token string -func (_e *SDK_Expecter) FreezeDomain(domainID interface{}, token interface{}) *SDK_FreezeDomain_Call { - return &SDK_FreezeDomain_Call{Call: _e.mock.On("FreezeDomain", domainID, token)} -} - -func (_c *SDK_FreezeDomain_Call) Run(run func(domainID string, token string)) *SDK_FreezeDomain_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_FreezeDomain_Call) Return(_a0 errors.SDKError) *SDK_FreezeDomain_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_FreezeDomain_Call) RunAndReturn(run func(string, string) errors.SDKError) *SDK_FreezeDomain_Call { - _c.Call.Return(run) - return _c -} - // Group provides a mock function with given fields: id, domainID, token func (_m *SDK) Group(id string, domainID string, token string) (sdk.Group, errors.SDKError) { ret := _m.Called(id, domainID, token) @@ -3867,36 +1750,6 @@ func (_m *SDK) Group(id string, domainID string, token string) (sdk.Group, error return r0, r1 } -// SDK_Group_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Group' -type SDK_Group_Call struct { - *mock.Call -} - -// Group is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) Group(id interface{}, domainID interface{}, token interface{}) *SDK_Group_Call { - return &SDK_Group_Call{Call: _e.mock.On("Group", id, domainID, token)} -} - -func (_c *SDK_Group_Call) Run(run func(id string, domainID string, token string)) *SDK_Group_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Group_Call) Return(_a0 sdk.Group, _a1 errors.SDKError) *SDK_Group_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Group_Call) RunAndReturn(run func(string, string, string) (sdk.Group, errors.SDKError)) *SDK_Group_Call { - _c.Call.Return(run) - return _c -} - // GroupRole provides a mock function with given fields: id, roleID, domainID, token func (_m *SDK) GroupRole(id string, roleID string, domainID string, token string) (sdk.Role, errors.SDKError) { ret := _m.Called(id, roleID, domainID, token) @@ -3927,37 +1780,6 @@ func (_m *SDK) GroupRole(id string, roleID string, domainID string, token string return r0, r1 } -// SDK_GroupRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GroupRole' -type SDK_GroupRole_Call struct { - *mock.Call -} - -// GroupRole is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) GroupRole(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_GroupRole_Call { - return &SDK_GroupRole_Call{Call: _e.mock.On("GroupRole", id, roleID, domainID, token)} -} - -func (_c *SDK_GroupRole_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_GroupRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_GroupRole_Call) Return(_a0 sdk.Role, _a1 errors.SDKError) *SDK_GroupRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_GroupRole_Call) RunAndReturn(run func(string, string, string, string) (sdk.Role, errors.SDKError)) *SDK_GroupRole_Call { - _c.Call.Return(run) - return _c -} - // GroupRoleActions provides a mock function with given fields: id, roleID, domainID, token func (_m *SDK) GroupRoleActions(id string, roleID string, domainID string, token string) ([]string, errors.SDKError) { ret := _m.Called(id, roleID, domainID, token) @@ -3990,37 +1812,6 @@ func (_m *SDK) GroupRoleActions(id string, roleID string, domainID string, token return r0, r1 } -// SDK_GroupRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GroupRoleActions' -type SDK_GroupRoleActions_Call struct { - *mock.Call -} - -// GroupRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) GroupRoleActions(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_GroupRoleActions_Call { - return &SDK_GroupRoleActions_Call{Call: _e.mock.On("GroupRoleActions", id, roleID, domainID, token)} -} - -func (_c *SDK_GroupRoleActions_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_GroupRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_GroupRoleActions_Call) Return(_a0 []string, _a1 errors.SDKError) *SDK_GroupRoleActions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_GroupRoleActions_Call) RunAndReturn(run func(string, string, string, string) ([]string, errors.SDKError)) *SDK_GroupRoleActions_Call { - _c.Call.Return(run) - return _c -} - // GroupRoleMembers provides a mock function with given fields: id, roleID, domainID, pm, token func (_m *SDK) GroupRoleMembers(id string, roleID string, domainID string, pm sdk.PageMetadata, token string) (sdk.RoleMembersPage, errors.SDKError) { ret := _m.Called(id, roleID, domainID, pm, token) @@ -4051,38 +1842,6 @@ func (_m *SDK) GroupRoleMembers(id string, roleID string, domainID string, pm sd return r0, r1 } -// SDK_GroupRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GroupRoleMembers' -type SDK_GroupRoleMembers_Call struct { - *mock.Call -} - -// GroupRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) GroupRoleMembers(id interface{}, roleID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_GroupRoleMembers_Call { - return &SDK_GroupRoleMembers_Call{Call: _e.mock.On("GroupRoleMembers", id, roleID, domainID, pm, token)} -} - -func (_c *SDK_GroupRoleMembers_Call) Run(run func(id string, roleID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_GroupRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(sdk.PageMetadata), args[4].(string)) - }) - return _c -} - -func (_c *SDK_GroupRoleMembers_Call) Return(_a0 sdk.RoleMembersPage, _a1 errors.SDKError) *SDK_GroupRoleMembers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_GroupRoleMembers_Call) RunAndReturn(run func(string, string, string, sdk.PageMetadata, string) (sdk.RoleMembersPage, errors.SDKError)) *SDK_GroupRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // GroupRoles provides a mock function with given fields: id, domainID, pm, token func (_m *SDK) GroupRoles(id string, domainID string, pm sdk.PageMetadata, token string) (sdk.RolesPage, errors.SDKError) { ret := _m.Called(id, domainID, pm, token) @@ -4113,37 +1872,6 @@ func (_m *SDK) GroupRoles(id string, domainID string, pm sdk.PageMetadata, token return r0, r1 } -// SDK_GroupRoles_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GroupRoles' -type SDK_GroupRoles_Call struct { - *mock.Call -} - -// GroupRoles is a helper method to define mock.On call -// - id string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) GroupRoles(id interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_GroupRoles_Call { - return &SDK_GroupRoles_Call{Call: _e.mock.On("GroupRoles", id, domainID, pm, token)} -} - -func (_c *SDK_GroupRoles_Call) Run(run func(id string, domainID string, pm sdk.PageMetadata, token string)) *SDK_GroupRoles_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string)) - }) - return _c -} - -func (_c *SDK_GroupRoles_Call) Return(_a0 sdk.RolesPage, _a1 errors.SDKError) *SDK_GroupRoles_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_GroupRoles_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.RolesPage, errors.SDKError)) *SDK_GroupRoles_Call { - _c.Call.Return(run) - return _c -} - // Groups provides a mock function with given fields: pm, domainID, token func (_m *SDK) Groups(pm sdk.PageMetadata, domainID string, token string) (sdk.GroupsPage, errors.SDKError) { ret := _m.Called(pm, domainID, token) @@ -4174,36 +1902,6 @@ func (_m *SDK) Groups(pm sdk.PageMetadata, domainID string, token string) (sdk.G return r0, r1 } -// SDK_Groups_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Groups' -type SDK_Groups_Call struct { - *mock.Call -} - -// Groups is a helper method to define mock.On call -// - pm sdk.PageMetadata -// - domainID string -// - token string -func (_e *SDK_Expecter) Groups(pm interface{}, domainID interface{}, token interface{}) *SDK_Groups_Call { - return &SDK_Groups_Call{Call: _e.mock.On("Groups", pm, domainID, token)} -} - -func (_c *SDK_Groups_Call) Run(run func(pm sdk.PageMetadata, domainID string, token string)) *SDK_Groups_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.PageMetadata), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Groups_Call) Return(_a0 sdk.GroupsPage, _a1 errors.SDKError) *SDK_Groups_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Groups_Call) RunAndReturn(run func(sdk.PageMetadata, string, string) (sdk.GroupsPage, errors.SDKError)) *SDK_Groups_Call { - _c.Call.Return(run) - return _c -} - // Health provides a mock function with given fields: service func (_m *SDK) Health(service string) (sdk.HealthInfo, errors.SDKError) { ret := _m.Called(service) @@ -4234,34 +1932,6 @@ func (_m *SDK) Health(service string) (sdk.HealthInfo, errors.SDKError) { return r0, r1 } -// SDK_Health_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Health' -type SDK_Health_Call struct { - *mock.Call -} - -// Health is a helper method to define mock.On call -// - service string -func (_e *SDK_Expecter) Health(service interface{}) *SDK_Health_Call { - return &SDK_Health_Call{Call: _e.mock.On("Health", service)} -} - -func (_c *SDK_Health_Call) Run(run func(service string)) *SDK_Health_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string)) - }) - return _c -} - -func (_c *SDK_Health_Call) Return(_a0 sdk.HealthInfo, _a1 errors.SDKError) *SDK_Health_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Health_Call) RunAndReturn(run func(string) (sdk.HealthInfo, errors.SDKError)) *SDK_Health_Call { - _c.Call.Return(run) - return _c -} - // Hierarchy provides a mock function with given fields: id, domainID, pm, token func (_m *SDK) Hierarchy(id string, domainID string, pm sdk.PageMetadata, token string) (sdk.GroupsHierarchyPage, errors.SDKError) { ret := _m.Called(id, domainID, pm, token) @@ -4292,37 +1962,6 @@ func (_m *SDK) Hierarchy(id string, domainID string, pm sdk.PageMetadata, token return r0, r1 } -// SDK_Hierarchy_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Hierarchy' -type SDK_Hierarchy_Call struct { - *mock.Call -} - -// Hierarchy is a helper method to define mock.On call -// - id string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) Hierarchy(id interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_Hierarchy_Call { - return &SDK_Hierarchy_Call{Call: _e.mock.On("Hierarchy", id, domainID, pm, token)} -} - -func (_c *SDK_Hierarchy_Call) Run(run func(id string, domainID string, pm sdk.PageMetadata, token string)) *SDK_Hierarchy_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string)) - }) - return _c -} - -func (_c *SDK_Hierarchy_Call) Return(_a0 sdk.GroupsHierarchyPage, _a1 errors.SDKError) *SDK_Hierarchy_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Hierarchy_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.GroupsHierarchyPage, errors.SDKError)) *SDK_Hierarchy_Call { - _c.Call.Return(run) - return _c -} - // Invitation provides a mock function with given fields: userID, domainID, token func (_m *SDK) Invitation(userID string, domainID string, token string) (sdk.Invitation, error) { ret := _m.Called(userID, domainID, token) @@ -4351,36 +1990,6 @@ func (_m *SDK) Invitation(userID string, domainID string, token string) (sdk.Inv return r0, r1 } -// SDK_Invitation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Invitation' -type SDK_Invitation_Call struct { - *mock.Call -} - -// Invitation is a helper method to define mock.On call -// - userID string -// - domainID string -// - token string -func (_e *SDK_Expecter) Invitation(userID interface{}, domainID interface{}, token interface{}) *SDK_Invitation_Call { - return &SDK_Invitation_Call{Call: _e.mock.On("Invitation", userID, domainID, token)} -} - -func (_c *SDK_Invitation_Call) Run(run func(userID string, domainID string, token string)) *SDK_Invitation_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_Invitation_Call) Return(invitation sdk.Invitation, err error) *SDK_Invitation_Call { - _c.Call.Return(invitation, err) - return _c -} - -func (_c *SDK_Invitation_Call) RunAndReturn(run func(string, string, string) (sdk.Invitation, error)) *SDK_Invitation_Call { - _c.Call.Return(run) - return _c -} - // Invitations provides a mock function with given fields: pm, token func (_m *SDK) Invitations(pm sdk.PageMetadata, token string) (sdk.InvitationPage, error) { ret := _m.Called(pm, token) @@ -4409,35 +2018,6 @@ func (_m *SDK) Invitations(pm sdk.PageMetadata, token string) (sdk.InvitationPag return r0, r1 } -// SDK_Invitations_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Invitations' -type SDK_Invitations_Call struct { - *mock.Call -} - -// Invitations is a helper method to define mock.On call -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) Invitations(pm interface{}, token interface{}) *SDK_Invitations_Call { - return &SDK_Invitations_Call{Call: _e.mock.On("Invitations", pm, token)} -} - -func (_c *SDK_Invitations_Call) Run(run func(pm sdk.PageMetadata, token string)) *SDK_Invitations_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.PageMetadata), args[1].(string)) - }) - return _c -} - -func (_c *SDK_Invitations_Call) Return(invitations sdk.InvitationPage, err error) *SDK_Invitations_Call { - _c.Call.Return(invitations, err) - return _c -} - -func (_c *SDK_Invitations_Call) RunAndReturn(run func(sdk.PageMetadata, string) (sdk.InvitationPage, error)) *SDK_Invitations_Call { - _c.Call.Return(run) - return _c -} - // IssueCert provides a mock function with given fields: clientID, validity, domainID, token func (_m *SDK) IssueCert(clientID string, validity string, domainID string, token string) (sdk.Cert, errors.SDKError) { ret := _m.Called(clientID, validity, domainID, token) @@ -4468,37 +2048,6 @@ func (_m *SDK) IssueCert(clientID string, validity string, domainID string, toke return r0, r1 } -// SDK_IssueCert_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'IssueCert' -type SDK_IssueCert_Call struct { - *mock.Call -} - -// IssueCert is a helper method to define mock.On call -// - clientID string -// - validity string -// - domainID string -// - token string -func (_e *SDK_Expecter) IssueCert(clientID interface{}, validity interface{}, domainID interface{}, token interface{}) *SDK_IssueCert_Call { - return &SDK_IssueCert_Call{Call: _e.mock.On("IssueCert", clientID, validity, domainID, token)} -} - -func (_c *SDK_IssueCert_Call) Run(run func(clientID string, validity string, domainID string, token string)) *SDK_IssueCert_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_IssueCert_Call) Return(_a0 sdk.Cert, _a1 errors.SDKError) *SDK_IssueCert_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_IssueCert_Call) RunAndReturn(run func(string, string, string, string) (sdk.Cert, errors.SDKError)) *SDK_IssueCert_Call { - _c.Call.Return(run) - return _c -} - // Journal provides a mock function with given fields: entityType, entityID, domainID, pm, token func (_m *SDK) Journal(entityType string, entityID string, domainID string, pm sdk.PageMetadata, token string) (sdk.JournalsPage, error) { ret := _m.Called(entityType, entityID, domainID, pm, token) @@ -4527,38 +2076,6 @@ func (_m *SDK) Journal(entityType string, entityID string, domainID string, pm s return r0, r1 } -// SDK_Journal_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Journal' -type SDK_Journal_Call struct { - *mock.Call -} - -// Journal is a helper method to define mock.On call -// - entityType string -// - entityID string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) Journal(entityType interface{}, entityID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_Journal_Call { - return &SDK_Journal_Call{Call: _e.mock.On("Journal", entityType, entityID, domainID, pm, token)} -} - -func (_c *SDK_Journal_Call) Run(run func(entityType string, entityID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_Journal_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(sdk.PageMetadata), args[4].(string)) - }) - return _c -} - -func (_c *SDK_Journal_Call) Return(journal sdk.JournalsPage, err error) *SDK_Journal_Call { - _c.Call.Return(journal, err) - return _c -} - -func (_c *SDK_Journal_Call) RunAndReturn(run func(string, string, string, sdk.PageMetadata, string) (sdk.JournalsPage, error)) *SDK_Journal_Call { - _c.Call.Return(run) - return _c -} - // ListChannelUsers provides a mock function with given fields: channelID, domainID, pm, token func (_m *SDK) ListChannelUsers(channelID string, domainID string, pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) { ret := _m.Called(channelID, domainID, pm, token) @@ -4589,37 +2106,6 @@ func (_m *SDK) ListChannelUsers(channelID string, domainID string, pm sdk.PageMe return r0, r1 } -// SDK_ListChannelUsers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListChannelUsers' -type SDK_ListChannelUsers_Call struct { - *mock.Call -} - -// ListChannelUsers is a helper method to define mock.On call -// - channelID string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) ListChannelUsers(channelID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ListChannelUsers_Call { - return &SDK_ListChannelUsers_Call{Call: _e.mock.On("ListChannelUsers", channelID, domainID, pm, token)} -} - -func (_c *SDK_ListChannelUsers_Call) Run(run func(channelID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ListChannelUsers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string)) - }) - return _c -} - -func (_c *SDK_ListChannelUsers_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_ListChannelUsers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ListChannelUsers_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_ListChannelUsers_Call { - _c.Call.Return(run) - return _c -} - // ListClientUsers provides a mock function with given fields: clientID, domainID, pm, token func (_m *SDK) ListClientUsers(clientID string, domainID string, pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) { ret := _m.Called(clientID, domainID, pm, token) @@ -4650,37 +2136,6 @@ func (_m *SDK) ListClientUsers(clientID string, domainID string, pm sdk.PageMeta return r0, r1 } -// SDK_ListClientUsers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListClientUsers' -type SDK_ListClientUsers_Call struct { - *mock.Call -} - -// ListClientUsers is a helper method to define mock.On call -// - clientID string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) ListClientUsers(clientID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ListClientUsers_Call { - return &SDK_ListClientUsers_Call{Call: _e.mock.On("ListClientUsers", clientID, domainID, pm, token)} -} - -func (_c *SDK_ListClientUsers_Call) Run(run func(clientID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ListClientUsers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string)) - }) - return _c -} - -func (_c *SDK_ListClientUsers_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_ListClientUsers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ListClientUsers_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_ListClientUsers_Call { - _c.Call.Return(run) - return _c -} - // ListDomainUsers provides a mock function with given fields: domainID, pm, token func (_m *SDK) ListDomainUsers(domainID string, pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) { ret := _m.Called(domainID, pm, token) @@ -4711,36 +2166,6 @@ func (_m *SDK) ListDomainUsers(domainID string, pm sdk.PageMetadata, token strin return r0, r1 } -// SDK_ListDomainUsers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListDomainUsers' -type SDK_ListDomainUsers_Call struct { - *mock.Call -} - -// ListDomainUsers is a helper method to define mock.On call -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) ListDomainUsers(domainID interface{}, pm interface{}, token interface{}) *SDK_ListDomainUsers_Call { - return &SDK_ListDomainUsers_Call{Call: _e.mock.On("ListDomainUsers", domainID, pm, token)} -} - -func (_c *SDK_ListDomainUsers_Call) Run(run func(domainID string, pm sdk.PageMetadata, token string)) *SDK_ListDomainUsers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(sdk.PageMetadata), args[2].(string)) - }) - return _c -} - -func (_c *SDK_ListDomainUsers_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_ListDomainUsers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ListDomainUsers_Call) RunAndReturn(run func(string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_ListDomainUsers_Call { - _c.Call.Return(run) - return _c -} - // ListSubscriptions provides a mock function with given fields: pm, token func (_m *SDK) ListSubscriptions(pm sdk.PageMetadata, token string) (sdk.SubscriptionPage, errors.SDKError) { ret := _m.Called(pm, token) @@ -4771,35 +2196,6 @@ func (_m *SDK) ListSubscriptions(pm sdk.PageMetadata, token string) (sdk.Subscri return r0, r1 } -// SDK_ListSubscriptions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListSubscriptions' -type SDK_ListSubscriptions_Call struct { - *mock.Call -} - -// ListSubscriptions is a helper method to define mock.On call -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) ListSubscriptions(pm interface{}, token interface{}) *SDK_ListSubscriptions_Call { - return &SDK_ListSubscriptions_Call{Call: _e.mock.On("ListSubscriptions", pm, token)} -} - -func (_c *SDK_ListSubscriptions_Call) Run(run func(pm sdk.PageMetadata, token string)) *SDK_ListSubscriptions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.PageMetadata), args[1].(string)) - }) - return _c -} - -func (_c *SDK_ListSubscriptions_Call) Return(_a0 sdk.SubscriptionPage, _a1 errors.SDKError) *SDK_ListSubscriptions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ListSubscriptions_Call) RunAndReturn(run func(sdk.PageMetadata, string) (sdk.SubscriptionPage, errors.SDKError)) *SDK_ListSubscriptions_Call { - _c.Call.Return(run) - return _c -} - // ListUserClients provides a mock function with given fields: userID, domainID, pm, token func (_m *SDK) ListUserClients(userID string, domainID string, pm sdk.PageMetadata, token string) (sdk.ClientsPage, errors.SDKError) { ret := _m.Called(userID, domainID, pm, token) @@ -4830,40 +2226,9 @@ func (_m *SDK) ListUserClients(userID string, domainID string, pm sdk.PageMetada return r0, r1 } -// SDK_ListUserClients_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListUserClients' -type SDK_ListUserClients_Call struct { - *mock.Call -} - -// ListUserClients is a helper method to define mock.On call -// - userID string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) ListUserClients(userID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_ListUserClients_Call { - return &SDK_ListUserClients_Call{Call: _e.mock.On("ListUserClients", userID, domainID, pm, token)} -} - -func (_c *SDK_ListUserClients_Call) Run(run func(userID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_ListUserClients_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string)) - }) - return _c -} - -func (_c *SDK_ListUserClients_Call) Return(_a0 sdk.ClientsPage, _a1 errors.SDKError) *SDK_ListUserClients_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ListUserClients_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.ClientsPage, errors.SDKError)) *SDK_ListUserClients_Call { - _c.Call.Return(run) - return _c -} - -// Members provides a mock function with given fields: groupID, domainID, pm, token -func (_m *SDK) Members(groupID string, domainID string, pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) { - ret := _m.Called(groupID, domainID, pm, token) +// Members provides a mock function with given fields: groupID, domainID, pm, token +func (_m *SDK) Members(groupID string, domainID string, pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) { + ret := _m.Called(groupID, domainID, pm, token) if len(ret) == 0 { panic("no return value specified for Members") @@ -4891,37 +2256,6 @@ func (_m *SDK) Members(groupID string, domainID string, pm sdk.PageMetadata, tok return r0, r1 } -// SDK_Members_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Members' -type SDK_Members_Call struct { - *mock.Call -} - -// Members is a helper method to define mock.On call -// - groupID string -// - domainID string -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) Members(groupID interface{}, domainID interface{}, pm interface{}, token interface{}) *SDK_Members_Call { - return &SDK_Members_Call{Call: _e.mock.On("Members", groupID, domainID, pm, token)} -} - -func (_c *SDK_Members_Call) Run(run func(groupID string, domainID string, pm sdk.PageMetadata, token string)) *SDK_Members_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(sdk.PageMetadata), args[3].(string)) - }) - return _c -} - -func (_c *SDK_Members_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_Members_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Members_Call) RunAndReturn(run func(string, string, sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_Members_Call { - _c.Call.Return(run) - return _c -} - // ReadMessages provides a mock function with given fields: pm, chanID, domainID, token func (_m *SDK) ReadMessages(pm sdk.MessagePageMetadata, chanID string, domainID string, token string) (sdk.MessagesPage, errors.SDKError) { ret := _m.Called(pm, chanID, domainID, token) @@ -4952,37 +2286,6 @@ func (_m *SDK) ReadMessages(pm sdk.MessagePageMetadata, chanID string, domainID return r0, r1 } -// SDK_ReadMessages_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReadMessages' -type SDK_ReadMessages_Call struct { - *mock.Call -} - -// ReadMessages is a helper method to define mock.On call -// - pm sdk.MessagePageMetadata -// - chanID string -// - domainID string -// - token string -func (_e *SDK_Expecter) ReadMessages(pm interface{}, chanID interface{}, domainID interface{}, token interface{}) *SDK_ReadMessages_Call { - return &SDK_ReadMessages_Call{Call: _e.mock.On("ReadMessages", pm, chanID, domainID, token)} -} - -func (_c *SDK_ReadMessages_Call) Run(run func(pm sdk.MessagePageMetadata, chanID string, domainID string, token string)) *SDK_ReadMessages_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.MessagePageMetadata), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_ReadMessages_Call) Return(_a0 sdk.MessagesPage, _a1 errors.SDKError) *SDK_ReadMessages_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ReadMessages_Call) RunAndReturn(run func(sdk.MessagePageMetadata, string, string, string) (sdk.MessagesPage, errors.SDKError)) *SDK_ReadMessages_Call { - _c.Call.Return(run) - return _c -} - // RefreshToken provides a mock function with given fields: token func (_m *SDK) RefreshToken(token string) (sdk.Token, errors.SDKError) { ret := _m.Called(token) @@ -5013,34 +2316,6 @@ func (_m *SDK) RefreshToken(token string) (sdk.Token, errors.SDKError) { return r0, r1 } -// SDK_RefreshToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RefreshToken' -type SDK_RefreshToken_Call struct { - *mock.Call -} - -// RefreshToken is a helper method to define mock.On call -// - token string -func (_e *SDK_Expecter) RefreshToken(token interface{}) *SDK_RefreshToken_Call { - return &SDK_RefreshToken_Call{Call: _e.mock.On("RefreshToken", token)} -} - -func (_c *SDK_RefreshToken_Call) Run(run func(token string)) *SDK_RefreshToken_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string)) - }) - return _c -} - -func (_c *SDK_RefreshToken_Call) Return(_a0 sdk.Token, _a1 errors.SDKError) *SDK_RefreshToken_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_RefreshToken_Call) RunAndReturn(run func(string) (sdk.Token, errors.SDKError)) *SDK_RefreshToken_Call { - _c.Call.Return(run) - return _c -} - // RejectInvitation provides a mock function with given fields: domainID, token func (_m *SDK) RejectInvitation(domainID string, token string) error { ret := _m.Called(domainID, token) @@ -5059,35 +2334,6 @@ func (_m *SDK) RejectInvitation(domainID string, token string) error { return r0 } -// SDK_RejectInvitation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RejectInvitation' -type SDK_RejectInvitation_Call struct { - *mock.Call -} - -// RejectInvitation is a helper method to define mock.On call -// - domainID string -// - token string -func (_e *SDK_Expecter) RejectInvitation(domainID interface{}, token interface{}) *SDK_RejectInvitation_Call { - return &SDK_RejectInvitation_Call{Call: _e.mock.On("RejectInvitation", domainID, token)} -} - -func (_c *SDK_RejectInvitation_Call) Run(run func(domainID string, token string)) *SDK_RejectInvitation_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_RejectInvitation_Call) Return(err error) *SDK_RejectInvitation_Call { - _c.Call.Return(err) - return _c -} - -func (_c *SDK_RejectInvitation_Call) RunAndReturn(run func(string, string) error) *SDK_RejectInvitation_Call { - _c.Call.Return(run) - return _c -} - // RemoveAllChildren provides a mock function with given fields: id, domainID, token func (_m *SDK) RemoveAllChildren(id string, domainID string, token string) errors.SDKError { ret := _m.Called(id, domainID, token) @@ -5108,36 +2354,6 @@ func (_m *SDK) RemoveAllChildren(id string, domainID string, token string) error return r0 } -// SDK_RemoveAllChildren_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveAllChildren' -type SDK_RemoveAllChildren_Call struct { - *mock.Call -} - -// RemoveAllChildren is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) RemoveAllChildren(id interface{}, domainID interface{}, token interface{}) *SDK_RemoveAllChildren_Call { - return &SDK_RemoveAllChildren_Call{Call: _e.mock.On("RemoveAllChildren", id, domainID, token)} -} - -func (_c *SDK_RemoveAllChildren_Call) Run(run func(id string, domainID string, token string)) *SDK_RemoveAllChildren_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_RemoveAllChildren_Call) Return(_a0 errors.SDKError) *SDK_RemoveAllChildren_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveAllChildren_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_RemoveAllChildren_Call { - _c.Call.Return(run) - return _c -} - // RemoveAllClientRoleActions provides a mock function with given fields: id, roleID, domainID, token func (_m *SDK) RemoveAllClientRoleActions(id string, roleID string, domainID string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, token) @@ -5158,37 +2374,6 @@ func (_m *SDK) RemoveAllClientRoleActions(id string, roleID string, domainID str return r0 } -// SDK_RemoveAllClientRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveAllClientRoleActions' -type SDK_RemoveAllClientRoleActions_Call struct { - *mock.Call -} - -// RemoveAllClientRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) RemoveAllClientRoleActions(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_RemoveAllClientRoleActions_Call { - return &SDK_RemoveAllClientRoleActions_Call{Call: _e.mock.On("RemoveAllClientRoleActions", id, roleID, domainID, token)} -} - -func (_c *SDK_RemoveAllClientRoleActions_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_RemoveAllClientRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveAllClientRoleActions_Call) Return(_a0 errors.SDKError) *SDK_RemoveAllClientRoleActions_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveAllClientRoleActions_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_RemoveAllClientRoleActions_Call { - _c.Call.Return(run) - return _c -} - // RemoveAllClientRoleMembers provides a mock function with given fields: id, roleID, domainID, token func (_m *SDK) RemoveAllClientRoleMembers(id string, roleID string, domainID string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, token) @@ -5209,37 +2394,6 @@ func (_m *SDK) RemoveAllClientRoleMembers(id string, roleID string, domainID str return r0 } -// SDK_RemoveAllClientRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveAllClientRoleMembers' -type SDK_RemoveAllClientRoleMembers_Call struct { - *mock.Call -} - -// RemoveAllClientRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) RemoveAllClientRoleMembers(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_RemoveAllClientRoleMembers_Call { - return &SDK_RemoveAllClientRoleMembers_Call{Call: _e.mock.On("RemoveAllClientRoleMembers", id, roleID, domainID, token)} -} - -func (_c *SDK_RemoveAllClientRoleMembers_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_RemoveAllClientRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveAllClientRoleMembers_Call) Return(_a0 errors.SDKError) *SDK_RemoveAllClientRoleMembers_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveAllClientRoleMembers_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_RemoveAllClientRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // RemoveAllDomainRoleActions provides a mock function with given fields: id, roleID, token func (_m *SDK) RemoveAllDomainRoleActions(id string, roleID string, token string) errors.SDKError { ret := _m.Called(id, roleID, token) @@ -5260,36 +2414,6 @@ func (_m *SDK) RemoveAllDomainRoleActions(id string, roleID string, token string return r0 } -// SDK_RemoveAllDomainRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveAllDomainRoleActions' -type SDK_RemoveAllDomainRoleActions_Call struct { - *mock.Call -} - -// RemoveAllDomainRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - token string -func (_e *SDK_Expecter) RemoveAllDomainRoleActions(id interface{}, roleID interface{}, token interface{}) *SDK_RemoveAllDomainRoleActions_Call { - return &SDK_RemoveAllDomainRoleActions_Call{Call: _e.mock.On("RemoveAllDomainRoleActions", id, roleID, token)} -} - -func (_c *SDK_RemoveAllDomainRoleActions_Call) Run(run func(id string, roleID string, token string)) *SDK_RemoveAllDomainRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_RemoveAllDomainRoleActions_Call) Return(_a0 errors.SDKError) *SDK_RemoveAllDomainRoleActions_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveAllDomainRoleActions_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_RemoveAllDomainRoleActions_Call { - _c.Call.Return(run) - return _c -} - // RemoveAllDomainRoleMembers provides a mock function with given fields: id, roleID, token func (_m *SDK) RemoveAllDomainRoleMembers(id string, roleID string, token string) errors.SDKError { ret := _m.Called(id, roleID, token) @@ -5310,36 +2434,6 @@ func (_m *SDK) RemoveAllDomainRoleMembers(id string, roleID string, token string return r0 } -// SDK_RemoveAllDomainRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveAllDomainRoleMembers' -type SDK_RemoveAllDomainRoleMembers_Call struct { - *mock.Call -} - -// RemoveAllDomainRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - token string -func (_e *SDK_Expecter) RemoveAllDomainRoleMembers(id interface{}, roleID interface{}, token interface{}) *SDK_RemoveAllDomainRoleMembers_Call { - return &SDK_RemoveAllDomainRoleMembers_Call{Call: _e.mock.On("RemoveAllDomainRoleMembers", id, roleID, token)} -} - -func (_c *SDK_RemoveAllDomainRoleMembers_Call) Run(run func(id string, roleID string, token string)) *SDK_RemoveAllDomainRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_RemoveAllDomainRoleMembers_Call) Return(_a0 errors.SDKError) *SDK_RemoveAllDomainRoleMembers_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveAllDomainRoleMembers_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_RemoveAllDomainRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // RemoveAllGroupRoleActions provides a mock function with given fields: id, roleID, domainID, token func (_m *SDK) RemoveAllGroupRoleActions(id string, roleID string, domainID string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, token) @@ -5360,37 +2454,6 @@ func (_m *SDK) RemoveAllGroupRoleActions(id string, roleID string, domainID stri return r0 } -// SDK_RemoveAllGroupRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveAllGroupRoleActions' -type SDK_RemoveAllGroupRoleActions_Call struct { - *mock.Call -} - -// RemoveAllGroupRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) RemoveAllGroupRoleActions(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_RemoveAllGroupRoleActions_Call { - return &SDK_RemoveAllGroupRoleActions_Call{Call: _e.mock.On("RemoveAllGroupRoleActions", id, roleID, domainID, token)} -} - -func (_c *SDK_RemoveAllGroupRoleActions_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_RemoveAllGroupRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveAllGroupRoleActions_Call) Return(_a0 errors.SDKError) *SDK_RemoveAllGroupRoleActions_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveAllGroupRoleActions_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_RemoveAllGroupRoleActions_Call { - _c.Call.Return(run) - return _c -} - // RemoveAllGroupRoleMembers provides a mock function with given fields: id, roleID, domainID, token func (_m *SDK) RemoveAllGroupRoleMembers(id string, roleID string, domainID string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, token) @@ -5411,87 +2474,6 @@ func (_m *SDK) RemoveAllGroupRoleMembers(id string, roleID string, domainID stri return r0 } -// SDK_RemoveAllGroupRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveAllGroupRoleMembers' -type SDK_RemoveAllGroupRoleMembers_Call struct { - *mock.Call -} - -// RemoveAllGroupRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - token string -func (_e *SDK_Expecter) RemoveAllGroupRoleMembers(id interface{}, roleID interface{}, domainID interface{}, token interface{}) *SDK_RemoveAllGroupRoleMembers_Call { - return &SDK_RemoveAllGroupRoleMembers_Call{Call: _e.mock.On("RemoveAllGroupRoleMembers", id, roleID, domainID, token)} -} - -func (_c *SDK_RemoveAllGroupRoleMembers_Call) Run(run func(id string, roleID string, domainID string, token string)) *SDK_RemoveAllGroupRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveAllGroupRoleMembers_Call) Return(_a0 errors.SDKError) *SDK_RemoveAllGroupRoleMembers_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveAllGroupRoleMembers_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_RemoveAllGroupRoleMembers_Call { - _c.Call.Return(run) - return _c -} - -// RemoveBootstrap provides a mock function with given fields: id, domainID, token -func (_m *SDK) RemoveBootstrap(id string, domainID string, token string) errors.SDKError { - ret := _m.Called(id, domainID, token) - - if len(ret) == 0 { - panic("no return value specified for RemoveBootstrap") - } - - var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string) errors.SDKError); ok { - r0 = rf(id, domainID, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(errors.SDKError) - } - } - - return r0 -} - -// SDK_RemoveBootstrap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveBootstrap' -type SDK_RemoveBootstrap_Call struct { - *mock.Call -} - -// RemoveBootstrap is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) RemoveBootstrap(id interface{}, domainID interface{}, token interface{}) *SDK_RemoveBootstrap_Call { - return &SDK_RemoveBootstrap_Call{Call: _e.mock.On("RemoveBootstrap", id, domainID, token)} -} - -func (_c *SDK_RemoveBootstrap_Call) Run(run func(id string, domainID string, token string)) *SDK_RemoveBootstrap_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_RemoveBootstrap_Call) Return(_a0 errors.SDKError) *SDK_RemoveBootstrap_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveBootstrap_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_RemoveBootstrap_Call { - _c.Call.Return(run) - return _c -} - // RemoveChannelParent provides a mock function with given fields: id, domainID, groupID, token func (_m *SDK) RemoveChannelParent(id string, domainID string, groupID string, token string) errors.SDKError { ret := _m.Called(id, domainID, groupID, token) @@ -5512,37 +2494,6 @@ func (_m *SDK) RemoveChannelParent(id string, domainID string, groupID string, t return r0 } -// SDK_RemoveChannelParent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveChannelParent' -type SDK_RemoveChannelParent_Call struct { - *mock.Call -} - -// RemoveChannelParent is a helper method to define mock.On call -// - id string -// - domainID string -// - groupID string -// - token string -func (_e *SDK_Expecter) RemoveChannelParent(id interface{}, domainID interface{}, groupID interface{}, token interface{}) *SDK_RemoveChannelParent_Call { - return &SDK_RemoveChannelParent_Call{Call: _e.mock.On("RemoveChannelParent", id, domainID, groupID, token)} -} - -func (_c *SDK_RemoveChannelParent_Call) Run(run func(id string, domainID string, groupID string, token string)) *SDK_RemoveChannelParent_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveChannelParent_Call) Return(_a0 errors.SDKError) *SDK_RemoveChannelParent_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveChannelParent_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_RemoveChannelParent_Call { - _c.Call.Return(run) - return _c -} - // RemoveChildren provides a mock function with given fields: id, domainID, groupIDs, token func (_m *SDK) RemoveChildren(id string, domainID string, groupIDs []string, token string) errors.SDKError { ret := _m.Called(id, domainID, groupIDs, token) @@ -5563,37 +2514,6 @@ func (_m *SDK) RemoveChildren(id string, domainID string, groupIDs []string, tok return r0 } -// SDK_RemoveChildren_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveChildren' -type SDK_RemoveChildren_Call struct { - *mock.Call -} - -// RemoveChildren is a helper method to define mock.On call -// - id string -// - domainID string -// - groupIDs []string -// - token string -func (_e *SDK_Expecter) RemoveChildren(id interface{}, domainID interface{}, groupIDs interface{}, token interface{}) *SDK_RemoveChildren_Call { - return &SDK_RemoveChildren_Call{Call: _e.mock.On("RemoveChildren", id, domainID, groupIDs, token)} -} - -func (_c *SDK_RemoveChildren_Call) Run(run func(id string, domainID string, groupIDs []string, token string)) *SDK_RemoveChildren_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].([]string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveChildren_Call) Return(_a0 errors.SDKError) *SDK_RemoveChildren_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveChildren_Call) RunAndReturn(run func(string, string, []string, string) errors.SDKError) *SDK_RemoveChildren_Call { - _c.Call.Return(run) - return _c -} - // RemoveClientParent provides a mock function with given fields: id, domainID, groupID, token func (_m *SDK) RemoveClientParent(id string, domainID string, groupID string, token string) errors.SDKError { ret := _m.Called(id, domainID, groupID, token) @@ -5614,37 +2534,6 @@ func (_m *SDK) RemoveClientParent(id string, domainID string, groupID string, to return r0 } -// SDK_RemoveClientParent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveClientParent' -type SDK_RemoveClientParent_Call struct { - *mock.Call -} - -// RemoveClientParent is a helper method to define mock.On call -// - id string -// - domainID string -// - groupID string -// - token string -func (_e *SDK_Expecter) RemoveClientParent(id interface{}, domainID interface{}, groupID interface{}, token interface{}) *SDK_RemoveClientParent_Call { - return &SDK_RemoveClientParent_Call{Call: _e.mock.On("RemoveClientParent", id, domainID, groupID, token)} -} - -func (_c *SDK_RemoveClientParent_Call) Run(run func(id string, domainID string, groupID string, token string)) *SDK_RemoveClientParent_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveClientParent_Call) Return(_a0 errors.SDKError) *SDK_RemoveClientParent_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveClientParent_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_RemoveClientParent_Call { - _c.Call.Return(run) - return _c -} - // RemoveClientRoleActions provides a mock function with given fields: id, roleID, domainID, actions, token func (_m *SDK) RemoveClientRoleActions(id string, roleID string, domainID string, actions []string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, actions, token) @@ -5665,38 +2554,6 @@ func (_m *SDK) RemoveClientRoleActions(id string, roleID string, domainID string return r0 } -// SDK_RemoveClientRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveClientRoleActions' -type SDK_RemoveClientRoleActions_Call struct { - *mock.Call -} - -// RemoveClientRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - actions []string -// - token string -func (_e *SDK_Expecter) RemoveClientRoleActions(id interface{}, roleID interface{}, domainID interface{}, actions interface{}, token interface{}) *SDK_RemoveClientRoleActions_Call { - return &SDK_RemoveClientRoleActions_Call{Call: _e.mock.On("RemoveClientRoleActions", id, roleID, domainID, actions, token)} -} - -func (_c *SDK_RemoveClientRoleActions_Call) Run(run func(id string, roleID string, domainID string, actions []string, token string)) *SDK_RemoveClientRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].([]string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_RemoveClientRoleActions_Call) Return(_a0 errors.SDKError) *SDK_RemoveClientRoleActions_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveClientRoleActions_Call) RunAndReturn(run func(string, string, string, []string, string) errors.SDKError) *SDK_RemoveClientRoleActions_Call { - _c.Call.Return(run) - return _c -} - // RemoveClientRoleMembers provides a mock function with given fields: id, roleID, domainID, members, token func (_m *SDK) RemoveClientRoleMembers(id string, roleID string, domainID string, members []string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, members, token) @@ -5717,38 +2574,6 @@ func (_m *SDK) RemoveClientRoleMembers(id string, roleID string, domainID string return r0 } -// SDK_RemoveClientRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveClientRoleMembers' -type SDK_RemoveClientRoleMembers_Call struct { - *mock.Call -} - -// RemoveClientRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - members []string -// - token string -func (_e *SDK_Expecter) RemoveClientRoleMembers(id interface{}, roleID interface{}, domainID interface{}, members interface{}, token interface{}) *SDK_RemoveClientRoleMembers_Call { - return &SDK_RemoveClientRoleMembers_Call{Call: _e.mock.On("RemoveClientRoleMembers", id, roleID, domainID, members, token)} -} - -func (_c *SDK_RemoveClientRoleMembers_Call) Run(run func(id string, roleID string, domainID string, members []string, token string)) *SDK_RemoveClientRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].([]string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_RemoveClientRoleMembers_Call) Return(_a0 errors.SDKError) *SDK_RemoveClientRoleMembers_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveClientRoleMembers_Call) RunAndReturn(run func(string, string, string, []string, string) errors.SDKError) *SDK_RemoveClientRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // RemoveDomainRoleActions provides a mock function with given fields: id, roleID, actions, token func (_m *SDK) RemoveDomainRoleActions(id string, roleID string, actions []string, token string) errors.SDKError { ret := _m.Called(id, roleID, actions, token) @@ -5769,37 +2594,6 @@ func (_m *SDK) RemoveDomainRoleActions(id string, roleID string, actions []strin return r0 } -// SDK_RemoveDomainRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveDomainRoleActions' -type SDK_RemoveDomainRoleActions_Call struct { - *mock.Call -} - -// RemoveDomainRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - actions []string -// - token string -func (_e *SDK_Expecter) RemoveDomainRoleActions(id interface{}, roleID interface{}, actions interface{}, token interface{}) *SDK_RemoveDomainRoleActions_Call { - return &SDK_RemoveDomainRoleActions_Call{Call: _e.mock.On("RemoveDomainRoleActions", id, roleID, actions, token)} -} - -func (_c *SDK_RemoveDomainRoleActions_Call) Run(run func(id string, roleID string, actions []string, token string)) *SDK_RemoveDomainRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].([]string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveDomainRoleActions_Call) Return(_a0 errors.SDKError) *SDK_RemoveDomainRoleActions_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveDomainRoleActions_Call) RunAndReturn(run func(string, string, []string, string) errors.SDKError) *SDK_RemoveDomainRoleActions_Call { - _c.Call.Return(run) - return _c -} - // RemoveDomainRoleMembers provides a mock function with given fields: id, roleID, members, token func (_m *SDK) RemoveDomainRoleMembers(id string, roleID string, members []string, token string) errors.SDKError { ret := _m.Called(id, roleID, members, token) @@ -5820,37 +2614,6 @@ func (_m *SDK) RemoveDomainRoleMembers(id string, roleID string, members []strin return r0 } -// SDK_RemoveDomainRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveDomainRoleMembers' -type SDK_RemoveDomainRoleMembers_Call struct { - *mock.Call -} - -// RemoveDomainRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - members []string -// - token string -func (_e *SDK_Expecter) RemoveDomainRoleMembers(id interface{}, roleID interface{}, members interface{}, token interface{}) *SDK_RemoveDomainRoleMembers_Call { - return &SDK_RemoveDomainRoleMembers_Call{Call: _e.mock.On("RemoveDomainRoleMembers", id, roleID, members, token)} -} - -func (_c *SDK_RemoveDomainRoleMembers_Call) Run(run func(id string, roleID string, members []string, token string)) *SDK_RemoveDomainRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].([]string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveDomainRoleMembers_Call) Return(_a0 errors.SDKError) *SDK_RemoveDomainRoleMembers_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveDomainRoleMembers_Call) RunAndReturn(run func(string, string, []string, string) errors.SDKError) *SDK_RemoveDomainRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // RemoveGroupParent provides a mock function with given fields: id, domainID, groupID, token func (_m *SDK) RemoveGroupParent(id string, domainID string, groupID string, token string) errors.SDKError { ret := _m.Called(id, domainID, groupID, token) @@ -5871,37 +2634,6 @@ func (_m *SDK) RemoveGroupParent(id string, domainID string, groupID string, tok return r0 } -// SDK_RemoveGroupParent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveGroupParent' -type SDK_RemoveGroupParent_Call struct { - *mock.Call -} - -// RemoveGroupParent is a helper method to define mock.On call -// - id string -// - domainID string -// - groupID string -// - token string -func (_e *SDK_Expecter) RemoveGroupParent(id interface{}, domainID interface{}, groupID interface{}, token interface{}) *SDK_RemoveGroupParent_Call { - return &SDK_RemoveGroupParent_Call{Call: _e.mock.On("RemoveGroupParent", id, domainID, groupID, token)} -} - -func (_c *SDK_RemoveGroupParent_Call) Run(run func(id string, domainID string, groupID string, token string)) *SDK_RemoveGroupParent_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_RemoveGroupParent_Call) Return(_a0 errors.SDKError) *SDK_RemoveGroupParent_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveGroupParent_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_RemoveGroupParent_Call { - _c.Call.Return(run) - return _c -} - // RemoveGroupRoleActions provides a mock function with given fields: id, roleID, domainID, actions, token func (_m *SDK) RemoveGroupRoleActions(id string, roleID string, domainID string, actions []string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, actions, token) @@ -5922,38 +2654,6 @@ func (_m *SDK) RemoveGroupRoleActions(id string, roleID string, domainID string, return r0 } -// SDK_RemoveGroupRoleActions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveGroupRoleActions' -type SDK_RemoveGroupRoleActions_Call struct { - *mock.Call -} - -// RemoveGroupRoleActions is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - actions []string -// - token string -func (_e *SDK_Expecter) RemoveGroupRoleActions(id interface{}, roleID interface{}, domainID interface{}, actions interface{}, token interface{}) *SDK_RemoveGroupRoleActions_Call { - return &SDK_RemoveGroupRoleActions_Call{Call: _e.mock.On("RemoveGroupRoleActions", id, roleID, domainID, actions, token)} -} - -func (_c *SDK_RemoveGroupRoleActions_Call) Run(run func(id string, roleID string, domainID string, actions []string, token string)) *SDK_RemoveGroupRoleActions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].([]string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_RemoveGroupRoleActions_Call) Return(_a0 errors.SDKError) *SDK_RemoveGroupRoleActions_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveGroupRoleActions_Call) RunAndReturn(run func(string, string, string, []string, string) errors.SDKError) *SDK_RemoveGroupRoleActions_Call { - _c.Call.Return(run) - return _c -} - // RemoveGroupRoleMembers provides a mock function with given fields: id, roleID, domainID, members, token func (_m *SDK) RemoveGroupRoleMembers(id string, roleID string, domainID string, members []string, token string) errors.SDKError { ret := _m.Called(id, roleID, domainID, members, token) @@ -5974,38 +2674,6 @@ func (_m *SDK) RemoveGroupRoleMembers(id string, roleID string, domainID string, return r0 } -// SDK_RemoveGroupRoleMembers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveGroupRoleMembers' -type SDK_RemoveGroupRoleMembers_Call struct { - *mock.Call -} - -// RemoveGroupRoleMembers is a helper method to define mock.On call -// - id string -// - roleID string -// - domainID string -// - members []string -// - token string -func (_e *SDK_Expecter) RemoveGroupRoleMembers(id interface{}, roleID interface{}, domainID interface{}, members interface{}, token interface{}) *SDK_RemoveGroupRoleMembers_Call { - return &SDK_RemoveGroupRoleMembers_Call{Call: _e.mock.On("RemoveGroupRoleMembers", id, roleID, domainID, members, token)} -} - -func (_c *SDK_RemoveGroupRoleMembers_Call) Run(run func(id string, roleID string, domainID string, members []string, token string)) *SDK_RemoveGroupRoleMembers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].([]string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_RemoveGroupRoleMembers_Call) Return(_a0 errors.SDKError) *SDK_RemoveGroupRoleMembers_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_RemoveGroupRoleMembers_Call) RunAndReturn(run func(string, string, string, []string, string) errors.SDKError) *SDK_RemoveGroupRoleMembers_Call { - _c.Call.Return(run) - return _c -} - // ResetPassword provides a mock function with given fields: password, confPass, token func (_m *SDK) ResetPassword(password string, confPass string, token string) errors.SDKError { ret := _m.Called(password, confPass, token) @@ -6026,36 +2694,6 @@ func (_m *SDK) ResetPassword(password string, confPass string, token string) err return r0 } -// SDK_ResetPassword_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ResetPassword' -type SDK_ResetPassword_Call struct { - *mock.Call -} - -// ResetPassword is a helper method to define mock.On call -// - password string -// - confPass string -// - token string -func (_e *SDK_Expecter) ResetPassword(password interface{}, confPass interface{}, token interface{}) *SDK_ResetPassword_Call { - return &SDK_ResetPassword_Call{Call: _e.mock.On("ResetPassword", password, confPass, token)} -} - -func (_c *SDK_ResetPassword_Call) Run(run func(password string, confPass string, token string)) *SDK_ResetPassword_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_ResetPassword_Call) Return(_a0 errors.SDKError) *SDK_ResetPassword_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_ResetPassword_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_ResetPassword_Call { - _c.Call.Return(run) - return _c -} - // ResetPasswordRequest provides a mock function with given fields: email func (_m *SDK) ResetPasswordRequest(email string) errors.SDKError { ret := _m.Called(email) @@ -6076,34 +2714,6 @@ func (_m *SDK) ResetPasswordRequest(email string) errors.SDKError { return r0 } -// SDK_ResetPasswordRequest_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ResetPasswordRequest' -type SDK_ResetPasswordRequest_Call struct { - *mock.Call -} - -// ResetPasswordRequest is a helper method to define mock.On call -// - email string -func (_e *SDK_Expecter) ResetPasswordRequest(email interface{}) *SDK_ResetPasswordRequest_Call { - return &SDK_ResetPasswordRequest_Call{Call: _e.mock.On("ResetPasswordRequest", email)} -} - -func (_c *SDK_ResetPasswordRequest_Call) Run(run func(email string)) *SDK_ResetPasswordRequest_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string)) - }) - return _c -} - -func (_c *SDK_ResetPasswordRequest_Call) Return(_a0 errors.SDKError) *SDK_ResetPasswordRequest_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_ResetPasswordRequest_Call) RunAndReturn(run func(string) errors.SDKError) *SDK_ResetPasswordRequest_Call { - _c.Call.Return(run) - return _c -} - // RevokeCert provides a mock function with given fields: clientID, domainID, token func (_m *SDK) RevokeCert(clientID string, domainID string, token string) (time.Time, errors.SDKError) { ret := _m.Called(clientID, domainID, token) @@ -6134,36 +2744,6 @@ func (_m *SDK) RevokeCert(clientID string, domainID string, token string) (time. return r0, r1 } -// SDK_RevokeCert_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RevokeCert' -type SDK_RevokeCert_Call struct { - *mock.Call -} - -// RevokeCert is a helper method to define mock.On call -// - clientID string -// - domainID string -// - token string -func (_e *SDK_Expecter) RevokeCert(clientID interface{}, domainID interface{}, token interface{}) *SDK_RevokeCert_Call { - return &SDK_RevokeCert_Call{Call: _e.mock.On("RevokeCert", clientID, domainID, token)} -} - -func (_c *SDK_RevokeCert_Call) Run(run func(clientID string, domainID string, token string)) *SDK_RevokeCert_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_RevokeCert_Call) Return(_a0 time.Time, _a1 errors.SDKError) *SDK_RevokeCert_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_RevokeCert_Call) RunAndReturn(run func(string, string, string) (time.Time, errors.SDKError)) *SDK_RevokeCert_Call { - _c.Call.Return(run) - return _c -} - // SearchUsers provides a mock function with given fields: pm, token func (_m *SDK) SearchUsers(pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) { ret := _m.Called(pm, token) @@ -6194,35 +2774,6 @@ func (_m *SDK) SearchUsers(pm sdk.PageMetadata, token string) (sdk.UsersPage, er return r0, r1 } -// SDK_SearchUsers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SearchUsers' -type SDK_SearchUsers_Call struct { - *mock.Call -} - -// SearchUsers is a helper method to define mock.On call -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) SearchUsers(pm interface{}, token interface{}) *SDK_SearchUsers_Call { - return &SDK_SearchUsers_Call{Call: _e.mock.On("SearchUsers", pm, token)} -} - -func (_c *SDK_SearchUsers_Call) Run(run func(pm sdk.PageMetadata, token string)) *SDK_SearchUsers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.PageMetadata), args[1].(string)) - }) - return _c -} - -func (_c *SDK_SearchUsers_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_SearchUsers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_SearchUsers_Call) RunAndReturn(run func(sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_SearchUsers_Call { - _c.Call.Return(run) - return _c -} - // SendInvitation provides a mock function with given fields: invitation, token func (_m *SDK) SendInvitation(invitation sdk.Invitation, token string) error { ret := _m.Called(invitation, token) @@ -6241,35 +2792,6 @@ func (_m *SDK) SendInvitation(invitation sdk.Invitation, token string) error { return r0 } -// SDK_SendInvitation_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendInvitation' -type SDK_SendInvitation_Call struct { - *mock.Call -} - -// SendInvitation is a helper method to define mock.On call -// - invitation sdk.Invitation -// - token string -func (_e *SDK_Expecter) SendInvitation(invitation interface{}, token interface{}) *SDK_SendInvitation_Call { - return &SDK_SendInvitation_Call{Call: _e.mock.On("SendInvitation", invitation, token)} -} - -func (_c *SDK_SendInvitation_Call) Run(run func(invitation sdk.Invitation, token string)) *SDK_SendInvitation_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Invitation), args[1].(string)) - }) - return _c -} - -func (_c *SDK_SendInvitation_Call) Return(err error) *SDK_SendInvitation_Call { - _c.Call.Return(err) - return _c -} - -func (_c *SDK_SendInvitation_Call) RunAndReturn(run func(sdk.Invitation, string) error) *SDK_SendInvitation_Call { - _c.Call.Return(run) - return _c -} - // SendMessage provides a mock function with given fields: chanID, msg, key func (_m *SDK) SendMessage(chanID string, msg string, key string) errors.SDKError { ret := _m.Called(chanID, msg, key) @@ -6290,36 +2812,6 @@ func (_m *SDK) SendMessage(chanID string, msg string, key string) errors.SDKErro return r0 } -// SDK_SendMessage_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SendMessage' -type SDK_SendMessage_Call struct { - *mock.Call -} - -// SendMessage is a helper method to define mock.On call -// - chanID string -// - msg string -// - key string -func (_e *SDK_Expecter) SendMessage(chanID interface{}, msg interface{}, key interface{}) *SDK_SendMessage_Call { - return &SDK_SendMessage_Call{Call: _e.mock.On("SendMessage", chanID, msg, key)} -} - -func (_c *SDK_SendMessage_Call) Run(run func(chanID string, msg string, key string)) *SDK_SendMessage_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_SendMessage_Call) Return(_a0 errors.SDKError) *SDK_SendMessage_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_SendMessage_Call) RunAndReturn(run func(string, string, string) errors.SDKError) *SDK_SendMessage_Call { - _c.Call.Return(run) - return _c -} - // SetChannelParent provides a mock function with given fields: id, domainID, groupID, token func (_m *SDK) SetChannelParent(id string, domainID string, groupID string, token string) errors.SDKError { ret := _m.Called(id, domainID, groupID, token) @@ -6340,37 +2832,6 @@ func (_m *SDK) SetChannelParent(id string, domainID string, groupID string, toke return r0 } -// SDK_SetChannelParent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetChannelParent' -type SDK_SetChannelParent_Call struct { - *mock.Call -} - -// SetChannelParent is a helper method to define mock.On call -// - id string -// - domainID string -// - groupID string -// - token string -func (_e *SDK_Expecter) SetChannelParent(id interface{}, domainID interface{}, groupID interface{}, token interface{}) *SDK_SetChannelParent_Call { - return &SDK_SetChannelParent_Call{Call: _e.mock.On("SetChannelParent", id, domainID, groupID, token)} -} - -func (_c *SDK_SetChannelParent_Call) Run(run func(id string, domainID string, groupID string, token string)) *SDK_SetChannelParent_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_SetChannelParent_Call) Return(_a0 errors.SDKError) *SDK_SetChannelParent_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_SetChannelParent_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_SetChannelParent_Call { - _c.Call.Return(run) - return _c -} - // SetClientParent provides a mock function with given fields: id, domainID, groupID, token func (_m *SDK) SetClientParent(id string, domainID string, groupID string, token string) errors.SDKError { ret := _m.Called(id, domainID, groupID, token) @@ -6391,37 +2852,6 @@ func (_m *SDK) SetClientParent(id string, domainID string, groupID string, token return r0 } -// SDK_SetClientParent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetClientParent' -type SDK_SetClientParent_Call struct { - *mock.Call -} - -// SetClientParent is a helper method to define mock.On call -// - id string -// - domainID string -// - groupID string -// - token string -func (_e *SDK_Expecter) SetClientParent(id interface{}, domainID interface{}, groupID interface{}, token interface{}) *SDK_SetClientParent_Call { - return &SDK_SetClientParent_Call{Call: _e.mock.On("SetClientParent", id, domainID, groupID, token)} -} - -func (_c *SDK_SetClientParent_Call) Run(run func(id string, domainID string, groupID string, token string)) *SDK_SetClientParent_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_SetClientParent_Call) Return(_a0 errors.SDKError) *SDK_SetClientParent_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_SetClientParent_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_SetClientParent_Call { - _c.Call.Return(run) - return _c -} - // SetContentType provides a mock function with given fields: ct func (_m *SDK) SetContentType(ct sdk.ContentType) errors.SDKError { ret := _m.Called(ct) @@ -6442,34 +2872,6 @@ func (_m *SDK) SetContentType(ct sdk.ContentType) errors.SDKError { return r0 } -// SDK_SetContentType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetContentType' -type SDK_SetContentType_Call struct { - *mock.Call -} - -// SetContentType is a helper method to define mock.On call -// - ct sdk.ContentType -func (_e *SDK_Expecter) SetContentType(ct interface{}) *SDK_SetContentType_Call { - return &SDK_SetContentType_Call{Call: _e.mock.On("SetContentType", ct)} -} - -func (_c *SDK_SetContentType_Call) Run(run func(ct sdk.ContentType)) *SDK_SetContentType_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.ContentType)) - }) - return _c -} - -func (_c *SDK_SetContentType_Call) Return(_a0 errors.SDKError) *SDK_SetContentType_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_SetContentType_Call) RunAndReturn(run func(sdk.ContentType) errors.SDKError) *SDK_SetContentType_Call { - _c.Call.Return(run) - return _c -} - // SetGroupParent provides a mock function with given fields: id, domainID, groupID, token func (_m *SDK) SetGroupParent(id string, domainID string, groupID string, token string) errors.SDKError { ret := _m.Called(id, domainID, groupID, token) @@ -6490,201 +2892,6 @@ func (_m *SDK) SetGroupParent(id string, domainID string, groupID string, token return r0 } -// SDK_SetGroupParent_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetGroupParent' -type SDK_SetGroupParent_Call struct { - *mock.Call -} - -// SetGroupParent is a helper method to define mock.On call -// - id string -// - domainID string -// - groupID string -// - token string -func (_e *SDK_Expecter) SetGroupParent(id interface{}, domainID interface{}, groupID interface{}, token interface{}) *SDK_SetGroupParent_Call { - return &SDK_SetGroupParent_Call{Call: _e.mock.On("SetGroupParent", id, domainID, groupID, token)} -} - -func (_c *SDK_SetGroupParent_Call) Run(run func(id string, domainID string, groupID string, token string)) *SDK_SetGroupParent_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_SetGroupParent_Call) Return(_a0 errors.SDKError) *SDK_SetGroupParent_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_SetGroupParent_Call) RunAndReturn(run func(string, string, string, string) errors.SDKError) *SDK_SetGroupParent_Call { - _c.Call.Return(run) - return _c -} - -// UpdateBootstrap provides a mock function with given fields: cfg, domainID, token -func (_m *SDK) UpdateBootstrap(cfg sdk.BootstrapConfig, domainID string, token string) errors.SDKError { - ret := _m.Called(cfg, domainID, token) - - if len(ret) == 0 { - panic("no return value specified for UpdateBootstrap") - } - - var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(sdk.BootstrapConfig, string, string) errors.SDKError); ok { - r0 = rf(cfg, domainID, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(errors.SDKError) - } - } - - return r0 -} - -// SDK_UpdateBootstrap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateBootstrap' -type SDK_UpdateBootstrap_Call struct { - *mock.Call -} - -// UpdateBootstrap is a helper method to define mock.On call -// - cfg sdk.BootstrapConfig -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateBootstrap(cfg interface{}, domainID interface{}, token interface{}) *SDK_UpdateBootstrap_Call { - return &SDK_UpdateBootstrap_Call{Call: _e.mock.On("UpdateBootstrap", cfg, domainID, token)} -} - -func (_c *SDK_UpdateBootstrap_Call) Run(run func(cfg sdk.BootstrapConfig, domainID string, token string)) *SDK_UpdateBootstrap_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.BootstrapConfig), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_UpdateBootstrap_Call) Return(_a0 errors.SDKError) *SDK_UpdateBootstrap_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_UpdateBootstrap_Call) RunAndReturn(run func(sdk.BootstrapConfig, string, string) errors.SDKError) *SDK_UpdateBootstrap_Call { - _c.Call.Return(run) - return _c -} - -// UpdateBootstrapCerts provides a mock function with given fields: id, clientCert, clientKey, ca, domainID, token -func (_m *SDK) UpdateBootstrapCerts(id string, clientCert string, clientKey string, ca string, domainID string, token string) (sdk.BootstrapConfig, errors.SDKError) { - ret := _m.Called(id, clientCert, clientKey, ca, domainID, token) - - if len(ret) == 0 { - panic("no return value specified for UpdateBootstrapCerts") - } - - var r0 sdk.BootstrapConfig - var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string, string, string, string) (sdk.BootstrapConfig, errors.SDKError)); ok { - return rf(id, clientCert, clientKey, ca, domainID, token) - } - if rf, ok := ret.Get(0).(func(string, string, string, string, string, string) sdk.BootstrapConfig); ok { - r0 = rf(id, clientCert, clientKey, ca, domainID, token) - } else { - r0 = ret.Get(0).(sdk.BootstrapConfig) - } - - if rf, ok := ret.Get(1).(func(string, string, string, string, string, string) errors.SDKError); ok { - r1 = rf(id, clientCert, clientKey, ca, domainID, token) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(errors.SDKError) - } - } - - return r0, r1 -} - -// SDK_UpdateBootstrapCerts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateBootstrapCerts' -type SDK_UpdateBootstrapCerts_Call struct { - *mock.Call -} - -// UpdateBootstrapCerts is a helper method to define mock.On call -// - id string -// - clientCert string -// - clientKey string -// - ca string -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateBootstrapCerts(id interface{}, clientCert interface{}, clientKey interface{}, ca interface{}, domainID interface{}, token interface{}) *SDK_UpdateBootstrapCerts_Call { - return &SDK_UpdateBootstrapCerts_Call{Call: _e.mock.On("UpdateBootstrapCerts", id, clientCert, clientKey, ca, domainID, token)} -} - -func (_c *SDK_UpdateBootstrapCerts_Call) Run(run func(id string, clientCert string, clientKey string, ca string, domainID string, token string)) *SDK_UpdateBootstrapCerts_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string), args[4].(string), args[5].(string)) - }) - return _c -} - -func (_c *SDK_UpdateBootstrapCerts_Call) Return(_a0 sdk.BootstrapConfig, _a1 errors.SDKError) *SDK_UpdateBootstrapCerts_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateBootstrapCerts_Call) RunAndReturn(run func(string, string, string, string, string, string) (sdk.BootstrapConfig, errors.SDKError)) *SDK_UpdateBootstrapCerts_Call { - _c.Call.Return(run) - return _c -} - -// UpdateBootstrapConnection provides a mock function with given fields: id, channels, domainID, token -func (_m *SDK) UpdateBootstrapConnection(id string, channels []string, domainID string, token string) errors.SDKError { - ret := _m.Called(id, channels, domainID, token) - - if len(ret) == 0 { - panic("no return value specified for UpdateBootstrapConnection") - } - - var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, []string, string, string) errors.SDKError); ok { - r0 = rf(id, channels, domainID, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(errors.SDKError) - } - } - - return r0 -} - -// SDK_UpdateBootstrapConnection_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateBootstrapConnection' -type SDK_UpdateBootstrapConnection_Call struct { - *mock.Call -} - -// UpdateBootstrapConnection is a helper method to define mock.On call -// - id string -// - channels []string -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateBootstrapConnection(id interface{}, channels interface{}, domainID interface{}, token interface{}) *SDK_UpdateBootstrapConnection_Call { - return &SDK_UpdateBootstrapConnection_Call{Call: _e.mock.On("UpdateBootstrapConnection", id, channels, domainID, token)} -} - -func (_c *SDK_UpdateBootstrapConnection_Call) Run(run func(id string, channels []string, domainID string, token string)) *SDK_UpdateBootstrapConnection_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].([]string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_UpdateBootstrapConnection_Call) Return(_a0 errors.SDKError) *SDK_UpdateBootstrapConnection_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_UpdateBootstrapConnection_Call) RunAndReturn(run func(string, []string, string, string) errors.SDKError) *SDK_UpdateBootstrapConnection_Call { - _c.Call.Return(run) - return _c -} - // UpdateChannel provides a mock function with given fields: channel, domainID, token func (_m *SDK) UpdateChannel(channel sdk.Channel, domainID string, token string) (sdk.Channel, errors.SDKError) { ret := _m.Called(channel, domainID, token) @@ -6715,36 +2922,6 @@ func (_m *SDK) UpdateChannel(channel sdk.Channel, domainID string, token string) return r0, r1 } -// SDK_UpdateChannel_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateChannel' -type SDK_UpdateChannel_Call struct { - *mock.Call -} - -// UpdateChannel is a helper method to define mock.On call -// - channel sdk.Channel -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateChannel(channel interface{}, domainID interface{}, token interface{}) *SDK_UpdateChannel_Call { - return &SDK_UpdateChannel_Call{Call: _e.mock.On("UpdateChannel", channel, domainID, token)} -} - -func (_c *SDK_UpdateChannel_Call) Run(run func(channel sdk.Channel, domainID string, token string)) *SDK_UpdateChannel_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Channel), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_UpdateChannel_Call) Return(_a0 sdk.Channel, _a1 errors.SDKError) *SDK_UpdateChannel_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateChannel_Call) RunAndReturn(run func(sdk.Channel, string, string) (sdk.Channel, errors.SDKError)) *SDK_UpdateChannel_Call { - _c.Call.Return(run) - return _c -} - // UpdateChannelTags provides a mock function with given fields: c, domainID, token func (_m *SDK) UpdateChannelTags(c sdk.Channel, domainID string, token string) (sdk.Channel, errors.SDKError) { ret := _m.Called(c, domainID, token) @@ -6775,36 +2952,6 @@ func (_m *SDK) UpdateChannelTags(c sdk.Channel, domainID string, token string) ( return r0, r1 } -// SDK_UpdateChannelTags_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateChannelTags' -type SDK_UpdateChannelTags_Call struct { - *mock.Call -} - -// UpdateChannelTags is a helper method to define mock.On call -// - c sdk.Channel -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateChannelTags(c interface{}, domainID interface{}, token interface{}) *SDK_UpdateChannelTags_Call { - return &SDK_UpdateChannelTags_Call{Call: _e.mock.On("UpdateChannelTags", c, domainID, token)} -} - -func (_c *SDK_UpdateChannelTags_Call) Run(run func(c sdk.Channel, domainID string, token string)) *SDK_UpdateChannelTags_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Channel), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_UpdateChannelTags_Call) Return(_a0 sdk.Channel, _a1 errors.SDKError) *SDK_UpdateChannelTags_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateChannelTags_Call) RunAndReturn(run func(sdk.Channel, string, string) (sdk.Channel, errors.SDKError)) *SDK_UpdateChannelTags_Call { - _c.Call.Return(run) - return _c -} - // UpdateClient provides a mock function with given fields: client, domainID, token func (_m *SDK) UpdateClient(client sdk.Client, domainID string, token string) (sdk.Client, errors.SDKError) { ret := _m.Called(client, domainID, token) @@ -6835,36 +2982,6 @@ func (_m *SDK) UpdateClient(client sdk.Client, domainID string, token string) (s return r0, r1 } -// SDK_UpdateClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateClient' -type SDK_UpdateClient_Call struct { - *mock.Call -} - -// UpdateClient is a helper method to define mock.On call -// - client sdk.Client -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateClient(client interface{}, domainID interface{}, token interface{}) *SDK_UpdateClient_Call { - return &SDK_UpdateClient_Call{Call: _e.mock.On("UpdateClient", client, domainID, token)} -} - -func (_c *SDK_UpdateClient_Call) Run(run func(client sdk.Client, domainID string, token string)) *SDK_UpdateClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Client), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_UpdateClient_Call) Return(_a0 sdk.Client, _a1 errors.SDKError) *SDK_UpdateClient_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateClient_Call) RunAndReturn(run func(sdk.Client, string, string) (sdk.Client, errors.SDKError)) *SDK_UpdateClient_Call { - _c.Call.Return(run) - return _c -} - // UpdateClientRole provides a mock function with given fields: id, roleID, newName, domainID, token func (_m *SDK) UpdateClientRole(id string, roleID string, newName string, domainID string, token string) (sdk.Role, errors.SDKError) { ret := _m.Called(id, roleID, newName, domainID, token) @@ -6884,47 +3001,15 @@ func (_m *SDK) UpdateClientRole(id string, roleID string, newName string, domain r0 = ret.Get(0).(sdk.Role) } - if rf, ok := ret.Get(1).(func(string, string, string, string, string) errors.SDKError); ok { - r1 = rf(id, roleID, newName, domainID, token) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(errors.SDKError) - } - } - - return r0, r1 -} - -// SDK_UpdateClientRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateClientRole' -type SDK_UpdateClientRole_Call struct { - *mock.Call -} - -// UpdateClientRole is a helper method to define mock.On call -// - id string -// - roleID string -// - newName string -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateClientRole(id interface{}, roleID interface{}, newName interface{}, domainID interface{}, token interface{}) *SDK_UpdateClientRole_Call { - return &SDK_UpdateClientRole_Call{Call: _e.mock.On("UpdateClientRole", id, roleID, newName, domainID, token)} -} - -func (_c *SDK_UpdateClientRole_Call) Run(run func(id string, roleID string, newName string, domainID string, token string)) *SDK_UpdateClientRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_UpdateClientRole_Call) Return(_a0 sdk.Role, _a1 errors.SDKError) *SDK_UpdateClientRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} + if rf, ok := ret.Get(1).(func(string, string, string, string, string) errors.SDKError); ok { + r1 = rf(id, roleID, newName, domainID, token) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(errors.SDKError) + } + } -func (_c *SDK_UpdateClientRole_Call) RunAndReturn(run func(string, string, string, string, string) (sdk.Role, errors.SDKError)) *SDK_UpdateClientRole_Call { - _c.Call.Return(run) - return _c + return r0, r1 } // UpdateClientSecret provides a mock function with given fields: id, secret, domainID, token @@ -6957,37 +3042,6 @@ func (_m *SDK) UpdateClientSecret(id string, secret string, domainID string, tok return r0, r1 } -// SDK_UpdateClientSecret_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateClientSecret' -type SDK_UpdateClientSecret_Call struct { - *mock.Call -} - -// UpdateClientSecret is a helper method to define mock.On call -// - id string -// - secret string -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateClientSecret(id interface{}, secret interface{}, domainID interface{}, token interface{}) *SDK_UpdateClientSecret_Call { - return &SDK_UpdateClientSecret_Call{Call: _e.mock.On("UpdateClientSecret", id, secret, domainID, token)} -} - -func (_c *SDK_UpdateClientSecret_Call) Run(run func(id string, secret string, domainID string, token string)) *SDK_UpdateClientSecret_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_UpdateClientSecret_Call) Return(_a0 sdk.Client, _a1 errors.SDKError) *SDK_UpdateClientSecret_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateClientSecret_Call) RunAndReturn(run func(string, string, string, string) (sdk.Client, errors.SDKError)) *SDK_UpdateClientSecret_Call { - _c.Call.Return(run) - return _c -} - // UpdateClientTags provides a mock function with given fields: client, domainID, token func (_m *SDK) UpdateClientTags(client sdk.Client, domainID string, token string) (sdk.Client, errors.SDKError) { ret := _m.Called(client, domainID, token) @@ -7018,36 +3072,6 @@ func (_m *SDK) UpdateClientTags(client sdk.Client, domainID string, token string return r0, r1 } -// SDK_UpdateClientTags_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateClientTags' -type SDK_UpdateClientTags_Call struct { - *mock.Call -} - -// UpdateClientTags is a helper method to define mock.On call -// - client sdk.Client -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateClientTags(client interface{}, domainID interface{}, token interface{}) *SDK_UpdateClientTags_Call { - return &SDK_UpdateClientTags_Call{Call: _e.mock.On("UpdateClientTags", client, domainID, token)} -} - -func (_c *SDK_UpdateClientTags_Call) Run(run func(client sdk.Client, domainID string, token string)) *SDK_UpdateClientTags_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Client), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_UpdateClientTags_Call) Return(_a0 sdk.Client, _a1 errors.SDKError) *SDK_UpdateClientTags_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateClientTags_Call) RunAndReturn(run func(sdk.Client, string, string) (sdk.Client, errors.SDKError)) *SDK_UpdateClientTags_Call { - _c.Call.Return(run) - return _c -} - // UpdateDomain provides a mock function with given fields: d, token func (_m *SDK) UpdateDomain(d sdk.Domain, token string) (sdk.Domain, errors.SDKError) { ret := _m.Called(d, token) @@ -7078,35 +3102,6 @@ func (_m *SDK) UpdateDomain(d sdk.Domain, token string) (sdk.Domain, errors.SDKE return r0, r1 } -// SDK_UpdateDomain_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateDomain' -type SDK_UpdateDomain_Call struct { - *mock.Call -} - -// UpdateDomain is a helper method to define mock.On call -// - d sdk.Domain -// - token string -func (_e *SDK_Expecter) UpdateDomain(d interface{}, token interface{}) *SDK_UpdateDomain_Call { - return &SDK_UpdateDomain_Call{Call: _e.mock.On("UpdateDomain", d, token)} -} - -func (_c *SDK_UpdateDomain_Call) Run(run func(d sdk.Domain, token string)) *SDK_UpdateDomain_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Domain), args[1].(string)) - }) - return _c -} - -func (_c *SDK_UpdateDomain_Call) Return(_a0 sdk.Domain, _a1 errors.SDKError) *SDK_UpdateDomain_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateDomain_Call) RunAndReturn(run func(sdk.Domain, string) (sdk.Domain, errors.SDKError)) *SDK_UpdateDomain_Call { - _c.Call.Return(run) - return _c -} - // UpdateDomainRole provides a mock function with given fields: id, roleID, newName, token func (_m *SDK) UpdateDomainRole(id string, roleID string, newName string, token string) (sdk.Role, errors.SDKError) { ret := _m.Called(id, roleID, newName, token) @@ -7137,37 +3132,6 @@ func (_m *SDK) UpdateDomainRole(id string, roleID string, newName string, token return r0, r1 } -// SDK_UpdateDomainRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateDomainRole' -type SDK_UpdateDomainRole_Call struct { - *mock.Call -} - -// UpdateDomainRole is a helper method to define mock.On call -// - id string -// - roleID string -// - newName string -// - token string -func (_e *SDK_Expecter) UpdateDomainRole(id interface{}, roleID interface{}, newName interface{}, token interface{}) *SDK_UpdateDomainRole_Call { - return &SDK_UpdateDomainRole_Call{Call: _e.mock.On("UpdateDomainRole", id, roleID, newName, token)} -} - -func (_c *SDK_UpdateDomainRole_Call) Run(run func(id string, roleID string, newName string, token string)) *SDK_UpdateDomainRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_UpdateDomainRole_Call) Return(_a0 sdk.Role, _a1 errors.SDKError) *SDK_UpdateDomainRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateDomainRole_Call) RunAndReturn(run func(string, string, string, string) (sdk.Role, errors.SDKError)) *SDK_UpdateDomainRole_Call { - _c.Call.Return(run) - return _c -} - // UpdateGroup provides a mock function with given fields: group, domainID, token func (_m *SDK) UpdateGroup(group sdk.Group, domainID string, token string) (sdk.Group, errors.SDKError) { ret := _m.Called(group, domainID, token) @@ -7198,36 +3162,6 @@ func (_m *SDK) UpdateGroup(group sdk.Group, domainID string, token string) (sdk. return r0, r1 } -// SDK_UpdateGroup_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateGroup' -type SDK_UpdateGroup_Call struct { - *mock.Call -} - -// UpdateGroup is a helper method to define mock.On call -// - group sdk.Group -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateGroup(group interface{}, domainID interface{}, token interface{}) *SDK_UpdateGroup_Call { - return &SDK_UpdateGroup_Call{Call: _e.mock.On("UpdateGroup", group, domainID, token)} -} - -func (_c *SDK_UpdateGroup_Call) Run(run func(group sdk.Group, domainID string, token string)) *SDK_UpdateGroup_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.Group), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_UpdateGroup_Call) Return(_a0 sdk.Group, _a1 errors.SDKError) *SDK_UpdateGroup_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateGroup_Call) RunAndReturn(run func(sdk.Group, string, string) (sdk.Group, errors.SDKError)) *SDK_UpdateGroup_Call { - _c.Call.Return(run) - return _c -} - // UpdateGroupRole provides a mock function with given fields: id, roleID, newName, domainID, token func (_m *SDK) UpdateGroupRole(id string, roleID string, newName string, domainID string, token string) (sdk.Role, errors.SDKError) { ret := _m.Called(id, roleID, newName, domainID, token) @@ -7258,38 +3192,6 @@ func (_m *SDK) UpdateGroupRole(id string, roleID string, newName string, domainI return r0, r1 } -// SDK_UpdateGroupRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateGroupRole' -type SDK_UpdateGroupRole_Call struct { - *mock.Call -} - -// UpdateGroupRole is a helper method to define mock.On call -// - id string -// - roleID string -// - newName string -// - domainID string -// - token string -func (_e *SDK_Expecter) UpdateGroupRole(id interface{}, roleID interface{}, newName interface{}, domainID interface{}, token interface{}) *SDK_UpdateGroupRole_Call { - return &SDK_UpdateGroupRole_Call{Call: _e.mock.On("UpdateGroupRole", id, roleID, newName, domainID, token)} -} - -func (_c *SDK_UpdateGroupRole_Call) Run(run func(id string, roleID string, newName string, domainID string, token string)) *SDK_UpdateGroupRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string), args[3].(string), args[4].(string)) - }) - return _c -} - -func (_c *SDK_UpdateGroupRole_Call) Return(_a0 sdk.Role, _a1 errors.SDKError) *SDK_UpdateGroupRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateGroupRole_Call) RunAndReturn(run func(string, string, string, string, string) (sdk.Role, errors.SDKError)) *SDK_UpdateGroupRole_Call { - _c.Call.Return(run) - return _c -} - // UpdatePassword provides a mock function with given fields: oldPass, newPass, token func (_m *SDK) UpdatePassword(oldPass string, newPass string, token string) (sdk.User, errors.SDKError) { ret := _m.Called(oldPass, newPass, token) @@ -7320,36 +3222,6 @@ func (_m *SDK) UpdatePassword(oldPass string, newPass string, token string) (sdk return r0, r1 } -// SDK_UpdatePassword_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdatePassword' -type SDK_UpdatePassword_Call struct { - *mock.Call -} - -// UpdatePassword is a helper method to define mock.On call -// - oldPass string -// - newPass string -// - token string -func (_e *SDK_Expecter) UpdatePassword(oldPass interface{}, newPass interface{}, token interface{}) *SDK_UpdatePassword_Call { - return &SDK_UpdatePassword_Call{Call: _e.mock.On("UpdatePassword", oldPass, newPass, token)} -} - -func (_c *SDK_UpdatePassword_Call) Run(run func(oldPass string, newPass string, token string)) *SDK_UpdatePassword_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_UpdatePassword_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_UpdatePassword_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdatePassword_Call) RunAndReturn(run func(string, string, string) (sdk.User, errors.SDKError)) *SDK_UpdatePassword_Call { - _c.Call.Return(run) - return _c -} - // UpdateProfilePicture provides a mock function with given fields: user, token func (_m *SDK) UpdateProfilePicture(user sdk.User, token string) (sdk.User, errors.SDKError) { ret := _m.Called(user, token) @@ -7380,35 +3252,6 @@ func (_m *SDK) UpdateProfilePicture(user sdk.User, token string) (sdk.User, erro return r0, r1 } -// SDK_UpdateProfilePicture_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateProfilePicture' -type SDK_UpdateProfilePicture_Call struct { - *mock.Call -} - -// UpdateProfilePicture is a helper method to define mock.On call -// - user sdk.User -// - token string -func (_e *SDK_Expecter) UpdateProfilePicture(user interface{}, token interface{}) *SDK_UpdateProfilePicture_Call { - return &SDK_UpdateProfilePicture_Call{Call: _e.mock.On("UpdateProfilePicture", user, token)} -} - -func (_c *SDK_UpdateProfilePicture_Call) Run(run func(user sdk.User, token string)) *SDK_UpdateProfilePicture_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.User), args[1].(string)) - }) - return _c -} - -func (_c *SDK_UpdateProfilePicture_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_UpdateProfilePicture_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateProfilePicture_Call) RunAndReturn(run func(sdk.User, string) (sdk.User, errors.SDKError)) *SDK_UpdateProfilePicture_Call { - _c.Call.Return(run) - return _c -} - // UpdateUser provides a mock function with given fields: user, token func (_m *SDK) UpdateUser(user sdk.User, token string) (sdk.User, errors.SDKError) { ret := _m.Called(user, token) @@ -7439,35 +3282,6 @@ func (_m *SDK) UpdateUser(user sdk.User, token string) (sdk.User, errors.SDKErro return r0, r1 } -// SDK_UpdateUser_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateUser' -type SDK_UpdateUser_Call struct { - *mock.Call -} - -// UpdateUser is a helper method to define mock.On call -// - user sdk.User -// - token string -func (_e *SDK_Expecter) UpdateUser(user interface{}, token interface{}) *SDK_UpdateUser_Call { - return &SDK_UpdateUser_Call{Call: _e.mock.On("UpdateUser", user, token)} -} - -func (_c *SDK_UpdateUser_Call) Run(run func(user sdk.User, token string)) *SDK_UpdateUser_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.User), args[1].(string)) - }) - return _c -} - -func (_c *SDK_UpdateUser_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_UpdateUser_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateUser_Call) RunAndReturn(run func(sdk.User, string) (sdk.User, errors.SDKError)) *SDK_UpdateUser_Call { - _c.Call.Return(run) - return _c -} - // UpdateUserEmail provides a mock function with given fields: user, token func (_m *SDK) UpdateUserEmail(user sdk.User, token string) (sdk.User, errors.SDKError) { ret := _m.Called(user, token) @@ -7498,35 +3312,6 @@ func (_m *SDK) UpdateUserEmail(user sdk.User, token string) (sdk.User, errors.SD return r0, r1 } -// SDK_UpdateUserEmail_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateUserEmail' -type SDK_UpdateUserEmail_Call struct { - *mock.Call -} - -// UpdateUserEmail is a helper method to define mock.On call -// - user sdk.User -// - token string -func (_e *SDK_Expecter) UpdateUserEmail(user interface{}, token interface{}) *SDK_UpdateUserEmail_Call { - return &SDK_UpdateUserEmail_Call{Call: _e.mock.On("UpdateUserEmail", user, token)} -} - -func (_c *SDK_UpdateUserEmail_Call) Run(run func(user sdk.User, token string)) *SDK_UpdateUserEmail_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.User), args[1].(string)) - }) - return _c -} - -func (_c *SDK_UpdateUserEmail_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_UpdateUserEmail_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateUserEmail_Call) RunAndReturn(run func(sdk.User, string) (sdk.User, errors.SDKError)) *SDK_UpdateUserEmail_Call { - _c.Call.Return(run) - return _c -} - // UpdateUserRole provides a mock function with given fields: user, token func (_m *SDK) UpdateUserRole(user sdk.User, token string) (sdk.User, errors.SDKError) { ret := _m.Called(user, token) @@ -7557,35 +3342,6 @@ func (_m *SDK) UpdateUserRole(user sdk.User, token string) (sdk.User, errors.SDK return r0, r1 } -// SDK_UpdateUserRole_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateUserRole' -type SDK_UpdateUserRole_Call struct { - *mock.Call -} - -// UpdateUserRole is a helper method to define mock.On call -// - user sdk.User -// - token string -func (_e *SDK_Expecter) UpdateUserRole(user interface{}, token interface{}) *SDK_UpdateUserRole_Call { - return &SDK_UpdateUserRole_Call{Call: _e.mock.On("UpdateUserRole", user, token)} -} - -func (_c *SDK_UpdateUserRole_Call) Run(run func(user sdk.User, token string)) *SDK_UpdateUserRole_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.User), args[1].(string)) - }) - return _c -} - -func (_c *SDK_UpdateUserRole_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_UpdateUserRole_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateUserRole_Call) RunAndReturn(run func(sdk.User, string) (sdk.User, errors.SDKError)) *SDK_UpdateUserRole_Call { - _c.Call.Return(run) - return _c -} - // UpdateUserTags provides a mock function with given fields: user, token func (_m *SDK) UpdateUserTags(user sdk.User, token string) (sdk.User, errors.SDKError) { ret := _m.Called(user, token) @@ -7616,35 +3372,6 @@ func (_m *SDK) UpdateUserTags(user sdk.User, token string) (sdk.User, errors.SDK return r0, r1 } -// SDK_UpdateUserTags_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateUserTags' -type SDK_UpdateUserTags_Call struct { - *mock.Call -} - -// UpdateUserTags is a helper method to define mock.On call -// - user sdk.User -// - token string -func (_e *SDK_Expecter) UpdateUserTags(user interface{}, token interface{}) *SDK_UpdateUserTags_Call { - return &SDK_UpdateUserTags_Call{Call: _e.mock.On("UpdateUserTags", user, token)} -} - -func (_c *SDK_UpdateUserTags_Call) Run(run func(user sdk.User, token string)) *SDK_UpdateUserTags_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.User), args[1].(string)) - }) - return _c -} - -func (_c *SDK_UpdateUserTags_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_UpdateUserTags_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateUserTags_Call) RunAndReturn(run func(sdk.User, string) (sdk.User, errors.SDKError)) *SDK_UpdateUserTags_Call { - _c.Call.Return(run) - return _c -} - // UpdateUsername provides a mock function with given fields: user, token func (_m *SDK) UpdateUsername(user sdk.User, token string) (sdk.User, errors.SDKError) { ret := _m.Called(user, token) @@ -7675,35 +3402,6 @@ func (_m *SDK) UpdateUsername(user sdk.User, token string) (sdk.User, errors.SDK return r0, r1 } -// SDK_UpdateUsername_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateUsername' -type SDK_UpdateUsername_Call struct { - *mock.Call -} - -// UpdateUsername is a helper method to define mock.On call -// - user sdk.User -// - token string -func (_e *SDK_Expecter) UpdateUsername(user interface{}, token interface{}) *SDK_UpdateUsername_Call { - return &SDK_UpdateUsername_Call{Call: _e.mock.On("UpdateUsername", user, token)} -} - -func (_c *SDK_UpdateUsername_Call) Run(run func(user sdk.User, token string)) *SDK_UpdateUsername_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.User), args[1].(string)) - }) - return _c -} - -func (_c *SDK_UpdateUsername_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_UpdateUsername_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UpdateUsername_Call) RunAndReturn(run func(sdk.User, string) (sdk.User, errors.SDKError)) *SDK_UpdateUsername_Call { - _c.Call.Return(run) - return _c -} - // User provides a mock function with given fields: id, token func (_m *SDK) User(id string, token string) (sdk.User, errors.SDKError) { ret := _m.Called(id, token) @@ -7734,35 +3432,6 @@ func (_m *SDK) User(id string, token string) (sdk.User, errors.SDKError) { return r0, r1 } -// SDK_User_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'User' -type SDK_User_Call struct { - *mock.Call -} - -// User is a helper method to define mock.On call -// - id string -// - token string -func (_e *SDK_Expecter) User(id interface{}, token interface{}) *SDK_User_Call { - return &SDK_User_Call{Call: _e.mock.On("User", id, token)} -} - -func (_c *SDK_User_Call) Run(run func(id string, token string)) *SDK_User_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_User_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_User_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_User_Call) RunAndReturn(run func(string, string) (sdk.User, errors.SDKError)) *SDK_User_Call { - _c.Call.Return(run) - return _c -} - // UserProfile provides a mock function with given fields: token func (_m *SDK) UserProfile(token string) (sdk.User, errors.SDKError) { ret := _m.Called(token) @@ -7793,34 +3462,6 @@ func (_m *SDK) UserProfile(token string) (sdk.User, errors.SDKError) { return r0, r1 } -// SDK_UserProfile_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UserProfile' -type SDK_UserProfile_Call struct { - *mock.Call -} - -// UserProfile is a helper method to define mock.On call -// - token string -func (_e *SDK_Expecter) UserProfile(token interface{}) *SDK_UserProfile_Call { - return &SDK_UserProfile_Call{Call: _e.mock.On("UserProfile", token)} -} - -func (_c *SDK_UserProfile_Call) Run(run func(token string)) *SDK_UserProfile_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string)) - }) - return _c -} - -func (_c *SDK_UserProfile_Call) Return(_a0 sdk.User, _a1 errors.SDKError) *SDK_UserProfile_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_UserProfile_Call) RunAndReturn(run func(string) (sdk.User, errors.SDKError)) *SDK_UserProfile_Call { - _c.Call.Return(run) - return _c -} - // Users provides a mock function with given fields: pm, token func (_m *SDK) Users(pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.SDKError) { ret := _m.Called(pm, token) @@ -7851,95 +3492,6 @@ func (_m *SDK) Users(pm sdk.PageMetadata, token string) (sdk.UsersPage, errors.S return r0, r1 } -// SDK_Users_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Users' -type SDK_Users_Call struct { - *mock.Call -} - -// Users is a helper method to define mock.On call -// - pm sdk.PageMetadata -// - token string -func (_e *SDK_Expecter) Users(pm interface{}, token interface{}) *SDK_Users_Call { - return &SDK_Users_Call{Call: _e.mock.On("Users", pm, token)} -} - -func (_c *SDK_Users_Call) Run(run func(pm sdk.PageMetadata, token string)) *SDK_Users_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(sdk.PageMetadata), args[1].(string)) - }) - return _c -} - -func (_c *SDK_Users_Call) Return(_a0 sdk.UsersPage, _a1 errors.SDKError) *SDK_Users_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_Users_Call) RunAndReturn(run func(sdk.PageMetadata, string) (sdk.UsersPage, errors.SDKError)) *SDK_Users_Call { - _c.Call.Return(run) - return _c -} - -// ViewBootstrap provides a mock function with given fields: id, domainID, token -func (_m *SDK) ViewBootstrap(id string, domainID string, token string) (sdk.BootstrapConfig, errors.SDKError) { - ret := _m.Called(id, domainID, token) - - if len(ret) == 0 { - panic("no return value specified for ViewBootstrap") - } - - var r0 sdk.BootstrapConfig - var r1 errors.SDKError - if rf, ok := ret.Get(0).(func(string, string, string) (sdk.BootstrapConfig, errors.SDKError)); ok { - return rf(id, domainID, token) - } - if rf, ok := ret.Get(0).(func(string, string, string) sdk.BootstrapConfig); ok { - r0 = rf(id, domainID, token) - } else { - r0 = ret.Get(0).(sdk.BootstrapConfig) - } - - if rf, ok := ret.Get(1).(func(string, string, string) errors.SDKError); ok { - r1 = rf(id, domainID, token) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(errors.SDKError) - } - } - - return r0, r1 -} - -// SDK_ViewBootstrap_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ViewBootstrap' -type SDK_ViewBootstrap_Call struct { - *mock.Call -} - -// ViewBootstrap is a helper method to define mock.On call -// - id string -// - domainID string -// - token string -func (_e *SDK_Expecter) ViewBootstrap(id interface{}, domainID interface{}, token interface{}) *SDK_ViewBootstrap_Call { - return &SDK_ViewBootstrap_Call{Call: _e.mock.On("ViewBootstrap", id, domainID, token)} -} - -func (_c *SDK_ViewBootstrap_Call) Run(run func(id string, domainID string, token string)) *SDK_ViewBootstrap_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_ViewBootstrap_Call) Return(_a0 sdk.BootstrapConfig, _a1 errors.SDKError) *SDK_ViewBootstrap_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ViewBootstrap_Call) RunAndReturn(run func(string, string, string) (sdk.BootstrapConfig, errors.SDKError)) *SDK_ViewBootstrap_Call { - _c.Call.Return(run) - return _c -} - // ViewCert provides a mock function with given fields: certID, domainID, token func (_m *SDK) ViewCert(certID string, domainID string, token string) (sdk.Cert, errors.SDKError) { ret := _m.Called(certID, domainID, token) @@ -7970,36 +3522,6 @@ func (_m *SDK) ViewCert(certID string, domainID string, token string) (sdk.Cert, return r0, r1 } -// SDK_ViewCert_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ViewCert' -type SDK_ViewCert_Call struct { - *mock.Call -} - -// ViewCert is a helper method to define mock.On call -// - certID string -// - domainID string -// - token string -func (_e *SDK_Expecter) ViewCert(certID interface{}, domainID interface{}, token interface{}) *SDK_ViewCert_Call { - return &SDK_ViewCert_Call{Call: _e.mock.On("ViewCert", certID, domainID, token)} -} - -func (_c *SDK_ViewCert_Call) Run(run func(certID string, domainID string, token string)) *SDK_ViewCert_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_ViewCert_Call) Return(_a0 sdk.Cert, _a1 errors.SDKError) *SDK_ViewCert_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ViewCert_Call) RunAndReturn(run func(string, string, string) (sdk.Cert, errors.SDKError)) *SDK_ViewCert_Call { - _c.Call.Return(run) - return _c -} - // ViewCertByClient provides a mock function with given fields: clientID, domainID, token func (_m *SDK) ViewCertByClient(clientID string, domainID string, token string) (sdk.CertSerials, errors.SDKError) { ret := _m.Called(clientID, domainID, token) @@ -8030,36 +3552,6 @@ func (_m *SDK) ViewCertByClient(clientID string, domainID string, token string) return r0, r1 } -// SDK_ViewCertByClient_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ViewCertByClient' -type SDK_ViewCertByClient_Call struct { - *mock.Call -} - -// ViewCertByClient is a helper method to define mock.On call -// - clientID string -// - domainID string -// - token string -func (_e *SDK_Expecter) ViewCertByClient(clientID interface{}, domainID interface{}, token interface{}) *SDK_ViewCertByClient_Call { - return &SDK_ViewCertByClient_Call{Call: _e.mock.On("ViewCertByClient", clientID, domainID, token)} -} - -func (_c *SDK_ViewCertByClient_Call) Run(run func(clientID string, domainID string, token string)) *SDK_ViewCertByClient_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string), args[2].(string)) - }) - return _c -} - -func (_c *SDK_ViewCertByClient_Call) Return(_a0 sdk.CertSerials, _a1 errors.SDKError) *SDK_ViewCertByClient_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ViewCertByClient_Call) RunAndReturn(run func(string, string, string) (sdk.CertSerials, errors.SDKError)) *SDK_ViewCertByClient_Call { - _c.Call.Return(run) - return _c -} - // ViewSubscription provides a mock function with given fields: id, token func (_m *SDK) ViewSubscription(id string, token string) (sdk.Subscription, errors.SDKError) { ret := _m.Called(id, token) @@ -8090,86 +3582,6 @@ func (_m *SDK) ViewSubscription(id string, token string) (sdk.Subscription, erro return r0, r1 } -// SDK_ViewSubscription_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ViewSubscription' -type SDK_ViewSubscription_Call struct { - *mock.Call -} - -// ViewSubscription is a helper method to define mock.On call -// - id string -// - token string -func (_e *SDK_Expecter) ViewSubscription(id interface{}, token interface{}) *SDK_ViewSubscription_Call { - return &SDK_ViewSubscription_Call{Call: _e.mock.On("ViewSubscription", id, token)} -} - -func (_c *SDK_ViewSubscription_Call) Run(run func(id string, token string)) *SDK_ViewSubscription_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(string)) - }) - return _c -} - -func (_c *SDK_ViewSubscription_Call) Return(_a0 sdk.Subscription, _a1 errors.SDKError) *SDK_ViewSubscription_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *SDK_ViewSubscription_Call) RunAndReturn(run func(string, string) (sdk.Subscription, errors.SDKError)) *SDK_ViewSubscription_Call { - _c.Call.Return(run) - return _c -} - -// Whitelist provides a mock function with given fields: clientID, state, domainID, token -func (_m *SDK) Whitelist(clientID string, state int, domainID string, token string) errors.SDKError { - ret := _m.Called(clientID, state, domainID, token) - - if len(ret) == 0 { - panic("no return value specified for Whitelist") - } - - var r0 errors.SDKError - if rf, ok := ret.Get(0).(func(string, int, string, string) errors.SDKError); ok { - r0 = rf(clientID, state, domainID, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(errors.SDKError) - } - } - - return r0 -} - -// SDK_Whitelist_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Whitelist' -type SDK_Whitelist_Call struct { - *mock.Call -} - -// Whitelist is a helper method to define mock.On call -// - clientID string -// - state int -// - domainID string -// - token string -func (_e *SDK_Expecter) Whitelist(clientID interface{}, state interface{}, domainID interface{}, token interface{}) *SDK_Whitelist_Call { - return &SDK_Whitelist_Call{Call: _e.mock.On("Whitelist", clientID, state, domainID, token)} -} - -func (_c *SDK_Whitelist_Call) Run(run func(clientID string, state int, domainID string, token string)) *SDK_Whitelist_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(string), args[1].(int), args[2].(string), args[3].(string)) - }) - return _c -} - -func (_c *SDK_Whitelist_Call) Return(_a0 errors.SDKError) *SDK_Whitelist_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *SDK_Whitelist_Call) RunAndReturn(run func(string, int, string, string) errors.SDKError) *SDK_Whitelist_Call { - _c.Call.Return(run) - return _c -} - // NewSDK creates a new instance of SDK. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewSDK(t interface { diff --git a/pkg/sdk/responses.go b/pkg/sdk/responses.go index 5a2c2a7d1d..f26b25703e 100644 --- a/pkg/sdk/responses.go +++ b/pkg/sdk/responses.go @@ -67,12 +67,6 @@ type revokeCertsRes struct { RevocationTime time.Time `json:"revocation_time"` } -// bootstrapsPage contains list of bootstrap configs in a page with proper metadata. -type BootstrapPage struct { - Configs []BootstrapConfig `json:"configs"` - PageRes -} - type CertSerials struct { Certs []Cert `json:"certs"` PageRes diff --git a/pkg/sdk/sdk.go b/pkg/sdk/sdk.go index 5b71efbf31..2922626168 100644 --- a/pkg/sdk/sdk.go +++ b/pkg/sdk/sdk.go @@ -1069,94 +1069,6 @@ type SDK interface { // fmt.Println(health) Health(service string) (HealthInfo, errors.SDKError) - // AddBootstrap add bootstrap configuration - // - // example: - // cfg := sdk.BootstrapConfig{ - // ClientID: "clientID", - // Name: "bootstrap", - // ExternalID: "externalID", - // ExternalKey: "externalKey", - // Channels: []string{"channel1", "channel2"}, - // } - // id, _ := sdk.AddBootstrap(cfg, "domainID", "token") - // fmt.Println(id) - AddBootstrap(cfg BootstrapConfig, domainID, token string) (string, errors.SDKError) - - // View returns Client Config with given ID belonging to the user identified by the given token. - // - // example: - // bootstrap, _ := sdk.ViewBootstrap("id", "domainID", "token") - // fmt.Println(bootstrap) - ViewBootstrap(id, domainID, token string) (BootstrapConfig, errors.SDKError) - - // Update updates editable fields of the provided Config. - // - // example: - // cfg := sdk.BootstrapConfig{ - // ClientID: "clientID", - // Name: "bootstrap", - // ExternalID: "externalID", - // ExternalKey: "externalKey", - // Channels: []string{"channel1", "channel2"}, - // } - // err := sdk.UpdateBootstrap(cfg, "domainID", "token") - // fmt.Println(err) - UpdateBootstrap(cfg BootstrapConfig, domainID, token string) errors.SDKError - - // Update bootstrap config certificates. - // - // example: - // err := sdk.UpdateBootstrapCerts("id", "clientCert", "clientKey", "ca", "domainID", "token") - // fmt.Println(err) - UpdateBootstrapCerts(id string, clientCert, clientKey, ca string, domainID, token string) (BootstrapConfig, errors.SDKError) - - // UpdateBootstrapConnection updates connections performs update of the channel list corresponding Client is connected to. - // - // example: - // err := sdk.UpdateBootstrapConnection("id", []string{"channel1", "channel2"}, "domainID", "token") - // fmt.Println(err) - UpdateBootstrapConnection(id string, channels []string, domainID, token string) errors.SDKError - - // Remove removes Config with specified token that belongs to the user identified by the given token. - // - // example: - // err := sdk.RemoveBootstrap("id", "domainID", "token") - // fmt.Println(err) - RemoveBootstrap(id, domainID, token string) errors.SDKError - - // Bootstrap returns Config to the Client with provided external ID using external key. - // - // example: - // bootstrap, _ := sdk.Bootstrap("externalID", "externalKey") - // fmt.Println(bootstrap) - Bootstrap(externalID, externalKey string) (BootstrapConfig, errors.SDKError) - - // BootstrapSecure retrieves a configuration with given external ID and encrypted external key. - // - // example: - // bootstrap, _ := sdk.BootstrapSecure("externalID", "externalKey", "cryptoKey") - // fmt.Println(bootstrap) - BootstrapSecure(externalID, externalKey, cryptoKey string) (BootstrapConfig, errors.SDKError) - - // Bootstraps retrieves a list of managed configs. - // - // example: - // pm := sdk.PageMetadata{ - // Offset: 0, - // Limit: 10, - // } - // bootstraps, _ := sdk.Bootstraps(pm, "domainID", "token") - // fmt.Println(bootstraps) - Bootstraps(pm PageMetadata, domainID, token string) (BootstrapPage, errors.SDKError) - - // Whitelist updates Client state Config with given ID belonging to the user identified by the given token. - // - // example: - // err := sdk.Whitelist("clientID", 1, "domainID", "token") - // fmt.Println(err) - Whitelist(clientID string, state int, domainID, token string) errors.SDKError - // IssueCert issues a certificate for a client required for mTLS. // // example: @@ -1456,7 +1368,6 @@ type SDK interface { } type mgSDK struct { - bootstrapURL string certsURL string httpAdapterURL string readerURL string @@ -1476,7 +1387,6 @@ type mgSDK struct { // Config contains sdk configuration parameters. type Config struct { - BootstrapURL string CertsURL string HTTPAdapterURL string ReaderURL string @@ -1497,7 +1407,6 @@ type Config struct { // NewSDK returns new supermq SDK instance. func NewSDK(conf Config) SDK { return &mgSDK{ - bootstrapURL: conf.BootstrapURL, certsURL: conf.CertsURL, httpAdapterURL: conf.HTTPAdapterURL, readerURL: conf.ReaderURL, diff --git a/provision/README.md b/provision/README.md deleted file mode 100644 index 39aa87a64e..0000000000 --- a/provision/README.md +++ /dev/null @@ -1,194 +0,0 @@ -# Provision service - -Provision service provides an HTTP API to interact with [SuperMQ][supermq]. -Provision service is used to setup initial applications configuration i.e. clients, channels, connections and certificates that will be required for the specific use case especially useful for gateway provision. - -For gateways to communicate with [SuperMQ][supermq] configuration is required (mqtt host, client, channels, certificates...). To get the configuration gateway will send a request to [Bootstrap][bootstrap] service providing `` and `` in request. To make a request to [Bootstrap][bootstrap] service you can use [Agent][agent] service on a gateway. - -To create bootstrap configuration you can use [Bootstrap][bootstrap] or `Provision` service. [SuperMQ UI][mgxui] uses [Bootstrap][bootstrap] service for creating gateway configurations. `Provision` service should provide an easy way of provisioning your gateways i.e creating bootstrap configuration and as many clients and channels that your setup requires. - -Also you may use provision service to create certificates for each client. Each service running on gateway may require more than one client and channel for communication. Let's say that you are using services [Agent][agent] and [Export][export] on a gateway you will need two channels for `Agent` (`data` and `control`) and one for `Export` and one client. Additionally if you enabled mtls each service will need its own client and certificate for access to [SuperMQ][supermq]. Your setup could require any number of clients and channels this kind of setup we can call `provision layout`. - -Provision service provides a way of specifying this `provision layout` and creating a setup according to that layout by serving requests on `/mapping` endpoint. Provision layout is configured in [config.toml](configs/config.toml). - -## 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 | -| ------------------------------------ | -------------------------------------------------- | ----------------------- | -| SMQ_PROVISION_LOG_LEVEL | Service log level | debug | -| SMQ_PROVISION_USER | User (email) for accessing SuperMQ | | -| SMQ_PROVISION_PASS | SuperMQ password | user123 | -| SMQ_PROVISION_API_KEY | SuperMQ authentication token | | -| SMQ_PROVISION_CONFIG_FILE | Provision config file | config.toml | -| SMQ_PROVISION_HTTP_PORT | Provision service listening port | 9016 | -| SMQ_PROVISION_ENV_CLIENTS_TLS | SuperMQ SDK TLS verification | false | -| SMQ_PROVISION_SERVER_CERT | SuperMQ gRPC secure server cert | | -| SMQ_PROVISION_SERVER_KEY | SuperMQ gRPC secure server key | | -| SMQ_PROVISION_USERS_LOCATION | Users service URL | | -| SMQ_PROVISION_CLIENTS_LOCATION | Clients service URL | | -| SMQ_PROVISION_BS_SVC_URL | SuperMQ Bootstrap service URL | | -| SMQ_PROVISION_CERTS_SVC_URL | Certificates service URL | | -| SMQ_PROVISION_X509_PROVISIONING | Should X509 client cert be provisioned | false | -| SMQ_PROVISION_BS_CONFIG_PROVISIONING | Should client config be saved in Bootstrap service | true | -| SMQ_PROVISION_BS_AUTO_WHITELIST | Should client be auto whitelisted | true | -| SMQ_PROVISION_BS_CONTENT | Bootstrap service configs content, JSON format | {} | -| SMQ_PROVISION_CERTS_RSA_BITS | Certificate RSA bits parameter | 4096 | -| SMQ_PROVISION_CERTS_HOURS_VALID | Number of hours that certificate is valid | "2400h" | -| SMQ_SEND_TELEMETRY | Send telemetry to supermq call home server | true | - -By default, call to `/mapping` endpoint will create one client and two channels (`control` and `data`) and connect it. If there is a requirement for different provision layout we can use [config](docker/configs/config.toml) file in addition to environment variables. - -For the purposes of running provision as an add-on in docker composition environment variables seems more suitable. Environment variables are set in [.env](.env). - -Configuration can be specified in [config.toml](configs/config.toml). Config file can specify all the settings that environment variables can configure and in addition -`/mapping` endpoint provision layout can be configured. - -In `config.toml` we can enlist array of clients and channels that we want to create and make connections between them which we call provision layout. - -Metadata can be whatever suits your needs except that at least one client needs to have `external_id` (which is populated with value from [request](#example)). Client that has `external_id` will be used for creating bootstrap configuration which can be fetched with [Agent][agent]. -For channels metadata `type` is reserved for `control` and `data` which we use with [Agent][agent]. - -Example of provision layout below - -```toml -[[clients]] - name = "client" - - [clients.metadata] - external_id = "xxxxxx" - - -[[channels]] - name = "control-channel" - - [channels.metadata] - type = "control" - -[[channels]] - name = "data-channel" - - [channels.metadata] - type = "data" - -[[channels]] - name = "export-channel" - - [channels.metadata] - type = "data" -``` - -## Authentication - -In order to create necessary entities provision service needs to authenticate against SuperMQ. To provide authentication credentials to the provision service you can pass it in an environment variable or in a config file as SuperMQ user and password or as API token that can be issued on `/users/tokens/issue`. - -Additionally users or API token can be passed in Authorization header, this authentication takes precedence over others. - -- `username`, `password` - (`SMQ_PROVISION_USER`, `SMQ_PROVISION_PASSWORD` in [.env](../.env), `mg_user`, `mg_pass` in [config.toml](../docker/addons/provision/configs/config.toml)) -- API Key - (`SMQ_PROVISION_API_KEY` in [.env](../.env) or [config.toml](../docker/addons/provision/configs/config.toml)) -- `Authorization: Bearer Token` - request authorization header containing either users token. - -## Running - -Provision service can be run as a standalone or in docker composition as addon to the core docker composition. - -Standalone: - -```bash -SMQ_PROVISION_BS_SVC_URL=http://localhost:9013 \ -SMQ_PROVISION_CLIENTS_LOCATION=http://localhost:9000 \ -SMQ_PROVISION_USERS_LOCATION=http://localhost:9002 \ -SMQ_PROVISION_CONFIG_FILE=docker/addons/provision/configs/config.toml \ -build/supermq-provision -``` - -Docker composition: - -```bash -docker compose -f docker/addons/provision/docker-compose.yml up -``` - -For the case that credentials or API token is passed in configuration file or environment variables, call to `/mapping` endpoint doesn't require `Authentication` header: - -```bash -curl -s -S -X POST http://localhost:/mapping -H 'Content-Type: application/json' -d '{"external_id": "33:52:77:99:43", "external_key": "223334fw2"}' -``` - -In the case that provision service is not deployed with credentials or API key or you want to use user other than one being set in environment (or config file): - -```bash -curl -s -S -X POST http://localhost:/mapping -H "Authorization: Bearer " -H 'Content-Type: application/json' -d '{"external_id": "", "external_key": ""}' -``` - -Or if you want to specify a name for client different than in `config.toml` you can specify post data as: - -```json -{ - "name": "", - "external_id": "", - "external_key": "" -} -``` - -Response contains created clients, channels and certificates if any: - -```json -{ - "clients": [ - { - "id": "c22b0c0f-8c03-40da-a06b-37ed3a72c8d1", - "name": "client", - "key": "007cce56-e0eb-40d6-b2b9-ed348a97d1eb", - "metadata": { - "external_id": "33:52:79:C3:43" - } - } - ], - "channels": [ - { - "id": "064c680e-181b-4b58-975e-6983313a5170", - "name": "control-channel", - "metadata": { - "type": "control" - } - }, - { - "id": "579da92d-6078-4801-a18a-dd1cfa2aa44f", - "name": "data-channel", - "metadata": { - "type": "data" - } - } - ], - "whitelisted": { - "c22b0c0f-8c03-40da-a06b-37ed3a72c8d1": true - } -} -``` - -## Certificates - -Provision service has `/certs` endpoint that can be used to generate certificates for clients when mTLS is required: - -- `users_token` - users authentication token or API token -- `client_id` - id of the client for which certificate is going to be generated - -```bash -curl -s -X POST http://localhost:8190/certs -H "Authorization: Bearer " -H 'Content-Type: application/json' -d '{"client_id": "", "ttl":"2400h" }' -``` - -```json -{ - "client_cert": "-----BEGIN CERTIFICATE-----\nMIIEmDCCA4CgAwIBAgIQCZ0NOq2oKLo+XftbAu0TfzANBgkqhkiG9w0BAQsFADBX\nMRIwEAYDVQQDDAlsb2NhbGhvc3QxETAPBgNVBAoMCE1haW5mbHV4MQwwCgYDVQQL\nDANJb1QxIDAeBgkqhkiG9w0BCQEWEWluZm9AbWFpbmZsdXguY29tMB4XDTIwMDYw\nNTEyMzc1M1oXDTIwMDkxMzEyMzc1M1owVTERMA8GA1UEChMITWFpbmZsdXgxETAP\nBgNVBAsTCG1haW5mbHV4MS0wKwYDVQQDEyQyYmZlYmZmMC05ODZhLTQ3ZTAtOGQ3\nYS00YTRiN2UyYjU3OGUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCn\nWvTuOIdhqOLEREcEJqfQAtDoYu3rUDijOffXuWFZgNqfZTGmoD5ZqJXxwbZ4tCST\npdSteHtyr7JXnPJQN1dsslU+q3haKjFoZRc39/7u4/8XCTwlqbMl9YVcwqS+FLkM\niLSyyqzryP7Y8H8cidTKg56p5JALaEKfzZS6Km3G+CCinR6hNNW9ckWsy29a0/9E\nMAUtM+Lsk5OjsHzOnWruuqHsCx4ODI5aJQaMC1qntkbXkht0WDiwAt9SDQ3uLWru\nAoSJDK9a6EgR3a0Jf7ZiVPiwlZNjrB/I5OQyFDGqcmSAl2rdJqPkmaDXKKFyL1cG\nMIyHv62QzJoMdRoXu20lxyGxAvEjQNVHux4LA3dbf/85nEVTI2uP8crMf2Jnzbg5\n9zF+iTMJGpUlatCyK2RJS/mvHbbUIf5Ro3VbcPHbgFroJ7qMFz0Fc5kYY8IdwXjG\nlyG9MobKEO2CfBGRjPmCuTQq2HcuOy7F6KfQf3HToI8MmC5hBtCmTNbV8I3GIjWA\n/xJQLm2pVZ41QhrnNGtuqAYoe3Zt6OldxGRcoAj7KlIpYcPZ55PJ6mWcV6dB9Fnl\n5mYOwQL8jtfybbGWvqJldhTxUqm7/EbAaF0Qjmh4oOHMl2xADrmYzJHvf0llwr6g\noRQuzqxPi0aW3tkFNsm63NX1Ab5BXFQhMSj5+82blwIDAQABo2IwYDAOBgNVHQ8B\nAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA4GA1UdDgQH\nBAUBAgMEBjAfBgNVHSMEGDAWgBRs4xR91qEjNRGmw391xS7x6Tc+8jANBgkqhkiG\n9w0BAQsFAAOCAQEAphLT8PjawRRWswU1B5oWnnqeTllnvGB88sjDPLAG0UiBlDLX\nwoPiBVPWuYV+MMJuaREgheYF1Ahx4Jrfy9stFDU7B99ON1T58oM1aKEq4rKc+/Ke\nyxrAFTonclC0LNaaOvpZZjsPFWr2muTQO8XHiS8icw3BLxEzoF+5aJ8ihtxRtfKL\nUvtHDqC6IPAbSUcvqyjrFh3RrTUAyGOzW12IEWSXP9DLwoiLPwJ6kCVoXdG/asjz\nUpk/jj7AUn9oJNF8nUbyhdOnmeJ2z0x1ylgYrIAxvGzm8zs+NEVN67CrBYKwstlN\nvw7DRQsCvGJjZzWj28VV3FGLtXFgu52bFZNBww==\n-----END CERTIFICATE-----\n", - "client_cert_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIJJwIBAAKCAgEAp1r07jiHYajixERHBCan0ALQ6GLt61A4ozn317lhWYDan2Ux\npqA+WaiV8cG2eLQkk6XUrXh7cq+yV5zyUDdXbLJVPqt4WioxaGUXN/f+7uP/Fwk8\nJamzJfWFXMKkvhS5DIi0ssqs68j+2PB/HInUyoOeqeSQC2hCn82Uuiptxvggop0e\noTTVvXJFrMtvWtP/RDAFLTPi7JOTo7B8zp1q7rqh7AseDgyOWiUGjAtap7ZG15Ib\ndFg4sALfUg0N7i1q7gKEiQyvWuhIEd2tCX+2YlT4sJWTY6wfyOTkMhQxqnJkgJdq\n3Saj5Jmg1yihci9XBjCMh7+tkMyaDHUaF7ttJcchsQLxI0DVR7seCwN3W3//OZxF\nUyNrj/HKzH9iZ824OfcxfokzCRqVJWrQsitkSUv5rx221CH+UaN1W3Dx24Ba6Ce6\njBc9BXOZGGPCHcF4xpchvTKGyhDtgnwRkYz5grk0Kth3Ljsuxein0H9x06CPDJgu\nYQbQpkzW1fCNxiI1gP8SUC5tqVWeNUIa5zRrbqgGKHt2bejpXcRkXKAI+ypSKWHD\n2eeTyeplnFenQfRZ5eZmDsEC/I7X8m2xlr6iZXYU8VKpu/xGwGhdEI5oeKDhzJds\nQA65mMyR739JZcK+oKEULs6sT4tGlt7ZBTbJutzV9QG+QVxUITEo+fvNm5cCAwEA\nAQKCAgAmCIfNc89gpG8Ux6eUC+zrWxh7F7CWX97fSZdH0XuMSbplqyvDgHtrCOM6\n1BlSCS6e13skCVOU1tUjECoJjOoza7vvyCxL4XblEMRcFeI8DFi2tYST0qNCJzAt\nypaCFFeRv6fBUkpGM6GnT9Czfad8drkiRy1tSj6J7sC0JlxYcZ+JFUgWvtksesHW\n6UzfSXqj1n32reoOdeOBueRDWIcqxgNyj3w/GR9o4S1BunrZzpT+/Nd8c2g+qAh0\nrz7ROEUq3iucseNQN6XZWZWvqPScGE+EYhni9wUqNMqfjvNSlzi7+K1yoQtyMm/Z\nNgSq3JNcdsAZQbiCRd1ko2BQsGm3ZBnbsAJ1Dxcn+i9nF5DT/ddWjUWin6LYWuUM\n/0Bqfv3etlrFuP6yxc8bPEMX0ucJg4yVxdkDrm1tYlJ+ANEQoOlZqhngvjz0f8uO\nOtEcDLmiG5VG6Yl72UtWIw+ALnKc5U7ib43Qve0bDAKR5zlHODcRetN9BCMvpekY\nOA4hohkllTP25xmMzLokBqY9n38zEt74kJOp67VKMvhoF7QkrLOfKWCRJjFL7/9I\nHDa6jb31INA9Wu+p/2LIa6I1SUYnMvCUqISgF2hBG9Q9S9TZvKnYUvfurhFS9jZv\n18sxW7IFYWmQyioo+gsAmfKLolJtLl9hCmTfYi7oqCh/EtZdIQKCAQEA0Umkp0Uu\nimVilLjgYGTWLcg8T3NWaELQzb2HYRXSzEq/M8GOtEr7TR7noJBm8fcgl55HEnPl\ni4cEJrr+VprzGbdMtXjHbCD+I945GA6vv3khg7mbqS9a1Uw6gjrQEZgZQU+/IVCu\n9Pbvx8Af32xaBWuN2cFzC7Z6iB815LPc2O5qyZ3+3nEUPah+Z+a9WEeTR6M0hy5c\nkkaRqhehugHDgqMRWGt8GfsFOmaR13kvfFfKadPRPkaGkftCSKBMWjrU4uX7aulm\nD7k4VDbnXIBMhI039+0znSkhZdcV1zk6qwBYn9TtZ11PTlspFPjtPxqS5M6IGflw\nsXkZGv4rZ5CkiQKCAQEAzLVdw2qw/8rWGsCV39EKp7hXLvp7+FuodPvX1L55lWB0\nvmSOldGcNvb2ZsK3RNvgteb8VfKRgaY6waeN5Qm1UXazsOX4F+GThPGHstdNuzkt\nJofRQQHQVR3npZbCngSkSZdahQ9SjiLIDKn8baPN8I8HfpJ4oHLUvkayavbch1kJ\nYWUfGtVKxHGX5m/nnxLdgbJEx9Q+3Qa7DDHuxTqsEqhkk0R0Ganred34HjpDNMs6\nV95HFNolW3yKfuHETKA1bLhej+XdMa11Ts5hBVGCMnnT07WcGhxtyK2dSa656SyT\ngT9+Hd1VWZ/KPpAkQmH9boOr2ihE+oAXiZ4D1t53HwKCAQAD0cA7fTu4Mtl1tVoC\n6FQwSbMwD/7HsFB3MLpDv041hDexDhs4lxW29pVrjLcUO1pQ6gaKA6twvGoK+uah\nVfqRwZKYzTd2dbOtm+SW183FRMSjzsNUdxTFR7rZnZEmgQwU8Quf5AUNW2RM1Oi/\n/w41gxz3mFwtHotl6IvnPJEPNGqme0enb5Da/zQvWTqjXcsGR6gxv1rZIIiP/hZp\nepbCz48FehCtuLMDudN3hzKipkd/Xuo2pLrX9ynigWpjSyePbHsGHHRMXSj2AHqA\naab71EftMlr6x0FgxmgToWu8qyjy4cPjWwSTfX5mb5SEzktX+ZzqPG8eDgOzRmgs\nX6thAoIBADL3kQG/hZQaL1Z3zpjsFggOKH7E1KrQP0/pCCKqzeC4JDjnFm0MxCUX\nNd/96N1XFUqU2QyZGUs7VPO0QOrekOtYb4LCrxNbEXyPGicX3f2YTbqDJEFYL0OR\n74PV1ly7cR/1dA8e8oH6/O3SQMwXdYXIRqhn1Wq1TGyXc4KYNe3o6CH8qFLo+fWR\nBq3T/MopS0coWGGcYY5sR5PQts8aPY9jp67W40UkfkFYV5dHEEaLttn7uJzjd1ug\n1Waj1VjypnqMKNcQ9xKQSl21mohVc+IXXPsgA16o51iIiVm4DAeXFp6ebUsIOWDY\nHOWYw75XYV7rn5TwY8Qusi2MTw5nUycCggEAB/45U0LW7ZGpks/aF/BeGaSWiLIG\nodBWUjRQ4w+Le/pTC8Ci9fiidxuCDH6TQbsUTGKOk7GsfncWHTQJogaMyO26IJ1N\nmYGgK2JJvs7PKyIkocPDVD/Yh0gIzQIE92ZdyXUT21pIYKDUB9e3p0fy/+E0pyeI\nsmsV8oaLr4tZRY1cMogI+pvtUUferbLQmZHhFd9X3m3RslR43Dl1qpYQyzE3x/a3\nWA2NJZbJhh+LiAKzqk7swXOqrTrmXuzLcjMG+T/3lizrbLLuKjQrf+eehlpw0db0\nHVVvkMLOP5ZH/ImkmvOZJY7xxup89VV7LD7TfMKwXafOrjMDdvTAYPtgxw==\n-----END RSA PRIVATE KEY-----\n" -} -``` - -[supermq]: https://github.com/absmach/supermq -[bootstrap]: https://github.com/absmach/supermq/tree/main/bootstrap -[export]: https://github.com/absmach/export -[agent]: https://github.com/absmach/agent -[mgxui]: https://github.com/absmach/supermq/ui diff --git a/provision/api/doc.go b/provision/api/doc.go deleted file mode 100644 index 2424852cc4..0000000000 --- a/provision/api/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package api contains API-related concerns: endpoint definitions, middlewares -// and all resource representations. -package api diff --git a/provision/api/endpoint.go b/provision/api/endpoint.go deleted file mode 100644 index c4e0fae0db..0000000000 --- a/provision/api/endpoint.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "context" - - apiutil "github.com/absmach/supermq/api/http/util" - "github.com/absmach/supermq/pkg/errors" - "github.com/absmach/supermq/provision" - "github.com/go-kit/kit/endpoint" -) - -func doProvision(svc provision.Service) endpoint.Endpoint { - return func(_ context.Context, request interface{}) (interface{}, error) { - req := request.(provisionReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - res, err := svc.Provision(req.domainID, req.token, req.Name, req.ExternalID, req.ExternalKey) - if err != nil { - return nil, err - } - - provisionResponse := provisionRes{ - Clients: res.Clients, - Channels: res.Channels, - ClientCert: res.ClientCert, - ClientKey: res.ClientKey, - CACert: res.CACert, - Whitelisted: res.Whitelisted, - } - - return provisionResponse, nil - } -} - -func getMapping(svc provision.Service) endpoint.Endpoint { - return func(_ context.Context, request interface{}) (interface{}, error) { - req := request.(mappingReq) - if err := req.validate(); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, err) - } - - res, err := svc.Mapping(req.token) - if err != nil { - return nil, err - } - - return mappingRes{Data: res}, nil - } -} diff --git a/provision/api/endpoint_test.go b/provision/api/endpoint_test.go deleted file mode 100644 index ea58c21137..0000000000 --- a/provision/api/endpoint_test.go +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api_test - -import ( - "fmt" - "io" - "net/http" - "net/http/httptest" - "strings" - "testing" - - apiutil "github.com/absmach/supermq/api/http/util" - "github.com/absmach/supermq/internal/testsutil" - smqlog "github.com/absmach/supermq/logger" - svcerr "github.com/absmach/supermq/pkg/errors/service" - "github.com/absmach/supermq/provision" - "github.com/absmach/supermq/provision/api" - "github.com/absmach/supermq/provision/mocks" - "github.com/stretchr/testify/assert" -) - -var ( - validToken = "valid" - validContenType = "application/json" - validID = testsutil.GenerateUUID(&testing.T{}) -) - -type testRequest struct { - client *http.Client - method string - url string - token string - contentType string - body io.Reader -} - -func (tr testRequest) make() (*http.Response, error) { - req, err := http.NewRequest(tr.method, tr.url, tr.body) - if err != nil { - return nil, err - } - - if tr.token != "" { - req.Header.Set("Authorization", apiutil.BearerPrefix+tr.token) - } - - if tr.contentType != "" { - req.Header.Set("Content-Type", tr.contentType) - } - - return tr.client.Do(req) -} - -func newProvisionServer() (*httptest.Server, *mocks.Service) { - svc := new(mocks.Service) - - logger := smqlog.NewMock() - mux := api.MakeHandler(svc, logger, "test") - return httptest.NewServer(mux), svc -} - -func TestProvision(t *testing.T) { - is, svc := newProvisionServer() - - cases := []struct { - desc string - token string - domainID string - data string - contentType string - status int - svcErr error - }{ - { - desc: "valid request", - token: validToken, - domainID: validID, - data: fmt.Sprintf(`{"name": "test", "external_id": "%s", "external_key": "%s"}`, validID, validID), - status: http.StatusCreated, - contentType: validContenType, - svcErr: nil, - }, - { - desc: "request with empty external id", - token: validToken, - domainID: validID, - data: fmt.Sprintf(`{"name": "test", "external_key": "%s"}`, validID), - status: http.StatusBadRequest, - contentType: validContenType, - svcErr: nil, - }, - { - desc: "request with empty external key", - token: validToken, - domainID: validID, - data: fmt.Sprintf(`{"name": "test", "external_id": "%s"}`, validID), - status: http.StatusBadRequest, - contentType: validContenType, - svcErr: nil, - }, - { - desc: "empty token", - token: "", - domainID: validID, - data: fmt.Sprintf(`{"name": "test", "external_id": "%s", "external_key": "%s"}`, validID, validID), - status: http.StatusCreated, - contentType: validContenType, - svcErr: nil, - }, - { - desc: "invalid content type", - token: validToken, - domainID: validID, - data: fmt.Sprintf(`{"name": "test", "external_id": "%s", "external_key": "%s"}`, validID, validID), - status: http.StatusUnsupportedMediaType, - contentType: "text/plain", - svcErr: nil, - }, - { - desc: "invalid request", - token: validToken, - domainID: validID, - data: `data`, - status: http.StatusBadRequest, - contentType: validContenType, - svcErr: nil, - }, - { - desc: "service error", - token: validToken, - domainID: validID, - data: fmt.Sprintf(`{"name": "test", "external_id": "%s", "external_key": "%s"}`, validID, validID), - status: http.StatusForbidden, - contentType: validContenType, - svcErr: svcerr.ErrAuthorization, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - repocall := svc.On("Provision", validID, tc.token, "test", validID, validID).Return(provision.Result{}, tc.svcErr) - req := testRequest{ - client: is.Client(), - method: http.MethodPost, - url: is.URL + fmt.Sprintf("/%s/mapping", tc.domainID), - token: tc.token, - contentType: tc.contentType, - body: strings.NewReader(tc.data), - } - - resp, err := req.make() - assert.Nil(t, err, tc.desc) - assert.Equal(t, tc.status, resp.StatusCode, tc.desc) - repocall.Unset() - }) - } -} - -func TestMapping(t *testing.T) { - is, svc := newProvisionServer() - - cases := []struct { - desc string - token string - domainID string - contentType string - status int - svcErr error - }{ - { - desc: "valid request", - token: validToken, - domainID: validID, - status: http.StatusOK, - contentType: validContenType, - svcErr: nil, - }, - { - desc: "empty token", - token: "", - domainID: validID, - status: http.StatusUnauthorized, - contentType: validContenType, - svcErr: nil, - }, - { - desc: "invalid content type", - token: validToken, - domainID: validID, - status: http.StatusUnsupportedMediaType, - contentType: "text/plain", - svcErr: nil, - }, - { - desc: "service error", - token: validToken, - domainID: validID, - status: http.StatusForbidden, - contentType: validContenType, - svcErr: svcerr.ErrAuthorization, - }, - } - - for _, tc := range cases { - t.Run(tc.desc, func(t *testing.T) { - repocall := svc.On("Mapping", tc.token).Return(map[string]interface{}{}, tc.svcErr) - req := testRequest{ - client: is.Client(), - method: http.MethodGet, - url: is.URL + fmt.Sprintf("/%s/mapping", tc.domainID), - token: tc.token, - contentType: tc.contentType, - } - - resp, err := req.make() - assert.Nil(t, err, tc.desc) - assert.Equal(t, tc.status, resp.StatusCode, tc.desc) - repocall.Unset() - }) - } -} diff --git a/provision/api/logging.go b/provision/api/logging.go deleted file mode 100644 index c3261d00b6..0000000000 --- a/provision/api/logging.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -//go:build !test - -package api - -import ( - "log/slog" - "time" - - "github.com/absmach/supermq/provision" -) - -var _ provision.Service = (*loggingMiddleware)(nil) - -type loggingMiddleware struct { - logger *slog.Logger - svc provision.Service -} - -// NewLoggingMiddleware adds logging facilities to the core service. -func NewLoggingMiddleware(svc provision.Service, logger *slog.Logger) provision.Service { - return &loggingMiddleware{logger, svc} -} - -func (lm *loggingMiddleware) Provision(domainID, token, name, externalID, externalKey string) (res provision.Result, err error) { - defer func(begin time.Time) { - args := []any{ - slog.String("duration", time.Since(begin).String()), - slog.String("name", name), - slog.String("external_id", externalID), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Provision failed", args...) - return - } - lm.logger.Info("Provision completed successfully", args...) - }(time.Now()) - - return lm.svc.Provision(domainID, token, name, externalID, externalKey) -} - -func (lm *loggingMiddleware) Cert(domainID, token, clientID, duration string) (cert, key string, err error) { - defer func(begin time.Time) { - args := []any{ - slog.String("duration", time.Since(begin).String()), - slog.String("client_id", clientID), - slog.String("ttl", duration), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Client certificate failed to create successfully", args...) - return - } - lm.logger.Info("Client certificate created successfully", args...) - }(time.Now()) - - return lm.svc.Cert(domainID, token, clientID, duration) -} - -func (lm *loggingMiddleware) Mapping(token string) (res map[string]interface{}, err error) { - defer func(begin time.Time) { - args := []any{ - slog.String("duration", time.Since(begin).String()), - } - if err != nil { - args = append(args, slog.Any("error", err)) - lm.logger.Warn("Mapping failed", args...) - return - } - lm.logger.Info("Mapping completed successfully", args...) - }(time.Now()) - - return lm.svc.Mapping(token) -} diff --git a/provision/api/requests.go b/provision/api/requests.go deleted file mode 100644 index 60f9106a99..0000000000 --- a/provision/api/requests.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import apiutil "github.com/absmach/supermq/api/http/util" - -type provisionReq struct { - token string - domainID string - Name string `json:"name"` - ExternalID string `json:"external_id"` - ExternalKey string `json:"external_key"` -} - -func (req provisionReq) validate() error { - if req.ExternalID == "" { - return apiutil.ErrMissingID - } - if req.domainID == "" { - return apiutil.ErrMissingDomainID - } - - if req.ExternalKey == "" { - return apiutil.ErrBearerKey - } - - if req.Name == "" { - return apiutil.ErrMissingName - } - - return nil -} - -type mappingReq struct { - token string - domainID string -} - -func (req mappingReq) validate() error { - if req.token == "" { - return apiutil.ErrBearerToken - } - if req.domainID == "" { - return apiutil.ErrMissingDomainID - } - return nil -} diff --git a/provision/api/requests_test.go b/provision/api/requests_test.go deleted file mode 100644 index 1fcc7626ff..0000000000 --- a/provision/api/requests_test.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "fmt" - "testing" - - apiutil "github.com/absmach/supermq/api/http/util" - "github.com/absmach/supermq/internal/testsutil" - "github.com/absmach/supermq/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestProvisioReq(t *testing.T) { - cases := []struct { - desc string - req provisionReq - err error - }{ - { - desc: "valid request", - req: provisionReq{ - token: "token", - domainID: testsutil.GenerateUUID(t), - Name: "name", - ExternalID: testsutil.GenerateUUID(t), - ExternalKey: testsutil.GenerateUUID(t), - }, - err: nil, - }, - { - desc: "empty external id", - req: provisionReq{ - token: "token", - domainID: testsutil.GenerateUUID(t), - Name: "name", - ExternalID: "", - ExternalKey: testsutil.GenerateUUID(t), - }, - err: apiutil.ErrMissingID, - }, - { - desc: "empty domain id", - req: provisionReq{ - token: "token", - domainID: "", - Name: "name", - ExternalID: testsutil.GenerateUUID(t), - ExternalKey: testsutil.GenerateUUID(t), - }, - err: apiutil.ErrMissingDomainID, - }, - { - desc: "empty external key", - req: provisionReq{ - token: "token", - domainID: testsutil.GenerateUUID(t), - Name: "name", - ExternalID: testsutil.GenerateUUID(t), - ExternalKey: "", - }, - err: apiutil.ErrBearerKey, - }, - } - - for _, tc := range cases { - err := tc.req.validate() - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected `%v` got `%v`", tc.desc, tc.err, err)) - } -} - -func TestMappingReq(t *testing.T) { - cases := []struct { - desc string - req mappingReq - err error - }{ - { - desc: "valid request", - req: mappingReq{ - token: "token", - domainID: testsutil.GenerateUUID(t), - }, - err: nil, - }, - { - desc: "empty token", - req: mappingReq{ - token: "", - domainID: testsutil.GenerateUUID(t), - }, - err: apiutil.ErrBearerToken, - }, - { - desc: "empty domain id", - req: mappingReq{ - token: "token", - domainID: "", - }, - err: apiutil.ErrMissingDomainID, - }, - } - - for _, tc := range cases { - err := tc.req.validate() - assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected `%v` got `%v`", tc.desc, tc.err, err)) - } -} diff --git a/provision/api/responses.go b/provision/api/responses.go deleted file mode 100644 index 8f85e8d079..0000000000 --- a/provision/api/responses.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "encoding/json" - "net/http" - - "github.com/absmach/supermq" - sdk "github.com/absmach/supermq/pkg/sdk" -) - -var _ supermq.Response = (*provisionRes)(nil) - -type provisionRes struct { - Clients []sdk.Client `json:"clients"` - Channels []sdk.Channel `json:"channels"` - ClientCert map[string]string `json:"client_cert,omitempty"` - ClientKey map[string]string `json:"client_key,omitempty"` - CACert string `json:"ca_cert,omitempty"` - Whitelisted map[string]bool `json:"whitelisted,omitempty"` -} - -func (res provisionRes) Code() int { - return http.StatusCreated -} - -func (res provisionRes) Headers() map[string]string { - return map[string]string{} -} - -func (res provisionRes) Empty() bool { - return false -} - -type mappingRes struct { - Data interface{} -} - -func (res mappingRes) Code() int { - return http.StatusOK -} - -func (res mappingRes) Headers() map[string]string { - return map[string]string{} -} - -func (res mappingRes) Empty() bool { - return false -} - -func (res mappingRes) MarshalJSON() ([]byte, error) { - return json.Marshal(res.Data) -} diff --git a/provision/api/transport.go b/provision/api/transport.go deleted file mode 100644 index 911cf68e9a..0000000000 --- a/provision/api/transport.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package api - -import ( - "context" - "encoding/json" - "log/slog" - "net/http" - - "github.com/absmach/supermq" - api "github.com/absmach/supermq/api/http" - apiutil "github.com/absmach/supermq/api/http/util" - "github.com/absmach/supermq/pkg/errors" - "github.com/absmach/supermq/provision" - "github.com/go-chi/chi/v5" - kithttp "github.com/go-kit/kit/transport/http" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -const ( - contentType = "application/json" -) - -// MakeHandler returns a HTTP handler for API endpoints. -func MakeHandler(svc provision.Service, logger *slog.Logger, instanceID string) http.Handler { - opts := []kithttp.ServerOption{ - kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)), - } - - r := chi.NewRouter() - - r.Route("/{domainID}", func(r chi.Router) { - r.Route("/mapping", func(r chi.Router) { - r.Post("/", kithttp.NewServer( - doProvision(svc), - decodeProvisionRequest, - api.EncodeResponse, - opts..., - ).ServeHTTP) - r.Get("/", kithttp.NewServer( - getMapping(svc), - decodeMappingRequest, - api.EncodeResponse, - opts..., - ).ServeHTTP) - }) - }) - r.Handle("/metrics", promhttp.Handler()) - r.Get("/health", supermq.Health("provision", instanceID)) - - return r -} - -func decodeProvisionRequest(_ context.Context, r *http.Request) (interface{}, error) { - if r.Header.Get("Content-Type") != contentType { - return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) - } - - req := provisionReq{ - token: apiutil.ExtractBearerToken(r), - domainID: chi.URLParam(r, "domainID"), - } - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity)) - } - - return req, nil -} - -func decodeMappingRequest(_ context.Context, r *http.Request) (interface{}, error) { - if r.Header.Get("Content-Type") != contentType { - return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType) - } - - req := mappingReq{ - token: apiutil.ExtractBearerToken(r), - domainID: chi.URLParam(r, "domainID"), - } - - return req, nil -} diff --git a/provision/config.go b/provision/config.go deleted file mode 100644 index 41e6ccae94..0000000000 --- a/provision/config.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package provision - -import ( - "fmt" - "os" - - "github.com/absmach/supermq/channels" - "github.com/absmach/supermq/clients" - "github.com/absmach/supermq/pkg/errors" - "github.com/pelletier/go-toml" -) - -var errFailedToReadConfig = errors.New("failed to read config file") - -// ServiceConf represents service config. -type ServiceConf struct { - Port string `toml:"port" env:"SMQ_PROVISION_HTTP_PORT" envDefault:"9016"` - LogLevel string `toml:"log_level" env:"SMQ_PROVISION_LOG_LEVEL" envDefault:"info"` - TLS bool `toml:"tls" env:"SMQ_PROVISION_ENV_CLIENTS_TLS" envDefault:"false"` - ServerCert string `toml:"server_cert" env:"SMQ_PROVISION_SERVER_CERT" envDefault:""` - ServerKey string `toml:"server_key" env:"SMQ_PROVISION_SERVER_KEY" envDefault:""` - ClientsURL string `toml:"clients_url" env:"SMQ_PROVISION_CLIENTS_LOCATION" envDefault:"http://localhost"` - UsersURL string `toml:"users_url" env:"SMQ_PROVISION_USERS_LOCATION" envDefault:"http://localhost"` - HTTPPort string `toml:"http_port" env:"SMQ_PROVISION_HTTP_PORT" envDefault:"9016"` - MgEmail string `toml:"smq_email" env:"SMQ_PROVISION_EMAIL" envDefault:"test@example.com"` - MgUsername string `toml:"smq_username" env:"SMQ_PROVISION_USERNAME" envDefault:"user"` - MgPass string `toml:"smq_pass" env:"SMQ_PROVISION_PASS" envDefault:"test"` - MgDomainID string `toml:"smq_domain_id" env:"SMQ_PROVISION_DOMAIN_ID" envDefault:""` - MgAPIKey string `toml:"smq_api_key" env:"SMQ_PROVISION_API_KEY" envDefault:""` - MgBSURL string `toml:"smq_bs_url" env:"SMQ_PROVISION_BS_SVC_URL" envDefault:"http://localhost:9000"` - MgCertsURL string `toml:"smq_certs_url" env:"SMQ_PROVISION_CERTS_SVC_URL" envDefault:"http://localhost:9019"` -} - -// Bootstrap represetns the Bootstrap config. -type Bootstrap struct { - X509Provision bool `toml:"x509_provision" env:"SMQ_PROVISION_X509_PROVISIONING" envDefault:"false"` - Provision bool `toml:"provision" env:"SMQ_PROVISION_BS_CONFIG_PROVISIONING" envDefault:"true"` - AutoWhiteList bool `toml:"autowhite_list" env:"SMQ_PROVISION_BS_AUTO_WHITELIST" envDefault:"true"` - Content map[string]interface{} `toml:"content"` -} - -// Gateway represetns the Gateway config. -type Gateway struct { - Type string `toml:"type" json:"type"` - ExternalID string `toml:"external_id" json:"external_id"` - ExternalKey string `toml:"external_key" json:"external_key"` - CtrlChannelID string `toml:"ctrl_channel_id" json:"ctrl_channel_id"` - DataChannelID string `toml:"data_channel_id" json:"data_channel_id"` - ExportChannelID string `toml:"export_channel_id" json:"export_channel_id"` - CfgID string `toml:"cfg_id" json:"cfg_id"` -} - -// Cert represetns the certificate config. -type Cert struct { - TTL string `json:"ttl" toml:"ttl" env:"SMQ_PROVISION_CERTS_HOURS_VALID" envDefault:"2400h"` -} - -// Config struct of Provision. -type Config struct { - File string `toml:"file" env:"SMQ_PROVISION_CONFIG_FILE" envDefault:"config.toml"` - Server ServiceConf `toml:"server" mapstructure:"server"` - Bootstrap Bootstrap `toml:"bootstrap" mapstructure:"bootstrap"` - Clients []clients.Client `toml:"clients" mapstructure:"clients"` - Channels []channels.Channel `toml:"channels" mapstructure:"channels"` - Cert Cert `toml:"cert" mapstructure:"cert"` - BSContent string `env:"SMQ_PROVISION_BS_CONTENT" envDefault:""` - SendTelemetry bool `env:"SMQ_SEND_TELEMETRY" envDefault:"true"` - InstanceID string `env:"SMQ_MQTT_ADAPTER_INSTANCE_ID" envDefault:""` -} - -// Save - store config in a file. -func Save(c Config, file string) error { - if file == "" { - return errors.ErrEmptyPath - } - - b, err := toml.Marshal(c) - if err != nil { - return errors.Wrap(errFailedToReadConfig, err) - } - if err := os.WriteFile(file, b, 0o644); err != nil { - return fmt.Errorf("Error writing toml: %w", err) - } - - return nil -} - -// Read - retrieve config from a file. -func Read(file string) (Config, error) { - data, err := os.ReadFile(file) - if err != nil { - return Config{}, errors.Wrap(errFailedToReadConfig, err) - } - - var c Config - if err := toml.Unmarshal(data, &c); err != nil { - return Config{}, fmt.Errorf("Error unmarshaling toml: %w", err) - } - - return c, nil -} diff --git a/provision/config_test.go b/provision/config_test.go deleted file mode 100644 index 2140f71acc..0000000000 --- a/provision/config_test.go +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package provision_test - -import ( - "fmt" - "os" - "testing" - - "github.com/absmach/supermq/channels" - "github.com/absmach/supermq/clients" - "github.com/absmach/supermq/pkg/errors" - "github.com/absmach/supermq/provision" - "github.com/pelletier/go-toml" - "github.com/stretchr/testify/assert" -) - -var ( - validConfig = provision.Config{ - Server: provision.ServiceConf{ - Port: "9016", - LogLevel: "info", - TLS: false, - }, - Bootstrap: provision.Bootstrap{ - X509Provision: true, - Provision: true, - AutoWhiteList: true, - Content: map[string]interface{}{ - "test": "test", - }, - }, - Clients: []clients.Client{ - { - ID: "1234567890", - Name: "test", - Tags: []string{"test"}, - Metadata: map[string]interface{}{ - "test": "test", - }, - Permissions: []string{"test"}, - }, - }, - Channels: []channels.Channel{ - { - ID: "1234567890", - Name: "test", - Tags: []string{"test"}, - Metadata: map[string]interface{}{ - "test": "test", - }, - Permissions: []string{"test"}, - }, - }, - Cert: provision.Cert{}, - SendTelemetry: true, - InstanceID: "1234567890", - } - validConfigFile = "./config.toml" - invalidConfig = provision.Config{ - Bootstrap: provision.Bootstrap{ - Content: map[string]interface{}{ - "invalid": make(chan int), - }, - }, - } - invalidConfigFile = "./invalid.toml" -) - -func createInvalidConfigFile() error { - config := map[string]interface{}{ - "invalid": "invalid", - } - b, err := toml.Marshal(config) - if err != nil { - return err - } - - f, err := os.Create(invalidConfigFile) - if err != nil { - return err - } - - if _, err = f.Write(b); err != nil { - return err - } - - return nil -} - -func createValidConfigFile() error { - b, err := toml.Marshal(validConfig) - if err != nil { - return err - } - - f, err := os.Create(validConfigFile) - if err != nil { - return err - } - - if _, err = f.Write(b); err != nil { - return err - } - - return nil -} - -func TestSave(t *testing.T) { - cases := []struct { - desc string - cfg provision.Config - file string - err error - }{ - { - desc: "save valid config", - cfg: validConfig, - file: validConfigFile, - err: nil, - }, - { - desc: "save valid config with empty file name", - cfg: validConfig, - file: "", - err: errors.ErrEmptyPath, - }, - { - desc: "save empty config with valid config file", - cfg: provision.Config{}, - file: validConfigFile, - err: nil, - }, - { - desc: "save empty config with empty file name", - cfg: provision.Config{}, - file: "", - err: errors.ErrEmptyPath, - }, - { - desc: "save invalid config", - cfg: invalidConfig, - file: invalidConfigFile, - err: errors.New("failed to read config file"), - }, - } - - for _, c := range cases { - t.Run(c.desc, func(t *testing.T) { - err := provision.Save(c.cfg, c.file) - assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected: %v, got: %v", c.err, err)) - - if err == nil { - defer func() { - if c.file != "" { - err := os.Remove(c.file) - assert.NoError(t, err) - } - }() - - cfg, err := provision.Read(c.file) - if c.cfg.Bootstrap.Content == nil { - c.cfg.Bootstrap.Content = map[string]interface{}{} - } - assert.Equal(t, c.err, err) - assert.Equal(t, c.cfg, cfg) - } - }) - } -} - -func TestRead(t *testing.T) { - err := createInvalidConfigFile() - assert.NoError(t, err) - - err = createValidConfigFile() - assert.NoError(t, err) - - t.Cleanup(func() { - err := os.Remove(invalidConfigFile) - assert.NoError(t, err) - err = os.Remove(validConfigFile) - assert.NoError(t, err) - }) - - cases := []struct { - desc string - file string - cfg provision.Config - err error - }{ - { - desc: "read valid config", - file: validConfigFile, - cfg: validConfig, - err: nil, - }, - { - desc: "read invalid config", - file: invalidConfigFile, - cfg: invalidConfig, - err: nil, - }, - { - desc: "read empty config", - file: "", - cfg: provision.Config{}, - err: errors.New("failed to read config file"), - }, - } - - for _, c := range cases { - t.Run(c.desc, func(t *testing.T) { - cfg, err := provision.Read(c.file) - if c.desc == "read invalid config" { - c.cfg.Bootstrap.Content = nil - } - assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected: %v, got: %v", c.err, err)) - assert.Equal(t, c.cfg, cfg) - }) - } -} diff --git a/provision/configs/config.toml b/provision/configs/config.toml deleted file mode 100644 index 650ed35186..0000000000 --- a/provision/configs/config.toml +++ /dev/null @@ -1,47 +0,0 @@ -# Copyright (c) Abstract Machines -# SPDX-License-Identifier: Apache-2.0 - -file = "config.toml" - -[bootstrap] - autowhite_list = true - content = "" - provision = true - x509_provision = false - - -[server] - LogLevel = "info" - ca_certs = "" - http_port = "8190" - mg_api_key = "" - mg_bs_url = "http://localhost:9013" - mg_certs_url = "http://localhost:9019" - mg_pass = "" - mg_user = "" - mqtt_url = "" - port = "" - server_cert = "" - server_key = "" - clients_location = "http://localhost:9006" - tls = true - users_location = "" - -[[clients]] - name = "client" - - [client.metadata] - external_id = "xxxxxx" - - -[[channels]] - name = "control-channel" - - [channels.metadata] - type = "control" - -[[channels]] - name = "data-channel" - - [channels.metadata] - type = "data" diff --git a/provision/doc.go b/provision/doc.go deleted file mode 100644 index e9b855294d..0000000000 --- a/provision/doc.go +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -// Package provision contains domain concept definitions needed to support -// Provision service feature, i.e. automate provision process. -package provision diff --git a/provision/mocks/service.go b/provision/mocks/service.go deleted file mode 100644 index 2a8cda9b03..0000000000 --- a/provision/mocks/service.go +++ /dev/null @@ -1,122 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -// Copyright (c) Abstract Machines - -package mocks - -import ( - provision "github.com/absmach/supermq/provision" - mock "github.com/stretchr/testify/mock" -) - -// Service is an autogenerated mock type for the Service type -type Service struct { - mock.Mock -} - -// Cert provides a mock function with given fields: domainID, token, clientID, duration -func (_m *Service) Cert(domainID string, token string, clientID string, duration string) (string, string, error) { - ret := _m.Called(domainID, token, clientID, duration) - - if len(ret) == 0 { - panic("no return value specified for Cert") - } - - var r0 string - var r1 string - var r2 error - if rf, ok := ret.Get(0).(func(string, string, string, string) (string, string, error)); ok { - return rf(domainID, token, clientID, duration) - } - if rf, ok := ret.Get(0).(func(string, string, string, string) string); ok { - r0 = rf(domainID, token, clientID, duration) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(string, string, string, string) string); ok { - r1 = rf(domainID, token, clientID, duration) - } else { - r1 = ret.Get(1).(string) - } - - if rf, ok := ret.Get(2).(func(string, string, string, string) error); ok { - r2 = rf(domainID, token, clientID, duration) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// Mapping provides a mock function with given fields: token -func (_m *Service) Mapping(token string) (map[string]interface{}, error) { - ret := _m.Called(token) - - if len(ret) == 0 { - panic("no return value specified for Mapping") - } - - var r0 map[string]interface{} - var r1 error - if rf, ok := ret.Get(0).(func(string) (map[string]interface{}, error)); ok { - return rf(token) - } - if rf, ok := ret.Get(0).(func(string) map[string]interface{}); ok { - r0 = rf(token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]interface{}) - } - } - - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// Provision provides a mock function with given fields: domainID, token, name, externalID, externalKey -func (_m *Service) Provision(domainID string, token string, name string, externalID string, externalKey string) (provision.Result, error) { - ret := _m.Called(domainID, token, name, externalID, externalKey) - - if len(ret) == 0 { - panic("no return value specified for Provision") - } - - var r0 provision.Result - var r1 error - if rf, ok := ret.Get(0).(func(string, string, string, string, string) (provision.Result, error)); ok { - return rf(domainID, token, name, externalID, externalKey) - } - if rf, ok := ret.Get(0).(func(string, string, string, string, string) provision.Result); ok { - r0 = rf(domainID, token, name, externalID, externalKey) - } else { - r0 = ret.Get(0).(provision.Result) - } - - if rf, ok := ret.Get(1).(func(string, string, string, string, string) error); ok { - r1 = rf(domainID, token, name, externalID, externalKey) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewService creates a new instance of Service. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewService(t interface { - mock.TestingT - Cleanup(func()) -}) *Service { - mock := &Service{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/provision/service.go b/provision/service.go deleted file mode 100644 index b5000dd181..0000000000 --- a/provision/service.go +++ /dev/null @@ -1,425 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package provision - -import ( - "encoding/json" - "fmt" - "log/slog" - - "github.com/absmach/supermq/pkg/errors" - sdk "github.com/absmach/supermq/pkg/sdk" -) - -const ( - externalIDKey = "external_id" - gateway = "gateway" - Active = 1 - - control = "control" - data = "data" - export = "export" -) - -var ( - ErrUnauthorized = errors.New("unauthorized access") - ErrFailedToCreateToken = errors.New("failed to create access token") - ErrEmptyClientsList = errors.New("clients list in configuration empty") - ErrClientUpdate = errors.New("failed to update client") - ErrEmptyChannelsList = errors.New("channels list in configuration is empty") - ErrFailedChannelCreation = errors.New("failed to create channel") - ErrFailedChannelRetrieval = errors.New("failed to retrieve channel") - ErrFailedClientCreation = errors.New("failed to create client") - ErrFailedClientRetrieval = errors.New("failed to retrieve client") - ErrMissingCredentials = errors.New("missing credentials") - ErrFailedBootstrapRetrieval = errors.New("failed to retrieve bootstrap") - ErrFailedCertCreation = errors.New("failed to create certificates") - ErrFailedCertView = errors.New("failed to view certificate") - ErrFailedBootstrap = errors.New("failed to create bootstrap config") - ErrFailedBootstrapValidate = errors.New("failed to validate bootstrap config creation") - ErrGatewayUpdate = errors.New("failed to updated gateway metadata") - - limit uint = 10 - offset uint = 0 -) - -var _ Service = (*provisionService)(nil) - -// Service specifies Provision service API. -// -//go:generate mockery --name Service --output=./mocks --filename service.go --quiet --note "Copyright (c) Abstract Machines" -type Service interface { - // Provision is the only method this API specifies. Depending on the configuration, - // the following actions will can be executed: - // - create a Client based on external_id (eg. MAC address) - // - create multiple Channels - // - create Bootstrap configuration - // - whitelist Client in Bootstrap configuration == connect Client to Channels - Provision(domainID, token, name, externalID, externalKey string) (Result, error) - - // Mapping returns current configuration used for provision - // useful for using in ui to create configuration that matches - // one created with Provision method. - Mapping(token string) (map[string]interface{}, error) - - // Certs creates certificate for clients that communicate over mTLS - // A duration string is a possibly signed sequence of decimal numbers, - // each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". - // Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". - Cert(domainID, token, clientID, duration string) (string, string, error) -} - -type provisionService struct { - logger *slog.Logger - sdk sdk.SDK - conf Config -} - -// Result represent what is created with additional info. -type Result struct { - Clients []sdk.Client `json:"clients,omitempty"` - Channels []sdk.Channel `json:"channels,omitempty"` - ClientCert map[string]string `json:"client_cert,omitempty"` - ClientKey map[string]string `json:"client_key,omitempty"` - CACert string `json:"ca_cert,omitempty"` - Whitelisted map[string]bool `json:"whitelisted,omitempty"` - Error string `json:"error,omitempty"` -} - -// New returns new provision service. -func New(cfg Config, mgsdk sdk.SDK, logger *slog.Logger) Service { - return &provisionService{ - logger: logger, - conf: cfg, - sdk: mgsdk, - } -} - -// Mapping retrieves current configuration. -func (ps *provisionService) Mapping(token string) (map[string]interface{}, error) { - pm := sdk.PageMetadata{ - Offset: uint64(offset), - Limit: uint64(limit), - } - - if _, err := ps.sdk.Users(pm, token); err != nil { - return map[string]interface{}{}, errors.Wrap(ErrUnauthorized, err) - } - - return ps.conf.Bootstrap.Content, nil -} - -// Provision is provision method for creating setup according to -// provision layout specified in config.toml. -func (ps *provisionService) Provision(domainID, token, name, externalID, externalKey string) (res Result, err error) { - var channels []sdk.Channel - var clients []sdk.Client - defer ps.recover(&err, &clients, &channels, &domainID, &token) - - token, err = ps.createTokenIfEmpty(token) - if err != nil { - return res, errors.Wrap(ErrFailedToCreateToken, err) - } - - if len(ps.conf.Clients) == 0 { - return res, ErrEmptyClientsList - } - if len(ps.conf.Channels) == 0 { - return res, ErrEmptyChannelsList - } - for _, c := range ps.conf.Clients { - // If client in configs contains metadata with external_id - // set value for it from the provision request - if _, ok := c.Metadata[externalIDKey]; ok { - c.Metadata[externalIDKey] = externalID - } - - cli := sdk.Client{ - Metadata: c.Metadata, - } - if name == "" { - name = c.Name - } - cli.Name = name - cli, err := ps.sdk.CreateClient(cli, domainID, token) - if err != nil { - res.Error = err.Error() - return res, errors.Wrap(ErrFailedClientCreation, err) - } - - // Get newly created client (in order to get the key). - cli, err = ps.sdk.Client(cli.ID, domainID, token) - if err != nil { - e := errors.Wrap(err, fmt.Errorf("client id: %s", cli.ID)) - return res, errors.Wrap(ErrFailedClientRetrieval, e) - } - clients = append(clients, cli) - } - - for _, channel := range ps.conf.Channels { - ch := sdk.Channel{ - Name: name + "_" + channel.Name, - Metadata: sdk.Metadata(channel.Metadata), - } - ch, err := ps.sdk.CreateChannel(ch, domainID, token) - if err != nil { - return res, errors.Wrap(ErrFailedChannelCreation, err) - } - ch, err = ps.sdk.Channel(ch.ID, domainID, token) - if err != nil { - e := errors.Wrap(err, fmt.Errorf("channel id: %s", ch.ID)) - return res, errors.Wrap(ErrFailedChannelRetrieval, e) - } - channels = append(channels, ch) - } - - res = Result{ - Clients: clients, - Channels: channels, - Whitelisted: map[string]bool{}, - ClientCert: map[string]string{}, - ClientKey: map[string]string{}, - } - - var cert sdk.Cert - var bsConfig sdk.BootstrapConfig - for _, c := range clients { - var chanIDs []string - - for _, ch := range channels { - chanIDs = append(chanIDs, ch.ID) - } - content, err := json.Marshal(ps.conf.Bootstrap.Content) - if err != nil { - return Result{}, errors.Wrap(ErrFailedBootstrap, err) - } - - if ps.conf.Bootstrap.Provision && needsBootstrap(c) { - bsReq := sdk.BootstrapConfig{ - ClientID: c.ID, - ExternalID: externalID, - ExternalKey: externalKey, - Channels: chanIDs, - CACert: res.CACert, - ClientCert: cert.Certificate, - ClientKey: cert.Key, - Content: string(content), - } - bsid, err := ps.sdk.AddBootstrap(bsReq, domainID, token) - if err != nil { - return Result{}, errors.Wrap(ErrFailedBootstrap, err) - } - - bsConfig, err = ps.sdk.ViewBootstrap(bsid, domainID, token) - if err != nil { - return Result{}, errors.Wrap(ErrFailedBootstrapValidate, err) - } - } - - if ps.conf.Bootstrap.X509Provision { - var cert sdk.Cert - - cert, err = ps.sdk.IssueCert(c.ID, ps.conf.Cert.TTL, domainID, token) - if err != nil { - e := errors.Wrap(err, fmt.Errorf("client id: %s", c.ID)) - return res, errors.Wrap(ErrFailedCertCreation, e) - } - cert, err := ps.sdk.ViewCert(cert.SerialNumber, domainID, token) - if err != nil { - return res, errors.Wrap(ErrFailedCertView, err) - } - - res.ClientCert[c.ID] = cert.Certificate - res.ClientKey[c.ID] = cert.Key - res.CACert = "" - - if needsBootstrap(c) { - if _, err = ps.sdk.UpdateBootstrapCerts(bsConfig.ClientID, cert.Certificate, cert.Key, "", domainID, token); err != nil { - return Result{}, errors.Wrap(ErrFailedCertCreation, err) - } - } - } - - if ps.conf.Bootstrap.AutoWhiteList { - if err := ps.sdk.Whitelist(c.ID, Active, domainID, token); err != nil { - res.Error = err.Error() - return res, ErrClientUpdate - } - res.Whitelisted[c.ID] = true - } - } - - if err = ps.updateGateway(domainID, token, bsConfig, channels); err != nil { - return res, err - } - return res, nil -} - -func (ps *provisionService) Cert(domainID, token, clientID, ttl string) (string, string, error) { - token, err := ps.createTokenIfEmpty(token) - if err != nil { - return "", "", errors.Wrap(ErrFailedToCreateToken, err) - } - - th, err := ps.sdk.Client(clientID, domainID, token) - if err != nil { - return "", "", errors.Wrap(ErrUnauthorized, err) - } - cert, err := ps.sdk.IssueCert(th.ID, ps.conf.Cert.TTL, domainID, token) - if err != nil { - return "", "", errors.Wrap(ErrFailedCertCreation, err) - } - cert, err = ps.sdk.ViewCert(cert.SerialNumber, domainID, token) - if err != nil { - return "", "", errors.Wrap(ErrFailedCertView, err) - } - return cert.Certificate, cert.Key, err -} - -func (ps *provisionService) createTokenIfEmpty(token string) (string, error) { - if token != "" { - return token, nil - } - - // If no token in request is provided - // use API key provided in config file or env - if ps.conf.Server.MgAPIKey != "" { - return ps.conf.Server.MgAPIKey, nil - } - - // If no API key use username and password provided to create access token. - if ps.conf.Server.MgUsername == "" || ps.conf.Server.MgPass == "" { - return token, ErrMissingCredentials - } - - u := sdk.Login{ - Username: ps.conf.Server.MgUsername, - Password: ps.conf.Server.MgPass, - } - tkn, err := ps.sdk.CreateToken(u) - if err != nil { - return token, errors.Wrap(ErrFailedToCreateToken, err) - } - - return tkn.AccessToken, nil -} - -func (ps *provisionService) updateGateway(domainID, token string, bs sdk.BootstrapConfig, channels []sdk.Channel) error { - var gw Gateway - for _, ch := range channels { - switch ch.Metadata["type"] { - case control: - gw.CtrlChannelID = ch.ID - case data: - gw.DataChannelID = ch.ID - case export: - gw.ExportChannelID = ch.ID - } - } - gw.ExternalID = bs.ExternalID - gw.ExternalKey = bs.ExternalKey - gw.CfgID = bs.ClientID - gw.Type = gateway - - c, sdkerr := ps.sdk.Client(bs.ClientID, domainID, token) - if sdkerr != nil { - return errors.Wrap(ErrGatewayUpdate, sdkerr) - } - b, err := json.Marshal(gw) - if err != nil { - return errors.Wrap(ErrGatewayUpdate, err) - } - if err := json.Unmarshal(b, &c.Metadata); err != nil { - return errors.Wrap(ErrGatewayUpdate, err) - } - if _, err := ps.sdk.UpdateClient(c, domainID, token); err != nil { - return errors.Wrap(ErrGatewayUpdate, err) - } - return nil -} - -func (ps *provisionService) errLog(err error) { - if err != nil { - ps.logger.Error(fmt.Sprintf("Error recovering: %s", err)) - } -} - -func clean(ps *provisionService, clients []sdk.Client, channels []sdk.Channel, domainID, token string) { - for _, t := range clients { - err := ps.sdk.DeleteClient(t.ID, domainID, token) - ps.errLog(err) - } - for _, c := range channels { - err := ps.sdk.DeleteChannel(c.ID, domainID, token) - ps.errLog(err) - } -} - -func (ps *provisionService) recover(e *error, ths *[]sdk.Client, chs *[]sdk.Channel, dm, tkn *string) { - if e == nil { - return - } - clients, channels, domainID, token, err := *ths, *chs, *dm, *tkn, *e - - if errors.Contains(err, ErrFailedClientRetrieval) || errors.Contains(err, ErrFailedChannelCreation) { - for _, c := range clients { - err := ps.sdk.DeleteClient(c.ID, domainID, token) - ps.errLog(err) - } - return - } - - if errors.Contains(err, ErrFailedBootstrap) || errors.Contains(err, ErrFailedChannelRetrieval) { - clean(ps, clients, channels, domainID, token) - return - } - - if errors.Contains(err, ErrFailedBootstrapValidate) || errors.Contains(err, ErrFailedCertCreation) { - clean(ps, clients, channels, domainID, token) - for _, th := range clients { - if needsBootstrap(th) { - ps.errLog(ps.sdk.RemoveBootstrap(th.ID, domainID, token)) - } - } - return - } - - if errors.Contains(err, ErrFailedBootstrapValidate) || errors.Contains(err, ErrFailedCertCreation) { - clean(ps, clients, channels, domainID, token) - for _, th := range clients { - if needsBootstrap(th) { - bs, err := ps.sdk.ViewBootstrap(th.ID, domainID, token) - ps.errLog(errors.Wrap(ErrFailedBootstrapRetrieval, err)) - ps.errLog(ps.sdk.RemoveBootstrap(bs.ClientID, domainID, token)) - } - } - } - - if errors.Contains(err, ErrClientUpdate) || errors.Contains(err, ErrGatewayUpdate) { - clean(ps, clients, channels, domainID, token) - for _, th := range clients { - if ps.conf.Bootstrap.X509Provision && needsBootstrap(th) { - _, err := ps.sdk.RevokeCert(th.ID, domainID, token) - ps.errLog(err) - } - if needsBootstrap(th) { - bs, err := ps.sdk.ViewBootstrap(th.ID, domainID, token) - ps.errLog(errors.Wrap(ErrFailedBootstrapRetrieval, err)) - ps.errLog(ps.sdk.RemoveBootstrap(bs.ClientID, domainID, token)) - } - } - return - } -} - -func needsBootstrap(th sdk.Client) bool { - if th.Metadata == nil { - return false - } - - if _, ok := th.Metadata[externalIDKey]; ok { - return true - } - return false -} diff --git a/provision/service_test.go b/provision/service_test.go deleted file mode 100644 index 732c9fd90b..0000000000 --- a/provision/service_test.go +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) Abstract Machines -// SPDX-License-Identifier: Apache-2.0 - -package provision_test - -import ( - "fmt" - "testing" - - "github.com/absmach/supermq/internal/testsutil" - smqlog "github.com/absmach/supermq/logger" - "github.com/absmach/supermq/pkg/errors" - repoerr "github.com/absmach/supermq/pkg/errors/repository" - svcerr "github.com/absmach/supermq/pkg/errors/service" - sdk "github.com/absmach/supermq/pkg/sdk" - sdkmocks "github.com/absmach/supermq/pkg/sdk/mocks" - "github.com/absmach/supermq/provision" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" -) - -var validToken = "valid" - -func TestMapping(t *testing.T) { - mgsdk := new(sdkmocks.SDK) - svc := provision.New(validConfig, mgsdk, smqlog.NewMock()) - - cases := []struct { - desc string - token string - content map[string]interface{} - sdkerr error - err error - }{ - { - desc: "valid token", - token: validToken, - content: validConfig.Bootstrap.Content, - sdkerr: nil, - err: nil, - }, - { - desc: "invalid token", - token: "invalid", - content: map[string]interface{}{}, - sdkerr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, 401), - err: provision.ErrUnauthorized, - }, - } - - for _, c := range cases { - t.Run(c.desc, func(t *testing.T) { - pm := sdk.PageMetadata{Offset: uint64(0), Limit: uint64(10)} - repocall := mgsdk.On("Users", pm, c.token).Return(sdk.UsersPage{}, c.sdkerr) - content, err := svc.Mapping(c.token) - assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected error %v, got %v", c.err, err)) - assert.Equal(t, c.content, content) - repocall.Unset() - }) - } -} - -func TestCert(t *testing.T) { - cases := []struct { - desc string - config provision.Config - domainID string - token string - clientID string - ttl string - serial string - cert string - key string - sdkClientErr error - sdkCertErr error - sdkTokenErr error - err error - }{ - { - desc: "valid", - config: validConfig, - domainID: testsutil.GenerateUUID(t), - token: validToken, - clientID: testsutil.GenerateUUID(t), - ttl: "1h", - cert: "cert", - key: "key", - sdkClientErr: nil, - sdkCertErr: nil, - sdkTokenErr: nil, - err: nil, - }, - { - desc: "empty token with config API key", - config: provision.Config{ - Server: provision.ServiceConf{MgAPIKey: "key"}, - Cert: provision.Cert{TTL: "1h"}, - }, - domainID: testsutil.GenerateUUID(t), - token: "", - clientID: testsutil.GenerateUUID(t), - ttl: "1h", - cert: "cert", - key: "key", - sdkClientErr: nil, - sdkCertErr: nil, - sdkTokenErr: nil, - err: nil, - }, - { - desc: "empty token with username and password", - config: provision.Config{ - Server: provision.ServiceConf{ - MgUsername: "testUsername", - MgPass: "12345678", - MgDomainID: testsutil.GenerateUUID(t), - }, - Cert: provision.Cert{TTL: "1h"}, - }, - domainID: testsutil.GenerateUUID(t), - token: "", - clientID: testsutil.GenerateUUID(t), - ttl: "1h", - cert: "cert", - key: "key", - sdkClientErr: nil, - sdkCertErr: nil, - sdkTokenErr: nil, - err: nil, - }, - { - desc: "empty token with username and invalid password", - config: provision.Config{ - Server: provision.ServiceConf{ - MgUsername: "testUsername", - MgPass: "12345678", - MgDomainID: testsutil.GenerateUUID(t), - }, - Cert: provision.Cert{TTL: "1h"}, - }, - domainID: testsutil.GenerateUUID(t), - token: "", - clientID: testsutil.GenerateUUID(t), - ttl: "1h", - cert: "", - key: "", - sdkClientErr: nil, - sdkCertErr: nil, - sdkTokenErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, 401), - err: provision.ErrFailedToCreateToken, - }, - { - desc: "empty token with empty username and password", - config: provision.Config{ - Server: provision.ServiceConf{}, - Cert: provision.Cert{TTL: "1h"}, - }, - domainID: testsutil.GenerateUUID(t), - token: "", - clientID: testsutil.GenerateUUID(t), - ttl: "1h", - cert: "", - key: "", - sdkClientErr: nil, - sdkCertErr: nil, - sdkTokenErr: nil, - err: provision.ErrMissingCredentials, - }, - { - desc: "invalid clientID", - config: validConfig, - domainID: testsutil.GenerateUUID(t), - token: "invalid", - clientID: testsutil.GenerateUUID(t), - ttl: "1h", - cert: "", - key: "", - sdkClientErr: errors.NewSDKErrorWithStatus(svcerr.ErrAuthentication, 401), - sdkCertErr: nil, - sdkTokenErr: nil, - err: provision.ErrUnauthorized, - }, - { - desc: "invalid clientID", - config: validConfig, - domainID: testsutil.GenerateUUID(t), - token: validToken, - clientID: "invalid", - ttl: "1h", - cert: "", - key: "", - sdkClientErr: errors.NewSDKErrorWithStatus(repoerr.ErrNotFound, 404), - sdkCertErr: nil, - sdkTokenErr: nil, - err: provision.ErrUnauthorized, - }, - { - desc: "failed to issue cert", - config: validConfig, - domainID: testsutil.GenerateUUID(t), - token: validToken, - clientID: testsutil.GenerateUUID(t), - ttl: "1h", - cert: "", - key: "", - sdkClientErr: nil, - sdkTokenErr: nil, - sdkCertErr: errors.NewSDKError(repoerr.ErrCreateEntity), - err: repoerr.ErrCreateEntity, - }, - } - - for _, c := range cases { - t.Run(c.desc, func(t *testing.T) { - mgsdk := new(sdkmocks.SDK) - svc := provision.New(c.config, mgsdk, smqlog.NewMock()) - - mgsdk.On("Client", c.clientID, c.domainID, mock.Anything).Return(sdk.Client{ID: c.clientID}, c.sdkClientErr) - mgsdk.On("IssueCert", c.clientID, c.config.Cert.TTL, c.domainID, mock.Anything).Return(sdk.Cert{SerialNumber: c.serial}, c.sdkCertErr) - mgsdk.On("ViewCert", c.serial, mock.Anything, mock.Anything).Return(sdk.Cert{Certificate: c.cert, Key: c.key}, c.sdkCertErr) - login := sdk.Login{ - Username: c.config.Server.MgUsername, - Password: c.config.Server.MgPass, - } - mgsdk.On("CreateToken", login).Return(sdk.Token{AccessToken: validToken}, c.sdkTokenErr) - cert, key, err := svc.Cert(c.domainID, c.token, c.clientID, c.ttl) - assert.Equal(t, c.cert, cert) - assert.Equal(t, c.key, key) - assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected error %v, got %v", c.err, err)) - }) - } -} diff --git a/tools/provision/provision.go b/tools/provision/provision.go index 35258fe57f..61c12badf8 100644 --- a/tools/provision/provision.go +++ b/tools/provision/provision.go @@ -66,7 +66,6 @@ func Provision(conf Config) error { UsersURL: conf.Host, ReaderURL: defReaderURL, HTTPAdapterURL: fmt.Sprintf("%s/http", conf.Host), - BootstrapURL: conf.Host, CertsURL: conf.Host, MsgContentType: sdk.ContentType(msgContentType), TLSVerification: false,