diff --git a/.github/workflows/build-publish.yaml b/.github/workflows/build-publish.yaml index db8d2f36a..1483fc143 100644 --- a/.github/workflows/build-publish.yaml +++ b/.github/workflows/build-publish.yaml @@ -109,6 +109,10 @@ jobs: - name: cert-tool directory: tools/cert-tool file: tools/cert-tool/Dockerfile + - name: snippet-service + directory: snippet-service + file: .tmp/docker/snippet-service/Dockerfile + template-file: tools/docker/Dockerfile.in - name: mongodb-standby-tool directory: tools/mongodb/standby-tool file: tools/mongodb/standby-tool/Dockerfile diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5c7139d79..79a19f626 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,7 +34,7 @@ jobs: log: level: "debug" dumpBody: "true" - + - name: test/cqldb cmd: test checkRace: "true" @@ -43,7 +43,6 @@ jobs: log: level: "debug" dumpBody: "true" - # test without check race - name: test/norace @@ -52,7 +51,7 @@ jobs: log: level: "debug" dumpBody: "true" - + - name: test/norace/cqldb cmd: test database: "cqldb" @@ -85,6 +84,10 @@ jobs: log: level: "debug" dumpBody: "true" + snippetService: + log: + level: "debug" + dumpBody: "true" # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -113,6 +116,7 @@ jobs: TEST_RESOURCE_AGGREGATE_LOG_LEVEL=${{ matrix.resourceAggregate.log.level }} TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY=${{ matrix.resourceAggregate.log.dumpBody }} \ TEST_GRPC_GATEWAY_LOG_LEVEL=${{ matrix.grpcGateway.log.level }} TEST_GRPC_GATEWAY_LOG_DUMP_BODY=${{ matrix.grpcGateway.log.dumpBody }} \ TEST_IDENTITY_STORE_LOG_LEVEL=${{ matrix.identityStore.log.level }} TEST_IDENTITY_STORE_LOG_DUMP_BODY=${{ matrix.identityStore.log.dumpBody }} \ + TEST_SNIPPET_SERVICE_LOG_LEVEL=${{ matrix.snippetService.log.level }} TEST_SNIPPET_SERVICE_LOG_DUMP_BODY=${{ matrix.snippetService.log.dumpBody }} \ TEST_DATABASE=${{ matrix.database }} \ ${{ matrix.args }} diff --git a/.vscode/settings.json b/.vscode/settings.json index 9207a2c6c..2b6faccea 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -35,6 +35,8 @@ "TEST_GRPC_GATEWAY_LOG_DUMP_BODY": "false", "TEST_IDENTITY_STORE_LOG_LEVEL": "info", "TEST_IDENTITY_STORE_LOG_DUMP_BODY": "false", + "TEST_SNIPPET_SERVICE_LOG_LEVEL": "info", + "TEST_SNIPPET_SERVICE_LOG_DUMP_BODY": "false", "TEST_DATABASE": "mongoDB", "TEST_BRIDGE_DEVICE_CONFIG": "${workspaceFolder}/.tmp/bridge/config-test.yaml", // "TEST_DEVICE_NAME": "bridged-device-0", diff --git a/Makefile b/Makefile index 612c32686..ddfe61fc2 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,8 @@ TEST_GRPC_GATEWAY_LOG_LEVEL ?= info TEST_GRPC_GATEWAY_LOG_DUMP_BODY ?= false TEST_IDENTITY_STORE_LOG_LEVEL ?= info TEST_IDENTITY_STORE_LOG_DUMP_BODY ?= false +TEST_SNIPPET_SERVICE_LOG_LEVEL ?= info +TEST_SNIPPET_SERVICE_LOG_DUMP_BODY ?= false TEST_MEMORY_COAP_GATEWAY_NUM_DEVICES ?= 1 TEST_MEMORY_COAP_GATEWAY_NUM_RESOURCES ?= 1 TEST_MEMORY_COAP_GATEWAY_EXPECTED_RSS_IN_MB ?= 50 @@ -42,7 +44,7 @@ CERT_TOOL_SIGN_ALG ?= ECDSA-SHA256 CERT_TOOL_ELLIPTIC_CURVE ?= P256 CERT_TOOL_IMAGE = ghcr.io/plgd-dev/hub/cert-tool:vnext -SUBDIRS := bundle certificate-authority cloud2cloud-connector cloud2cloud-gateway coap-gateway grpc-gateway resource-aggregate resource-directory http-gateway identity-store test/oauth-server tools/cert-tool +SUBDIRS := bundle certificate-authority cloud2cloud-connector cloud2cloud-gateway coap-gateway grpc-gateway resource-aggregate resource-directory http-gateway identity-store snippet-service test/oauth-server tools/cert-tool .PHONY: $(SUBDIRS) push proto/generate clean build test env mongo nats certificates hub-build http-gateway-www simulators default: build @@ -327,9 +329,9 @@ define RUN-TESTS-IN-DIRECTORY COVERAGE_FILE=/coverage/$$(echo $(1) | sed -e "s/[\.\/]//g").coverage.txt ; \ JSON_REPORT_FILE=$(WORKING_DIRECTORY)/.tmp/report/$$(echo $(1) | sed -e "s/[\.\/]//g").report.json ; \ if [ -n "$${JSON_REPORT}" ]; then \ - $(call RUN-DOCKER, go test -timeout=45m -race -p 1 -v $(1)... -covermode=atomic -coverprofile=$${COVERAGE_FILE} -json > "$${JSON_REPORT_FILE}") \ + $(call RUN-DOCKER, /bin/sh -c "$(2) go test -timeout=45m -race -p 1 -v $(1)... -covermode=atomic -coverprofile=$${COVERAGE_FILE} -json > $${JSON_REPORT_FILE}") \ else \ - $(call RUN-DOCKER, go test -timeout=45m -race -p 1 -v $(1)... -covermode=atomic -coverprofile=$${COVERAGE_FILE}) \ + $(call RUN-DOCKER, /bin/sh -c "$(2) go test -timeout=45m -race -p 1 -v $(1)... -covermode=atomic -coverprofile=$${COVERAGE_FILE}") \ fi ; \ EXIT_STATUS=$$? ; \ if [ $${EXIT_STATUS} -ne 0 ]; then \ @@ -372,6 +374,7 @@ define RUN-TESTS-UDP TEST_RESOURCE_AGGREGATE_LEVEL=$(TEST_RESOURCE_AGGREGATE_LEVEL) TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY=$(TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY) \ TEST_GRPC_GATEWAY_LOG_LEVEL=$(TEST_GRPC_GATEWAY_LOG_LEVEL) TEST_GRPC_GATEWAY_LOG_DUMP_BODY=$(TEST_GRPC_GATEWAY_LOG_DUMP_BODY) \ TEST_IDENTITY_STORE_LOG_LEVEL=$(TEST_IDENTITY_STORE_LOG_LEVEL) TEST_IDENTITY_STORE_LOG_DUMP_BODY=$(TEST_IDENTITY_STORE_LOG_DUMP_BODY) \ + TEST_SNIPPET_SERVICE_LOG_LEVEL=$(TEST_SNIPPET_SERVICE_LOG_LEVEL) TEST_SNIPPET_SERVICE_LOG_DUMP_BODY=$(TEST_SNIPPET_SERVICE_LOG_DUMP_BODY) \ TEST_DATABASE=$(TEST_DATABASE)) $(call RUN-TESTS,iotivity-lite-dtls,./test/iotivity-lite/service,-timeout=$(TEST_TIMEOUT) $(GO_BUILD_ARG) -p 1 -v -tags=test,\ TEST_COAP_GATEWAY_UDP_ENABLED=$(TEST_COAP_GATEWAY_UDP_ENABLED) \ @@ -379,6 +382,7 @@ define RUN-TESTS-UDP TEST_RESOURCE_AGGREGATE_LEVEL=$(TEST_RESOURCE_AGGREGATE_LEVEL) TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY=$(TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY) \ TEST_GRPC_GATEWAY_LOG_LEVEL=$(TEST_GRPC_GATEWAY_LOG_LEVEL) TEST_GRPC_GATEWAY_LOG_DUMP_BODY=$(TEST_GRPC_GATEWAY_LOG_DUMP_BODY) \ TEST_IDENTITY_STORE_LOG_LEVEL=$(TEST_IDENTITY_STORE_LOG_LEVEL) TEST_IDENTITY_STORE_LOG_DUMP_BODY=$(TEST_IDENTITY_STORE_LOG_DUMP_BODY) \ + TEST_SNIPPET_SERVICE_LOG_LEVEL=$(TEST_SNIPPET_SERVICE_LOG_LEVEL) TEST_SNIPPET_SERVICE_LOG_DUMP_BODY=$(TEST_SNIPPET_SERVICE_LOG_DUMP_BODY) \ TEST_DATABASE=$(TEST_DATABASE)) endef @@ -391,6 +395,7 @@ test: env hub-test TEST_RESOURCE_AGGREGATE_LEVEL=$(TEST_RESOURCE_AGGREGATE_LEVEL) TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY=$(TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY) \ TEST_GRPC_GATEWAY_LOG_LEVEL=$(TEST_GRPC_GATEWAY_LOG_LEVEL) TEST_GRPC_GATEWAY_LOG_DUMP_BODY=$(TEST_GRPC_GATEWAY_LOG_DUMP_BODY) \ TEST_IDENTITY_STORE_LOG_LEVEL=$(TEST_IDENTITY_STORE_LOG_LEVEL) TEST_IDENTITY_STORE_LOG_DUMP_BODY=$(TEST_IDENTITY_STORE_LOG_DUMP_BODY) \ + TEST_SNIPPET_SERVICE_LOG_LEVEL=$(TEST_SNIPPET_SERVICE_LOG_LEVEL) TEST_SNIPPET_SERVICE_LOG_DUMP_BODY=$(TEST_SNIPPET_SERVICE_LOG_DUMP_BODY) \ TEST_DATABASE=$(TEST_DATABASE)) ifeq ($(TEST_COAP_GATEWAY_UDP_ENABLED),true) @$(call RUN-TESTS-UDP) @@ -411,6 +416,7 @@ test/mem: env/test/mem hub-test TEST_RESOURCE_AGGREGATE_LEVEL=$(TEST_RESOURCE_AGGREGATE_LEVEL) TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY=$(TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY) \ TEST_GRPC_GATEWAY_LOG_LEVEL=$(TEST_GRPC_GATEWAY_LOG_LEVEL) TEST_GRPC_GATEWAY_LOG_DUMP_BODY=$(TEST_GRPC_GATEWAY_LOG_DUMP_BODY) \ TEST_IDENTITY_STORE_LOG_LEVEL=$(TEST_IDENTITY_STORE_LOG_LEVEL) TEST_IDENTITY_STORE_LOG_DUMP_BODY=$(TEST_IDENTITY_STORE_LOG_DUMP_BODY)\ + TEST_SNIPPET_SERVICE_LOG_LEVEL=$(TEST_SNIPPET_SERVICE_LOG_LEVEL) TEST_SNIPPET_SERVICE_LOG_DUMP_BODY=$(TEST_SNIPPET_SERVICE_LOG_DUMP_BODY) \ TEST_DATABASE=$(TEST_DATABASE)) .PHONY: test/mem @@ -428,7 +434,14 @@ $(test-targets): %: env hub-test echo "No golang files detected, directory $$TARGET_DIRECTORY skipped"; \ exit 0; \ fi ; \ - $(call RUN-TESTS-IN-DIRECTORY,$(patsubst test-%,./%/,$@)) + $(call RUN-TESTS-IN-DIRECTORY,$(patsubst test-%,./%/,$@),\ + TEST_COAP_GATEWAY_UDP_ENABLED=$(TEST_COAP_GATEWAY_UDP_ENABLED) \ + TEST_COAP_GATEWAY_LOG_LEVEL=$(TEST_COAP_GATEWAY_LOG_LEVEL) TEST_COAP_GATEWAY_LOG_DUMP_BODY=$(TEST_COAP_GATEWAY_LOG_DUMP_BODY) \ + TEST_RESOURCE_AGGREGATE_LEVEL=$(TEST_RESOURCE_AGGREGATE_LEVEL) TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY=$(TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY) \ + TEST_GRPC_GATEWAY_LOG_LEVEL=$(TEST_GRPC_GATEWAY_LOG_LEVEL) TEST_GRPC_GATEWAY_LOG_DUMP_BODY=$(TEST_GRPC_GATEWAY_LOG_DUMP_BODY) \ + TEST_IDENTITY_STORE_LOG_LEVEL=$(TEST_IDENTITY_STORE_LOG_LEVEL) TEST_IDENTITY_STORE_LOG_DUMP_BODY=$(TEST_IDENTITY_STORE_LOG_DUMP_BODY) \ + TEST_SNIPPET_SERVICE_LOG_LEVEL=$(TEST_SNIPPET_SERVICE_LOG_LEVEL) TEST_SNIPPET_SERVICE_LOG_DUMP_BODY=$(TEST_SNIPPET_SERVICE_LOG_DUMP_BODY) \ + TEST_DATABASE=$(TEST_DATABASE)) .PHONY: $(test-targets) diff --git a/bundle/Dockerfile b/bundle/Dockerfile index 9cc19ab46..3b9a66e7a 100644 --- a/bundle/Dockerfile +++ b/bundle/Dockerfile @@ -113,6 +113,13 @@ RUN go build \ -o "/go/bin/$tool" \ ./ +#snippet-service +ARG service=snippet-service +WORKDIR $root_directory/$service +RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service + #nats WORKDIR $root_directory RUN apkArch="$(apk --print-arch)"; \ @@ -178,6 +185,8 @@ COPY --from=build /go/bin/cloud2cloud-connector /usr/local/bin/cloud2cloud-conne COPY --from=build /go/src/github.com/plgd-dev/hub/cloud2cloud-connector/config.yaml /configs/cloud2cloud-connector.yaml COPY --from=build /go/src/github.com/plgd-dev/hub/bundle/run.sh /usr/local/bin/run.sh COPY --from=build /go/src/github.com/plgd-dev/hub/bundle/nginx /nginx +COPY --from=build /go/bin/snippet-service /usr/local/bin/snippet-service +COPY --from=build /go/src/github.com/plgd-dev/hub/snippet-service/config.yaml /configs/snippet-service.yaml # install scylla RUN curl -sSf get.scylladb.com/server | sudo bash -s -- --scylla-version 5.2 @@ -232,6 +241,8 @@ ENV NATS_PORT=10001 ENV SCYLLA_SMP=1 ENV SCYLLA_DEVELOPER_MODE=true ENV SCYLLA_PORT=29142 +ENV SNIPPET_SERVICE_PORT=9091 +ENV HTTP_SNIPPET_SERVICE_PORT=9092 ENV M2M_OAUTH_SERVER_PORT=9080 # OAuth diff --git a/bundle/nginx/nginx.conf.template b/bundle/nginx/nginx.conf.template index fbcb44c8d..312c36a9f 100644 --- a/bundle/nginx/nginx.conf.template +++ b/bundle/nginx/nginx.conf.template @@ -121,6 +121,20 @@ http { proxy_set_header Connection $connection_upgrade; proxy_set_header Host $host; } + location ~ ^(/snippet-service) { + set $upstream_snippet_service https://127.0.0.1:REPLACE_HTTP_SNIPPET_SERVICE_PORT; + proxy_pass $upstream_snippet_service; + proxy_ssl_certificate /data/certs/internal/endpoint.crt; + proxy_ssl_certificate_key /data/certs/internal/endpoint.key; + proxy_ssl_trusted_certificate /data/certs/root_ca.crt; + proxy_ssl_verify on; + set $cors_headers 'Authority,Method,Path,Scheme,Accept,Accept-Encoding,Accept-Language,Content-Type,Origin,Refer,Sec-Fetch-Dest,Sec-Fetch-Mode,Sec-Fetch-Site,Authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,correlation-id'; + include /nginx/cors.conf; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + } location ~ ^/ { set $upstream_http_gateway https://127.0.0.1:REPLACE_HTTP_GATEWAY_PORT; proxy_pass $upstream_http_gateway; diff --git a/bundle/run.sh b/bundle/run.sh index ac423c9fa..d6d944b39 100755 --- a/bundle/run.sh +++ b/bundle/run.sh @@ -15,6 +15,7 @@ export NGINX_PATH="/data/nginx" export JETSTREAM_PATH="/data/jetstream" export CERTIFICATE_AUTHORITY_ADDRESS="localhost:${CERTIFICATE_AUTHORITY_PORT}" +export CERTIFICATE_AUTHORITY_HTTP_ADDRESS="localhost:${HTTP_CERTIFICATE_AUTHORITY_PORT}" export MOCK_OAUTH_SERVER_ADDRESS="localhost:${MOCK_OAUTH_SERVER_PORT}" export RESOURCE_AGGREGATE_ADDRESS="localhost:${RESOURCE_AGGREGATE_PORT}" export RESOURCE_DIRECTORY_ADDRESS="localhost:${RESOURCE_DIRECTORY_PORT}" @@ -23,6 +24,8 @@ export GRPC_GATEWAY_ADDRESS="localhost:${GRPC_GATEWAY_PORT}" export HTTP_GATEWAY_ADDRESS="localhost:${HTTP_GATEWAY_PORT}" export CLOUD2CLOUD_GATEWAY_ADDRESS="localhost:${CLOUD2CLOUD_GATEWAY_PORT}" export CLOUD2CLOUD_CONNECTOR_ADDRESS="localhost:${CLOUD2CLOUD_CONNECTOR_PORT}" +export SNIPPET_SERVICE_ADDRESS="localhost:${SNIPPET_SERVICE_PORT}" +export SNIPPET_SERVICE_HTTP_ADDRESS="localhost:${HTTP_SNIPPET_SERVICE_PORT}" export M2M_OAUTH_SERVER_ADDRESS="localhost:${M2M_OAUTH_SERVER_PORT}" export INTERNAL_CERT_DIR_PATH="$CERTIFICATES_PATH/internal" @@ -484,6 +487,7 @@ if [ "${OVERRIDE_FILES}" = "true" ] || [ ! -f "${NGINX_PATH}/nginx.conf" ]; then sed -i "s/REPLACE_CLOUD2CLOUD_GATEWAY_PORT/$CLOUD2CLOUD_GATEWAY_PORT/g" ${NGINX_PATH}/nginx.conf sed -i "s/REPLACE_CLOUD2CLOUD_CONNECTOR_PORT/$CLOUD2CLOUD_CONNECTOR_PORT/g" ${NGINX_PATH}/nginx.conf sed -i "s/REPLACE_HTTP_CERTIFICATE_AUTHORITY_PORT/$HTTP_CERTIFICATE_AUTHORITY_PORT/g" ${NGINX_PATH}/nginx.conf + sed -i "s/REPLACE_HTTP_SNIPPET_SERVICE_PORT/$HTTP_SNIPPET_SERVICE_PORT/g" ${NGINX_PATH}/nginx.conf sed -i "s/REPLACE_M2M_OAUTH_SERVER_PORT/$M2M_OAUTH_SERVER_PORT/g" ${NGINX_PATH}/nginx.conf fi @@ -1009,6 +1013,7 @@ cat /configs/certificate-authority.yaml | yq e "\ .apis.grpc.authorization.http.tls.useSystemCAPool = true | .apis.grpc.authorization.authority = \"https://${OAUTH_ENDPOINT}\" | .apis.grpc.authorization.ownerClaim = \"${OWNER_CLAIM}\" | + .apis.http.address = \"${CERTIFICATE_AUTHORITY_HTTP_ADDRESS}\" | .clients.storage.use = \"${DATABASE_USE}\" | .clients.storage.mongoDB.uri = \"${MONGODB_URI}\" | .clients.storage.cqlDB.hosts = [ \"${SCYLLA_HOSTNAME}\" ] | @@ -1241,7 +1246,51 @@ while true; do sleep 1 done +# snippet-service +echo "starting snippet-service" +## configuration +if [ "${OVERRIDE_FILES}" = "true" ] || [ ! -f "/data/snippet-service.yaml" ]; then +cat /configs/snippet-service.yaml | yq e "\ + .hubID = \"${HUB_ID}\" | + .log.level = \"${LOG_LEVEL}\" | + .apis.grpc.address = \"${SNIPPET_SERVICE_ADDRESS}\" | + .apis.grpc.authorization.audience = \"${SERVICE_OAUTH_AUDIENCE}\" | + .apis.grpc.authorization.http.tls.useSystemCAPool = true | + .apis.grpc.authorization.authority = \"https://${OAUTH_ENDPOINT}\" | + .apis.grpc.authorization.ownerClaim = \"${OWNER_CLAIM}\" | + .apis.http.address = \"${SNIPPET_SERVICE_HTTP_ADDRESS}\" | + .clients.storage.use = \"${DATABASE_USE}\" | + .clients.storage.mongoDB.uri = \"${MONGODB_URI}\" | + .clients.storage.cqlDB.hosts = [ \"${SCYLLA_HOSTNAME}\" ] | + .clients.storage.cqlDB.port = ${SCYLLA_PORT} | + .clients.openTelemetryCollector.grpc.enabled = ${OPEN_TELEMETRY_EXPORTER_ENABLED} | + .clients.openTelemetryCollector.grpc.address = \"${OPEN_TELEMETRY_EXPORTER_ADDRESS}\" | + .clients.openTelemetryCollector.grpc.tls.caPool = \"${OPEN_TELEMETRY_EXPORTER_CA_POOL}\" | + .clients.openTelemetryCollector.grpc.tls.keyFile = \"${OPEN_TELEMETRY_EXPORTER_KEY_FILE}\" | + .clients.openTelemetryCollector.grpc.tls.certFile = \"${OPEN_TELEMETRY_EXPORTER_CERT_FILE}\" | + .clients.openTelemetryCollector.grpc.tls.useSystemCAPool = true +" - > /data/snippet-service.yaml +fi +snippet-service --config /data/snippet-service.yaml >$LOGS_PATH/snippet-service.log 2>&1 & +status=$? +snippet_service_pid=$! +if [ $status -ne 0 ]; then + echo "Failed to start snippet-service: $status" + sync + cat $LOGS_PATH/snippet-service.log + exit $status +fi +# waiting for ca. Without wait, sometimes the service didn't connect. +i=0 +while true; do + i=$((i+1)) + if openssl s_client -connect ${SNIPPET_SERVICE_ADDRESS} -cert ${INTERNAL_CERT_DIR_PATH}/${GRPC_INTERNAL_CERT_NAME} -key ${INTERNAL_CERT_DIR_PATH}/${GRPC_INTERNAL_CERT_KEY_NAME} <<< "Q" 2>/dev/null > /dev/null; then + break + fi + echo "Try to reconnect to snippet-service(${SNIPPET_SERVICE_ADDRESS}) $i" + sleep 1 +done echo "Open browser at https://${DOMAIN}" @@ -1367,4 +1416,11 @@ while sleep 10; do exit 1 fi fi + ps aux |grep $snippet_service_pid |grep -q -v grep + if [ $? -ne 0 ]; then + echo "snippet-service has already exited." + sync + cat $LOGS_PATH/snippet-service.log + exit 1 + fi done diff --git a/charts/plgd-hub/templates/http-gateway/_helpers.tpl b/charts/plgd-hub/templates/http-gateway/_helpers.tpl index e8c19c261..f3e42db4b 100644 --- a/charts/plgd-hub/templates/http-gateway/_helpers.tpl +++ b/charts/plgd-hub/templates/http-gateway/_helpers.tpl @@ -83,6 +83,20 @@ {{- end }} {{- end }} +{{- define "plgd-hub.httpgateway.snippetServiceApiDomain" -}} + {{- $domain := "" }} + {{- if .Values.snippetservice }} + {{- if .Values.snippetservice.enabled }} + {{- if .Values.snippetservice.domain }} + {{- $domain = printf "https://%s" .Values.snippetservice.domain }} + {{- else }} + {{- $domain = printf "https://api.%s" .Values.global.domain }} + {{- end }} + {{- end }} + {{- end }} + {{- printf $domain }} +{{- end }} + {{- define "plgd-hub.httpgateway.uiDomain" -}} {{- if .Values.httpgateway.uiDomain }} {{- printf "%s" .Values.httpgateway.uiDomain }} diff --git a/charts/plgd-hub/templates/http-gateway/config.yaml b/charts/plgd-hub/templates/http-gateway/config.yaml index b5daac2db..ca7a94470 100644 --- a/charts/plgd-hub/templates/http-gateway/config.yaml +++ b/charts/plgd-hub/templates/http-gateway/config.yaml @@ -53,6 +53,7 @@ data: webConfiguration: httpGatewayAddress: {{ .ui.webConfiguration.httpGatewayAddress | default ( printf "https://%s" ( include "plgd-hub.httpgateway.apiDomain" $)) | quote }} deviceProvisioningService: {{ .ui.webConfiguration.deviceProvisioningService | default ( include "plgd-hub.httpgateway.dpsApiDomain" $) | quote }} + snippetService: {{ .ui.webConfiguration.snippetService | default ( include "plgd-hub.httpgateway.snippetServiceApiDomain" $) | quote }} {{- if not $.Values.mockoauthserver.enabled }} webOAuthClient: authority: {{ required ".ui.webConfiguration.webOAuthClient.authority or global.authority is required" ( .ui.webConfiguration.webOAuthClient.authority | default $.Values.global.authority ) | quote }} diff --git a/charts/plgd-hub/templates/snippet-service/_helpers.tpl b/charts/plgd-hub/templates/snippet-service/_helpers.tpl new file mode 100644 index 000000000..0d2d07419 --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/_helpers.tpl @@ -0,0 +1,53 @@ +{{- define "plgd-hub.snippetservice.fullname" -}} +{{- if .Values.snippetservice.fullnameOverride }} +{{- .Values.snippetservice.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Values.snippetservice.name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s-%s" .Release.Name $name .Values.snippetservice.name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "plgd-hub.snippetservice.configName" -}} + {{- $fullName := include "plgd-hub.snippetservice.fullname" . -}} + {{- printf "%s-cfg" $fullName }} +{{- end -}} + +{{- define "plgd-hub.snippetservice.createServiceCertByCm" }} + {{- $serviceTls := .Values.snippetservice.apis.grpc.tls.certFile }} + {{- if $serviceTls }} + {{- printf "" -}} + {{- else }} + {{- printf "true" -}} + {{- end }} +{{- end }} + +{{- define "plgd-hub.snippetservice.domain" -}} + {{- if .Values.snippetservice.domain }} + {{- printf "%s" .Values.snippetservice.domain }} + {{- else }} + {{- printf "api.%s" .Values.global.domain }} + {{- end }} +{{- end }} + +{{- define "plgd-hub.snippetservice.serviceCertName" -}} + {{- $fullName := include "plgd-hub.snippetservice.fullname" . -}} + {{- printf "%s-crt" $fullName -}} +{{- end }} + +{{- define "plgd-hub.snippetservice.domainCertName" -}} + {{- if .Values.snippetservice.ingress.secretName }} + {{- printf "%s" .Values.snippetservice.ingress.secretName -}} + {{- else }} + {{- $fullName := include "plgd-hub.snippetservice.fullname" . -}} + {{- printf "%s-domain-crt" $fullName -}} + {{- end }} +{{- end }} + +{{- define "plgd-hub.snippetservice.selectorLabels" -}} +app.kubernetes.io/name: {{ .Values.snippetservice.name }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} \ No newline at end of file diff --git a/charts/plgd-hub/templates/snippet-service/config.yaml b/charts/plgd-hub/templates/snippet-service/config.yaml new file mode 100644 index 000000000..384f60237 --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/config.yaml @@ -0,0 +1,112 @@ +{{- if .Values.snippetservice.enabled }} +{{- $cert := "/certs" }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "plgd-hub.snippetservice.configName" . }} + namespace: {{ .Release.Namespace }} +data: + {{ .Values.snippetservice.config.fileName }}: | + {{- with .Values.snippetservice }} + hubID: {{ required "snippetservice.hubId or global.hubId is required" ( .hubId | default $.Values.global.hubId) | quote }} + log: + level: {{ .log.level }} + dumpBody: {{ .log.dumpBody }} + encoding: {{ .log.encoding }} + stacktrace: + enabled: {{ .log.stacktrace.enabled }} + level: {{ .log.stacktrace.level }} + encoderConfig: + timeEncoder: {{ .log.encoderConfig.timeEncoder }} + apis: + grpc: + address: {{ .apis.grpc.address | default (printf "0.0.0.0:%v" .port) | quote }} + sendMsgSize: {{ int64 .apis.grpc.sendMsgSize | default 4194304 }} + recvMsgSize: {{ int64 .apis.grpc.recvMsgSize | default 4194304 }} + enforcementPolicy: + minTime: {{ .apis.grpc.enforcementPolicy.minTime }} + permitWithoutStream: {{ .apis.grpc.enforcementPolicy.permitWithoutStream }} + keepAlive: + # 0s - means infinity + maxConnectionIdle: {{ .apis.grpc.keepAlive.maxConnectionIdle }} + # 0s - means infinity + maxConnectionAge: {{ .apis.grpc.keepAlive.maxConnectionIdle }} + # 0s - means infinity + maxConnectionAgeGrace: {{ .apis.grpc.keepAlive.maxConnectionAgeGrace }} + time: {{ .apis.grpc.keepAlive.maxConnectionIdle }} + timeout: {{ .apis.grpc.keepAlive.maxConnectionIdle }} + tls: + {{- $tls := .apis.grpc.tls }} + {{- include "plgd-hub.certificateConfig" (list $ $tls $cert ) | indent 8 }} + clientCertificateRequired: {{ .apis.grpc.tls.clientCertificateRequired }} + authorization: + {{- $authorization := .apis.grpc.authorization }} + {{- include "plgd-hub.authorizationConfig" (list $ $authorization "snippetservice.apis.grpc.authorization" $cert ) | indent 8 }} + http: + address: {{ .apis.http.address | default (printf "0.0.0.0:%v" .httpPort) | quote }} + readTimeout: {{ .apis.http.readTimeout }} + readHeaderTimeout: {{ .apis.http.readHeaderTimeout }} + writeTimeout: {{ .apis.http.writeTimeout }} + idleTimeout: {{ .apis.http.idleTimeout }} + clients: + eventBus: + subscriptionID: {{ .clients.eventBus.subscriptionID | default "snippet-service" }} + nats: + url: {{ printf " " }}{{- include "plgd-hub.natsUri" (list $ .clients.eventBus.nats.url) | quote }} + pendingLimits: + msgLimit: {{ .clients.eventBus.nats.pendingLimits.msgLimit }} + bytesLimit: {{ printf "%v" .clients.eventBus.nats.pendingLimits.bytesLimit }} + tls: + {{- $natsTls := .clients.eventBus.nats.tls }} + {{- include "plgd-hub.certificateConfig" (list $ $natsTls $cert ) | indent 10 }} + useSystemCAPool: {{ .clients.eventBus.nats.tls.useSystemCAPool }} + storage: + use: {{ include "plgd-hub.useDatabase" (list $ . .clients.storage.use) | quote }} + mongoDB: + uri: {{ include "plgd-hub.mongoDBUri" (list $ .clients.storage.mongoDB.uri ) | quote }} + database: {{ .clients.storage.mongoDB.database }} + maxPoolSize: {{ .clients.storage.mongoDB.maxPoolSize }} + maxConnIdleTime: {{ .clients.storage.mongoDB.maxConnIdleTime }} + tls: + {{- $mongoDbTls := .clients.storage.mongoDB.tls }} + {{- include "plgd-hub.certificateConfig" (list $ $mongoDbTls $cert ) | indent 10 }} + useSystemCAPool: {{ .clients.storage.mongoDB.tls.useSystemCAPool }} + cqlDB: + hosts: + {{- include "plgd-hub.cqlDBHosts" (list $ .clients.storage.cqlDB.hosts ) | indent 8 }} + port: {{ .clients.storage.cqlDB.port | default 9142 }} + table: {{ .clients.storage.cqlDB.table | quote }} + numConnections: {{ .clients.storage.cqlDB.numConnections }} + connectTimeout: {{ .clients.storage.cqlDB.connectTimeout }} + useHostnameResolution: {{ .clients.storage.cqlDB.useHostnameResolution }} + reconnectionPolicy: + constant: + interval: {{ .clients.storage.cqlDB.reconnectionPolicy.constant.interval }} + maxRetries: {{ .clients.storage.cqlDB.reconnectionPolicy.constant.maxRetries }} + keyspace: + name: {{ .clients.storage.cqlDB.keyspace.name }} + create: {{ .clients.storage.cqlDB.keyspace.create }} + replication: + {{- toYaml .clients.storage.cqlDB.keyspace.replication | nindent 14 }} + tls: + {{- $cqlDbTls := .clients.storage.cqlDB.tls }} + {{- include "plgd-hub.certificateConfig" (list $ $cqlDbTls $cert ) | indent 10 }} + useSystemCAPool: {{ .clients.storage.cqlDB.tls.useSystemCAPool }} + resourceUpdater: + cleanUpExpiredUpdates: {{ .clients.resourceUpdater.cleanUpExpiredUpdates | quote }} + grpc: + {{- $resourceUpdater := .clients.resourceUpdater.grpc.address }} + address:{{ printf " " }}{{- include "plgd-hub.resourceAggregateAddress" (list $ $resourceUpdater ) | quote }} + sendMsgSize: {{ int64 .clients.resourceUpdater.grpc.sendMsgSize | default 4194304 }} + recvMsgSize: {{ int64 .clients.resourceUpdater.grpc.recvMsgSize | default 4194304 }} + keepAlive: + time: {{ .clients.resourceUpdater.grpc.keepAlive.time }} + timeout: {{ .clients.resourceUpdater.grpc.keepAlive.timeout }} + permitWithoutStream: {{ .clients.resourceUpdater.grpc.keepAlive.permitWithoutStream }} + tls: + {{- $raClientTls := .clients.resourceUpdater.grpc.tls }} + {{- include "plgd-hub.certificateConfig" (list $ $raClientTls $cert) | indent 10 }} + useSystemCAPool: {{ .clients.resourceUpdater.grpc.tls.useSystemCAPool }} + {{- include "plgd-hub.openTelemetryExporterConfig" (list $ $cert ) | nindent 6 }} + {{- end }} +{{- end }} diff --git a/charts/plgd-hub/templates/snippet-service/deployment.yaml b/charts/plgd-hub/templates/snippet-service/deployment.yaml new file mode 100644 index 000000000..e433aa572 --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/deployment.yaml @@ -0,0 +1,129 @@ +{{- if .Values.snippetservice.enabled }} +{{- $cert := "/certs" }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "plgd-hub.snippetservice.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "plgd-hub.labels" . | nindent 4 }} + {{- with .Values.snippetservice.deploymentLabels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + {{- with .Values.snippetservice.deploymentAnnotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +spec: + replicas: {{ .Values.snippetservice.replicas }} + selector: + matchLabels: + {{- include "plgd-hub.snippetservice.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.snippetservice.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "plgd-hub.snippetservice.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.snippetservice.securityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.snippetservice.rbac.enabled }} + serviceAccountName: {{ .Values.snippetservice.rbac.serviceAccountName }} + {{- end }} + {{- with .Values.snippetservice.image.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + restartPolicy: {{ .Values.snippetservice.restartPolicy }} + {{- if .Values.snippetservice.initContainersTpl }} + initContainers: + {{- tpl .Values.snippetservice.initContainersTpl . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Values.snippetservice.name }} + {{- with .Values.snippetservice.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: {{ include "plgd-hub.image" (list . .Values.snippetservice) | quote }} + imagePullPolicy: {{ .Values.snippetservice.image.pullPolicy }} + {{- if .Values.snippetservice.command }} + command: + {{- range .Values.snippetservice.command }} + - {{ . | quote }} + {{- end }} + {{- end}} + args: + - "--config" + - {{ printf "%s/%s" .Values.snippetservice.config.mountPath .Values.snippetservice.config.fileName | quote }} + ports: + - name: grpc + containerPort: {{ .Values.snippetservice.port }} + protocol: TCP + - name: http + containerPort: {{ .Values.snippetservice.httpPort }} + protocol: TCP + {{- with .Values.snippetservice.livenessProbe }} + livenessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.snippetservice.readinessProbe }} + readinessProbe: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.snippetservice.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: {{ .Values.snippetservice.config.volume }} + mountPath: {{ .Values.snippetservice.config.mountPath }} + {{- if ( include "plgd-hub.snippetservice.createServiceCertByCm" . ) }} + - name: service-crt + mountPath: {{ $cert }} + {{- end }} + {{- if .Values.global.authorizationCAPool }} + - name: {{ .Values.extraAuthorizationCAPool.name }} + mountPath: {{ .Values.extraAuthorizationCAPool.mountPath }} + {{- end }} + {{- with .Values.snippetservice.extraVolumeMounts }} + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.snippetservice.extraContainers }} + {{- include "plgd-hub.tplvalues.render" ( dict "value" .Values.snippetservice.extraContainers "context" $ ) | nindent 8 }} + {{- end }} + volumes: + - name: {{ .Values.resourcedirectory.config.volume }} + configMap: + name: {{ include "plgd-hub.snippetservice.configName" . }} + {{- if ( include "plgd-hub.snippetservice.createServiceCertByCm" . ) }} + - name: service-crt + secret: + secretName: {{ include "plgd-hub.snippetservice.serviceCertName" . }} + {{- end }} + {{- if .Values.global.authorizationCAPool }} + - name: {{ .Values.extraAuthorizationCAPool.name }} + secret: + secretName: {{ .Values.extraAuthorizationCAPool.name }} + {{- end }} + {{- with .Values.snippetservice.extraVolumes }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.snippetservice.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.snippetservice.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.snippetservice.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} diff --git a/charts/plgd-hub/templates/snippet-service/domain-crt.yaml b/charts/plgd-hub/templates/snippet-service/domain-crt.yaml new file mode 100644 index 000000000..c1d06ff62 --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/domain-crt.yaml @@ -0,0 +1,34 @@ +{{- $domainCrt := include "plgd-hub.snippetservice.domainCertName" . }} +{{- if and $domainCrt .Values.certmanager.enabled .Values.snippetservice.enabled (not $.Values.global.enableWildCartCert ) }} +{{- $serviceDns := include "plgd-hub.snippetservice.fullname" . }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ $domainCrt }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "plgd-hub.labels" . | nindent 4 }} + {{- with .Values.certmanager.external.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + {{- with .Values.certmanager.external.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +spec: + secretName: {{ $domainCrt }} + privateKey: + algorithm: {{ .Values.certmanager.external.cert.key.algorithm | default .Values.certmanager.default.cert.key.algorithm }} + size: {{ .Values.certmanager.external.cert.key.size | default .Values.certmanager.default.cert.key.size }} + usages: + - server auth + - client auth + dnsNames: + - {{ include "plgd-hub.snippetservice.domain" . | quote }} + duration: {{ .Values.certmanager.external.cert.duration | default .Values.certmanager.default.cert.duration }} + renewBefore: {{ .Values.certmanager.external.cert.renewBefore | default .Values.certmanager.default.cert.renewBefore }} + issuerRef: + name: {{ .Values.certmanager.external.issuer.name | default .Values.certmanager.default.issuer.name }} + kind: {{ .Values.certmanager.external.issuer.kind | default .Values.certmanager.default.issuer.kind }} + group: {{ .Values.certmanager.external.issuer.group | default .Values.certmanager.default.issuer.group }} +{{- end }} diff --git a/charts/plgd-hub/templates/snippet-service/grpc-ingress.yaml b/charts/plgd-hub/templates/snippet-service/grpc-ingress.yaml new file mode 100644 index 000000000..12ef47117 --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/grpc-ingress.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.snippetservice.enabled .Values.snippetservice.ingress.grpc.enabled }} +{{- $fullname := include "plgd-hub.snippetservice.fullname" . }} +{{- $port := .Values.snippetservice.port }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullname }}-grpc + namespace: {{ .Release.Namespace }} + labels: + {{- include "plgd-hub.labels" . | nindent 4 }} + annotations: + {{- if .Values.snippetservice.ingress.grpc.annotations }} + {{- include "plgd-hub.tplvalues.render" ( dict "value" .Values.snippetservice.ingress.grpc.annotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.snippetservice.ingress.grpc.customAnnotations }} + {{- include "plgd-hub.tplvalues.render" ( dict "value" .Values.snippetservice.ingress.grpc.customAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + tls: + - hosts: + - {{ include "plgd-hub.snippetservice.domain" . | quote }} + {{- if $.Values.global.enableWildCartCert }} + secretName: {{ include "plgd-hub.wildCardCertName" . | quote }} + {{- else }} + secretName: {{ include "plgd-hub.snippetservice.domainCertName" . | quote }} + {{- end }} + rules: + - host: {{ include "plgd-hub.snippetservice.domain" . | quote }} + http: + paths: + {{- range .Values.snippetservice.ingress.grpc.paths }} + - path: {{ . }} + pathType: Prefix + backend: + service: + name: {{ $fullname }}-grpc + port: + number: {{ $port }} + {{- end }} +{{- end }} diff --git a/charts/plgd-hub/templates/snippet-service/grpc-service.yaml b/charts/plgd-hub/templates/snippet-service/grpc-service.yaml new file mode 100644 index 000000000..e2d37681f --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/grpc-service.yaml @@ -0,0 +1,25 @@ +{{- if .Values.snippetservice.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "plgd-hub.snippetservice.fullname" . }}-grpc + namespace: {{ .Release.Namespace }} + labels: + {{- include "plgd-hub.labels" . | nindent 4 }} + {{- with .Values.snippetservice.service.grpc.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + {{- if .Values.snippetservice.service.grpc.annotations }} + annotations: + {{- include "plgd-hub.tplvalues.render" ( dict "value" .Values.snippetservice.service.grpc.annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.snippetservice.service.grpc.type | default "ClusterIP" }} + ports: + - port: {{ .Values.snippetservice.port }} + targetPort: {{ .Values.snippetservice.service.grpc.targetPort }} + protocol: {{ .Values.snippetservice.service.grpc.protocol }} + name: {{ .Values.snippetservice.service.grpc.name }} + selector: + {{- include "plgd-hub.snippetservice.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/plgd-hub/templates/snippet-service/http-ingress.yaml b/charts/plgd-hub/templates/snippet-service/http-ingress.yaml new file mode 100644 index 000000000..3ee3cd2b2 --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/http-ingress.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.snippetservice.enabled .Values.snippetservice.ingress.http.enabled }} +{{- $fullname := include "plgd-hub.snippetservice.fullname" . }} +{{- $port := .Values.snippetservice.httpPort }} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullname }}-http + namespace: {{ .Release.Namespace }} + labels: + {{- include "plgd-hub.labels" . | nindent 4 }} + annotations: + {{- if .Values.snippetservice.ingress.http.annotations }} + {{- include "plgd-hub.tplvalues.render" ( dict "value" .Values.snippetservice.ingress.http.annotations "context" $ ) | nindent 4 }} + {{- end }} + {{- if .Values.snippetservice.ingress.http.customAnnotations }} + {{- include "plgd-hub.tplvalues.render" ( dict "value" .Values.snippetservice.ingress.http.customAnnotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + tls: + - hosts: + - {{ include "plgd-hub.snippetservice.domain" . | quote }} + {{- if $.Values.global.enableWildCartCert }} + secretName: {{ include "plgd-hub.wildCardCertName" . | quote }} + {{- else }} + secretName: {{ include "plgd-hub.snippetservice.domainCertName" . | quote }} + {{- end }} + rules: + - host: {{ include "plgd-hub.snippetservice.domain" . | quote }} + http: + paths: + {{- range .Values.snippetservice.ingress.http.paths }} + - path: {{ . }} + pathType: Prefix + backend: + service: + name: {{ $fullname }}-http + port: + number: {{ $port }} + {{- end }} +{{- end }} diff --git a/charts/plgd-hub/templates/snippet-service/http-service.yaml b/charts/plgd-hub/templates/snippet-service/http-service.yaml new file mode 100644 index 000000000..1e6cf659c --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/http-service.yaml @@ -0,0 +1,25 @@ +{{- if .Values.snippetservice.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "plgd-hub.snippetservice.fullname" . }}-http + namespace: {{ .Release.Namespace }} + labels: + {{- include "plgd-hub.labels" . | nindent 4 }} + {{- with .Values.snippetservice.service.http.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + {{- if .Values.snippetservice.service.http.annotations }} + annotations: + {{- include "plgd-hub.tplvalues.render" ( dict "value" .Values.snippetservice.service.http.annotations "context" $ ) | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.snippetservice.service.http.type | default "ClusterIP" }} + ports: + - port: {{ .Values.snippetservice.httpPort }} + targetPort: {{ .Values.snippetservice.service.http.targetPort }} + protocol: {{ .Values.snippetservice.service.http.protocol }} + name: {{ .Values.snippetservice.service.http.name }} + selector: + {{- include "plgd-hub.snippetservice.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/charts/plgd-hub/templates/snippet-service/role.yaml b/charts/plgd-hub/templates/snippet-service/role.yaml new file mode 100644 index 000000000..0dc01b10c --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/role.yaml @@ -0,0 +1,3 @@ +{{- if and .Values.snippetservice.rbac.enabled .Values.snippetservice.rbac.roleBindingDefitionTpl }} +{{- tpl .Values.snippetservice.rbac.roleBindingDefitionTpl $ }} +{{- end }} diff --git a/charts/plgd-hub/templates/snippet-service/service-account.yaml b/charts/plgd-hub/templates/snippet-service/service-account.yaml new file mode 100644 index 000000000..b1a4a7081 --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/service-account.yaml @@ -0,0 +1,9 @@ +{{- if and .Values.snippetservice.rbac.enabled .Values.snippetservice.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Values.snippetservice.rbac.serviceAccountName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "plgd-hub.labels" . | nindent 4 }} +{{- end }} diff --git a/charts/plgd-hub/templates/snippet-service/service-crt.yaml b/charts/plgd-hub/templates/snippet-service/service-crt.yaml new file mode 100644 index 000000000..afce0d74b --- /dev/null +++ b/charts/plgd-hub/templates/snippet-service/service-crt.yaml @@ -0,0 +1,44 @@ +{{- $createServiceCert := include "plgd-hub.snippetservice.serviceCertName" . }} +{{- if and $createServiceCert .Values.certmanager.enabled .Values.snippetservice.enabled }} +{{- $serviceCertName := include "plgd-hub.snippetservice.serviceCertName" . }} +{{- $serviceDns := include "plgd-hub.snippetservice.fullname" . }} +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: {{ $serviceCertName }} + namespace: {{ .Release.Namespace }} + labels: + {{- include "plgd-hub.labels" . | nindent 4 }} + {{- with .Values.certmanager.internal.labels }} + {{- . | toYaml | nindent 4 }} + {{- end }} + {{- with .Values.certmanager.internal.annotations }} + annotations: + {{- . | toYaml | nindent 4 }} + {{- end }} +spec: + secretName: {{ $serviceCertName }} + privateKey: + algorithm: {{ .Values.certmanager.internal.cert.key.algorithm | default .Values.certmanager.default.cert.key.algorithm }} + size: {{ .Values.certmanager.internal.cert.key.size | default .Values.certmanager.default.cert.key.size }} + usages: + - server auth + - client auth + dnsNames: + - {{ printf "%s-http.%s.svc.%s" $serviceDns .Release.Namespace .Values.cluster.dns | quote }} + - {{ printf "%s-grpc.%s.svc.%s" $serviceDns .Release.Namespace .Values.cluster.dns | quote }} + - {{ printf "%s-http" $serviceDns | quote }} + - {{ printf "%s-grpc" $serviceDns | quote }} + {{- if .Values.snippetservice.service.grpc.crt.extraDnsNames }} + {{- toYaml .Values.snippetservice.service.grpc.crt.extraDnsNames | nindent 4}} + {{- end }} + {{- if .Values.snippetservice.service.http.crt.extraDnsNames }} + {{- toYaml .Values.snippetservice.service.http.crt.extraDnsNames | nindent 4}} + {{- end }} + duration: {{ .Values.certmanager.internal.cert.duration | default .Values.certmanager.default.cert.duration }} + renewBefore: {{ .Values.certmanager.internal.cert.renewBefore | default .Values.certmanager.default.cert.renewBefore }} + issuerRef: + name: {{ .Values.certmanager.internal.issuer.name | default .Values.certmanager.default.issuer.name }} + kind: {{ .Values.certmanager.internal.issuer.kind | default .Values.certmanager.default.issuer.kind }} + group: {{ .Values.certmanager.internal.issuer.group | default .Values.certmanager.default.issuer.group }} +{{- end }} diff --git a/charts/plgd-hub/values.yaml b/charts/plgd-hub/values.yaml index fe6831bab..082f9e255 100644 --- a/charts/plgd-hub/values.yaml +++ b/charts/plgd-hub/values.yaml @@ -1740,6 +1740,7 @@ httpgateway: webConfiguration: httpGatewayAddress: "" deviceProvisioningService: "" + snippetService: "" webOAuthClient: authority: "" clientID: "" @@ -2292,6 +2293,253 @@ certificateauthority: validFrom: "now-1h" expiresIn: "87600h" +snippetservice: + # -- Enable snippet-service + enabled: true + # -- Name of component. Used in label selectors + name: snippet-service + # -- Full name to override + fullnameOverride: + # -- Number of replicas + replicas: 1 + # -- Additional labels for snippet-service deployment + deploymentLabels: {} + # -- Additional annotations for snippet-service deployment + deploymentAnnotations: {} + # -- Pod security context + podSecurityContext: {} + # -- Labels for snippet-service pod + podLabels: {} + # -- Annotations for snippet-service pod + podAnnotations: {} + service: + grpc: + # -- Service type + type: ClusterIP + # -- Labels for snippet-service + labels: {} + # -- Annotations for snippet-service + annotations: {} + # -- Target port + targetPort: grpc + # -- Protocol + protocol: TCP + # -- Name + name: grpc + crt: + # -- Extra DNS names for service certificate + extraDnsNames: [] + http: + # -- Service type + type: ClusterIP + # -- Labels for snippet service + labels: {} + # -- Annotations for snippet service + annotations: {} + # -- Target port + targetPort: http + # -- Protocol + protocol: TCP + # -- Name + name: http + crt: + # -- Extra DNS names for service certificate + extraDnsNames: [] + # -- RBAC configuration + rbac: + # -- Enable RBAC + enabled: false + # -- Name of snippet service SA + serviceAccountName: snippet-service + # -- Template definition for Role/binding etc.. + roleBindingDefitionTpl: + # -- Security context for pod + securityContext: + # -- Image pull secrets + imagePullSecrets: + # -- Restart policy for pod + restartPolicy: Always + # -- Init containers definition + initContainersTpl: + # -- Extra POD containers + extraContainers: {} + image: + # -- Image registry + registry: ghcr.io/ + # -- Image repository + repository: plgd-dev/hub/snippet-service + # -- Image tag. + tag: + # -- Image pull policy + pullPolicy: Always + # -- Image pull secrets + imagePullSecrets: + # -- Liveness probe. snippet-service doesn't have any default liveness probe + livenessProbe: + # -- Readiness probe. snippet-service doesn't have aby default readiness probe + readinessProbe: + # -- Resources limit + resources: + # -- Node selector + nodeSelector: + # -- Affinity definition + affinity: + # -- Toleration definition + tolerations: + # -- Optional extra volumes + extraVolumes: + # -- Optional extra volume mounts + extraVolumeMounts: + # -- External domain for snippet-service. Default: api.{{ global.domain }} + domain: + ingress: + http: + # -- Enable ingress + enabled: true + # -- Override name of host/tls secret. If not specified, it will be generated + secretName: + # -- Pre defined map of Ingress annotation + annotations: + nginx.org/grpc-services: "{{ include \"plgd-hub.snippetservice.fullname\" . }}-http" + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/enable-cors: "true" + cert-manager.io/private-key-rotation-policy: always + # -- Custom map of Ingress annotation + customAnnotations: {} + # -- Ingress path + paths: + - /snippet-service + grpc: + # -- Enable ingress + enabled: true + # -- Override name of host/tls secret. If not specified, it will be generated + secretName: + # -- Pre defined map of Ingress annotation + annotations: + nginx.org/grpc-services: "{{ include \"plgd-hub.snippetservice.fullname\" . }}-grpc" + nginx.ingress.kubernetes.io/backend-protocol: "GRPCS" + ingress.kubernetes.io/force-ssl-redirect: "true" + nginx.ingress.kubernetes.io/enable-cors: "true" + cert-manager.io/private-key-rotation-policy: always + # -- Custom map of Ingress annotation + customAnnotations: { } + # -- Paths + paths: + - /snippetservice.pb.SnippetService + # -- Service configuration + config: + # -- File name for config file + fileName: service.yaml + # -- Config file volume name + volume: config + # -- Mount path + mountPath: /config + # -- Service and POD port + port: 9100 + httpPort: 9101 + # -- Hub ID. Overrides the global.hubId + hubId: + # -- Log section + log: + # -- Logging enabled from level + level: info + # -- Dump grpc messages + dumpBody: false + # -- The supported values are: "json", "console" + encoding: json + stacktrace: + # -- Log stacktrace + enabled: false + # -- Stacktrace from level + level: warn + encoderConfig: + # -- Time format for logs. The supported values are: "rfc3339nano", "rfc3339" + timeEncoder: rfc3339nano + # -- For complete snippet-service configuration see [plgd/snippet-service](https://github.com/plgd-dev/hub/tree/main/snippet-service) + apis: + grpc: + address: + sendMsgSize: 4194304 + recvMsgSize: 4194304 + enforcementPolicy: + minTime: 5s + permitWithoutStream: true + keepAlive: + # 0s - means infinity + maxConnectionIdle: 0s + # 0s - means infinity + maxConnectionAge: 0s + # 0s - means infinity + maxConnectionAgeGrace: 0s + time: 2h + timeout: 20s + tls: + caPool: + keyFile: + certFile: + clientCertificateRequired: false + authorization: + ownerClaim: + authority: + audience: + http: + maxIdleConns: 16 + maxConnsPerHost: 32 + maxIdleConnsPerHost: 16 + idleConnTimeout: "30s" + timeout: "10s" + tls: + caPool: + keyFile: + certFile: + useSystemCAPool: true + http: + address: + readTimeout: 8s + readHeaderTimeout: 4s + writeTimeout: 16s + idleTimeout: 30s + clients: + eventBus: + subscriptionID: snippet-service + nats: + url: "" + pendingLimits: + msgLimit: "524288" + bytesLimit: "67108864" + tls: + caPool: + keyFile: + certFile: + useSystemCAPool: false + storage: + use: mongoDB + mongoDB: + uri: + database: snippetService + maxPoolSize: 16 + maxConnIdleTime: 4m0s + tls: + caPool: + keyFile: + certFile: + useSystemCAPool: false + resourceUpdater: + cleanUpExpiredUpdates: "0 * * * *" + grpc: + address: "" + sendMsgSize: 4194304 + recvMsgSize: 4194304 + keepAlive: + time: 10s + timeout: 20s + permitWithoutStream: true + tls: + caPool: + keyFile: + certFile: + useSystemCAPool: false mockoauthserver: oauth: diff --git a/cloud2cloud-gateway/service/retrieveDevice.go b/cloud2cloud-gateway/service/retrieveDevice.go index 36fde2079..7cf16ee97 100644 --- a/cloud2cloud-gateway/service/retrieveDevice.go +++ b/cloud2cloud-gateway/service/retrieveDevice.go @@ -10,13 +10,10 @@ import ( "github.com/gorilla/mux" "github.com/plgd-dev/device/v2/schema" - "github.com/plgd-dev/go-coap/v3/message" pbGRPC "github.com/plgd-dev/hub/v2/grpc-gateway/pb" "github.com/plgd-dev/hub/v2/pkg/log" kitNetHttp "github.com/plgd-dev/hub/v2/pkg/net/http" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" - "github.com/plgd-dev/kit/v2/codec/cbor" - "github.com/plgd-dev/kit/v2/codec/json" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -77,34 +74,10 @@ type Representation struct { } func unmarshalContent(c *commands.Content, m interface{}) error { - switch c.GetContentType() { - case message.AppCBOR.String(), message.AppOcfCbor.String(): - err := cbor.Decode(c.GetData(), m) - if err != nil { - return fmt.Errorf("cannot unmarshal resource content: %w", err) - } - case message.AppJSON.String(): - err := json.Decode(c.GetData(), m) - if err != nil { - return fmt.Errorf("cannot unmarshal resource content: %w", err) - } - case message.TextPlain.String(): - switch v := m.(type) { - case *string: - *v = string(c.GetData()) - case *[]byte: - *v = c.GetData() - case *interface{}: - *v = string(c.GetData()) - default: - return fmt.Errorf("cannot unmarshal resource content: invalid type (%T)", m) - } - case "": + if c.GetContentType() == "" { return nil - default: - return fmt.Errorf("cannot unmarshal resource content: unknown content type (%v)", c.GetContentType()) } - return nil + return commands.DecodeContent(c, m) } func (rh *RequestHandler) RetrieveResources(ctx context.Context, resourceIdFilter []*pbGRPC.ResourceIdFilter, deviceIdFilter []string) (map[string][]Representation, error) { diff --git a/cloud2cloud-gateway/test/test.go b/cloud2cloud-gateway/test/test.go index f9924c0e7..500dbee87 100644 --- a/cloud2cloud-gateway/test/test.go +++ b/cloud2cloud-gateway/test/test.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "net" + "slices" "sync" "testing" "time" @@ -15,7 +16,6 @@ import ( "github.com/plgd-dev/hub/v2/pkg/mongodb" "github.com/plgd-dev/hub/v2/pkg/net/http" "github.com/plgd-dev/hub/v2/pkg/security/certManager/server" - pkgStrings "github.com/plgd-dev/hub/v2/pkg/strings" "github.com/plgd-dev/hub/v2/test/config" testHttp "github.com/plgd-dev/hub/v2/test/http" "github.com/stretchr/testify/require" @@ -38,7 +38,7 @@ func MakeConfig(t require.TestingT) service.Config { cfg.APIs.HTTP.Connection = config.MakeListenerConfig(config.C2C_GW_HOST) cfg.APIs.HTTP.Connection.TLS.ClientCertificateRequired = false - cfg.APIs.HTTP.Authorization = config.MakeAuthorizationConfig() + cfg.APIs.HTTP.Authorization = config.MakeValidatorConfig() cfg.APIs.HTTP.Server = config.MakeHttpServerConfig() cfg.Clients.Eventbus.NATS = config.MakeSubscriberConfig() @@ -98,7 +98,7 @@ func C2CURI(uri string) string { func GetUniqueSubscriptionID(subIDS ...string) string { id := uuid.NewString() for { - if !pkgStrings.Contains(subIDS, id) { + if !slices.Contains(subIDS, id) { break } id = uuid.NewString() diff --git a/coap-gateway/service/clientObserveHandler.go b/coap-gateway/service/clientObserveHandler.go index 00f8d4813..a2f265505 100644 --- a/coap-gateway/service/clientObserveHandler.go +++ b/coap-gateway/service/clientObserveHandler.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "slices" "sync" "sync/atomic" @@ -17,7 +18,6 @@ import ( "github.com/plgd-dev/hub/v2/coap-gateway/service/message" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" "github.com/plgd-dev/hub/v2/grpc-gateway/subscription" - "github.com/plgd-dev/hub/v2/pkg/strings" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" "github.com/plgd-dev/hub/v2/resource-aggregate/events" ) @@ -119,7 +119,7 @@ func (s *resourceSubscription) isDuplicateEvent(ev *events.ResourceChanged) bool func (s *resourceSubscription) eventHandler(e *pb.Event) error { switch { case e.GetResourceUnpublished() != nil: - if !strings.Contains(e.GetResourceUnpublished().GetHrefs(), s.href) { + if !slices.Contains(e.GetResourceUnpublished().GetHrefs(), s.href) { return nil } s.cancelSubscription(coapCodes.ServiceUnavailable) diff --git a/coap-gateway/service/clientSubscriber.go b/coap-gateway/service/clientSubscriber.go index 28d9e8324..cc761724a 100644 --- a/coap-gateway/service/clientSubscriber.go +++ b/coap-gateway/service/clientSubscriber.go @@ -11,6 +11,19 @@ func (c *session) replaceDeviceSubscriber(deviceSubscriber *grpcClient.DeviceSub return s } +func (c *session) getDeviceSubscriber() *grpcClient.DeviceSubscriber { + c.private.mutex.Lock() + defer c.private.mutex.Unlock() + return c.private.deviceSubscriber +} + +func (c *session) triggerDeviceSubscriber() { + deviceSubscriber := c.getDeviceSubscriber() + if deviceSubscriber != nil { + deviceSubscriber.TriggerGetPendingCommands() + } +} + // Replace the deviceSubscriber instance in the client with nil and clean up the previous instance. func (c *session) closeDeviceSubscriber() error { deviceSubscriber := c.replaceDeviceSubscriber(nil) diff --git a/coap-gateway/service/observation/deviceObserver.go b/coap-gateway/service/observation/deviceObserver.go index baaf63218..cd99da812 100644 --- a/coap-gateway/service/observation/deviceObserver.go +++ b/coap-gateway/service/observation/deviceObserver.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net" + "slices" "github.com/plgd-dev/device/v2/schema" "github.com/plgd-dev/device/v2/schema/interfaces" @@ -16,7 +17,6 @@ import ( "github.com/plgd-dev/hub/v2/grpc-gateway/pb" "github.com/plgd-dev/hub/v2/pkg/log" "github.com/plgd-dev/hub/v2/pkg/net/coap" - pkgStrings "github.com/plgd-dev/hub/v2/pkg/strings" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" pbRD "github.com/plgd-dev/hub/v2/resource-directory/pb" "google.golang.org/grpc" @@ -308,7 +308,7 @@ func IsDiscoveryResourceObservable(links schema.ResourceLinks) (bool, error) { return observable, nil } - return pkgStrings.Contains(res.Interfaces, observeInterface), nil + return slices.Contains(res.Interfaces, observeInterface), nil } func detectObservationType(links schema.ResourceLinks) (ObservationType, error) { diff --git a/coap-gateway/service/resourceDirectory.go b/coap-gateway/service/resourceDirectory.go index 61c6a8dcb..6deccec75 100644 --- a/coap-gateway/service/resourceDirectory.go +++ b/coap-gateway/service/resourceDirectory.go @@ -173,6 +173,8 @@ func resourceDirectoryPublishHandler(req *mux.Message, client *session) (*pool.M if errCode, errO := observeResources(req.Context(), client, w, req.Sequence()); errO != nil { return nil, statusErrorf(errCode, "%w", errO) } + // trigger device subscriber to get pending commands for the resources that have been published + client.triggerDeviceSubscriber() accept := coapconv.GetAccept(req.Options()) encode, err := coapconv.GetEncoder(accept) diff --git a/coap-gateway/service/signIn.go b/coap-gateway/service/signIn.go index fcf6ff884..a3b5551c0 100644 --- a/coap-gateway/service/signIn.go +++ b/coap-gateway/service/signIn.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "slices" "time" "github.com/plgd-dev/go-coap/v3/message" @@ -14,7 +15,6 @@ import ( grpcgwClient "github.com/plgd-dev/hub/v2/grpc-gateway/client" "github.com/plgd-dev/hub/v2/identity-store/events" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" - "github.com/plgd-dev/hub/v2/pkg/strings" pkgTime "github.com/plgd-dev/hub/v2/pkg/time" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" "github.com/plgd-dev/kit/v2/codec/cbor" @@ -173,7 +173,7 @@ func subscribeToDeviceEvents(client *session, owner, deviceID string) error { if evt.GetOwner() != owner { return } - if !strings.Contains(evt.GetDeviceIds(), deviceID) { + if !slices.Contains(evt.GetDeviceIds(), deviceID) { return } client.Close() diff --git a/coap-gateway/test/test.go b/coap-gateway/test/test.go index fe78b1527..ad4884ff8 100644 --- a/coap-gateway/test/test.go +++ b/coap-gateway/test/test.go @@ -52,7 +52,7 @@ func MakeConfig(t require.TestingT) service.Config { Config: config.MakeDeviceAuthorization(), }, }, - Authority: config.MakeAuthorizationConfig(), + Authority: config.MakeValidatorConfig(), } cfg.Clients.IdentityStore.Connection = config.MakeGrpcClientConfig(config.IDENTITY_STORE_HOST) cfg.Clients.ResourceAggregate.Connection = config.MakeGrpcClientConfig(config.RESOURCE_AGGREGATE_HOST) diff --git a/dependency/googleapis b/dependency/googleapis index 821a6ddff..7976ffadc 160000 --- a/dependency/googleapis +++ b/dependency/googleapis @@ -1 +1 @@ -Subproject commit 821a6ddff3ab55d2639dc2ca95a07f0e0b957a26 +Subproject commit 7976ffadc0f21ee9149708c0c97ef000e15de1eb diff --git a/go.mod b/go.mod index 0f0702299..4393d4499 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 github.com/hashicorp/go-multierror v1.1.1 + github.com/itchyny/gojq v0.12.16 github.com/jessevdk/go-flags v1.6.1 github.com/json-iterator/go v1.1.12 github.com/jtacoma/uritemplates v1.0.0 @@ -56,6 +57,7 @@ require ( golang.org/x/net v0.26.0 golang.org/x/oauth2 v0.21.0 golang.org/x/sync v0.7.0 + google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 google.golang.org/grpc v1.64.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.4.0 @@ -86,6 +88,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/huandu/xstrings v1.0.0 // indirect github.com/imdario/mergo v0.3.4 // indirect + github.com/itchyny/timefmt-go v0.1.6 // indirect github.com/jhump/protoreflect v1.16.0 // indirect github.com/jonboulle/clockwork v0.4.0 // indirect github.com/klauspost/compress v1.17.9 // indirect @@ -118,7 +121,6 @@ require ( golang.org/x/crypto v0.24.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) diff --git a/go.sum b/go.sum index 6e0c4a23e..0009ba293 100644 --- a/go.sum +++ b/go.sum @@ -143,6 +143,10 @@ github.com/huandu/xstrings v1.0.0 h1:pO2K/gKgKaat5LdpAhxhluX2GPQMaI3W5FUz/I/UnWk github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/imdario/mergo v0.3.4 h1:mKkfHkZWD8dC7WxKx3N9WCF0Y+dLau45704YQmY6H94= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/itchyny/gojq v0.12.16 h1:yLfgLxhIr/6sJNVmYfQjTIv0jGctu6/DgDoivmxTr7g= +github.com/itchyny/gojq v0.12.16/go.mod h1:6abHbdC2uB9ogMS38XsErnfqJ94UlngIJGlRAIj4jTM= +github.com/itchyny/timefmt-go v0.1.6 h1:ia3s54iciXDdzWzwaVKXZPbiXzxxnv1SPGFfM/myJ5Q= +github.com/itchyny/timefmt-go v0.1.6/go.mod h1:RRDZYC5s9ErkjQvTvvU7keJjxUYzIISJGxm9/mAERQg= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4= github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc= diff --git a/grpc-gateway/client/client_test.go b/grpc-gateway/client/client_test.go index 94555f8c9..bfb571a1d 100644 --- a/grpc-gateway/client/client_test.go +++ b/grpc-gateway/client/client_test.go @@ -2,13 +2,9 @@ package client_test import ( "context" - "crypto/tls" - "crypto/x509" - "testing" "github.com/plgd-dev/device/v2/schema/device" "github.com/plgd-dev/go-coap/v3/message" - "github.com/plgd-dev/hub/v2/grpc-gateway/client" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" "github.com/plgd-dev/hub/v2/pkg/net/grpc/server" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" @@ -16,7 +12,6 @@ import ( "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" "github.com/plgd-dev/kit/v2/codec/cbor" - "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -26,22 +21,6 @@ const ( TestManufacturer = "Test Manufacturer" ) -func NewTestClient(t *testing.T) *client.Client { - rootCAs := x509.NewCertPool() - for _, c := range test.GetRootCertificateAuthorities(t) { - rootCAs.AddCert(c) - } - tlsCfg := tls.Config{ - RootCAs: rootCAs, - } - clientConfig := client.Config{ - GatewayAddress: config.GRPC_GW_HOST, - } - c, err := client.NewFromConfig(&clientConfig, &tlsCfg) - require.NoError(t, err) - return c -} - func NewGateway(addr string) (*server.Server, error) { s, err := server.NewServer(addr) if err != nil { diff --git a/grpc-gateway/client/createResource_test.go b/grpc-gateway/client/createResource_test.go index aad482a4c..745e73b7e 100644 --- a/grpc-gateway/client/createResource_test.go +++ b/grpc-gateway/client/createResource_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/plgd-dev/device/v2/schema/device" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" @@ -67,7 +68,7 @@ func TestClient_CreateResource(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) diff --git a/grpc-gateway/client/deleteResource_test.go b/grpc-gateway/client/deleteResource_test.go index 9dbc20918..3d53a7fbc 100644 --- a/grpc-gateway/client/deleteResource_test.go +++ b/grpc-gateway/client/deleteResource_test.go @@ -10,6 +10,7 @@ import ( "github.com/plgd-dev/device/v2/schema/resources" "github.com/plgd-dev/hub/v2/grpc-gateway/client" extCodes "github.com/plgd-dev/hub/v2/grpc-gateway/pb/codes" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" @@ -83,7 +84,7 @@ func TestClientDeleteResource(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) @@ -172,7 +173,7 @@ func TestClientBatchDeleteResource(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) diff --git a/grpc-gateway/client/deviceSubscriber.go b/grpc-gateway/client/deviceSubscriber.go index 23e76688a..a59bde07f 100644 --- a/grpc-gateway/client/deviceSubscriber.go +++ b/grpc-gateway/client/deviceSubscriber.go @@ -266,6 +266,14 @@ func (s *DeviceSubscriber) triggerReconnect() { } } +func (s *DeviceSubscriber) TriggerGetPendingCommands() { + select { + case <-s.done: + case s.reconnectChan <- true: + default: + } +} + func (s *DeviceSubscriber) reconnect() { for { var wantToSetPendingCommandsHandler bool diff --git a/grpc-gateway/client/deviceSubscriptions_test.go b/grpc-gateway/client/deviceSubscriptions_test.go index 069fca867..ee672927b 100644 --- a/grpc-gateway/client/deviceSubscriptions_test.go +++ b/grpc-gateway/client/deviceSubscriptions_test.go @@ -9,6 +9,7 @@ import ( "github.com/plgd-dev/device/v2/schema/platform" "github.com/plgd-dev/go-coap/v3/message" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" "github.com/plgd-dev/hub/v2/pkg/fsnotify" "github.com/plgd-dev/hub/v2/pkg/log" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" @@ -82,7 +83,7 @@ func TestObserveDeviceResourcesRetrieve(t *testing.T) { }() rac := raservice.NewResourceAggregateClient(raConn.GRPC()) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { errC := c.Close() require.NoError(t, errC) @@ -177,7 +178,7 @@ func TestObserveDeviceResourcesUpdate(t *testing.T) { }() rac := raservice.NewResourceAggregateClient(raConn.GRPC()) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { errC := c.Close() require.NoError(t, errC) @@ -306,7 +307,7 @@ func TestObserveDeviceResourcesCreateAndDelete(t *testing.T) { }() rac := raservice.NewResourceAggregateClient(raConn.GRPC()) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { errC := c.Close() require.NoError(t, errC) diff --git a/grpc-gateway/client/getDevice_test.go b/grpc-gateway/client/getDevice_test.go index 525d5f517..28399270f 100644 --- a/grpc-gateway/client/getDevice_test.go +++ b/grpc-gateway/client/getDevice_test.go @@ -10,6 +10,7 @@ import ( "github.com/plgd-dev/device/v2/test/resource/types" "github.com/plgd-dev/hub/v2/grpc-gateway/client" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" test "github.com/plgd-dev/hub/v2/test" @@ -92,7 +93,7 @@ func TestClient_GetDevice(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) diff --git a/grpc-gateway/client/getDevices_test.go b/grpc-gateway/client/getDevices_test.go index e92774ab1..546bc7eb5 100644 --- a/grpc-gateway/client/getDevices_test.go +++ b/grpc-gateway/client/getDevices_test.go @@ -6,6 +6,7 @@ import ( "time" "github.com/plgd-dev/hub/v2/grpc-gateway/client" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" test "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" @@ -69,7 +70,7 @@ func TestClient_GetDevices(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) diff --git a/grpc-gateway/client/getResource_test.go b/grpc-gateway/client/getResource_test.go index 6131789f8..2467f73ab 100644 --- a/grpc-gateway/client/getResource_test.go +++ b/grpc-gateway/client/getResource_test.go @@ -8,6 +8,7 @@ import ( "github.com/plgd-dev/device/v2/schema/configuration" "github.com/plgd-dev/device/v2/schema/interfaces" "github.com/plgd-dev/hub/v2/grpc-gateway/client" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" @@ -100,7 +101,7 @@ func TestClientGetResource(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) diff --git a/grpc-gateway/client/maintenance.go b/grpc-gateway/client/maintenance.go index 088ee18ec..1201aa0cc 100644 --- a/grpc-gateway/client/maintenance.go +++ b/grpc-gateway/client/maintenance.go @@ -3,10 +3,10 @@ package client import ( "context" "net/http" + "slices" "github.com/plgd-dev/device/v2/schema/maintenance" "github.com/plgd-dev/hub/v2/pkg/net/grpc" - "github.com/plgd-dev/hub/v2/pkg/strings" "github.com/plgd-dev/hub/v2/resource-aggregate/events" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -65,7 +65,7 @@ func (c *Client) updateMaintenanceResource( } var href string for _, r := range v.GetResources() { - if r.GetDeviceId() == deviceID && strings.Contains(r.GetResourceTypes(), maintenance.ResourceType) { + if r.GetDeviceId() == deviceID && slices.Contains(r.GetResourceTypes(), maintenance.ResourceType) { href = r.GetHref() break } diff --git a/grpc-gateway/client/maintenance_test.go b/grpc-gateway/client/maintenance_test.go index 7256a3b0e..6ec137392 100644 --- a/grpc-gateway/client/maintenance_test.go +++ b/grpc-gateway/client/maintenance_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" test "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" @@ -50,7 +51,7 @@ func TestClientFactoryReset(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) @@ -104,7 +105,7 @@ func TestClientReboot(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) diff --git a/grpc-gateway/client/observeDeviceResources_test.go b/grpc-gateway/client/observeDeviceResources_test.go index 9a05ff6a8..0c29b82c7 100644 --- a/grpc-gateway/client/observeDeviceResources_test.go +++ b/grpc-gateway/client/observeDeviceResources_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/resource-aggregate/events" test "github.com/plgd-dev/hub/v2/test" @@ -24,7 +25,7 @@ func TestObserveDeviceResourcesPublish(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) diff --git a/grpc-gateway/client/observeDevices_test.go b/grpc-gateway/client/observeDevices_test.go index 6f32642a2..964bcf8cc 100644 --- a/grpc-gateway/client/observeDevices_test.go +++ b/grpc-gateway/client/observeDevices_test.go @@ -7,6 +7,7 @@ import ( "testing" client "github.com/plgd-dev/hub/v2/grpc-gateway/client" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" @@ -23,7 +24,7 @@ func TestObserveDevices(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) diff --git a/grpc-gateway/client/observeResource_test.go b/grpc-gateway/client/observeResource_test.go index cdeaca197..1e7e81c4b 100644 --- a/grpc-gateway/client/observeResource_test.go +++ b/grpc-gateway/client/observeResource_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/plgd-dev/device/v2/schema/configuration" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" @@ -25,7 +26,7 @@ func TestObservingResource(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { errC := c.Close() require.NoError(t, errC) diff --git a/grpc-gateway/client/updateResource_test.go b/grpc-gateway/client/updateResource_test.go index f77e1e8f9..e2a69ae1f 100644 --- a/grpc-gateway/client/updateResource_test.go +++ b/grpc-gateway/client/updateResource_test.go @@ -8,6 +8,7 @@ import ( "github.com/plgd-dev/device/v2/schema/configuration" "github.com/plgd-dev/device/v2/schema/interfaces" "github.com/plgd-dev/hub/v2/grpc-gateway/client" + grpcgwTest "github.com/plgd-dev/hub/v2/grpc-gateway/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" @@ -94,7 +95,7 @@ func TestClientUpdateResource(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { errC := c.Close() require.NoError(t, errC) @@ -131,7 +132,7 @@ func TestUpdateConfigurationName(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - c := NewTestClient(t) + c := grpcgwTest.NewTestClient(t) defer func() { err := c.Close() require.NoError(t, err) diff --git a/grpc-gateway/pb/README.md b/grpc-gateway/pb/README.md index e4b6b1c72..086a6ba58 100644 --- a/grpc-gateway/pb/README.md +++ b/grpc-gateway/pb/README.md @@ -223,6 +223,8 @@ | resource_id | [resourceaggregate.pb.ResourceId](#resourceaggregate-pb-ResourceId) | | | | content | [Content](#grpcgateway-pb-Content) | | | | time_to_live | [int64](#int64) | | command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms). | +| force | [bool](#bool) | | if true, the command will be executed even if the resource does not exist | +| async | [bool](#bool) | | if true, the command will finish immediately after pending event is created | @@ -285,6 +287,8 @@ | resource_id | [resourceaggregate.pb.ResourceId](#resourceaggregate-pb-ResourceId) | | | | time_to_live | [int64](#int64) | | command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms). | | resource_interface | [string](#string) | | | +| force | [bool](#bool) | | if true, the command will be executed even if the resource does not exist | +| async | [bool](#bool) | | if true, the command will finish immediately after pending event is created | @@ -695,6 +699,8 @@ Certain filters perform a logical "or" operation among the elements of t | resource_interface | [string](#string) | | | | time_to_live | [int64](#int64) | | command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms). | | content | [Content](#grpcgateway-pb-Content) | | | +| force | [bool](#bool) | | if true, the command will be executed even if the resource does not exist | +| async | [bool](#bool) | | if true, the command will finish immediately after pending event is created | @@ -905,6 +911,7 @@ Certain filters perform a logical "or" operation among the elements of t | device_id_filter | [string](#string) | repeated | | | type_filter | [string](#string) | repeated | | | resource_id_filter | [ResourceIdFilter](#grpcgateway-pb-ResourceIdFilter) | repeated | New resource ID filter. For HTTP requests, use it multiple times as a query parameter like "resourceIdFilter={deviceID}{href}". | +| include_hidden_resources | [bool](#bool) | | Get all pending commands for all resources, even if the resource is not published. | @@ -1050,6 +1057,7 @@ UI configuration | ----- | ---- | ----- | ----------- | | visibility | [UIVisibility](#grpcgateway-pb-UIVisibility) | | | | device_provisioning_service | [string](#string) | | Address to device provisioning service HTTP API in format https://host:port | +| snippet_service | [string](#string) | | Address to snippet service HTTP API in format https://host:port | diff --git a/grpc-gateway/pb/createResource.go b/grpc-gateway/pb/createResource.go index 68476c13c..6de21b418 100644 --- a/grpc-gateway/pb/createResource.go +++ b/grpc-gateway/pb/createResource.go @@ -5,6 +5,7 @@ import ( "github.com/google/uuid" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" + "github.com/plgd-dev/hub/v2/resource-aggregate/events" "google.golang.org/grpc/peer" ) @@ -35,5 +36,13 @@ func (req *CreateResourceRequest) ToRACommand(ctx context.Context) (*commands.Cr CommandMetadata: &commands.CommandMetadata{ ConnectionId: connectionID, }, + Force: req.GetForce(), }, nil } + +func (x *CreateResourceResponse) SetData(data *events.ResourceCreated) { + if x == nil { + return + } + x.Data = data +} diff --git a/grpc-gateway/pb/deleteResource.go b/grpc-gateway/pb/deleteResource.go index db1b5e557..a632fda2d 100644 --- a/grpc-gateway/pb/deleteResource.go +++ b/grpc-gateway/pb/deleteResource.go @@ -5,6 +5,7 @@ import ( "github.com/google/uuid" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" + "github.com/plgd-dev/hub/v2/resource-aggregate/events" "google.golang.org/grpc/peer" ) @@ -30,5 +31,13 @@ func (req *DeleteResourceRequest) ToRACommand(ctx context.Context) (*commands.De ConnectionId: connectionID, }, ResourceInterface: req.GetResourceInterface(), + Force: req.GetForce(), }, nil } + +func (x *DeleteResourceResponse) SetData(data *events.ResourceDeleted) { + if x == nil { + return + } + x.Data = data +} diff --git a/grpc-gateway/pb/devices.pb.go b/grpc-gateway/pb/devices.pb.go index 49f7d3df8..8c27f6cd0 100644 --- a/grpc-gateway/pb/devices.pb.go +++ b/grpc-gateway/pb/devices.pb.go @@ -781,6 +781,8 @@ type UpdateResourceRequest struct { ResourceInterface string `protobuf:"bytes,3,opt,name=resource_interface,json=resourceInterface,proto3" json:"resource_interface,omitempty"` TimeToLive int64 `protobuf:"varint,4,opt,name=time_to_live,json=timeToLive,proto3" json:"time_to_live,omitempty"` // command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms). Content *Content `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` + Force bool `protobuf:"varint,5,opt,name=force,proto3" json:"force,omitempty"` // if true, the command will be executed even if the resource does not exist + Async bool `protobuf:"varint,6,opt,name=async,proto3" json:"async,omitempty"` // if true, the command will finish immediately after pending event is created } func (x *UpdateResourceRequest) Reset() { @@ -843,6 +845,20 @@ func (x *UpdateResourceRequest) GetContent() *Content { return nil } +func (x *UpdateResourceRequest) GetForce() bool { + if x != nil { + return x.Force + } + return false +} + +func (x *UpdateResourceRequest) GetAsync() bool { + if x != nil { + return x.Async + } + return false +} + type UpdateResourceResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1533,6 +1549,8 @@ type DeleteResourceRequest struct { ResourceId *commands.ResourceId `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` TimeToLive int64 `protobuf:"varint,2,opt,name=time_to_live,json=timeToLive,proto3" json:"time_to_live,omitempty"` // command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms). ResourceInterface string `protobuf:"bytes,3,opt,name=resource_interface,json=resourceInterface,proto3" json:"resource_interface,omitempty"` + Force bool `protobuf:"varint,4,opt,name=force,proto3" json:"force,omitempty"` // if true, the command will be executed even if the resource does not exist + Async bool `protobuf:"varint,5,opt,name=async,proto3" json:"async,omitempty"` // if true, the command will finish immediately after pending event is created } func (x *DeleteResourceRequest) Reset() { @@ -1588,6 +1606,20 @@ func (x *DeleteResourceRequest) GetResourceInterface() string { return "" } +func (x *DeleteResourceRequest) GetForce() bool { + if x != nil { + return x.Force + } + return false +} + +func (x *DeleteResourceRequest) GetAsync() bool { + if x != nil { + return x.Async + } + return false +} + type DeleteResourceResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1643,6 +1675,8 @@ type CreateResourceRequest struct { ResourceId *commands.ResourceId `protobuf:"bytes,1,opt,name=resource_id,json=resourceId,proto3" json:"resource_id,omitempty"` Content *Content `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` TimeToLive int64 `protobuf:"varint,3,opt,name=time_to_live,json=timeToLive,proto3" json:"time_to_live,omitempty"` // command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms). + Force bool `protobuf:"varint,4,opt,name=force,proto3" json:"force,omitempty"` // if true, the command will be executed even if the resource does not exist + Async bool `protobuf:"varint,5,opt,name=async,proto3" json:"async,omitempty"` // if true, the command will finish immediately after pending event is created } func (x *CreateResourceRequest) Reset() { @@ -1698,6 +1732,20 @@ func (x *CreateResourceRequest) GetTimeToLive() int64 { return 0 } +func (x *CreateResourceRequest) GetForce() bool { + if x != nil { + return x.Force + } + return false +} + +func (x *CreateResourceRequest) GetAsync() bool { + if x != nil { + return x.Async + } + return false +} + type CreateResourceResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2309,7 +2357,7 @@ var file_grpc_gateway_pb_devices_proto_rawDesc = []byte{ 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, - 0x22, 0xde, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x22, 0x8a, 0x02, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, @@ -2323,341 +2371,349 @@ var file_grpc_gateway_pb_devices_proto_rawDesc = []byte{ 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x22, 0x53, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xa6, 0x08, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x54, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x67, 0x0a, 0x13, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x54, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x48, - 0x00, 0x52, 0x12, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x67, 0x0a, 0x13, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5f, - 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x54, 0x6f, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x79, 0x6e, 0x63, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x22, 0x53, 0x0a, + 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x22, 0xa6, 0x08, 0x0a, 0x11, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x54, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x67, 0x0a, 0x13, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x54, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x12, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x67, 0x0a, 0x13, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x54, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x12, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, + 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x65, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x1a, 0xce, 0x05, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5d, 0x0a, 0x0c, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x3a, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, + 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x54, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x12, 0x39, 0x0a, 0x17, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x14, 0x68, 0x74, 0x74, 0x70, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, + 0x68, 0x72, 0x65, 0x66, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0a, 0x68, 0x72, 0x65, 0x66, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x4e, 0x0a, + 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x10, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x82, 0x03, + 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x0a, 0x52, 0x45, 0x47, 0x49, 0x53, + 0x54, 0x45, 0x52, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x55, 0x4e, 0x52, 0x45, 0x47, + 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x45, 0x56, + 0x49, 0x43, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x55, 0x50, 0x44, + 0x41, 0x54, 0x45, 0x44, 0x10, 0x04, 0x12, 0x22, 0x0a, 0x1e, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, + 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, + 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, + 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x45, 0x44, + 0x10, 0x06, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, + 0x4e, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x07, 0x12, 0x1b, 0x0a, 0x17, + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, + 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x08, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x53, + 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, 0x10, 0x09, 0x12, + 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x52, 0x45, 0x54, 0x52, + 0x49, 0x45, 0x56, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x0a, 0x12, 0x16, + 0x0a, 0x12, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x52, 0x45, 0x54, 0x52, 0x49, + 0x45, 0x56, 0x45, 0x44, 0x10, 0x0b, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, + 0x43, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, + 0x47, 0x10, 0x0c, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, + 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x0d, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x53, + 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e, + 0x44, 0x49, 0x4e, 0x47, 0x10, 0x0e, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, + 0x43, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x0f, 0x12, 0x14, 0x0a, 0x10, + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x44, + 0x10, 0x10, 0x1a, 0x3d, 0x0a, 0x12, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x62, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x42, 0x08, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x85, 0x15, 0x0a, 0x05, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x65, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x1a, 0xce, 0x05, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5d, 0x0a, 0x0c, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0e, 0x32, 0x3a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x54, 0x6f, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x0b, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x10, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, - 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x17, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x14, 0x68, 0x74, 0x74, 0x70, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x72, 0x65, 0x66, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, - 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x72, 0x65, 0x66, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x12, 0x4e, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, - 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x22, 0x82, 0x03, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x0a, 0x52, - 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x55, - 0x4e, 0x52, 0x45, 0x47, 0x49, 0x53, 0x54, 0x45, 0x52, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1b, 0x0a, - 0x17, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, - 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x44, 0x10, 0x04, 0x12, 0x22, 0x0a, 0x1e, 0x44, 0x45, - 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x55, 0x50, - 0x44, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x16, - 0x0a, 0x12, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x50, 0x55, 0x42, 0x4c, 0x49, - 0x53, 0x48, 0x45, 0x44, 0x10, 0x06, 0x12, 0x18, 0x0a, 0x14, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x55, 0x4e, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x07, - 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x50, 0x44, - 0x41, 0x54, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x08, 0x12, 0x14, 0x0a, - 0x10, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, - 0x44, 0x10, 0x09, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, - 0x52, 0x45, 0x54, 0x52, 0x49, 0x45, 0x56, 0x45, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, - 0x10, 0x0a, 0x12, 0x16, 0x0a, 0x12, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x52, - 0x45, 0x54, 0x52, 0x49, 0x45, 0x56, 0x45, 0x44, 0x10, 0x0b, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x45, - 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x5f, 0x50, 0x45, - 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x0c, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x53, 0x4f, 0x55, - 0x52, 0x43, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x44, 0x10, 0x0d, 0x12, 0x1b, 0x0a, - 0x17, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, - 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x0e, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, - 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x0f, - 0x12, 0x14, 0x0a, 0x10, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43, 0x48, 0x41, - 0x4e, 0x47, 0x45, 0x44, 0x10, 0x10, 0x1a, 0x3d, 0x0a, 0x12, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, - 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x08, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x85, 0x15, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x55, 0x0a, 0x11, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, - 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x48, 0x00, 0x52, 0x10, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, - 0x12, 0x5b, 0x0a, 0x13, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x6e, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x72, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x48, 0x00, 0x52, 0x12, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, 0x5d, 0x0a, - 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, - 0x68, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x50, 0x75, - 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x48, 0x00, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x63, 0x0a, 0x14, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x6e, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x73, 0x68, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x55, - 0x6e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x48, 0x00, 0x52, 0x13, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x6e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, - 0x64, 0x12, 0x52, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x5b, 0x0a, 0x13, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x48, 0x00, 0x52, 0x12, - 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x65, 0x64, 0x12, 0x61, 0x0a, 0x15, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, - 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, - 0x14, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x6e, - 0x63, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x52, 0x0a, 0x10, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, - 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x12, 0x6b, 0x0a, 0x19, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x74, - 0x72, 0x69, 0x65, 0x76, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x0e, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x48, 0x00, 0x52, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, - 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x58, 0x0a, - 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, - 0x76, 0x65, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, - 0x65, 0x64, 0x48, 0x00, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, - 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x12, 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x52, - 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x48, - 0x00, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x12, 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x48, 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x52, 0x0a, 0x10, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x13, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x78, 0x0a, - 0x1e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, - 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x1b, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x65, 0x0a, 0x17, 0x64, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x15, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x1a, 0xba, - 0x02, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, - 0x64, 0x73, 0x12, 0x46, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x76, 0x0a, 0x16, 0x6f, 0x70, - 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, - 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, - 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, - 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, - 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xbe, 0x02, 0x0a, 0x12, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, - 0x73, 0x12, 0x46, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x74, 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x78, 0x0a, 0x16, 0x6f, 0x70, 0x65, - 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, - 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x55, 0x0a, 0x11, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x26, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, + 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x48, 0x00, 0x52, 0x10, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, 0x5b, 0x0a, 0x13, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x75, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, - 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, - 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, - 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, - 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x90, 0x02, 0x0a, - 0x12, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, - 0x73, 0x65, 0x64, 0x12, 0x57, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, - 0x73, 0x65, 0x64, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x0b, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0xa0, 0x01, 0x0a, - 0x0b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4d, 0x0a, 0x04, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, - 0x73, 0x73, 0x65, 0x64, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x28, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x06, 0x0a, - 0x02, 0x4f, 0x4b, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, - 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x1a, - 0x2e, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, - 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x43, 0x0a, 0x0f, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, - 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, - 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x93, 0x06, 0x0a, - 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4c, - 0x0a, 0x11, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x6d, 0x61, 0x6e, 0x75, - 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, - 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, - 0x1e, 0x0a, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, - 0x36, 0x0a, 0x17, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, - 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x15, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x70, 0x65, - 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x72, 0x65, 0x64, 0x48, 0x00, 0x52, 0x12, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x55, 0x6e, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, 0x5d, 0x0a, 0x12, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x51, 0x0a, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x0f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x53, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x73, 0x1a, 0xd3, 0x01, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x40, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x14, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x29, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, - 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x74, 0x77, 0x69, - 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x47, 0x0a, 0x0f, 0x4f, 0x77, 0x6e, - 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, - 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4f, - 0x57, 0x4e, 0x45, 0x44, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x57, 0x4e, 0x45, 0x44, 0x10, - 0x02, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x55, 0x50, 0x50, 0x4f, 0x52, 0x54, 0x45, 0x44, - 0x10, 0x03, 0x22, 0x40, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, - 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x22, 0xab, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, - 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, - 0x69, 0x76, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x22, 0x53, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x64, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xaf, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, + 0x68, 0x65, 0x64, 0x48, 0x00, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, + 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x63, 0x0a, 0x14, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x6e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, - 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, - 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x22, 0x53, 0x0a, 0x16, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x73, 0x55, 0x6e, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x48, 0x00, 0x52, 0x13, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x55, 0x6e, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x52, 0x0a, + 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x48, 0x00, + 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x64, 0x12, 0x5b, 0x0a, 0x13, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x48, 0x00, 0x52, 0x12, 0x6f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x12, 0x61, + 0x0a, 0x15, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x48, 0x00, 0x52, 0x14, 0x73, 0x75, 0x62, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, + 0x64, 0x12, 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, + 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x52, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x6b, 0x0a, 0x19, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, + 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, + 0x52, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, + 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x58, 0x0a, 0x12, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x48, 0x00, + 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, + 0x76, 0x65, 0x64, 0x12, 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x10, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x48, 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x52, 0x0a, 0x10, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x11, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x65, + 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x15, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x52, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x78, 0x0a, 0x1e, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x14, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x31, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x1b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x12, 0x65, 0x0a, 0x17, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x15, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x64, 0x48, 0x00, 0x52, 0x15, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x1a, 0xba, 0x02, 0x0a, 0x10, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, 0x12, 0x46, + 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x76, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, + 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x2e, 0x4f, + 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, + 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, + 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, + 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, + 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0xbe, 0x02, 0x0a, 0x12, 0x44, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, 0x12, 0x46, 0x0a, + 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x78, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, + 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, + 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x55, 0x6e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0x2e, + 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, + 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, + 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, + 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x90, 0x02, 0x0a, 0x12, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x12, + 0x57, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, 0x2e, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x0b, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0xa0, 0x01, 0x0a, 0x0b, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x4d, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x65, 0x64, + 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x43, 0x6f, 0x64, + 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x22, 0x28, 0x0a, 0x04, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, + 0x00, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, + 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x1a, 0x2e, 0x0a, 0x14, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x22, 0x43, 0x0a, 0x0f, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, + 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x93, 0x06, 0x0a, 0x06, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x05, 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, + 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, + 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x4c, 0x0a, 0x11, 0x6d, 0x61, + 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x10, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, + 0x75, 0x72, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x6f, 0x64, 0x65, + 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x49, 0x6e, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, + 0x74, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x42, 0x2f, - 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6c, 0x67, - 0x64, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x76, 0x32, 0x2f, 0x67, 0x72, 0x70, - 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x70, 0x62, 0x3b, 0x70, 0x62, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x51, + 0x0a, 0x10, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x2e, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x0f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x0b, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, + 0xd3, 0x01, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x40, 0x0a, 0x0a, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, + 0x0a, 0x14, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x74, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, + 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, + 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4a, + 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0x47, 0x0a, 0x0f, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, + 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4f, 0x57, 0x4e, 0x45, 0x44, + 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x57, 0x4e, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0f, 0x0a, + 0x0b, 0x55, 0x4e, 0x53, 0x55, 0x50, 0x50, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x40, + 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x22, 0xd7, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x20, 0x0a, + 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, + 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x14, + 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, + 0x6f, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x22, 0x53, 0x0a, 0x16, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, + 0xdb, 0x01, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, + 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x31, 0x0a, 0x07, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, + 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x79, 0x6e, 0x63, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x73, 0x79, 0x6e, 0x63, 0x22, 0x53, 0x0a, + 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x70, 0x6c, 0x67, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x76, 0x32, + 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x70, 0x62, + 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/grpc-gateway/pb/devices.proto b/grpc-gateway/pb/devices.proto index 54acada11..19fbe585e 100644 --- a/grpc-gateway/pb/devices.proto +++ b/grpc-gateway/pb/devices.proto @@ -67,6 +67,8 @@ message UpdateResourceRequest { string resource_interface = 3; int64 time_to_live = 4; // command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms). Content content = 2; + bool force = 5; // if true, the command will be executed even if the resource does not exist + bool async = 6; // if true, the command will finish immediately after pending event is created } message UpdateResourceResponse { @@ -220,6 +222,8 @@ message DeleteResourceRequest { resourceaggregate.pb.ResourceId resource_id = 1; int64 time_to_live = 2; // command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms). string resource_interface = 3; + bool force = 4; // if true, the command will be executed even if the resource does not exist + bool async = 5; // if true, the command will finish immediately after pending event is created } message DeleteResourceResponse { @@ -230,6 +234,8 @@ message CreateResourceRequest { resourceaggregate.pb.ResourceId resource_id = 1; Content content = 2; int64 time_to_live = 3; // command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms). + bool force = 4; // if true, the command will be executed even if the resource does not exist + bool async = 5; // if true, the command will finish immediately after pending event is created } message CreateResourceResponse { diff --git a/grpc-gateway/pb/doc.html b/grpc-gateway/pb/doc.html index 5c2af8ccb..05126e27f 100644 --- a/grpc-gateway/pb/doc.html +++ b/grpc-gateway/pb/doc.html @@ -841,6 +841,20 @@

CreateResourceRequest

command validity in nanoseconds. 0 means forever and minimal value is 100000000 (100ms).

+ + force + bool + +

if true, the command will be executed even if the resource does not exist

+ + + + async + bool + +

if true, the command will finish immediately after pending event is created

+ + @@ -951,6 +965,20 @@

DeleteResourceRequest

+ + force + bool + +

if true, the command will be executed even if the resource does not exist

+ + + + async + bool + +

if true, the command will finish immediately after pending event is created

+ + @@ -1951,6 +1979,20 @@

UpdateResourceRequest

+ + force + bool + +

if true, the command will be executed even if the resource does not exist

+ + + + async + bool + +

if true, the command will finish immediately after pending event is created

+ + @@ -2483,6 +2525,13 @@

GetPendingCommandsRequest

New resource ID filter. For HTTP requests, use it multiple times as a query parameter like "resourceIdFilter={deviceID}{href}".

+ + include_hidden_resources + bool + +

Get all pending commands for all resources, even if the resource is not published.

+ + @@ -2889,6 +2938,13 @@

UIConfiguration

Address to device provisioning service HTTP API in format https://host:port

+ + snippet_service + string + +

Address to snippet service HTTP API in format https://host:port

+ + diff --git a/grpc-gateway/pb/getPendingCommands.pb.go b/grpc-gateway/pb/getPendingCommands.pb.go index 65363c8a9..ba2113eac 100644 --- a/grpc-gateway/pb/getPendingCommands.pb.go +++ b/grpc-gateway/pb/getPendingCommands.pb.go @@ -83,10 +83,11 @@ type GetPendingCommandsRequest struct { CommandFilter []GetPendingCommandsRequest_Command `protobuf:"varint,1,rep,packed,name=command_filter,json=commandFilter,proto3,enum=grpcgateway.pb.GetPendingCommandsRequest_Command" json:"command_filter,omitempty"` // Deprecated: Marked as deprecated in grpc-gateway/pb/getPendingCommands.proto. - HttpResourceIdFilter []string `protobuf:"bytes,2,rep,name=http_resource_id_filter,json=httpResourceIdFilter,proto3" json:"http_resource_id_filter,omitempty"` - DeviceIdFilter []string `protobuf:"bytes,3,rep,name=device_id_filter,json=deviceIdFilter,proto3" json:"device_id_filter,omitempty"` - TypeFilter []string `protobuf:"bytes,4,rep,name=type_filter,json=typeFilter,proto3" json:"type_filter,omitempty"` - ResourceIdFilter []*ResourceIdFilter `protobuf:"bytes,5,rep,name=resource_id_filter,json=resourceIdFilter,proto3" json:"resource_id_filter,omitempty"` // New resource ID filter. For HTTP requests, use it multiple times as a query parameter like "resourceIdFilter={deviceID}{href}". + HttpResourceIdFilter []string `protobuf:"bytes,2,rep,name=http_resource_id_filter,json=httpResourceIdFilter,proto3" json:"http_resource_id_filter,omitempty"` + DeviceIdFilter []string `protobuf:"bytes,3,rep,name=device_id_filter,json=deviceIdFilter,proto3" json:"device_id_filter,omitempty"` + TypeFilter []string `protobuf:"bytes,4,rep,name=type_filter,json=typeFilter,proto3" json:"type_filter,omitempty"` + ResourceIdFilter []*ResourceIdFilter `protobuf:"bytes,5,rep,name=resource_id_filter,json=resourceIdFilter,proto3" json:"resource_id_filter,omitempty"` // New resource ID filter. For HTTP requests, use it multiple times as a query parameter like "resourceIdFilter={deviceID}{href}". + IncludeHiddenResources bool `protobuf:"varint,6,opt,name=include_hidden_resources,json=includeHiddenResources,proto3" json:"include_hidden_resources,omitempty"` // Get all pending commands for all resources, even if the resource is not published. } func (x *GetPendingCommandsRequest) Reset() { @@ -157,6 +158,13 @@ func (x *GetPendingCommandsRequest) GetResourceIdFilter() []*ResourceIdFilter { return nil } +func (x *GetPendingCommandsRequest) GetIncludeHiddenResources() bool { + if x != nil { + return x.IncludeHiddenResources + } + return false +} + type PendingCommand struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -290,7 +298,7 @@ var file_grpc_gateway_pb_getPendingCommands_proto_rawDesc = []byte{ 0x75, 0x72, 0x63, 0x65, 0x2d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2f, 0x70, 0x62, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x70, 0x62, 0x2f, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc8, 0x03, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x82, 0x04, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x58, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, @@ -311,54 +319,58 @@ var file_grpc_gateway_pb_getPendingCommands_proto_rawDesc = []byte{ 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x07, 0x43, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, - 0x43, 0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, - 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x52, 0x45, 0x54, 0x52, 0x49, 0x45, 0x56, 0x45, - 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, - 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x53, 0x4f, 0x55, - 0x52, 0x43, 0x45, 0x5f, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, - 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, - 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, 0x04, 0x22, 0xb7, 0x04, 0x0a, 0x0e, 0x50, 0x65, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x65, 0x0a, 0x17, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x70, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x12, 0x6b, 0x0a, 0x19, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, - 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, - 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, - 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x78, 0x0a, - 0x1e, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x1b, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x70, 0x6c, 0x67, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x76, 0x32, - 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x70, 0x62, - 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x63, 0x65, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x38, 0x0a, 0x18, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x5f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x48, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x7b, 0x0a, 0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x43, 0x52, 0x45, + 0x41, 0x54, 0x45, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, + 0x45, 0x5f, 0x52, 0x45, 0x54, 0x52, 0x49, 0x45, 0x56, 0x45, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, + 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x10, + 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x52, 0x45, 0x53, 0x4f, 0x55, 0x52, 0x43, 0x45, 0x5f, 0x44, 0x45, + 0x4c, 0x45, 0x54, 0x45, 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, + 0x5f, 0x4d, 0x45, 0x54, 0x41, 0x44, 0x41, 0x54, 0x41, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, + 0x10, 0x04, 0x22, 0xb7, 0x04, 0x0a, 0x0e, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x6b, 0x0a, 0x19, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, + 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x2d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, + 0x52, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, + 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, + 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x12, 0x65, 0x0a, 0x17, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x00, + 0x52, 0x15, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x78, 0x0a, 0x1e, 0x64, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x31, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x48, 0x00, 0x52, 0x1b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x42, 0x2f, 0x5a, 0x2d, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6c, 0x67, 0x64, 0x2d, + 0x64, 0x65, 0x76, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x76, 0x32, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, + 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x70, 0x62, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/grpc-gateway/pb/getPendingCommands.proto b/grpc-gateway/pb/getPendingCommands.proto index a2fb881ee..f0f57c9b9 100644 --- a/grpc-gateway/pb/getPendingCommands.proto +++ b/grpc-gateway/pb/getPendingCommands.proto @@ -20,6 +20,7 @@ message GetPendingCommandsRequest { repeated string device_id_filter = 3; repeated string type_filter = 4; repeated ResourceIdFilter resource_id_filter = 5; // New resource ID filter. For HTTP requests, use it multiple times as a query parameter like "resourceIdFilter={deviceID}{href}". + bool include_hidden_resources = 6; // Get all pending commands for all resources, even if the resource is not published. } message PendingCommand { diff --git a/grpc-gateway/pb/hubConfiguration.pb.go b/grpc-gateway/pb/hubConfiguration.pb.go index 67304d6e9..229b6be6f 100644 --- a/grpc-gateway/pb/hubConfiguration.pb.go +++ b/grpc-gateway/pb/hubConfiguration.pb.go @@ -66,7 +66,7 @@ type OAuthClient struct { ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty" yaml:"clientID"` // @gotags: yaml:"clientID" Audience string `protobuf:"bytes,2,opt,name=audience,proto3" json:"audience,omitempty"` Scopes []string `protobuf:"bytes,3,rep,name=scopes,proto3" json:"scopes,omitempty"` - ProviderName string `protobuf:"bytes,4,opt,name=provider_name,json=providerName,proto3" json:"provider_name,omitempty" yaml:"providerName"` // @gotags: yaml:"providerName" + ProviderName string `protobuf:"bytes,4,opt,name=provider_name,json=providerName,proto3" json:"provider_name,omitempty" yaml:"providerName"` // @gotags: yaml:"providerName" ClientAssertionType string `protobuf:"bytes,5,opt,name=client_assertion_type,json=clientAssertionType,proto3" json:"client_assertion_type,omitempty" yaml:"clientAssertionType"` // @gotags: yaml:"clientAssertionType" Authority string `protobuf:"bytes,6,opt,name=authority,proto3" json:"authority,omitempty"` GrantType string `protobuf:"bytes,7,opt,name=grant_type,json=grantType,proto3" json:"grant_type,omitempty" yaml:"grantType"` // @gotags: yaml:"grantType" @@ -296,6 +296,8 @@ type UIConfiguration struct { Visibility *UIVisibility `protobuf:"bytes,1,opt,name=visibility,proto3" json:"visibility,omitempty"` // Address to device provisioning service HTTP API in format https://host:port DeviceProvisioningService string `protobuf:"bytes,2,opt,name=device_provisioning_service,json=deviceProvisioningService,proto3" json:"device_provisioning_service,omitempty"` + // Address to snippet service HTTP API in format https://host:port + SnippetService string `protobuf:"bytes,3,opt,name=snippet_service,json=snippetService,proto3" json:"snippet_service,omitempty"` } func (x *UIConfiguration) Reset() { @@ -344,6 +346,13 @@ func (x *UIConfiguration) GetDeviceProvisioningService() string { return "" } +func (x *UIConfiguration) GetSnippetService() string { + if x != nil { + return x.SnippetService + } + return "" +} + type HubConfigurationResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -731,7 +740,7 @@ var file_grpc_gateway_pb_hubConfiguration_proto_rawDesc = []byte{ 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x61, 0x70, 0x69, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x68, 0x75, 0x62, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x48, 0x75, - 0x62, 0x22, 0x8f, 0x01, 0x0a, 0x0f, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x62, 0x22, 0xb8, 0x01, 0x0a, 0x0f, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x49, 0x56, 0x69, 0x73, @@ -740,59 +749,62 @@ var file_grpc_gateway_pb_hubConfiguration_proto_rawDesc = []byte{ 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x19, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x22, 0x8b, 0x06, 0x0a, 0x18, 0x48, 0x75, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, - 0x69, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6a, 0x77, 0x74, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, - 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6a, 0x77, - 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x2d, 0x0a, 0x13, 0x6a, - 0x77, 0x74, 0x5f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x63, 0x6c, 0x61, - 0x69, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x6a, 0x77, 0x74, 0x44, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x49, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, - 0x61, 0x70, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x63, 0x6f, 0x61, 0x70, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x37, 0x0a, - 0x17, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, - 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x1c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, - 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, - 0x6c, 0x69, 0x76, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x18, 0x64, 0x65, 0x66, 0x61, - 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x6f, - 0x4c, 0x69, 0x76, 0x65, 0x12, 0x33, 0x0a, 0x15, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x14, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x74, 0x74, - 0x70, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x68, 0x74, 0x74, 0x70, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x45, 0x0a, 0x10, 0x77, - 0x65, 0x62, 0x5f, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, - 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x41, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x52, 0x0e, 0x77, 0x65, 0x62, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x13, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6f, 0x61, 0x75, - 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, - 0x2e, 0x4f, 0x41, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x11, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, - 0x45, 0x0a, 0x10, 0x6d, 0x32, 0x6d, 0x5f, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x41, 0x75, 0x74, 0x68, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x6d, 0x32, 0x6d, 0x4f, 0x61, 0x75, 0x74, 0x68, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x02, 0x75, 0x69, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x75, 0x69, 0x12, 0x38, 0x0a, 0x0a, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x75, 0x69, - 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x66, - 0x6f, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x70, 0x6c, 0x67, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x76, 0x32, 0x2f, - 0x67, 0x72, 0x70, 0x63, 0x2d, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x70, 0x62, 0x3b, - 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x6e, 0x69, 0x70, 0x70, 0x65, 0x74, 0x5f, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x6e, + 0x69, 0x70, 0x70, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x8b, 0x06, 0x0a, + 0x18, 0x48, 0x75, 0x62, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x26, 0x0a, 0x0f, + 0x6a, 0x77, 0x74, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6a, 0x77, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x43, + 0x6c, 0x61, 0x69, 0x6d, 0x12, 0x2d, 0x0a, 0x13, 0x6a, 0x77, 0x74, 0x5f, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x10, 0x6a, 0x77, 0x74, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x43, 0x6c, + 0x61, 0x69, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x61, 0x70, 0x5f, 0x67, 0x61, 0x74, 0x65, + 0x77, 0x61, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x61, 0x70, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x37, 0x0a, 0x17, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, + 0x1c, 0x0a, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, + 0x1c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x18, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x33, 0x0a, + 0x15, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x63, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x12, 0x30, 0x0a, 0x14, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x12, 0x68, 0x74, 0x74, 0x70, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x41, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x12, 0x45, 0x0a, 0x10, 0x77, 0x65, 0x62, 0x5f, 0x6f, 0x61, 0x75, 0x74, + 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, + 0x4f, 0x41, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x0e, 0x77, 0x65, 0x62, + 0x4f, 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x13, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x41, 0x75, 0x74, 0x68, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, 0x11, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x61, 0x75, + 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x45, 0x0a, 0x10, 0x6d, 0x32, 0x6d, 0x5f, + 0x6f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x2e, 0x70, 0x62, 0x2e, 0x4f, 0x41, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x52, + 0x0e, 0x6d, 0x32, 0x6d, 0x4f, 0x61, 0x75, 0x74, 0x68, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, + 0x2f, 0x0a, 0x02, 0x75, 0x69, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x49, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x75, 0x69, + 0x12, 0x38, 0x0a, 0x0a, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0d, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x67, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x2e, 0x70, 0x62, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x09, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6c, 0x67, 0x64, 0x2d, 0x64, 0x65, + 0x76, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x76, 0x32, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2d, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x2f, 0x70, 0x62, 0x3b, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/grpc-gateway/pb/hubConfiguration.proto b/grpc-gateway/pb/hubConfiguration.proto index 58503a18d..17d64e90f 100644 --- a/grpc-gateway/pb/hubConfiguration.proto +++ b/grpc-gateway/pb/hubConfiguration.proto @@ -58,6 +58,8 @@ message UIConfiguration { UIVisibility visibility = 1; // Address to device provisioning service HTTP API in format https://host:port string device_provisioning_service = 2; + // Address to snippet service HTTP API in format https://host:port + string snippet_service = 3; } message HubConfigurationResponse { diff --git a/grpc-gateway/pb/service.swagger.json b/grpc-gateway/pb/service.swagger.json index be83686ce..78645c9a0 100644 --- a/grpc-gateway/pb/service.swagger.json +++ b/grpc-gateway/pb/service.swagger.json @@ -356,6 +356,20 @@ "in": "query", "required": false, "type": "string" + }, + { + "name": "force", + "description": "if true, the command will be executed even if the resource does not exist", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "async", + "description": "if true, the command will finish immediately after pending event is created", + "in": "query", + "required": false, + "type": "boolean" } ], "tags": [ @@ -408,6 +422,20 @@ "required": false, "type": "string", "format": "int64" + }, + { + "name": "force", + "description": "if true, the command will be executed even if the resource does not exist", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "async", + "description": "if true, the command will finish immediately after pending event is created", + "in": "query", + "required": false, + "type": "boolean" } ], "tags": [ @@ -530,6 +558,20 @@ "required": false, "type": "string", "format": "int64" + }, + { + "name": "force", + "description": "if true, the command will be executed even if the resource does not exist", + "in": "query", + "required": false, + "type": "boolean" + }, + { + "name": "async", + "description": "if true, the command will finish immediately after pending event is created", + "in": "query", + "required": false, + "type": "boolean" } ], "tags": [ @@ -674,6 +716,13 @@ "type": "string" }, "collectionFormat": "multi" + }, + { + "name": "includeHiddenResources", + "description": "Get all pending commands for all resources, even if the resource is not published.", + "in": "query", + "required": false, + "type": "boolean" } ], "tags": [ @@ -2301,6 +2350,10 @@ "deviceProvisioningService": { "type": "string", "title": "Address to device provisioning service HTTP API in format https://host:port" + }, + "snippetService": { + "type": "string", + "title": "Address to snippet service HTTP API in format https://host:port" } }, "title": "UI configuration" diff --git a/grpc-gateway/pb/updateResource.go b/grpc-gateway/pb/updateResource.go index 9790a5ad7..d4128b0f7 100644 --- a/grpc-gateway/pb/updateResource.go +++ b/grpc-gateway/pb/updateResource.go @@ -5,6 +5,7 @@ import ( "github.com/google/uuid" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" + "github.com/plgd-dev/hub/v2/resource-aggregate/events" "google.golang.org/grpc/peer" ) @@ -36,5 +37,13 @@ func (req *UpdateResourceRequest) ToRACommand(ctx context.Context) (*commands.Up CommandMetadata: &commands.CommandMetadata{ ConnectionId: connectionID, }, + Force: req.GetForce(), }, nil } + +func (x *UpdateResourceResponse) SetData(data *events.ResourceUpdated) { + if x == nil { + return + } + x.Data = data +} diff --git a/grpc-gateway/service/createResource.go b/grpc-gateway/service/createResource.go index a633d301d..863b97ab6 100644 --- a/grpc-gateway/service/createResource.go +++ b/grpc-gateway/service/createResource.go @@ -6,25 +6,76 @@ import ( "github.com/plgd-dev/hub/v2/grpc-gateway/pb" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" + "google.golang.org/grpc" "google.golang.org/grpc/codes" ) -func createResourceError(err error) error { - return kitNetGrpc.ForwardErrorf(codes.Internal, "cannot create resource: %v", err) +func resourceError(action string, err error) error { + return kitNetGrpc.ForwardErrorf(codes.Internal, "cannot %s resource: %v", action, err) } -func (r *RequestHandler) CreateResource(ctx context.Context, req *pb.CreateResourceRequest) (*pb.CreateResourceResponse, error) { - createCommand, err := req.ToRACommand(ctx) +type reqRACommand interface { + *commands.CreateResourceRequest | *commands.DeleteResourceRequest | *commands.UpdateResourceRequest +} + +type respCommand[Event any] interface { + SetData(v Event) +} + +type reqCommand[v reqRACommand] interface { + ToRACommand(ctx context.Context) (v, error) + GetAsync() bool +} + +type ( + syncFunc[Req reqRACommand, Res commands.EventContent] func(ctx context.Context, owner string, req Req) (Res, error) + asyncFunc[Req reqRACommand, Res any] func(ctx context.Context, req Req, opts ...grpc.CallOption) (Res, error) +) + +func handleResourceRequest[ReqRA reqRACommand, Event commands.EventContent, AsyncRes any]( + ctx context.Context, + req reqCommand[ReqRA], + action string, + syncFunc syncFunc[ReqRA, Event], + asyncFunc asyncFunc[ReqRA, AsyncRes], + resp respCommand[Event], +) error { + var err error + var event Event + + raCommand, err := req.ToRACommand(ctx) if err != nil { - return nil, createResourceError(err) + return resourceError(action, err) + } + + if req.GetAsync() { + _, err = asyncFunc(ctx, raCommand) + if err != nil { + return resourceError(action, err) + } + return nil } - createdEvent, err := r.resourceAggregateClient.SyncCreateResource(ctx, "*", createCommand) + event, err = syncFunc(ctx, "*", raCommand) if err != nil { - return nil, createResourceError(err) + return resourceError(action, err) } - if err = commands.CheckEventContent(createdEvent); err != nil { - return nil, createResourceError(err) + if err = commands.CheckEventContent(event); err != nil { + return resourceError(action, err) } - return &pb.CreateResourceResponse{Data: createdEvent}, nil + + resp.SetData(event) + return nil +} + +func (r *RequestHandler) CreateResource(ctx context.Context, req *pb.CreateResourceRequest) (*pb.CreateResourceResponse, error) { + var resp pb.CreateResourceResponse + return &resp, handleResourceRequest( + ctx, + req, + "create", + r.resourceAggregateClient.SyncCreateResource, + r.resourceAggregateClient.CreateResource, + &resp, + ) } diff --git a/grpc-gateway/service/deleteResource.go b/grpc-gateway/service/deleteResource.go index 24a8beb00..3d9ef759b 100644 --- a/grpc-gateway/service/deleteResource.go +++ b/grpc-gateway/service/deleteResource.go @@ -4,26 +4,16 @@ import ( "context" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" - kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" - "github.com/plgd-dev/hub/v2/resource-aggregate/commands" - "google.golang.org/grpc/codes" ) -func deleteResourceError(err error) error { - return kitNetGrpc.ForwardErrorf(codes.Internal, "cannot delete resource: %v", err) -} - func (r *RequestHandler) DeleteResource(ctx context.Context, req *pb.DeleteResourceRequest) (*pb.DeleteResourceResponse, error) { - deleteCommand, err := req.ToRACommand(ctx) - if err != nil { - return nil, deleteResourceError(err) - } - deletedEvent, err := r.resourceAggregateClient.SyncDeleteResource(ctx, "*", deleteCommand) - if err != nil { - return nil, deleteResourceError(err) - } - if err = commands.CheckEventContent(deletedEvent); err != nil { - return nil, deleteResourceError(err) - } - return &pb.DeleteResourceResponse{Data: deletedEvent}, err + var resp pb.DeleteResourceResponse + return &resp, handleResourceRequest( + ctx, + req, + "delete", + r.resourceAggregateClient.SyncDeleteResource, + r.resourceAggregateClient.DeleteResource, + &resp, + ) } diff --git a/grpc-gateway/service/subscribeToEvents_test.go b/grpc-gateway/service/subscribeToEvents_test.go index 913024c9b..b6593e815 100644 --- a/grpc-gateway/service/subscribeToEvents_test.go +++ b/grpc-gateway/service/subscribeToEvents_test.go @@ -667,9 +667,7 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { secureGWShutdown() createFn := func(timeToLive time.Duration) { - createCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(ctx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -678,8 +676,9 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { }), }, TimeToLive: int64(timeToLive), + Async: true, }) - require.Error(t, errC) + require.NoError(t, errC) } createFn(time.Millisecond * 500) // for test expired event createFn(0) @@ -697,9 +696,7 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { retrieveFn(0) updateFn := func(timeToLive time.Duration) { - updateCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -708,20 +705,20 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { }), }, TimeToLive: int64(timeToLive), + Async: true, }) - require.Error(t, errU) + require.NoError(t, errU) } updateFn(time.Millisecond * 500) // for test expired event updateFn(0) deleteFn := func(timeToLive time.Duration) { - deleteCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), TimeToLive: int64(timeToLive), + Async: true, }) - require.Error(t, errD) + require.NoError(t, errD) } deleteFn(time.Millisecond * 500) // for test expired event deleteFn(0) diff --git a/grpc-gateway/service/updateResource.go b/grpc-gateway/service/updateResource.go index 715e97dd7..8c8164efb 100644 --- a/grpc-gateway/service/updateResource.go +++ b/grpc-gateway/service/updateResource.go @@ -4,27 +4,16 @@ import ( "context" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" - kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" - "github.com/plgd-dev/hub/v2/resource-aggregate/commands" - "google.golang.org/grpc/codes" ) -func updateResourceError(err error) error { - return kitNetGrpc.ForwardErrorf(codes.Internal, "cannot update resource: %v", err) -} - func (r *RequestHandler) UpdateResource(ctx context.Context, req *pb.UpdateResourceRequest) (*pb.UpdateResourceResponse, error) { - updateCommand, err := req.ToRACommand(ctx) - if err != nil { - return nil, updateResourceError(err) - } - updatedEvent, err := r.resourceAggregateClient.SyncUpdateResource(ctx, "*", updateCommand) - if err != nil { - return nil, updateResourceError(err) - } - err = commands.CheckEventContent(updatedEvent) - if err != nil { - return nil, updateResourceError(err) - } - return &pb.UpdateResourceResponse{Data: updatedEvent}, nil + var resp pb.UpdateResourceResponse + return &resp, handleResourceRequest( + ctx, + req, + "update", + r.resourceAggregateClient.SyncUpdateResource, + r.resourceAggregateClient.UpdateResource, + &resp, + ) } diff --git a/grpc-gateway/service/updateResource_test.go b/grpc-gateway/service/updateResource_test.go index 10e1f05f5..0653992b1 100644 --- a/grpc-gateway/service/updateResource_test.go +++ b/grpc-gateway/service/updateResource_test.go @@ -15,6 +15,8 @@ import ( "github.com/plgd-dev/go-coap/v3/message" coapTest "github.com/plgd-dev/hub/v2/coap-gateway/test" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" + isPb "github.com/plgd-dev/hub/v2/identity-store/pb" + isTest "github.com/plgd-dev/hub/v2/identity-store/test" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" "github.com/plgd-dev/hub/v2/resource-aggregate/events" @@ -412,3 +414,239 @@ func TestRequestHandlerRunMultipleParallelUpdateResource(t *testing.T) { } wg.Wait() } + +func TestUpdateCreateOnNotExistingResource(t *testing.T) { + deviceID := test.MustFindDeviceByName(test.TestDeviceName) + switchID := "1" + + ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) + defer cancel() + + isCfg := isTest.MakeConfig(t) + isCfg.APIs.GRPC.TLS.ClientCertificateRequired = false + tearDown := service.SetUp(ctx, t, service.WithISConfig(isCfg)) + defer tearDown() + ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) + + // associate device with owner + isConn, err := grpc.NewClient(config.IDENTITY_STORE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: test.GetRootCertificatePool(t), + }))) + require.NoError(t, err) + defer func() { + _ = isConn.Close() + }() + isClient := isPb.NewIdentityStoreClient(isConn) + _, err = isClient.AddDevice(ctx, &isPb.AddDeviceRequest{ + DeviceId: deviceID, + }) + require.NoError(t, err) + + // update/create resources of the registered device + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: test.GetRootCertificatePool(t), + }))) + require.NoError(t, err) + defer func() { + _ = conn.Close() + }() + c := pb.NewGrpcGatewayClient(conn) + + createResourceSub := &pb.SubscribeToEvents{ + CorrelationId: "testToken", + Action: &pb.SubscribeToEvents_CreateSubscription_{ + CreateSubscription: &pb.SubscribeToEvents_CreateSubscription{ + EventFilter: []pb.SubscribeToEvents_CreateSubscription_Event{ + pb.SubscribeToEvents_CreateSubscription_RESOURCE_CHANGED, + pb.SubscribeToEvents_CreateSubscription_RESOURCE_UPDATED, + pb.SubscribeToEvents_CreateSubscription_RESOURCE_CREATED, + pb.SubscribeToEvents_CreateSubscription_RESOURCE_DELETED, + pb.SubscribeToEvents_CreateSubscription_RESOURCE_UPDATE_PENDING, + pb.SubscribeToEvents_CreateSubscription_RESOURCE_CREATE_PENDING, + pb.SubscribeToEvents_CreateSubscription_RESOURCE_DELETE_PENDING, + }, + }, + }, + } + subClient, err := c.SubscribeToEvents(ctx) + require.NoError(t, err) + defer func() { + err2 := subClient.CloseSend() + require.NoError(t, err2) + }() + err = subClient.Send(createResourceSub) + require.NoError(t, err) + + ev, err := subClient.Recv() + require.NoError(t, err) + expectedEvent := &pb.Event{ + SubscriptionId: ev.GetSubscriptionId(), + Type: &pb.Event_OperationProcessed_{ + OperationProcessed: &pb.Event_OperationProcessed{ + ErrorStatus: &pb.Event_OperationProcessed_ErrorStatus{ + Code: pb.Event_OperationProcessed_ErrorStatus_OK, + }, + }, + }, + CorrelationId: "testToken", + } + pbTest.CmpEvent(t, expectedEvent, ev, "") + + powerTest := 654321 + _, err = c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), + Content: &pb.Content{ + ContentType: message.AppOcfCbor.String(), + Data: test.EncodeToCbor(t, map[string]interface{}{ + "power": powerTest, + }), + }, + Force: true, + Async: true, + }) + require.NoError(t, err) + + _, err = c.CreateResource(ctx, &pb.CreateResourceRequest{ + ResourceId: commands.NewResourceID(deviceID, test.TestResourceSwitchesHref), + Content: &pb.Content{ + ContentType: message.AppOcfCbor.String(), + Data: test.EncodeToCbor(t, test.MakeSwitchResourceDefaultData()), + }, + Force: true, + Async: true, + }) + require.NoError(t, err) + + _, err = c.DeleteResource(ctx, &pb.DeleteResourceRequest{ + ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), + Force: true, + Async: true, + }) + require.NoError(t, err) + + pendingCommandsClient, err := c.GetPendingCommands(ctx, &pb.GetPendingCommandsRequest{ + DeviceIdFilter: []string{deviceID}, + IncludeHiddenResources: true, + }) + require.NoError(t, err) + numPendingCommands := 0 + for { + ev, err2 := pendingCommandsClient.Recv() + if errors.Is(err2, io.EOF) { + break + } + require.NoError(t, err2) + if ev.GetResourceCreatePending() != nil { + require.Equal(t, deviceID, ev.GetResourceCreatePending().GetResourceId().GetDeviceId()) + require.Equal(t, test.TestResourceSwitchesHref, ev.GetResourceCreatePending().GetResourceId().GetHref()) + numPendingCommands++ + } + if ev.GetResourceUpdatePending() != nil { + require.Equal(t, deviceID, ev.GetResourceUpdatePending().GetResourceId().GetDeviceId()) + switch ev.GetResourceUpdatePending().GetResourceId().GetHref() { + case test.TestResourceLightInstanceHref("1"): + numPendingCommands++ + default: + require.FailNowf(t, "unexpected pending command", "%v", ev) + } + } + if ev.GetResourceDeletePending() != nil { + require.Equal(t, deviceID, ev.GetResourceDeletePending().GetResourceId().GetDeviceId()) + require.Equal(t, test.TestResourceLightInstanceHref("1"), ev.GetResourceDeletePending().GetResourceId().GetHref()) + numPendingCommands++ + } + } + require.Equal(t, 3, numPendingCommands) + + _, shutdownDevSim := test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) + defer shutdownDevSim() + + var lightChanged *events.ResourceChanged + var switchChanged *events.ResourceChanged + var lightUpdated *events.ResourceUpdated + var switchCreated *events.ResourceCreated + var lightDeleted *events.ResourceDeleted + for { + ev, err2 := subClient.Recv() + require.NoError(t, err2) + if ch := ev.GetResourceChanged(); ch != nil { + if ch.GetResourceId().GetHref() == test.TestResourceLightInstanceHref("1") { + d := test.DecodeCbor(t, ch.GetContent().GetData()) + if m, ok := d.(map[interface{}]interface{}); ok && m["power"] == uint64(powerTest) { + lightChanged = ch + } + } + if ch.GetResourceId().GetHref() == test.TestResourceSwitchesInstanceHref(switchID) { + switchChanged = ch + } + } + if updated := ev.GetResourceUpdated(); updated != nil { + if updated.GetResourceId().GetHref() == test.TestResourceLightInstanceHref("1") { + lightUpdated = updated + } + } + if created := ev.GetResourceCreated(); created != nil { + if created.GetResourceId().GetHref() == test.TestResourceSwitchesHref { + switchCreated = created + } + } + if deleted := ev.GetResourceDeleted(); deleted != nil { + if deleted.GetResourceId().GetHref() == test.TestResourceLightInstanceHref("1") { + lightDeleted = deleted + } + } + if lightChanged != nil && switchChanged != nil && lightUpdated != nil && switchCreated != nil && lightDeleted != nil { + break + } + } + + _, err = c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + ResourceId: commands.NewResourceID(deviceID, "/not/existing/resource"), + Content: &pb.Content{ + ContentType: message.AppOcfCbor.String(), + Data: test.EncodeToCbor(t, map[string]interface{}{ + "power": powerTest, + }), + }, + Force: true, + Async: true, + }) + require.NoError(t, err) + + pendingCommandsClient, err = c.GetPendingCommands(ctx, &pb.GetPendingCommandsRequest{ + DeviceIdFilter: []string{deviceID}, + IncludeHiddenResources: true, + }) + require.NoError(t, err) + numPendingCommands = 0 + for { + ev, err2 := pendingCommandsClient.Recv() + if errors.Is(err2, io.EOF) { + break + } + require.NoError(t, err2) + if ev.GetResourceUpdatePending() != nil { + require.Equal(t, deviceID, ev.GetResourceUpdatePending().GetResourceId().GetDeviceId()) + switch ev.GetResourceUpdatePending().GetResourceId().GetHref() { + case "/not/existing/resource": + numPendingCommands++ + default: + require.FailNowf(t, "unexpected pending command", "%v", ev) + } + } else { + require.FailNowf(t, "unexpected pending command", "%v", ev) + } + } + require.Equal(t, 1, numPendingCommands) + + _, err = c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), + Content: &pb.Content{ + ContentType: message.AppOcfCbor.String(), + Data: test.EncodeToCbor(t, map[string]interface{}{ + "power": 0, + }), + }, + }) + require.NoError(t, err) +} diff --git a/grpc-gateway/test/test.go b/grpc-gateway/test/test.go index 5cc26e62c..9ac9ebba1 100644 --- a/grpc-gateway/test/test.go +++ b/grpc-gateway/test/test.go @@ -2,16 +2,37 @@ package test import ( "context" + "crypto/tls" + "crypto/x509" "sync" + "testing" "time" + "github.com/plgd-dev/hub/v2/grpc-gateway/client" "github.com/plgd-dev/hub/v2/grpc-gateway/service" "github.com/plgd-dev/hub/v2/pkg/fsnotify" "github.com/plgd-dev/hub/v2/pkg/log" + "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" "github.com/stretchr/testify/require" ) +func NewTestClient(t *testing.T) *client.Client { + rootCAs := x509.NewCertPool() + for _, c := range test.GetRootCertificateAuthorities(t) { + rootCAs.AddCert(c) + } + tlsCfg := tls.Config{ + RootCAs: rootCAs, + } + clientConfig := client.Config{ + GatewayAddress: config.GRPC_GW_HOST, + } + c, err := client.NewFromConfig(&clientConfig, &tlsCfg) + require.NoError(t, err) + return c +} + func MakeConfig(t require.TestingT) service.Config { var cfg service.Config diff --git a/http-gateway/config.yaml b/http-gateway/config.yaml index e48c42a8a..53f85480d 100644 --- a/http-gateway/config.yaml +++ b/http-gateway/config.yaml @@ -71,6 +71,7 @@ ui: webConfiguration: httpGatewayAddress: "" deviceProvisioningService: "" + snippetService: "" webOAuthClient: authority: "" clientID: "" diff --git a/http-gateway/service/config.go b/http-gateway/service/config.go index 2a85bfc70..7e2f206f4 100644 --- a/http-gateway/service/config.go +++ b/http-gateway/service/config.go @@ -193,6 +193,7 @@ type WebConfiguration struct { Authority string `yaml:"-" json:"authority"` HTTPGatewayAddress string `yaml:"httpGatewayAddress" json:"httpGatewayAddress"` DeviceProvisioningService string `yaml:"deviceProvisioningService" json:"deviceProvisioningService"` + SnippetService string `yaml:"snippetService" json:"snippetService"` WebOAuthClient OAuthClient `yaml:"webOAuthClient" json:"webOauthClient"` DeviceOAuthClient OAuthClient `yaml:"deviceOAuthClient" json:"deviceOauthClient"` M2MOAuthClient *OAuthClient `yaml:"m2mOAuthClient" json:"m2mOauthClient"` diff --git a/http-gateway/service/getDevicePendingCommands_test.go b/http-gateway/service/getDevicePendingCommands_test.go index 42fe7bc5c..28c906605 100644 --- a/http-gateway/service/getDevicePendingCommands_test.go +++ b/http-gateway/service/getDevicePendingCommands_test.go @@ -253,9 +253,7 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { secureGWShutdown() createFn := func() { - createCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(ctx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -263,8 +261,9 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { "power": 1, }), }, + Async: true, }) - require.Error(t, errC) + require.NoError(t, errC) } createFn() retrieveFn := func() { @@ -277,9 +276,7 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { } retrieveFn() updateFn := func() { - updateCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -287,17 +284,17 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { "power": 1, }), }, + Async: true, }) - require.Error(t, errU) + require.NoError(t, errU) } updateFn() deleteFn := func() { - deleteCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), + Async: true, }) - require.Error(t, errD) + require.NoError(t, errD) } deleteFn() updateDeviceMetadataFn := func() { diff --git a/http-gateway/service/getDeviceResourceLinks_test.go b/http-gateway/service/getDeviceResourceLinks_test.go index a7a71b7e1..13a8a650c 100644 --- a/http-gateway/service/getDeviceResourceLinks_test.go +++ b/http-gateway/service/getDeviceResourceLinks_test.go @@ -6,6 +6,7 @@ import ( "errors" "io" "net/http" + "slices" "testing" "time" @@ -16,7 +17,6 @@ import ( httpgwTest "github.com/plgd-dev/hub/v2/http-gateway/test" "github.com/plgd-dev/hub/v2/http-gateway/uri" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" - "github.com/plgd-dev/hub/v2/pkg/strings" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" "github.com/plgd-dev/hub/v2/resource-aggregate/events" test "github.com/plgd-dev/hub/v2/test" @@ -100,8 +100,8 @@ func TestRequestHandlerGetDeviceResourceLinks(t *testing.T) { { DeviceId: deviceID, Resources: test.ResourceLinksToResources(deviceID, test.FilterResourceLink(func(rl schema.ResourceLink) bool { - return strings.Contains(rl.ResourceTypes, collection.ResourceType) || - strings.Contains(rl.ResourceTypes, types.BINARY_SWITCH) + return slices.Contains(rl.ResourceTypes, collection.ResourceType) || + slices.Contains(rl.ResourceTypes, types.BINARY_SWITCH) }, resourceLinks)), AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), }, diff --git a/http-gateway/service/getHubConfiguration.go b/http-gateway/service/getHubConfiguration.go index 6467821b4..c693de243 100644 --- a/http-gateway/service/getHubConfiguration.go +++ b/http-gateway/service/getHubConfiguration.go @@ -75,6 +75,7 @@ func (requestHandler *RequestHandler) getHubConfiguration(w http.ResponseWriter, resp.Ui = &pb.UIConfiguration{ Visibility: requestHandler.config.UI.WebConfiguration.Visibility.ToProto(), DeviceProvisioningService: requestHandler.config.UI.WebConfiguration.DeviceProvisioningService, + SnippetService: requestHandler.config.UI.WebConfiguration.SnippetService, } if accept == pkgHttp.ApplicationProtoJsonContentType { m := serverMux.NewJsonpbMarshaler() diff --git a/http-gateway/service/getHubConfiguration_test.go b/http-gateway/service/getHubConfiguration_test.go index 351500f83..fba747935 100644 --- a/http-gateway/service/getHubConfiguration_test.go +++ b/http-gateway/service/getHubConfiguration_test.go @@ -30,6 +30,7 @@ func TestRequestHandlerGetHubConfiguration(t *testing.T) { expected.Ui = &pb.UIConfiguration{ Visibility: httpCfg.UI.WebConfiguration.Visibility.ToProto(), DeviceProvisioningService: httpCfg.UI.WebConfiguration.DeviceProvisioningService, + SnippetService: httpCfg.UI.WebConfiguration.SnippetService, } tests := []struct { name string @@ -85,6 +86,7 @@ func TestRequestHandlerGetHubConfigurationWithoutM2MOAuthClient(t *testing.T) { expected.Ui = &pb.UIConfiguration{ Visibility: httpCfg.UI.WebConfiguration.Visibility.ToProto(), DeviceProvisioningService: httpCfg.UI.WebConfiguration.DeviceProvisioningService, + SnippetService: httpCfg.UI.WebConfiguration.SnippetService, } tests := []struct { name string diff --git a/http-gateway/service/getPendingCommands_test.go b/http-gateway/service/getPendingCommands_test.go index d790d18a3..a39ca1c2f 100644 --- a/http-gateway/service/getPendingCommands_test.go +++ b/http-gateway/service/getPendingCommands_test.go @@ -300,9 +300,7 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { secureGWShutdown() createFn := func() { - createCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(ctx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -310,8 +308,9 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { "power": 1, }), }, + Async: true, }) - require.Error(t, errC) + require.NoError(t, errC) } createFn() retrieveFn := func() { @@ -324,9 +323,7 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { } retrieveFn() updateFn := func() { - updateCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -334,17 +331,17 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { "power": 1, }), }, + Async: true, }) - require.Error(t, errU) + require.NoError(t, errU) } updateFn() deleteFn := func() { - deleteCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), + Async: true, }) - require.Error(t, errD) + require.NoError(t, errD) } deleteFn() updateDeviceMetadataFn := func() { diff --git a/http-gateway/service/getResourcePendingCommands_test.go b/http-gateway/service/getResourcePendingCommands_test.go index 7d66de5d1..d75438626 100644 --- a/http-gateway/service/getResourcePendingCommands_test.go +++ b/http-gateway/service/getResourcePendingCommands_test.go @@ -165,9 +165,7 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { secureGWShutdown() createFn := func() { - createCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(ctx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -175,8 +173,9 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { "power": 1, }), }, + Async: true, }) - require.Error(t, errC) + require.NoError(t, errC) } createFn() retrieveFn := func() { @@ -189,9 +188,7 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { } retrieveFn() updateFn := func() { - updateCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -199,17 +196,17 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { "power": 1, }), }, + Async: true, }) - require.Error(t, errU) + require.NoError(t, errU) } updateFn() deleteFn := func() { - deleteCtx, cancel := context.WithTimeout(ctx, time.Second) - defer cancel() - _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), + Async: true, }) - require.Error(t, errD) + require.NoError(t, errD) } deleteFn() updateDeviceMetadataFn := func() { diff --git a/http-gateway/test/test.go b/http-gateway/test/test.go index a15981d17..0019d542b 100644 --- a/http-gateway/test/test.go +++ b/http-gateway/test/test.go @@ -21,6 +21,7 @@ func MakeWebConfigurationConfig() service.WebConfiguration { Authority: testHttp.HTTPS_SCHEME + config.OAUTH_SERVER_HOST, HTTPGatewayAddress: testHttp.HTTPS_SCHEME + config.HTTP_GW_HOST, DeviceProvisioningService: testHttp.HTTPS_SCHEME + config.HTTP_GW_HOST, + SnippetService: testHttp.HTTPS_SCHEME + config.SNIPPET_SERVICE_HTTP_HOST, WebOAuthClient: service.OAuthClient{ Authority: testHttp.HTTPS_SCHEME + config.OAUTH_SERVER_HOST, ClientID: config.OAUTH_MANAGER_CLIENT_ID, @@ -51,7 +52,7 @@ func MakeConfig(t require.TestingT, enableUI bool) service.Config { cfg.Log = log.MakeDefaultConfig() - cfg.APIs.HTTP.Authorization = config.MakeAuthorizationConfig() + cfg.APIs.HTTP.Authorization = config.MakeValidatorConfig() cfg.APIs.HTTP.Connection = config.MakeListenerConfig(config.HTTP_GW_HOST) cfg.APIs.HTTP.Connection.TLS.ClientCertificateRequired = false cfg.APIs.HTTP.WebSocket.StreamBodyLimit = 256 * 1024 diff --git a/http-gateway/uri/uri.go b/http-gateway/uri/uri.go index 0a4fd3323..05aba37dd 100644 --- a/http-gateway/uri/uri.go +++ b/http-gateway/uri/uri.go @@ -7,21 +7,23 @@ const ( ResourceHrefKey = "resourceHref" CorrelationIDKey = "correlationId" - ResourceInterfaceQueryKey = "resourceInterface" - TwinQueryKey = "twin" - CommandFilterQueryKey = "commandFilter" - TypeFilterQueryKey = "typeFilter" - StatusFilterQueryKey = "statusFilter" - DeviceIdFilterQueryKey = "deviceIdFilter" - TimeToLiveQueryKey = "timeToLive" - ResourceIdFilterQueryKey = "resourceIdFilter" - HttpResourceIdFilterQueryKey = "httpResourceIdFilter" - AcceptQueryKey = "accept" // for websocket - CorrelationIDQueryKey = "correlationId" - TimestampFilterQueryKey = "timestampFilter" - CorrelationIdFilterQueryKey = "correlationIdFilter" - ETagQueryKey = "etag" - OnlyContentQueryKey = "onlyContent" + ResourceInterfaceQueryKey = "resourceInterface" + TwinQueryKey = "twin" + CommandFilterQueryKey = "commandFilter" + TypeFilterQueryKey = "typeFilter" + StatusFilterQueryKey = "statusFilter" + DeviceIdFilterQueryKey = "deviceIdFilter" + TimeToLiveQueryKey = "timeToLive" + ResourceIdFilterQueryKey = "resourceIdFilter" + HttpResourceIdFilterQueryKey = "httpResourceIdFilter" + AcceptQueryKey = "accept" // for websocket + CorrelationIDQueryKey = "correlationId" + TimestampFilterQueryKey = "timestampFilter" + CorrelationIdFilterQueryKey = "correlationIdFilter" + ETagQueryKey = "etag" + OnlyContentQueryKey = "onlyContent" + IncludeHiddenResourcesQueryKey = "includeHiddenResources" + ForceQueryKey = "force" AliasInterfaceQueryKey = "interface" AliasCommandFilterQueryKey = "command" @@ -116,23 +118,25 @@ const ( ) var QueryCaseInsensitive = map[string]string{ - strings.ToLower(AliasInterfaceQueryKey): ResourceInterfaceQueryKey, - strings.ToLower(CommandFilterQueryKey): CommandFilterQueryKey, - strings.ToLower(DeviceIdFilterQueryKey): DeviceIdFilterQueryKey, - strings.ToLower(ResourceIdFilterQueryKey): HttpResourceIdFilterQueryKey, - strings.ToLower(ResourceInterfaceQueryKey): ResourceInterfaceQueryKey, - strings.ToLower(TwinQueryKey): TwinQueryKey, - strings.ToLower(TypeFilterQueryKey): TypeFilterQueryKey, - strings.ToLower(AliasCommandFilterQueryKey): CommandFilterQueryKey, - strings.ToLower(AliasDeviceIdFilterQueryKey): DeviceIdFilterQueryKey, - strings.ToLower(AliasResourceIdFilterQueryKey): HttpResourceIdFilterQueryKey, - strings.ToLower(AliasTypeFilterQueryKey): TypeFilterQueryKey, - strings.ToLower(AcceptQueryKey): AcceptQueryKey, - strings.ToLower(StatusFilterQueryKey): StatusFilterQueryKey, - strings.ToLower(AliasStatusFilterQueryKey): StatusFilterQueryKey, - strings.ToLower(CorrelationIDQueryKey): CorrelationIDQueryKey, - strings.ToLower(TimestampFilterQueryKey): TimestampFilterQueryKey, - strings.ToLower(TimeToLiveQueryKey): TimeToLiveQueryKey, - strings.ToLower(CorrelationIdFilterQueryKey): CorrelationIdFilterQueryKey, - strings.ToLower(OnlyContentQueryKey): OnlyContentQueryKey, + strings.ToLower(AliasInterfaceQueryKey): ResourceInterfaceQueryKey, + strings.ToLower(CommandFilterQueryKey): CommandFilterQueryKey, + strings.ToLower(DeviceIdFilterQueryKey): DeviceIdFilterQueryKey, + strings.ToLower(ResourceIdFilterQueryKey): HttpResourceIdFilterQueryKey, + strings.ToLower(ResourceInterfaceQueryKey): ResourceInterfaceQueryKey, + strings.ToLower(TwinQueryKey): TwinQueryKey, + strings.ToLower(TypeFilterQueryKey): TypeFilterQueryKey, + strings.ToLower(AliasCommandFilterQueryKey): CommandFilterQueryKey, + strings.ToLower(AliasDeviceIdFilterQueryKey): DeviceIdFilterQueryKey, + strings.ToLower(AliasResourceIdFilterQueryKey): HttpResourceIdFilterQueryKey, + strings.ToLower(AliasTypeFilterQueryKey): TypeFilterQueryKey, + strings.ToLower(AcceptQueryKey): AcceptQueryKey, + strings.ToLower(StatusFilterQueryKey): StatusFilterQueryKey, + strings.ToLower(AliasStatusFilterQueryKey): StatusFilterQueryKey, + strings.ToLower(CorrelationIDQueryKey): CorrelationIDQueryKey, + strings.ToLower(TimestampFilterQueryKey): TimestampFilterQueryKey, + strings.ToLower(TimeToLiveQueryKey): TimeToLiveQueryKey, + strings.ToLower(CorrelationIdFilterQueryKey): CorrelationIdFilterQueryKey, + strings.ToLower(OnlyContentQueryKey): OnlyContentQueryKey, + strings.ToLower(IncludeHiddenResourcesQueryKey): IncludeHiddenResourcesQueryKey, + strings.ToLower(ForceQueryKey): ForceQueryKey, } diff --git a/http-gateway/web/package-lock.json b/http-gateway/web/package-lock.json index 5ecb906f0..0e5358ac4 100644 --- a/http-gateway/web/package-lock.json +++ b/http-gateway/web/package-lock.json @@ -36963,7 +36963,9 @@ "license": "ISC", "dependencies": { "cors": "^2.8.5", - "express-validator": "^7.1.0" + "escape-html": "^1.0.3", + "express-validator": "^7.1.0", + "lodash": "^4.17.21" }, "devDependencies": { "express": "^4.18.2" @@ -37051,6 +37053,7 @@ "react-table": "^7.8.0", "react-toastify": "^9.1.3", "react-transition-group": "^4.4.5", + "recoil": "^0.7.7", "swiper": "^10.2.0", "tsconfig-paths-webpack-plugin": "^4.1.0", "typescript": "^4.9.5", @@ -37094,7 +37097,7 @@ "eslint-plugin-import": "^2.29.0", "eslint-plugin-jest": "^27.6.0", "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-prettier": "^5.0.1", + "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-storybook": "^0.8.0", @@ -37110,7 +37113,7 @@ "npm-run-all": "^4.1.5", "path": "^0.12.7", "postcss-modules": "^6.0.0", - "prettier": "^3.1.0", + "prettier": "^3.3.2", "prop-types": "^15.8.1", "resize-observer-polyfill": "^1.5.1", "rimraf": "^5.0.5", @@ -37125,6 +37128,21 @@ "yargs": "^17.7.2" } }, + "packages/shared-ui/node_modules/prettier": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "packages/shared-ui/node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", diff --git a/http-gateway/web/packages/mock-server/package.json b/http-gateway/web/packages/mock-server/package.json index 460b398b3..2fdafde62 100644 --- a/http-gateway/web/packages/mock-server/package.json +++ b/http-gateway/web/packages/mock-server/package.json @@ -14,6 +14,8 @@ }, "dependencies": { "cors": "^2.8.5", - "express-validator": "^7.1.0" + "escape-html": "^1.0.3", + "express-validator": "^7.1.0", + "lodash": "^4.17.21" } } diff --git a/http-gateway/web/packages/mock-server/src/data/dps/enrollment-groups/detail/4f0d3d81-0e09-4f1e-9706-0997488011af.json b/http-gateway/web/packages/mock-server/src/data/dps/enrollment-groups/detail/4f0d3d81-0e09-4f1e-9706-0997488011af.json new file mode 100644 index 000000000..a2f174a3d --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/dps/enrollment-groups/detail/4f0d3d81-0e09-4f1e-9706-0997488011af.json @@ -0,0 +1,17 @@ +{ + "result": { + "id": "4f0d3d81-0e09-4f1e-9706-0997488011af", + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "attestationMechanism": { + "x509": { + "certificateChain": "/secrets/enrollmentgroups/x509/4f0d3d81-0e09-4f1e-9706-0997488011af/certificatechain.crt", + "leadCertificateName": "MfgRootCA", + "expiredCertificateEnabled": false + } + }, + "hubIds": [ + "1c10a3b6-287c-11ec-ac2d-13054959c274" + ], + "name": "4f0d3d81-0e09-4f1e-9706-0997488011af" + } +} \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/dps/enrollment-groups/detail/75eacc2f-ac28-4a42-a155-164393970ba4.json b/http-gateway/web/packages/mock-server/src/data/dps/enrollment-groups/detail/75eacc2f-ac28-4a42-a155-164393970ba4.json new file mode 100644 index 000000000..5092c07f9 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/dps/enrollment-groups/detail/75eacc2f-ac28-4a42-a155-164393970ba4.json @@ -0,0 +1,17 @@ +{ + "result": { + "id": "75eacc2f-ac28-4a42-a155-164393970ba4", + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "attestationMechanism": { + "x509": { + "certificateChain": "/secrets/enrollmentgroups/x509/75eacc2f-ac28-4a42-a155-164393970ba4/certificatechain.crt", + "leadCertificateName": "root.ca.plgd.cloud", + "expiredCertificateEnabled": false + } + }, + "hubIds": [ + "1c10a3b6-287c-11ec-ac2d-13054959c274" + ], + "name": "75eacc2f-ac28-4a42-a155-164393970ba4" + } +} \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/dps/enrollment-groups/list/list.json b/http-gateway/web/packages/mock-server/src/data/dps/enrollment-groups/list/list.json new file mode 100644 index 000000000..fdd469730 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/dps/enrollment-groups/list/list.json @@ -0,0 +1,35 @@ +[ + { + "result": { + "id": "75eacc2f-ac28-4a42-a155-164393970ba4", + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "attestationMechanism": { + "x509": { + "certificateChain": "/secrets/enrollmentgroups/x509/75eacc2f-ac28-4a42-a155-164393970ba4/certificatechain.crt", + "leadCertificateName": "root.ca.plgd.cloud", + "expiredCertificateEnabled": false + } + }, + "hubIds": [ + "1c10a3b6-287c-11ec-ac2d-13054959c274" + ], + "name": "75eacc2f-ac28-4a42-a155-164393970ba4" + } + },{ + "result": { + "hubIds": [ + "1c10a3b6-287c-11ec-ac2d-13054959c274" + ], + "name": "4f0d3d81-0e09-4f1e-9706-0997488011af", + "id": "4f0d3d81-0e09-4f1e-9706-0997488011af", + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "attestationMechanism": { + "x509": { + "certificateChain": "/secrets/enrollmentgroups/x509/4f0d3d81-0e09-4f1e-9706-0997488011af/certificatechain.crt", + "leadCertificateName": "MfgRootCA", + "expiredCertificateEnabled": false + } + } + } +} +] \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/dps/linked-hubs/detail/1c10a3b6-287c-11ec-ac2d-13054959c274.json b/http-gateway/web/packages/mock-server/src/data/dps/linked-hubs/detail/1c10a3b6-287c-11ec-ac2d-13054959c274.json new file mode 100644 index 000000000..b857b8c11 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/dps/linked-hubs/detail/1c10a3b6-287c-11ec-ac2d-13054959c274.json @@ -0,0 +1,56 @@ +{ + "result": { + "name": "1c10a3b6-287c-11ec-ac2d-13054959c274", + "hubId": "1c10a3b6-287c-11ec-ac2d-13054959c274", + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "id": "1c10a3b6-287c-11ec-ac2d-13054959c274", + "gateways": [ + "coaps+tcp://try.plgd.cloud:5684" + ], + "certificateAuthority": { + "grpc": { + "tls": { + "caPool": [ + "/certs/client/ca.crt" + ], + "key": "/certs/client/tls.key", + "cert": "/certs/client/tls.crt", + "useSystemCaPool": true + }, + "address": "csr.try.plgd.cloud:443", + "keepAlive": { + "timeout": "20000000000", + "permitWithoutStream": true, + "time": "10000000000" + } + } + }, + "authorization": { + "ownerClaim": "owner-id", + "provider": { + "clientId": "p2elIQo8ZOQZ7pSgAfi0JyebeE6uwWNK", + "scopes": [ + "openid" + ], + "clientSecret": "/secrets/enrollmentgroups/hubs/oauth/4f0d3d81-0e09-4f1e-9706-0997488011af/clientsecret", + "http": { + "maxConnsPerHost": 32, + "maxIdleConnsPerHost": 16, + "idleConnTimeout": "30000000000", + "timeout": "10000000000", + "tls": { + "key": "/certs/client/tls.key", + "cert": "/certs/client/tls.crt", + "useSystemCaPool": true, + "caPool": [ + "/certs/client/ca.crt" + ] + }, + "maxIdleConns": 16 + }, + "name": "plgd.dps", + "authority": "https://auth.plgd.cloud/realms/shared" + } + } + } +} \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/dps/linked-hubs/list/list.json b/http-gateway/web/packages/mock-server/src/data/dps/linked-hubs/list/list.json new file mode 100644 index 000000000..63c7fc522 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/dps/linked-hubs/list/list.json @@ -0,0 +1,58 @@ +[ + { + "result": { + "certificateAuthority": { + "grpc": { + "address": "csr.try.plgd.cloud:443", + "keepAlive": { + "time": "10000000000", + "timeout": "20000000000", + "permitWithoutStream": true + }, + "tls": { + "cert": "/certs/client/tls.crt", + "useSystemCaPool": true, + "caPool": [ + "/certs/client/ca.crt" + ], + "key": "/certs/client/tls.key" + } + } + }, + "authorization": { + "provider": { + "clientSecret": "/secrets/enrollmentgroups/hubs/oauth/4f0d3d81-0e09-4f1e-9706-0997488011af/clientsecret", + "http": { + "maxIdleConns": 16, + "maxConnsPerHost": 32, + "maxIdleConnsPerHost": 16, + "idleConnTimeout": "30000000000", + "timeout": "10000000000", + "tls": { + "caPool": [ + "/certs/client/ca.crt" + ], + "key": "/certs/client/tls.key", + "cert": "/certs/client/tls.crt", + "useSystemCaPool": true + } + }, + "name": "plgd.dps", + "authority": "https://auth.plgd.cloud/realms/shared", + "clientId": "p2elIQo8ZOQZ7pSgAfi0JyebeE6uwWNK", + "scopes": [ + "openid" + ] + }, + "ownerClaim": "owner-id" + }, + "name": "1c10a3b6-287c-11ec-ac2d-13054959c274", + "hubId": "1c10a3b6-287c-11ec-ac2d-13054959c274", + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "id": "1c10a3b6-287c-11ec-ac2d-13054959c274", + "gateways": [ + "coaps+tcp://try.plgd.cloud:5684" + ] + } + } +] \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/dps/provisioning-records/detail/4a0d78b2-9a21-557d-ab08-bb4eaccfcbb0.json b/http-gateway/web/packages/mock-server/src/data/dps/provisioning-records/detail/4a0d78b2-9a21-557d-ab08-bb4eaccfcbb0.json new file mode 100644 index 000000000..95dd44eab --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/dps/provisioning-records/detail/4a0d78b2-9a21-557d-ab08-bb4eaccfcbb0.json @@ -0,0 +1,250 @@ +{ + "result": { + "deviceId": "bcd30976-10e4-4145-5282-eb50ee55dfae", + "enrollmentGroupId": "4f0d3d81-0e09-4f1e-9706-0997488011af", + "attestation": { + "date": "1717157743336135946", + "x509": { + "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIBhTCCASugAwIBAgIRAJ+UC+MPMl6jc9FVeHZEgB4wCgYIKoZIzj0EAwIwFDES\nMBAGA1UEAxMJTWZnUm9vdENBMCAXDTIzMTIxMTEyNTIwMVoYDzIxMjMxMTE3MTI1\nMjAxWjATMREwDwYDVQQDEwhNZmdDZXJ0MTBZMBMGByqGSM49AgEGCCqGSM49AwEH\nA0IABFU2BHkqcNsiN68hGoFGzk+QtK78su3HpObu0U6Yhq5tnbGffQ4oTcel4Lhx\nlW5FHWUPI/l2LV9Ej/i3DSaurs6jXTBbMB8GA1UdIwQYMBaAFFyGFDlvMWlF0wb8\n0yDIfbRH7lTPMAwGA1UdEwQFMAMBAQAwCwYDVR0PBAQDAgOIMB0GA1UdJQQWMBQG\nCCsGAQUFBwMCBggrBgEFBQcDATAKBggqhkjOPQQDAgNIADBFAiBM31BMFp/ImqVt\nwH55aaqYSYp00pabSyIbKwFle6B+2wIhAMqXjZ3zoEECNU7zUo/hpYPTqanak2t6\ndPVwtlKcRlPx\n-----END CERTIFICATE-----\n", + "commonName": "MfgCert1" + } + }, + "acl": { + "status": { + "date": "1717157743480774484", + "coapCode": 69 + }, + "accessControlList": [ + { + "deviceSubject": { + "deviceId": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "permissions": [ + "CREATE", + "READ", + "WRITE", + "DELETE", + "NOTIFY" + ], + "resources": [ + { + "href": "/CoapCloudConfResURI", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/sec/sp" + }, + { + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "wildcard": "NONE", + "href": "/oc/con", + "interfaces": [ + "*" + ] + }, + { + "href": "/oc/swu", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/mnt" + }, + { + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONCFG_ALL" + } + ] + }, + { + "connectionSubject": { + "type": "ANON_CLEAR" + }, + "permissions": [ + "READ" + ], + "resources": [ + { + "href": "/oic/d", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oic/p", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oic/res", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/sec/sdi" + }, + { + "href": "/oic/sec/doxm", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + } + ] + }, + { + "deviceSubject": { + "deviceId": "1c10a3b6-287c-11ec-ac2d-13054959c274" + }, + "permissions": [ + "CREATE", + "READ", + "WRITE", + "DELETE", + "NOTIFY" + ], + "resources": [ + { + "href": "/oc/con", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oc/swu", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oic/mnt", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/x.plgd.dev/time" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONCFG_ALL" + } + ] + } + ] + }, + "cloud": { + "status": { + "date": "1717157743426800468", + "coapCode": 68 + }, + "providerName": "plgd.dps", + "gateways": [ + { + "id": "1c10a3b6-287c-11ec-ac2d-13054959c274", + "uri": "coaps+tcp://try.plgd.cloud:5684" + } + ], + "selectedGateway": 0 + }, + "ownership": { + "status": { + "date": "1717157743352900277", + "coapCode": 69 + }, + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "localEndpoints": [ + "coap://10.110.110.12:45396", + "coaps://10.110.110.12:52852", + "coap+tcp://10.110.110.12:51863", + "coaps+tcp://10.110.110.12:38145" + ], + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "id": "4a0d78b2-9a21-557d-ab08-bb4eaccfcbb0", + "creationDate": "1716656687662199144", + "credential": { + "status": { + "date": "1717157743461436598", + "coapCode": 68 + }, + "identityCertificatePem": "-----BEGIN CERTIFICATE-----\nMIIBojCCAUigAwIBAgIQIm1TIO0PH7O+w+LXTfV1KTAKBggqhkjOPQQDAjASMRAw\nDgYDVQQDEwdwbGdkLWNhMB4XDTI0MDUzMTExMTU0M1oXDTI1MDUyNTE3MDI1MVow\nNDEyMDAGA1UEAxMpdXVpZDpiY2QzMDk3Ni0xMGU0LTQxNDUtNTI4Mi1lYjUwZWU1\nNWRmYWUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQK9W+P4MDWdABFVSgZOWnW\nDGEkU8abmg2zVW1MlGPZF4YKpKWEUIoqeVxpm5D/yKtzG15uuvx3U2oU3UbRGL5t\no14wXDAOBgNVHQ8BAf8EBAMCA4gwKQYDVR0lBCIwIAYIKwYBBQUHAwIGCCsGAQUF\nBwMBBgorBgEEAYLefAEGMB8GA1UdIwQYMBaAFCM9S7rizy2ArYhiARButOX7DTPa\nMAoGCCqGSM49BAMCA0gAMEUCIBMdkdXzDBJgThKP3Q1hTV/XzigwlSe7+YlXoINl\ngW8DAiEA7f9ghvAZzBbep1sMDmcTFFLquzAPNsRBSCkSquyYUNQ=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIBkDCCATagAwIBAgIQFq/ergts3Jlaxk3N92FfzTAKBggqhkjOPQQDAjAdMRsw\nGQYDVQQDExJyb290LmNhLnBsZ2QuY2xvdWQwHhcNMjQwNTI1MTcwMjUxWhcNMjUw\nNTI1MTcwMjUxWjASMRAwDgYDVQQDEwdwbGdkLWNhMFkwEwYHKoZIzj0CAQYIKoZI\nzj0DAQcDQgAE5s5zak9SL6OCMM49iyJYpNvnHly3UVdTe4jaAxmMS2YM63e68Cix\nevhl849SzCnpoD9yJzFA2HmhEc82IVt66KNjMGEwDgYDVR0PAQH/BAQDAgGGMA8G\nA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCM9S7rizy2ArYhiARButOX7DTPaMB8G\nA1UdIwQYMBaAFELK01Gtmvz99kTvIM5idzOLxerIMAoGCCqGSM49BAMCA0gAMEUC\nIG4Cnqkb+atbFIAeTFyIR4v3ABi0CjPub07xnt/bvN6FAiEAxgyW5sibfw7z3/xc\nQnA0w68sKmVRZhvfUNMYkqbk/2w=\n-----END CERTIFICATE-----\n", + "credentials": [ + { + "type": [ + "ASYMMETRIC_SIGNING_WITH_CERTIFICATE" + ], + "usage": "CERT", + "publicData": { + "data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJvakNDQVVpZ0F3SUJBZ0lRSW0xVElPMFBIN08rdytMWFRmVjFLVEFLQmdncWhrak9QUVFEQWpBU01SQXcKRGdZRFZRUURFd2R3Ykdka0xXTmhNQjRYRFRJME1EVXpNVEV4TVRVME0xb1hEVEkxTURVeU5URTNNREkxTVZvdwpOREV5TURBR0ExVUVBeE1wZFhWcFpEcGlZMlF6TURrM05pMHhNR1UwTFRReE5EVXROVEk0TWkxbFlqVXdaV1UxCk5XUm1ZV1V3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFLOVcrUDRNRFdkQUJGVlNnWk9XblcKREdFa1U4YWJtZzJ6VlcxTWxHUFpGNFlLcEtXRVVJb3FlVnhwbTVEL3lLdHpHMTV1dXZ4M1Uyb1UzVWJSR0w1dApvMTR3WERBT0JnTlZIUThCQWY4RUJBTUNBNGd3S1FZRFZSMGxCQ0l3SUFZSUt3WUJCUVVIQXdJR0NDc0dBUVVGCkJ3TUJCZ29yQmdFRUFZTGVmQUVHTUI4R0ExVWRJd1FZTUJhQUZDTTlTN3JpenkyQXJZaGlBUkJ1dE9YN0RUUGEKTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUJNZGtkWHpEQkpnVGhLUDNRMWhUVi9Yemlnd2xTZTcrWWxYb0lObApnVzhEQWlFQTdmOWdodkFaekJiZXAxc01EbWNURkZMcXV6QVBOc1JCU0NrU3F1eVlVTlE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrRENDQVRhZ0F3SUJBZ0lRRnEvZXJndHMzSmxheGszTjkyRmZ6VEFLQmdncWhrak9QUVFEQWpBZE1Sc3cKR1FZRFZRUURFeEp5YjI5MExtTmhMbkJzWjJRdVkyeHZkV1F3SGhjTk1qUXdOVEkxTVRjd01qVXhXaGNOTWpVdwpOVEkxTVRjd01qVXhXakFTTVJBd0RnWURWUVFERXdkd2JHZGtMV05oTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJCnpqMERBUWNEUWdBRTVzNXphazlTTDZPQ01NNDlpeUpZcE52bkhseTNVVmRUZTRqYUF4bU1TMllNNjNlNjhDaXgKZXZobDg0OVN6Q25wb0Q5eUp6RkEySG1oRWM4MklWdDY2S05qTUdFd0RnWURWUjBQQVFIL0JBUURBZ0dHTUE4RwpBMVVkRXdFQi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZDTTlTN3JpenkyQXJZaGlBUkJ1dE9YN0RUUGFNQjhHCkExVWRJd1FZTUJhQUZFTEswMUd0bXZ6OTlrVHZJTTVpZHpPTHhlcklNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUMKSUc0Q25xa2IrYXRiRklBZVRGeUlSNHYzQUJpMENqUHViMDd4bnQvYnZONkZBaUVBeGd5VzVzaWJmdzd6My94YwpRbkEwdzY4c0ttVlJaaHZmVU5NWWtxYmsvMnc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "encoding": "PEM" + }, + "id": "0", + "subject": "bcd30976-10e4-4145-5282-eb50ee55dfae" + }, + { + "publicData": { + "data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNPZ0F3SUJBZ0lSQUlwR0Jrb0U2ZXdwdFJMT1FaMXZrb1V3Q2dZSUtvWkl6ajBFQXdJd0hURWIKTUJrR0ExVUVBeE1TY205dmRDNWpZUzV3Ykdka0xtTnNiM1ZrTUNBWERUSXpNVEF4T1RBNE5EZ3hOVm9ZRHpJeApNak13T1RJMU1EZzBPREUxV2pBZE1Sc3dHUVlEVlFRREV4SnliMjkwTG1OaExuQnNaMlF1WTJ4dmRXUXdXVEFUCkJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFtMHgrMTZCdWt2ditIV0FlcnkvMG8vVlFBTzhib3hzNHcKT2lhWFRybDBhbi9iUkR6REFwc1J2cDY5SHdJY2haS0FjZTVPQ3JkZFNpVVJOdDZRZWYwQ28wSXdRREFPQmdOVgpIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVUXNyVFVhMmEvUDMyClJPOGd6bUozTTR2RjZzZ3dDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWdOMHBnS1N4d2RvUklkV1RxaTdUcDd0eVAKb05LNERxeElsWWJuRUlJb3BlZ0NJUURsd2FUMmg2RUtaM1R3SHFBcTU1UXl3TDM3RzJwdjVKOE03dDFFcVBnQQpZQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "encoding": "PEM" + }, + "id": "0", + "subject": "beb32777-9680-4f42-8761-350eebe76a85", + "usage": "TRUST_CA", + "type": [ + "ASYMMETRIC_SIGNING_WITH_CERTIFICATE" + ] + } + ] + }, + "plgdTime": { + "date": "1717157743283612068", + "coapCode": 69 + } + } +} \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/dps/provisioning-records/detail/69f23484-171a-56a9-b300-89cd3007a70c.json b/http-gateway/web/packages/mock-server/src/data/dps/provisioning-records/detail/69f23484-171a-56a9-b300-89cd3007a70c.json new file mode 100644 index 000000000..7c7b62a56 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/dps/provisioning-records/detail/69f23484-171a-56a9-b300-89cd3007a70c.json @@ -0,0 +1,250 @@ +{ + "result": { + "localEndpoints": [ + "coap://10.110.110.12:41885", + "coaps://10.110.110.12:49997", + "coap+tcp://10.110.110.12:35389", + "coaps+tcp://10.110.110.12:33711" + ], + "deviceId": "d9dde79c-3916-433b-4789-ca10aad6fc4a", + "creationDate": "1716652467413672050", + "attestation": { + "date": "1719474938251929779", + "x509": { + "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIBgjCCASmgAwIBAgIQdYzG5cWdt18FWrG0WxBqNzAKBggqhkjOPQQDAjAUMRIw\nEAYDVQQDEwlNZmdSb290Q0EwIBcNMjMxMTA2MDcyNzU5WhgPMjEyMzEwMTMwNzI3\nNTlaMBIxEDAOBgNVBAMTB01mZ0NlcnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\nAAQMkz/uQi1sbMmuxgagH/A5II6CcxZz9sWpSjuxLEqPNEbL021yUaQX6/U2GBYs\npFVWzGPWIog30mgGq/jvDyQKo10wWzAfBgNVHSMEGDAWgBRchhQ5bzFpRdMG/NMg\nyH20R+5UzzAMBgNVHRMEBTADAQEAMAsGA1UdDwQEAwIDiDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwCgYIKoZIzj0EAwIDRwAwRAIgbqEU4iOhHpD4YnjC\nO5J8lTIw+RbZ+r9uZD1K2fz4ZfkCIGFzidJQAmBSPVvEdK4X4CSf76BjEoRwXxm2\nKaeI8Vkl\n-----END CERTIFICATE-----\n", + "commonName": "MfgCert" + } + }, + "cloud": { + "status": { + "coapCode": 68, + "date": "1719474938285092512" + }, + "providerName": "plgd.dps", + "gateways": [ + { + "uri": "coaps+tcp://try.plgd.cloud:5684", + "id": "1c10a3b6-287c-11ec-ac2d-13054959c274" + } + ], + "selectedGateway": 0 + }, + "ownership": { + "status": { + "date": "1719474938266133666", + "coapCode": 69 + }, + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "plgdTime": { + "date": "1719474938192355476", + "coapCode": 69 + }, + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "id": "69f23484-171a-56a9-b300-89cd3007a70c", + "enrollmentGroupId": "4f0d3d81-0e09-4f1e-9706-0997488011af", + "credential": { + "status": { + "date": "1719474938324358862", + "coapCode": 68 + }, + "identityCertificatePem": "-----BEGIN CERTIFICATE-----\nMIIBpDCCAUmgAwIBAgIRAPJNdAgYEQhNPjTxlF3/1v0wCgYIKoZIzj0EAwIwEjEQ\nMA4GA1UEAxMHcGxnZC1jYTAeFw0yNDA2MjcwNjU1MzhaFw0yNTA1MjUxNzAyNTFa\nMDQxMjAwBgNVBAMTKXV1aWQ6ZDlkZGU3OWMtMzkxNi00MzNiLTQ3ODktY2ExMGFh\nZDZmYzRhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaWg0Wurmnrl8LTvARHc+\nCu8eiLBIsKXp/RALqr2htsFK0jlkStpuxMWfSofbTiY/8gD1YmM3Q833CL0Sg+C5\nZaNeMFwwDgYDVR0PAQH/BAQDAgOIMCkGA1UdJQQiMCAGCCsGAQUFBwMCBggrBgEF\nBQcDAQYKKwYBBAGC3nwBBjAfBgNVHSMEGDAWgBQjPUu64s8tgK2IYgEQbrTl+w0z\n2jAKBggqhkjOPQQDAgNJADBGAiEA/bvt26yZJozHeXJGusuH4HLZd4eAkQy7Bc9x\nSmt3UukCIQDx9g2DUPECP/20MV18FKkitUAN3Ed4tB/gmX17tCBuQw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIBkDCCATagAwIBAgIQFq/ergts3Jlaxk3N92FfzTAKBggqhkjOPQQDAjAdMRsw\nGQYDVQQDExJyb290LmNhLnBsZ2QuY2xvdWQwHhcNMjQwNTI1MTcwMjUxWhcNMjUw\nNTI1MTcwMjUxWjASMRAwDgYDVQQDEwdwbGdkLWNhMFkwEwYHKoZIzj0CAQYIKoZI\nzj0DAQcDQgAE5s5zak9SL6OCMM49iyJYpNvnHly3UVdTe4jaAxmMS2YM63e68Cix\nevhl849SzCnpoD9yJzFA2HmhEc82IVt66KNjMGEwDgYDVR0PAQH/BAQDAgGGMA8G\nA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCM9S7rizy2ArYhiARButOX7DTPaMB8G\nA1UdIwQYMBaAFELK01Gtmvz99kTvIM5idzOLxerIMAoGCCqGSM49BAMCA0gAMEUC\nIG4Cnqkb+atbFIAeTFyIR4v3ABi0CjPub07xnt/bvN6FAiEAxgyW5sibfw7z3/xc\nQnA0w68sKmVRZhvfUNMYkqbk/2w=\n-----END CERTIFICATE-----\n", + "credentials": [ + { + "type": [ + "ASYMMETRIC_SIGNING_WITH_CERTIFICATE" + ], + "usage": "CERT", + "id": "0", + "subject": "d9dde79c-3916-433b-4789-ca10aad6fc4a", + "publicData": { + "data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJwRENDQVVtZ0F3SUJBZ0lSQVBKTmRBZ1lFUWhOUGpUeGxGMy8xdjB3Q2dZSUtvWkl6ajBFQXdJd0VqRVEKTUE0R0ExVUVBeE1IY0d4blpDMWpZVEFlRncweU5EQTJNamN3TmpVMU16aGFGdzB5TlRBMU1qVXhOekF5TlRGYQpNRFF4TWpBd0JnTlZCQU1US1hWMWFXUTZaRGxrWkdVM09XTXRNemt4TmkwME16TmlMVFEzT0RrdFkyRXhNR0ZoClpEWm1ZelJoTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFYVdnMFd1cm1ucmw4TFR2QVJIYysKQ3U4ZWlMQklzS1hwL1JBTHFyMmh0c0ZLMGpsa1N0cHV4TVdmU29mYlRpWS84Z0QxWW1NM1E4MzNDTDBTZytDNQpaYU5lTUZ3d0RnWURWUjBQQVFIL0JBUURBZ09JTUNrR0ExVWRKUVFpTUNBR0NDc0dBUVVGQndNQ0JnZ3JCZ0VGCkJRY0RBUVlLS3dZQkJBR0MzbndCQmpBZkJnTlZIU01FR0RBV2dCUWpQVXU2NHM4dGdLMklZZ0VRYnJUbCt3MHoKMmpBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQS9idnQyNnlaSm96SGVYSkd1c3VINEhMWmQ0ZUFrUXk3QmM5eApTbXQzVXVrQ0lRRHg5ZzJEVVBFQ1AvMjBNVjE4RktraXRVQU4zRWQ0dEIvZ21YMTd0Q0J1UXc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlCa0RDQ0FUYWdBd0lCQWdJUUZxL2VyZ3RzM0psYXhrM045MkZmelRBS0JnZ3Foa2pPUFFRREFqQWRNUnN3CkdRWURWUVFERXhKeWIyOTBMbU5oTG5Cc1oyUXVZMnh2ZFdRd0hoY05NalF3TlRJMU1UY3dNalV4V2hjTk1qVXcKTlRJMU1UY3dNalV4V2pBU01SQXdEZ1lEVlFRREV3ZHdiR2RrTFdOaE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSQp6ajBEQVFjRFFnQUU1czV6YWs5U0w2T0NNTTQ5aXlKWXBOdm5IbHkzVVZkVGU0amFBeG1NUzJZTTYzZTY4Q2l4CmV2aGw4NDlTekNucG9EOXlKekZBMkhtaEVjODJJVnQ2NktOak1HRXdEZ1lEVlIwUEFRSC9CQVFEQWdHR01BOEcKQTFVZEV3RUIvd1FGTUFNQkFmOHdIUVlEVlIwT0JCWUVGQ005UzdyaXp5MkFyWWhpQVJCdXRPWDdEVFBhTUI4RwpBMVVkSXdRWU1CYUFGRUxLMDFHdG12ejk5a1R2SU01aWR6T0x4ZXJJTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDCklHNENucWtiK2F0YkZJQWVURnlJUjR2M0FCaTBDalB1YjA3eG50L2J2TjZGQWlFQXhneVc1c2liZnc3ejMveGMKUW5BMHc2OHNLbVZSWmh2ZlVOTVlrcWJrLzJ3PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==", + "encoding": "PEM" + } + }, + { + "publicData": { + "data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNPZ0F3SUJBZ0lSQUlwR0Jrb0U2ZXdwdFJMT1FaMXZrb1V3Q2dZSUtvWkl6ajBFQXdJd0hURWIKTUJrR0ExVUVBeE1TY205dmRDNWpZUzV3Ykdka0xtTnNiM1ZrTUNBWERUSXpNVEF4T1RBNE5EZ3hOVm9ZRHpJeApNak13T1RJMU1EZzBPREUxV2pBZE1Sc3dHUVlEVlFRREV4SnliMjkwTG1OaExuQnNaMlF1WTJ4dmRXUXdXVEFUCkJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFtMHgrMTZCdWt2ditIV0FlcnkvMG8vVlFBTzhib3hzNHcKT2lhWFRybDBhbi9iUkR6REFwc1J2cDY5SHdJY2haS0FjZTVPQ3JkZFNpVVJOdDZRZWYwQ28wSXdRREFPQmdOVgpIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVUXNyVFVhMmEvUDMyClJPOGd6bUozTTR2RjZzZ3dDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWdOMHBnS1N4d2RvUklkV1RxaTdUcDd0eVAKb05LNERxeElsWWJuRUlJb3BlZ0NJUURsd2FUMmg2RUtaM1R3SHFBcTU1UXl3TDM3RzJwdjVKOE03dDFFcVBnQQpZQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "encoding": "PEM" + }, + "subject": "beb32777-9680-4f42-8761-350eebe76a85", + "type": [ + "ASYMMETRIC_SIGNING_WITH_CERTIFICATE" + ], + "usage": "TRUST_CA", + "id": "0" + } + ] + }, + "acl": { + "accessControlList": [ + { + "deviceSubject": { + "deviceId": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "permissions": [ + "CREATE", + "READ", + "WRITE", + "DELETE", + "NOTIFY" + ], + "resources": [ + { + "href": "/CoapCloudConfResURI", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/sec/sp" + }, + { + "wildcard": "NONE", + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ] + }, + { + "href": "/oc/con", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oc/swu", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oic/mnt", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/x.plgd.dev/time" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONCFG_ALL" + } + ] + }, + { + "resources": [ + { + "href": "/oic/d", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/p" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/res" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/sec/sdi" + }, + { + "href": "/oic/sec/doxm", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + } + ], + "connectionSubject": { + "type": "ANON_CLEAR" + }, + "permissions": [ + "READ" + ] + }, + { + "permissions": [ + "CREATE", + "READ", + "WRITE", + "DELETE", + "NOTIFY" + ], + "resources": [ + { + "wildcard": "NONE", + "href": "/oc/con", + "interfaces": [ + "*" + ] + }, + { + "wildcard": "NONE", + "href": "/oc/swu", + "interfaces": [ + "*" + ] + }, + { + "href": "/oic/mnt", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONCFG_ALL" + } + ], + "deviceSubject": { + "deviceId": "1c10a3b6-287c-11ec-ac2d-13054959c274" + } + } + ], + "status": { + "date": "1719474938340859252", + "coapCode": 69 + } + } + } +} \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/dps/provisioning-records/list/list.json b/http-gateway/web/packages/mock-server/src/data/dps/provisioning-records/list/list.json new file mode 100644 index 000000000..b337d0998 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/dps/provisioning-records/list/list.json @@ -0,0 +1,501 @@ +[ + { + "result": { + "enrollmentGroupId": "4f0d3d81-0e09-4f1e-9706-0997488011af", + "creationDate": "1716652467413672050", + "attestation": { + "date": "1719474938251929779", + "x509": { + "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIBgjCCASmgAwIBAgIQdYzG5cWdt18FWrG0WxBqNzAKBggqhkjOPQQDAjAUMRIw\nEAYDVQQDEwlNZmdSb290Q0EwIBcNMjMxMTA2MDcyNzU5WhgPMjEyMzEwMTMwNzI3\nNTlaMBIxEDAOBgNVBAMTB01mZ0NlcnQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC\nAAQMkz/uQi1sbMmuxgagH/A5II6CcxZz9sWpSjuxLEqPNEbL021yUaQX6/U2GBYs\npFVWzGPWIog30mgGq/jvDyQKo10wWzAfBgNVHSMEGDAWgBRchhQ5bzFpRdMG/NMg\nyH20R+5UzzAMBgNVHRMEBTADAQEAMAsGA1UdDwQEAwIDiDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwCgYIKoZIzj0EAwIDRwAwRAIgbqEU4iOhHpD4YnjC\nO5J8lTIw+RbZ+r9uZD1K2fz4ZfkCIGFzidJQAmBSPVvEdK4X4CSf76BjEoRwXxm2\nKaeI8Vkl\n-----END CERTIFICATE-----\n", + "commonName": "MfgCert" + } + }, + "cloud": { + "status": { + "coapCode": 68, + "date": "1719474938285092512" + }, + "providerName": "plgd.dps", + "gateways": [ + { + "id": "1c10a3b6-287c-11ec-ac2d-13054959c274", + "uri": "coaps+tcp://try.plgd.cloud:5684" + } + ], + "selectedGateway": 0 + }, + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "id": "69f23484-171a-56a9-b300-89cd3007a70c", + "deviceId": "d9dde79c-3916-433b-4789-ca10aad6fc4a", + "credential": { + "status": { + "date": "1719474938324358862", + "coapCode": 68 + }, + "identityCertificatePem": "-----BEGIN CERTIFICATE-----\nMIIBpDCCAUmgAwIBAgIRAPJNdAgYEQhNPjTxlF3/1v0wCgYIKoZIzj0EAwIwEjEQ\nMA4GA1UEAxMHcGxnZC1jYTAeFw0yNDA2MjcwNjU1MzhaFw0yNTA1MjUxNzAyNTFa\nMDQxMjAwBgNVBAMTKXV1aWQ6ZDlkZGU3OWMtMzkxNi00MzNiLTQ3ODktY2ExMGFh\nZDZmYzRhMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEaWg0Wurmnrl8LTvARHc+\nCu8eiLBIsKXp/RALqr2htsFK0jlkStpuxMWfSofbTiY/8gD1YmM3Q833CL0Sg+C5\nZaNeMFwwDgYDVR0PAQH/BAQDAgOIMCkGA1UdJQQiMCAGCCsGAQUFBwMCBggrBgEF\nBQcDAQYKKwYBBAGC3nwBBjAfBgNVHSMEGDAWgBQjPUu64s8tgK2IYgEQbrTl+w0z\n2jAKBggqhkjOPQQDAgNJADBGAiEA/bvt26yZJozHeXJGusuH4HLZd4eAkQy7Bc9x\nSmt3UukCIQDx9g2DUPECP/20MV18FKkitUAN3Ed4tB/gmX17tCBuQw==\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIBkDCCATagAwIBAgIQFq/ergts3Jlaxk3N92FfzTAKBggqhkjOPQQDAjAdMRsw\nGQYDVQQDExJyb290LmNhLnBsZ2QuY2xvdWQwHhcNMjQwNTI1MTcwMjUxWhcNMjUw\nNTI1MTcwMjUxWjASMRAwDgYDVQQDEwdwbGdkLWNhMFkwEwYHKoZIzj0CAQYIKoZI\nzj0DAQcDQgAE5s5zak9SL6OCMM49iyJYpNvnHly3UVdTe4jaAxmMS2YM63e68Cix\nevhl849SzCnpoD9yJzFA2HmhEc82IVt66KNjMGEwDgYDVR0PAQH/BAQDAgGGMA8G\nA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCM9S7rizy2ArYhiARButOX7DTPaMB8G\nA1UdIwQYMBaAFELK01Gtmvz99kTvIM5idzOLxerIMAoGCCqGSM49BAMCA0gAMEUC\nIG4Cnqkb+atbFIAeTFyIR4v3ABi0CjPub07xnt/bvN6FAiEAxgyW5sibfw7z3/xc\nQnA0w68sKmVRZhvfUNMYkqbk/2w=\n-----END CERTIFICATE-----\n", + "credentials": [ + { + "type": [ + "ASYMMETRIC_SIGNING_WITH_CERTIFICATE" + ], + "publicData": { + "data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJwRENDQVVtZ0F3SUJBZ0lSQVBKTmRBZ1lFUWhOUGpUeGxGMy8xdjB3Q2dZSUtvWkl6ajBFQXdJd0VqRVEKTUE0R0ExVUVBeE1IY0d4blpDMWpZVEFlRncweU5EQTJNamN3TmpVMU16aGFGdzB5TlRBMU1qVXhOekF5TlRGYQpNRFF4TWpBd0JnTlZCQU1US1hWMWFXUTZaRGxrWkdVM09XTXRNemt4TmkwME16TmlMVFEzT0RrdFkyRXhNR0ZoClpEWm1ZelJoTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFYVdnMFd1cm1ucmw4TFR2QVJIYysKQ3U4ZWlMQklzS1hwL1JBTHFyMmh0c0ZLMGpsa1N0cHV4TVdmU29mYlRpWS84Z0QxWW1NM1E4MzNDTDBTZytDNQpaYU5lTUZ3d0RnWURWUjBQQVFIL0JBUURBZ09JTUNrR0ExVWRKUVFpTUNBR0NDc0dBUVVGQndNQ0JnZ3JCZ0VGCkJRY0RBUVlLS3dZQkJBR0MzbndCQmpBZkJnTlZIU01FR0RBV2dCUWpQVXU2NHM4dGdLMklZZ0VRYnJUbCt3MHoKMmpBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQS9idnQyNnlaSm96SGVYSkd1c3VINEhMWmQ0ZUFrUXk3QmM5eApTbXQzVXVrQ0lRRHg5ZzJEVVBFQ1AvMjBNVjE4RktraXRVQU4zRWQ0dEIvZ21YMTd0Q0J1UXc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCi0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLQpNSUlCa0RDQ0FUYWdBd0lCQWdJUUZxL2VyZ3RzM0psYXhrM045MkZmelRBS0JnZ3Foa2pPUFFRREFqQWRNUnN3CkdRWURWUVFERXhKeWIyOTBMbU5oTG5Cc1oyUXVZMnh2ZFdRd0hoY05NalF3TlRJMU1UY3dNalV4V2hjTk1qVXcKTlRJMU1UY3dNalV4V2pBU01SQXdEZ1lEVlFRREV3ZHdiR2RrTFdOaE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSQp6ajBEQVFjRFFnQUU1czV6YWs5U0w2T0NNTTQ5aXlKWXBOdm5IbHkzVVZkVGU0amFBeG1NUzJZTTYzZTY4Q2l4CmV2aGw4NDlTekNucG9EOXlKekZBMkhtaEVjODJJVnQ2NktOak1HRXdEZ1lEVlIwUEFRSC9CQVFEQWdHR01BOEcKQTFVZEV3RUIvd1FGTUFNQkFmOHdIUVlEVlIwT0JCWUVGQ005UzdyaXp5MkFyWWhpQVJCdXRPWDdEVFBhTUI4RwpBMVVkSXdRWU1CYUFGRUxLMDFHdG12ejk5a1R2SU01aWR6T0x4ZXJJTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDCklHNENucWtiK2F0YkZJQWVURnlJUjR2M0FCaTBDalB1YjA3eG50L2J2TjZGQWlFQXhneVc1c2liZnc3ejMveGMKUW5BMHc2OHNLbVZSWmh2ZlVOTVlrcWJrLzJ3PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==", + "encoding": "PEM" + }, + "id": "0", + "subject": "d9dde79c-3916-433b-4789-ca10aad6fc4a", + "usage": "CERT" + }, + { + "subject": "beb32777-9680-4f42-8761-350eebe76a85", + "usage": "TRUST_CA", + "id": "0", + "type": [ + "ASYMMETRIC_SIGNING_WITH_CERTIFICATE" + ], + "publicData": { + "data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNPZ0F3SUJBZ0lSQUlwR0Jrb0U2ZXdwdFJMT1FaMXZrb1V3Q2dZSUtvWkl6ajBFQXdJd0hURWIKTUJrR0ExVUVBeE1TY205dmRDNWpZUzV3Ykdka0xtTnNiM1ZrTUNBWERUSXpNVEF4T1RBNE5EZ3hOVm9ZRHpJeApNak13T1RJMU1EZzBPREUxV2pBZE1Sc3dHUVlEVlFRREV4SnliMjkwTG1OaExuQnNaMlF1WTJ4dmRXUXdXVEFUCkJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFtMHgrMTZCdWt2ditIV0FlcnkvMG8vVlFBTzhib3hzNHcKT2lhWFRybDBhbi9iUkR6REFwc1J2cDY5SHdJY2haS0FjZTVPQ3JkZFNpVVJOdDZRZWYwQ28wSXdRREFPQmdOVgpIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVUXNyVFVhMmEvUDMyClJPOGd6bUozTTR2RjZzZ3dDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWdOMHBnS1N4d2RvUklkV1RxaTdUcDd0eVAKb05LNERxeElsWWJuRUlJb3BlZ0NJUURsd2FUMmg2RUtaM1R3SHFBcTU1UXl3TDM3RzJwdjVKOE03dDFFcVBnQQpZQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "encoding": "PEM" + } + } + ] + }, + "acl": { + "status": { + "coapCode": 69, + "date": "1719474938340859252" + }, + "accessControlList": [ + { + "permissions": [ + "CREATE", + "READ", + "WRITE", + "DELETE", + "NOTIFY" + ], + "resources": [ + { + "href": "/CoapCloudConfResURI", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oic/sec/sp", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oc/con", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oc/swu", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/mnt" + }, + { + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONCFG_ALL" + } + ], + "deviceSubject": { + "deviceId": "beb32777-9680-4f42-8761-350eebe76a85" + } + }, + { + "connectionSubject": { + "type": "ANON_CLEAR" + }, + "permissions": [ + "READ" + ], + "resources": [ + { + "href": "/oic/d", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/p" + }, + { + "href": "/oic/res", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oic/sec/sdi", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "wildcard": "NONE", + "href": "/oic/sec/doxm", + "interfaces": [ + "*" + ] + } + ] + }, + { + "deviceSubject": { + "deviceId": "1c10a3b6-287c-11ec-ac2d-13054959c274" + }, + "permissions": [ + "CREATE", + "READ", + "WRITE", + "DELETE", + "NOTIFY" + ], + "resources": [ + { + "href": "/oc/con", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oc/swu", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/mnt" + }, + { + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONCFG_ALL" + } + ] + } + ] + }, + "ownership": { + "status": { + "coapCode": 69, + "date": "1719474938266133666" + }, + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "plgdTime": { + "date": "1719474938192355476", + "coapCode": 69 + }, + "localEndpoints": [ + "coap://10.110.110.12:41885", + "coaps://10.110.110.12:49997", + "coap+tcp://10.110.110.12:35389", + "coaps+tcp://10.110.110.12:33711" + ] + } + },{ + "result": { + "attestation": { + "date": "1717157743336135946", + "x509": { + "commonName": "MfgCert1", + "certificatePem": "-----BEGIN CERTIFICATE-----\nMIIBhTCCASugAwIBAgIRAJ+UC+MPMl6jc9FVeHZEgB4wCgYIKoZIzj0EAwIwFDES\nMBAGA1UEAxMJTWZnUm9vdENBMCAXDTIzMTIxMTEyNTIwMVoYDzIxMjMxMTE3MTI1\nMjAxWjATMREwDwYDVQQDEwhNZmdDZXJ0MTBZMBMGByqGSM49AgEGCCqGSM49AwEH\nA0IABFU2BHkqcNsiN68hGoFGzk+QtK78su3HpObu0U6Yhq5tnbGffQ4oTcel4Lhx\nlW5FHWUPI/l2LV9Ej/i3DSaurs6jXTBbMB8GA1UdIwQYMBaAFFyGFDlvMWlF0wb8\n0yDIfbRH7lTPMAwGA1UdEwQFMAMBAQAwCwYDVR0PBAQDAgOIMB0GA1UdJQQWMBQG\nCCsGAQUFBwMCBggrBgEFBQcDATAKBggqhkjOPQQDAgNIADBFAiBM31BMFp/ImqVt\nwH55aaqYSYp00pabSyIbKwFle6B+2wIhAMqXjZ3zoEECNU7zUo/hpYPTqanak2t6\ndPVwtlKcRlPx\n-----END CERTIFICATE-----\n" + } + }, + "cloud": { + "gateways": [ + { + "uri": "coaps+tcp://try.plgd.cloud:5684", + "id": "1c10a3b6-287c-11ec-ac2d-13054959c274" + } + ], + "selectedGateway": 0, + "status": { + "coapCode": 68, + "date": "1717157743426800468" + }, + "providerName": "plgd.dps" + }, + "ownership": { + "status": { + "date": "1717157743352900277", + "coapCode": 69 + }, + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "plgdTime": { + "date": "1717157743283612068", + "coapCode": 69 + }, + "id": "4a0d78b2-9a21-557d-ab08-bb4eaccfcbb0", + "deviceId": "bcd30976-10e4-4145-5282-eb50ee55dfae", + "creationDate": "1716656687662199144", + "localEndpoints": [ + "coap://10.110.110.12:45396", + "coaps://10.110.110.12:52852", + "coap+tcp://10.110.110.12:51863", + "coaps+tcp://10.110.110.12:38145" + ], + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "enrollmentGroupId": "4f0d3d81-0e09-4f1e-9706-0997488011af", + "credential": { + "identityCertificatePem": "-----BEGIN CERTIFICATE-----\nMIIBojCCAUigAwIBAgIQIm1TIO0PH7O+w+LXTfV1KTAKBggqhkjOPQQDAjASMRAw\nDgYDVQQDEwdwbGdkLWNhMB4XDTI0MDUzMTExMTU0M1oXDTI1MDUyNTE3MDI1MVow\nNDEyMDAGA1UEAxMpdXVpZDpiY2QzMDk3Ni0xMGU0LTQxNDUtNTI4Mi1lYjUwZWU1\nNWRmYWUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQK9W+P4MDWdABFVSgZOWnW\nDGEkU8abmg2zVW1MlGPZF4YKpKWEUIoqeVxpm5D/yKtzG15uuvx3U2oU3UbRGL5t\no14wXDAOBgNVHQ8BAf8EBAMCA4gwKQYDVR0lBCIwIAYIKwYBBQUHAwIGCCsGAQUF\nBwMBBgorBgEEAYLefAEGMB8GA1UdIwQYMBaAFCM9S7rizy2ArYhiARButOX7DTPa\nMAoGCCqGSM49BAMCA0gAMEUCIBMdkdXzDBJgThKP3Q1hTV/XzigwlSe7+YlXoINl\ngW8DAiEA7f9ghvAZzBbep1sMDmcTFFLquzAPNsRBSCkSquyYUNQ=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIBkDCCATagAwIBAgIQFq/ergts3Jlaxk3N92FfzTAKBggqhkjOPQQDAjAdMRsw\nGQYDVQQDExJyb290LmNhLnBsZ2QuY2xvdWQwHhcNMjQwNTI1MTcwMjUxWhcNMjUw\nNTI1MTcwMjUxWjASMRAwDgYDVQQDEwdwbGdkLWNhMFkwEwYHKoZIzj0CAQYIKoZI\nzj0DAQcDQgAE5s5zak9SL6OCMM49iyJYpNvnHly3UVdTe4jaAxmMS2YM63e68Cix\nevhl849SzCnpoD9yJzFA2HmhEc82IVt66KNjMGEwDgYDVR0PAQH/BAQDAgGGMA8G\nA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFCM9S7rizy2ArYhiARButOX7DTPaMB8G\nA1UdIwQYMBaAFELK01Gtmvz99kTvIM5idzOLxerIMAoGCCqGSM49BAMCA0gAMEUC\nIG4Cnqkb+atbFIAeTFyIR4v3ABi0CjPub07xnt/bvN6FAiEAxgyW5sibfw7z3/xc\nQnA0w68sKmVRZhvfUNMYkqbk/2w=\n-----END CERTIFICATE-----\n", + "credentials": [ + { + "publicData": { + "data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJvakNDQVVpZ0F3SUJBZ0lRSW0xVElPMFBIN08rdytMWFRmVjFLVEFLQmdncWhrak9QUVFEQWpBU01SQXcKRGdZRFZRUURFd2R3Ykdka0xXTmhNQjRYRFRJME1EVXpNVEV4TVRVME0xb1hEVEkxTURVeU5URTNNREkxTVZvdwpOREV5TURBR0ExVUVBeE1wZFhWcFpEcGlZMlF6TURrM05pMHhNR1UwTFRReE5EVXROVEk0TWkxbFlqVXdaV1UxCk5XUm1ZV1V3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFLOVcrUDRNRFdkQUJGVlNnWk9XblcKREdFa1U4YWJtZzJ6VlcxTWxHUFpGNFlLcEtXRVVJb3FlVnhwbTVEL3lLdHpHMTV1dXZ4M1Uyb1UzVWJSR0w1dApvMTR3WERBT0JnTlZIUThCQWY4RUJBTUNBNGd3S1FZRFZSMGxCQ0l3SUFZSUt3WUJCUVVIQXdJR0NDc0dBUVVGCkJ3TUJCZ29yQmdFRUFZTGVmQUVHTUI4R0ExVWRJd1FZTUJhQUZDTTlTN3JpenkyQXJZaGlBUkJ1dE9YN0RUUGEKTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUJNZGtkWHpEQkpnVGhLUDNRMWhUVi9Yemlnd2xTZTcrWWxYb0lObApnVzhEQWlFQTdmOWdodkFaekJiZXAxc01EbWNURkZMcXV6QVBOc1JCU0NrU3F1eVlVTlE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrRENDQVRhZ0F3SUJBZ0lRRnEvZXJndHMzSmxheGszTjkyRmZ6VEFLQmdncWhrak9QUVFEQWpBZE1Sc3cKR1FZRFZRUURFeEp5YjI5MExtTmhMbkJzWjJRdVkyeHZkV1F3SGhjTk1qUXdOVEkxTVRjd01qVXhXaGNOTWpVdwpOVEkxTVRjd01qVXhXakFTTVJBd0RnWURWUVFERXdkd2JHZGtMV05oTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJCnpqMERBUWNEUWdBRTVzNXphazlTTDZPQ01NNDlpeUpZcE52bkhseTNVVmRUZTRqYUF4bU1TMllNNjNlNjhDaXgKZXZobDg0OVN6Q25wb0Q5eUp6RkEySG1oRWM4MklWdDY2S05qTUdFd0RnWURWUjBQQVFIL0JBUURBZ0dHTUE4RwpBMVVkRXdFQi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZDTTlTN3JpenkyQXJZaGlBUkJ1dE9YN0RUUGFNQjhHCkExVWRJd1FZTUJhQUZFTEswMUd0bXZ6OTlrVHZJTTVpZHpPTHhlcklNQW9HQ0NxR1NNNDlCQU1DQTBnQU1FVUMKSUc0Q25xa2IrYXRiRklBZVRGeUlSNHYzQUJpMENqUHViMDd4bnQvYnZONkZBaUVBeGd5VzVzaWJmdzd6My94YwpRbkEwdzY4c0ttVlJaaHZmVU5NWWtxYmsvMnc9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "encoding": "PEM" + }, + "subject": "bcd30976-10e4-4145-5282-eb50ee55dfae", + "usage": "CERT", + "id": "0", + "type": [ + "ASYMMETRIC_SIGNING_WITH_CERTIFICATE" + ] + }, + { + "id": "0", + "type": [ + "ASYMMETRIC_SIGNING_WITH_CERTIFICATE" + ], + "subject": "beb32777-9680-4f42-8761-350eebe76a85", + "usage": "TRUST_CA", + "publicData": { + "data": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmVENDQVNPZ0F3SUJBZ0lSQUlwR0Jrb0U2ZXdwdFJMT1FaMXZrb1V3Q2dZSUtvWkl6ajBFQXdJd0hURWIKTUJrR0ExVUVBeE1TY205dmRDNWpZUzV3Ykdka0xtTnNiM1ZrTUNBWERUSXpNVEF4T1RBNE5EZ3hOVm9ZRHpJeApNak13T1RJMU1EZzBPREUxV2pBZE1Sc3dHUVlEVlFRREV4SnliMjkwTG1OaExuQnNaMlF1WTJ4dmRXUXdXVEFUCkJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFtMHgrMTZCdWt2ditIV0FlcnkvMG8vVlFBTzhib3hzNHcKT2lhWFRybDBhbi9iUkR6REFwc1J2cDY5SHdJY2haS0FjZTVPQ3JkZFNpVVJOdDZRZWYwQ28wSXdRREFPQmdOVgpIUThCQWY4RUJBTUNBUVl3RHdZRFZSMFRBUUgvQkFVd0F3RUIvekFkQmdOVkhRNEVGZ1FVUXNyVFVhMmEvUDMyClJPOGd6bUozTTR2RjZzZ3dDZ1lJS29aSXpqMEVBd0lEU0FBd1JRSWdOMHBnS1N4d2RvUklkV1RxaTdUcDd0eVAKb05LNERxeElsWWJuRUlJb3BlZ0NJUURsd2FUMmg2RUtaM1R3SHFBcTU1UXl3TDM3RzJwdjVKOE03dDFFcVBnQQpZQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K", + "encoding": "PEM" + } + } + ], + "status": { + "date": "1717157743461436598", + "coapCode": 68 + } + }, + "acl": { + "status": { + "date": "1717157743480774484", + "coapCode": 69 + }, + "accessControlList": [ + { + "permissions": [ + "CREATE", + "READ", + "WRITE", + "DELETE", + "NOTIFY" + ], + "resources": [ + { + "href": "/CoapCloudConfResURI", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oic/sec/sp", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oc/con", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oc/swu", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/mnt" + }, + { + "wildcard": "NONE", + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ] + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONCFG_ALL" + } + ], + "deviceSubject": { + "deviceId": "beb32777-9680-4f42-8761-350eebe76a85" + } + }, + { + "connectionSubject": { + "type": "ANON_CLEAR" + }, + "permissions": [ + "READ" + ], + "resources": [ + { + "href": "/oic/d", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "href": "/oic/p", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/res" + }, + { + "href": "/oic/sec/sdi", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONE", + "href": "/oic/sec/doxm" + } + ] + }, + { + "deviceSubject": { + "deviceId": "1c10a3b6-287c-11ec-ac2d-13054959c274" + }, + "permissions": [ + "CREATE", + "READ", + "WRITE", + "DELETE", + "NOTIFY" + ], + "resources": [ + { + "href": "/oc/con", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "wildcard": "NONE", + "href": "/oc/swu", + "interfaces": [ + "*" + ] + }, + { + "href": "/oic/mnt", + "interfaces": [ + "*" + ], + "wildcard": "NONE" + }, + { + "wildcard": "NONE", + "href": "/x.plgd.dev/time", + "interfaces": [ + "*" + ] + }, + { + "interfaces": [ + "*" + ], + "wildcard": "NONCFG_ALL" + } + ] + } + ] + } + } +} +] \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/pending-commands.json b/http-gateway/web/packages/mock-server/src/data/pending-commands.json index 0ab710b6d..f827e419f 100644 --- a/http-gateway/web/packages/mock-server/src/data/pending-commands.json +++ b/http-gateway/web/packages/mock-server/src/data/pending-commands.json @@ -1,50 +1,82 @@ [ { - "resourceUpdatePending": { - "resourceId": { - "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", - "href": "/light/1" - }, - "content": { - "state": false, - "power": 1, - "powera": 1, - "powerb": 1, - "powerc": 1, - "powerd": 1, - "powere": 1, - "powerf": 1, - "powerg": 1, - "powerh": 1, - "poweri": 1, - "powerj": 1, - "powerk": 1, - "powerl": 1, - "powerm": 1, - "powern": 1, - "powero": 1, - "powerp": 1, - "powerq": 1, - "powerr": 1, - "name": "Light" - }, - "auditContext": { - "correlationId": "a3e05bc0-205a-48b1-92ed-78ea0b23e78f", - "userId": "98120ad9-eefa-4b93-aa53-696420b639fd" - }, - "eventMetadata": { - "connectionId": "10.1.65.233:38320", - "sequence": "0", - "version": "4", - "timestamp": "1679950925732370668" - }, - "validUntil": "1679950935732388581", - "openTelemetryCarrier": { - "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" + "result": { + "resourceUpdatePending": { + "resourceId": { + "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", + "href": "/light/1" + }, + "content": { + "state": false, + "power": 1, + "powera": 1, + "powerb": 1, + "powerc": 1, + "powerd": 1, + "powere": 1, + "powerf": 1, + "powerg": 1, + "powerh": 1, + "poweri": 1, + "powerj": 1, + "powerk": 1, + "powerl": 1, + "powerm": 1, + "powern": 1, + "powero": 1, + "powerp": 1, + "powerq": 1, + "powerr": 1, + "name": "Light" + }, + "auditContext": { + "correlationId": "a3e05bc0-205a-48b1-92ed-78ea0b23e78f", + "userId": "98120ad9-eefa-4b93-aa53-696420b639fd" + }, + "eventMetadata": { + "connectionId": "10.1.65.233:38320", + "sequence": "0", + "version": "4", + "timestamp": "1679950925732370668" + }, + "validUntil": "1679950935732388581", + "openTelemetryCarrier": { + "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" + } + } + } +}, +{ + "result": { + "resourceUpdatePending": { + "resourceId": { + "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", + "href": "/light/1" + }, + "content": { + "state": false, + "power": 1, + "name": "Light" + }, + "auditContext": { + "correlationId": "a3e05bc0-205a-48b1-92ed-78ea0b23e78f", + "userId": "98120ad9-eefa-4b93-aa53-696420b639fd" + }, + "eventMetadata": { + "connectionId": "10.1.65.233:38320", + "sequence": "0", + "version": "4", + "timestamp": "1679950925732370668" + }, + "validUntil": "1679950935732388581", + "openTelemetryCarrier": { + "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" + } } } - }, - { +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -69,9 +101,11 @@ "openTelemetryCarrier": { "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } - } - }, - { + } +} +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -97,8 +131,10 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, - { +} +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -124,8 +160,10 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, - { + } +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -151,8 +189,10 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, - { + } +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -178,8 +218,10 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, - { + } +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -205,8 +247,10 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, - { +} +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -232,8 +276,10 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, - { +} +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -259,8 +305,10 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, - { +} +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -286,8 +334,10 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, - { +} +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -313,8 +363,10 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, - { +} +}, +{ + "result": { "resourceUpdatePending": { "resourceId": { "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", @@ -340,59 +392,59 @@ "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" } } - }, + } +}, { - "resourceUpdatePending": { - "resourceId": { - "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", - "href": "/light/1" - }, - "content": { - "state": false, - "power": 1, - "name": "Light" - }, - "auditContext": { - "correlationId": "a3e05bc0-205a-48b1-92ed-78ea0b23e78f", - "userId": "98120ad9-eefa-4b93-aa53-696420b639fd" - }, - "eventMetadata": { - "connectionId": "10.1.65.233:38320", - "sequence": "0", - "version": "4", - "timestamp": "1679950925732370668" - }, - "validUntil": "1679950935732388581", - "openTelemetryCarrier": { - "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" + "result": { + "resourceUpdatePending": { + "resourceId": { + "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", + "href": "/light/1" + }, + "content": { + "state": false, + "power": 1, + "name": "Light" + }, + "auditContext": { + "correlationId": "a3e05bc0-205a-48b1-92ed-78ea0b23e78f", + "userId": "98120ad9-eefa-4b93-aa53-696420b639fd" + }, + "eventMetadata": { + "connectionId": "10.1.65.233:38320", + "sequence": "0", + "version": "4", + "timestamp": "1679950925732370668" + }, + "validUntil": "1679950935732388581", + "openTelemetryCarrier": { + "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" + } } } }, { - "resourceUpdatePending": { - "resourceId": { - "deviceId": "9c387d90-6ca4-4473-4b6c-f4fb2f8ad0e9", - "href": "/light/1" - }, - "content": { - "state": false, - "power": 1, - "name": "Light" - }, - "auditContext": { - "correlationId": "a3e05bc0-205a-48b1-92ed-78ea0b23e78f", - "userId": "98120ad9-eefa-4b93-aa53-696420b639fd" - }, - "eventMetadata": { - "connectionId": "10.1.65.233:38320", - "sequence": "0", - "version": "4", - "timestamp": "1679950925732370668" - }, - "validUntil": "1679950935732388581", - "openTelemetryCarrier": { - "traceparent": "00-8177df6ddb079f50d1eef17eb893b048-992be580d42978b1-01" + "result": { + "resourceUpdatePending": { + "eventMetadata": { + "version": "2", + "timestamp": "1718962348706048929", + "connectionId": "48998f7d-2a70-46a4-8a68-745b69d55489", + "sequence": "0", + "hubId": "1c10a3b6-287c-11ec-ac2d-13054959c274" + }, + "validUntil": "1719480748706050211", + "resourceId": { + "deviceId": "bcd30976-10e4-4145-5282-eb50ee55dfae", + "href": "/not/existing" + }, + "content": 123456, + "auditContext": { + "correlationId": "b3e46873-228b-403e-ad91-b5f97be3b3d7", + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "userId": "beb32777-9680-4f42-8761-350eebe76a85" + } } } } -] \ No newline at end of file +] diff --git a/http-gateway/web/packages/mock-server/src/data/snippet-service/applied-configurations/list/httpConfigurationIdFilter-48998f7d-2a70-46a4-8a68-745b69d55489.json b/http-gateway/web/packages/mock-server/src/data/snippet-service/applied-configurations/list/httpConfigurationIdFilter-48998f7d-2a70-46a4-8a68-745b69d55489.json new file mode 100644 index 000000000..f56e8a539 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/snippet-service/applied-configurations/list/httpConfigurationIdFilter-48998f7d-2a70-46a4-8a68-745b69d55489.json @@ -0,0 +1,272 @@ +[ + { + "result": { + "resources": [ + { + "resourceUpdated": { + "auditContext": { + "correlationId": "8d140cad-62ac-4fff-aa8f-48f413ca85ca.412a4dd7-3c9b-4dcb-9696-1f0eb6918a6d", + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "eventMetadata": { + "version": "0", + "timestamp": "0", + "connectionId": "48998f7d-2a70-46a4-8a68-745b69d55489", + "sequence": "0" + }, + "resourceId": { + "deviceId": "7b645eab-01c3-483a-6289-98fc24e32bc1", + "href": "/not/existing" + }, + "status": "ERROR", + "content": "pending resource update canceled" + }, + "validUntil": "0", + "href": "/not/existing", + "correlationId": "8d140cad-62ac-4fff-aa8f-48f413ca85ca.412a4dd7-3c9b-4dcb-9696-1f0eb6918a6d", + "status": "DONE" + }, + { + "status": "DONE", + "resourceUpdated": { + "resourceId": { + "deviceId": "7b645eab-01c3-483a-6289-98fc24e32bc1", + "href": "/oc/con" + }, + "status": "CANCELED", + "auditContext": { + "userId": "beb32777-9680-4f42-8761-350eebe76a85", + "correlationId": "8d140cad-62ac-4fff-aa8f-48f413ca85ca.55d8f61c-f85b-4a0c-aaba-c77f237600dd", + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "eventMetadata": { + "version": "2", + "timestamp": "1719582951907143230", + "connectionId": "10.1.65.223:46696", + "sequence": "0", + "hubId": "1c10a3b6-287c-11ec-ac2d-13054959c274" + }, + "resourceTypes": [ + "oic.wk.con" + ] + }, + "validUntil": "0", + "href": "/oc/con", + "correlationId": "8d140cad-62ac-4fff-aa8f-48f413ca85ca.55d8f61c-f85b-4a0c-aaba-c77f237600dd" + } + ], + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "timestamp": "1719817002027697453", + "id": "8d140cad-62ac-4fff-aa8f-48f413ca85ca", + "deviceId": "7b645eab-01c3-483a-6289-98fc24e32bc1", + "configurationId": { + "id": "48998f7d-2a70-46a4-8a68-745b69d55489", + "version": "0" + }, + "onDemand": true + } + }, + { + "result": { + "onDemand": true, + "resources": [ + { + "href": "/not/existing", + "correlationId": "0f9dc817-333f-4556-9888-c01ed2676478.dd79c0ab-004f-43e3-bc03-58c8c44c6fcd", + "status": "DONE", + "resourceUpdated": { + "status": "ERROR", + "content": "pending resource update canceled", + "auditContext": { + "correlationId": "0f9dc817-333f-4556-9888-c01ed2676478.dd79c0ab-004f-43e3-bc03-58c8c44c6fcd", + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "eventMetadata": { + "connectionId": "48998f7d-2a70-46a4-8a68-745b69d55489", + "sequence": "0", + "version": "0", + "timestamp": "0" + }, + "resourceId": { + "deviceId": "bcd30976-10e4-4145-5282-eb50ee55dfae", + "href": "/not/existing" + } + }, + "validUntil": "0" + }, + { + "href": "/oc/con", + "correlationId": "0f9dc817-333f-4556-9888-c01ed2676478.75be0ddc-e1e0-4738-9a88-b704ae0fc248", + "status": "DONE", + "resourceUpdated": { + "resourceTypes": [ + "oic.wk.con" + ], + "resourceId": { + "deviceId": "bcd30976-10e4-4145-5282-eb50ee55dfae", + "href": "/oc/con" + }, + "status": "OK", + "content": { + "n": "prezentacia dankovi" + }, + "auditContext": { + "userId": "1e3a67e3-ec52-42e2-8bb0-aae61d4af7c8", + "correlationId": "0f9dc817-333f-4556-9888-c01ed2676478.75be0ddc-e1e0-4738-9a88-b704ae0fc248", + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "eventMetadata": { + "version": "281", + "timestamp": "1719595063306772686", + "connectionId": "10.110.110.10:30226", + "sequence": "10159", + "hubId": "1c10a3b6-287c-11ec-ac2d-13054959c274" + } + }, + "validUntil": "0" + } + ], + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "timestamp": "1719817002006350403", + "id": "0f9dc817-333f-4556-9888-c01ed2676478", + "deviceId": "bcd30976-10e4-4145-5282-eb50ee55dfae", + "configurationId": { + "id": "48998f7d-2a70-46a4-8a68-745b69d55489", + "version": "0" + } + } +}, + { + "result": { + "deviceId": "d9dde79c-3916-433b-4789-ca10aad6fc4a", + "configurationId": { + "id": "48998f7d-2a70-46a4-8a68-745b69d55489", + "version": "0" + }, + "onDemand": true, + "resources": [ + { + "status": "DONE", + "resourceUpdated": { + "resourceId": { + "deviceId": "d9dde79c-3916-433b-4789-ca10aad6fc4a", + "href": "/not/existing" + }, + "status": "ERROR", + "content": "pending resource update canceled", + "auditContext": { + "correlationId": "9dae740f-a598-4411-8cd0-cbf7c804426a.a0c76318-6f04-4c04-9c98-c0f87a0e8a1f", + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "eventMetadata": { + "connectionId": "48998f7d-2a70-46a4-8a68-745b69d55489", + "sequence": "0", + "version": "0", + "timestamp": "0" + } + }, + "validUntil": "0", + "href": "/not/existing", + "correlationId": "9dae740f-a598-4411-8cd0-cbf7c804426a.a0c76318-6f04-4c04-9c98-c0f87a0e8a1f" + }, + { + "status": "DONE", + "resourceUpdated": { + "resourceId": { + "deviceId": "d9dde79c-3916-433b-4789-ca10aad6fc4a", + "href": "/oc/con" + }, + "status": "OK", + "content": { + "n": "prezentacia dankovi" + }, + "auditContext": { + "correlationId": "9dae740f-a598-4411-8cd0-cbf7c804426a.38e0d0de-4b86-468f-8a61-e7e5df3edf98", + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "userId": "1e3a67e3-ec52-42e2-8bb0-aae61d4af7c8" + }, + "eventMetadata": { + "version": "5", + "timestamp": "1719595063306023868", + "connectionId": "10.110.110.10:56076", + "sequence": "10153", + "hubId": "1c10a3b6-287c-11ec-ac2d-13054959c274" + }, + "resourceTypes": [ + "oic.wk.con" + ] + }, + "validUntil": "0", + "href": "/oc/con", + "correlationId": "9dae740f-a598-4411-8cd0-cbf7c804426a.38e0d0de-4b86-468f-8a61-e7e5df3edf98" + } + ], + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "timestamp": "1719817002023535166", + "id": "9dae740f-a598-4411-8cd0-cbf7c804426a" + } +}, + { + "result": { + "timestamp": "1719595103190656748", + "id": "40cab4b8-e9d6-47d7-bd70-4daa85c094ad", + "deviceId": "wdsw", + "configurationId": { + "id": "48998f7d-2a70-46a4-8a68-745b69d55489", + "version": "0" + }, + "onDemand": true, + "resources": [ + { + "validUntil": "0", + "href": "/not/existing", + "correlationId": "40cab4b8-e9d6-47d7-bd70-4daa85c094ad.18830e29-5204-4fc9-a76f-91ab65409431", + "status": "DONE", + "resourceUpdated": { + "status": "ERROR", + "content": "rpc error: code = PermissionDenied desc = cannot validate user access: rpc error: code = PermissionDenied desc = access denied", + "auditContext": { + "correlationId": "40cab4b8-e9d6-47d7-bd70-4daa85c094ad.18830e29-5204-4fc9-a76f-91ab65409431", + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "eventMetadata": { + "version": "0", + "timestamp": "0", + "connectionId": "48998f7d-2a70-46a4-8a68-745b69d55489", + "sequence": "0" + }, + "resourceId": { + "deviceId": "wdsw", + "href": "/not/existing" + } + } + }, + { + "href": "/oc/con", + "correlationId": "40cab4b8-e9d6-47d7-bd70-4daa85c094ad.d4de7422-8543-4a67-bb25-4f41e1fc7e6d", + "status": "DONE", + "resourceUpdated": { + "resourceId": { + "deviceId": "wdsw", + "href": "/oc/con" + }, + "status": "ERROR", + "content": "rpc error: code = PermissionDenied desc = cannot validate user access: rpc error: code = PermissionDenied desc = access denied", + "auditContext": { + "correlationId": "40cab4b8-e9d6-47d7-bd70-4daa85c094ad.d4de7422-8543-4a67-bb25-4f41e1fc7e6d", + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + }, + "eventMetadata": { + "sequence": "0", + "version": "0", + "timestamp": "0", + "connectionId": "48998f7d-2a70-46a4-8a68-745b69d55489" + } + }, + "validUntil": "0" + } + ], + "owner": "beb32777-9680-4f42-8761-350eebe76a85" + } +} +] \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/snippet-service/conditions/list/list.json b/http-gateway/web/packages/mock-server/src/data/snippet-service/conditions/list/list.json new file mode 100644 index 000000000..2667ea980 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/snippet-service/conditions/list/list.json @@ -0,0 +1,18 @@ +[ + { + "result": { + "id": "00fa41ad-b3bf-4f00-bfe1-c71c439e4cda", + "enabled": true, + "jqExpressionFilter": ".n == \"new name value\"", + "version": "6", + "name": "jkralik-cond-0", + "configurationId": "48998f7d-2a70-46a4-8a68-745b69d55489", + "resourceHrefFilter": [ + "/oic/d" + ], + "apiAccessToken": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJRQkp3R192eHhVSUNXVjFlZjRlOHlFamgtVHZmYW1FWFBMZGt4WGtENU1jIn0.eyJleHAiOjE3MTk1MDE1MTcsImlhdCI6MTcxOTQ5NDMxNywiYXV0aF90aW1lIjoxNzE5NDc0NzA3LCJqdGkiOiJhM2UyYjU2OC0zYWY4LTQ2ZDMtOGJlOC1jMDMyYWU5NDM0YTgiLCJpc3MiOiJodHRwczovL2F1dGgucGxnZC5jbG91ZC9yZWFsbXMvc2hhcmVkIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImJlYjMyNzc3LTk2ODAtNGY0Mi04NzYxLTM1MGVlYmU3NmE4NSIsInR5cCI6IkJlYXJlciIsImF6cCI6IkxYWjlPaEtXV1JZcWYxMlcwQjVPWGR1cXQwMnEwempTIiwic2Vzc2lvbl9zdGF0ZSI6ImRlYzBhNjk5LWE2NWYtNDcxYy05MGMyLWNlZTAwM2VmMDIxMCIsImFjciI6IjAiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovLzEyNy4wLjAuMTozMDAwIiwiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwiaHR0cHM6Ly90cnkucGxnZC5jbG91ZCJdLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsiZGVmYXVsdC1yb2xlcy1zaGFyZWQiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJyb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJvcGVuaWQgZW1haWwgcHJvZmlsZSIsInNpZCI6ImRlYzBhNjk5LWE2NWYtNDcxYy05MGMyLWNlZTAwM2VmMDIxMCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJvd25lci1pZCI6ImJlYjMyNzc3LTk2ODAtNGY0Mi04NzYxLTM1MGVlYmU3NmE4NSIsIm5hbWUiOiJUZXN0IFRlc3QiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0LnVzZXIub2NmY2xvdWRAZ21haWwuY29tIiwiZ2l2ZW5fbmFtZSI6IlRlc3QiLCJmYW1pbHlfbmFtZSI6IlRlc3QiLCJlbWFpbCI6InRlc3QudXNlci5vY2ZjbG91ZEBnbWFpbC5jb20ifQ.aL52J-JuGuW_2R2x33pAVUX3fxJzPcz7OUeqvrPaijOqikOiQSwDyVdt0QIJtD2WBq0StTI-YqSHpt01Kpy1CgUricVWXoCI1j9eRBgveQ7zwiWKqNa1-ctXOHmDugVwSuhYoNBUP94qK1yrTFxSU5Lamj8l7H6pN4KVOMhs48Xbn-EJ7DPbJJ7Z26fJaYwj2P-e_ucV5JrIDPzSGRCBsXpqGlm6w2E2Z-SbwRclU4Xvf7V44bIJLFOV8wS0PrIz030n41F52c0dF1CC-ebnRQsFih6unR0l6J1P2sVoM4EKnR-mVIzfxmCxpXgduIaQU-jVo420vMrgCmluc23vnw", + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "timestamp": "1719494607886702017" + } + } +] \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/snippet-service/configurations/detail/48998f7d-2a70-46a4-8a68-745b69d55489.json b/http-gateway/web/packages/mock-server/src/data/snippet-service/configurations/detail/48998f7d-2a70-46a4-8a68-745b69d55489.json new file mode 100644 index 000000000..26e548bd8 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/snippet-service/configurations/detail/48998f7d-2a70-46a4-8a68-745b69d55489.json @@ -0,0 +1,50 @@ +[ + { + "result": { + "id": "48998f7d-2a70-46a4-8a68-745b69d55489", + "version": "0", + "name": "my-cfg-1", + "resources": [ + { + "href": "/not/existing", + "content": 123456, + "timeToLive": "0" + }, + { + "timeToLive": "0", + "href": "/oc/con", + "content": { + "n": "prezentacia dankovi" + } + } + ], + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "timestamp": "1718961203704580832" + } + }, + { + "result": { + "id": "48998f7d-2a70-46a4-8a68-745b69d55489", + "version": "1", + "name": "my-cfg-11", + "resources": [ + { + "href": "/not/existing", + "content": 123456, + "timeToLive": "0" + }, + { + "href": "/oc/con", + "content": { + "data": "W29iamVjdCBPYmplY3Rd", + "contentType": "application/json", + "coapContentFormat": -1 + }, + "timeToLive": "0" + } + ], + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "timestamp": "1719739387326389953" + } +} +] \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/data/snippet-service/configurations/list/list.json b/http-gateway/web/packages/mock-server/src/data/snippet-service/configurations/list/list.json new file mode 100644 index 000000000..a941dd07c --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/data/snippet-service/configurations/list/list.json @@ -0,0 +1,25 @@ +[ + { + "result": { + "id": "48998f7d-2a70-46a4-8a68-745b69d55489", + "version": "1", + "name": "my-cfg-1", + "resources": [ + { + "href": "/not/existing", + "content": 123456, + "timeToLive": "0" + }, + { + "href": "/oc/con", + "content": { + "n": "prezentacia dankovi" + }, + "timeToLive": "0" + } + ], + "owner": "beb32777-9680-4f42-8761-350eebe76a85", + "timestamp": "1718961203704580832" + } + } +] \ No newline at end of file diff --git a/http-gateway/web/packages/mock-server/src/index.js b/http-gateway/web/packages/mock-server/src/index.js index b03978aa2..45f303a15 100644 --- a/http-gateway/web/packages/mock-server/src/index.js +++ b/http-gateway/web/packages/mock-server/src/index.js @@ -1,25 +1,15 @@ const express = require('express') -const { check, validationResult } = require('express-validator') const cors = require('cors') -const path = require('path') +const axios = require('axios') +const { checkError, loadResponseStreamFromFile } = require('./utils') + +const devices = require('./routes/devices') +const dps = require('./routes/dps') +const snippetService = require('./routes/snippet-service') const app = express() const port = 8181 -let deletedDevice = false -let resourceColorUpdatedValue = false - -const deviceIdCheck = [check('deviceId').notEmpty().withMessage('Device ID must be alphanumeric')] - -const checkError = (req, res) => { - const errors = validationResult(req) - if (!errors.isEmpty()) { - return res.status(400).json({ errors: errors.array() }) - } - - console.log(`${req.method}`, req.url) -} - app.use( cors({ origin: '*', @@ -27,116 +17,46 @@ app.use( }) ) -const loadResponseFromFile = (file, res) => { - const targetDirectory = `${__dirname}/data` - - res.sendFile(file, { root: targetDirectory }) -} - -// ----- DEVICES ----- -app.get('/api/v1/devices', function (req, res) { - console.log(`${req.method}`, req.url) - - if (deletedDevice) { - loadResponseFromFile(path.join('devices', 'list', 'list-deleted-state.json'), res) - } else { - loadResponseFromFile(path.join('devices', 'list', 'list.json'), res) - } -}) - -app.delete('/api/v1/devices', function (req, res) { +// ----- PENDING COMMANDS ----- +app.get('/api/v1/pending-commands', function (req, res) { console.log(`${req.method}`, req.url) - deletedDevice = true - res.send() -}) - -app.get('/api/v1/devices/:deviceId', deviceIdCheck, function (req, res) { - checkError(req, res) - loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}.json`), res) -}) - -app.get('/api/v1/devices/:deviceId/pending-commands', deviceIdCheck, function (req, res) { - checkError(req, res) - res.send() -}) - -app.get('/api/v1/devices/:deviceId/resources', deviceIdCheck, function (req, res) { - checkError(req, res) - res.send() -}) - -app.put('/api/v1/devices/:deviceId/metadata', deviceIdCheck, function (req, res) { - checkError(req, res) - res.send() -}) - -// change device name -app.put('/api/v1/devices/:deviceId/resources/oc/con', deviceIdCheck, function (req, res) { - checkError(req, res) - res.send({ n: 'New Device Name' }) -}) - -// resource detail -app.get('/api/v1/devices/:deviceId/resources/light/1', deviceIdCheck, function (req, res) { - checkError(req, res) - loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-light-1.json`), res) + loadResponseStreamFromFile('pending-commands.json', res) }) -// resource detail -app.get('/api/v1/devices/:deviceId/resources/.well-known/wot', deviceIdCheck, function (req, res) { - checkError(req, res) - loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-well-known-wot.json`), res) +app.get('/', () => { + console.log(`HUB API mock server listening on port ${port}`) }) -app.get('/api/v1/devices/:deviceId/resources/color', deviceIdCheck, function (req, res) { - checkError(req, res) - - if (resourceColorUpdatedValue) { - loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-color-update.json`), res) - } else { - loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-color.json`), res) +app.get('/.well-known/configuration', (req, res) => { + try { + checkError(req, res) + axios.get('https://try.plgd.cloud/.well-known/configuration').then((r) => res.send(r.data)) + } catch (e) { + res.status(500).send(e.toString()) } }) -app.put('/api/v1/devices/:deviceId/resources/color', deviceIdCheck, function (req, res) { - checkError(req, res) - resourceColorUpdatedValue = true - loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-color-update.json`), res) -}) - -// resource detail update -app.put('/api/v1/devices/:deviceId/resources/light/1', deviceIdCheck, function (req, res) { - checkError(req, res) - loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-light-1.json`), res) -}) - -// ----- GENERAL for devices ----- -app.get('/api/v1/resource-links', function (req, res) { - console.log(`${req.method}`, req.url) - loadResponseFromFile(path.join('devices', 'detail', `${req.query['device_id_filter']}-resource-links.json`), res) -}) - -app.get('/api/v1/provisioning-records', function (req, res) { - console.log(`${req.method}`, req.url) - loadResponseFromFile(path.join('devices', 'detail', `${req.query['deviceIdFilter']}-provisioning-records.json`), res) -}) - -app.get('/api/v1/signing/records', function (req, res) { - console.log(`${req.method}`, req.url) - loadResponseFromFile(path.join('devices', 'detail', `${req.query['deviceIdFilter']}-signin-records.json`), res) +app.get('/theme/theme.json', (req, res) => { + try { + checkError(req, res) + axios.get('https://try.plgd.cloud/theme/theme.json').then((r) => res.send(r.data)) + } catch (e) { + res.status(500).send(e.toString()) + } }) -// ----- PENDING COMMANDS ----- -app.get('/api/v1/pending-commands', function (req, res) { - console.log(`${req.method}`, req.url) - loadResponseFromFile('pending-commands.json', res) +app.get('/repos/plgd-dev/hub/releases/latest', (req, res) => { + try { + checkError(req, res) + axios.get('https://api.github.com/repos/plgd-dev/hub/releases/latest').then((r) => res.send(r.data)) + } catch (e) { + res.status(500).send(e.toString()) + } }) -app.get('/', () => { - console.log(`HUB API mock server listening on port ${port}`) - deletedDevice = false - resourceColorUpdatedValue = false -}) +app.use(devices) +app.use(dps) +app.use('/snippet-service', snippetService) app.listen(port, () => { console.log(`HUB API mock server listening on port ${port}`) diff --git a/http-gateway/web/packages/mock-server/src/routes/devices.js b/http-gateway/web/packages/mock-server/src/routes/devices.js new file mode 100644 index 000000000..f16a7e2e4 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/routes/devices.js @@ -0,0 +1,181 @@ +const express = require('express') +const { checkError, loadResponseFromFile } = require('../utils') +const path = require('path') +const { check } = require('express-validator') +const escapeHtml = require('escape-html') + +const router = express.Router() + +let deletedDevice = false +let resourceColorUpdatedValue = false + +const deviceIdCheck = [check('deviceId').notEmpty().withMessage('Device ID must be alphanumeric')] + +router.get('/api/v1/devices/api-reset', (req, res) => { + try { + checkError(req, res) + + deletedDevice = false + resourceColorUpdatedValue = false + + res.send('OK') + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.get('/api/v1/devices', (req, res) => { + try { + checkError(req, res) + + if (deletedDevice) { + loadResponseFromFile(path.join('devices', 'list', 'list-deleted-state.json'), res) + } else { + loadResponseFromFile(path.join('devices', 'list', 'list.json'), res) + } + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.delete('/api/v1/devices', (req, res) => { + try { + checkError(req, res) + deletedDevice = true + + res.send('OK') + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.get('/api/v1/devices/:deviceId', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}.json`), res) + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.get('/api/v1/devices/:deviceId/pending-commands', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + res.send() + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.get('/api/v1/devices/:deviceId/resources', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + res.send() + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.put('/api/v1/devices/:deviceId/metadata', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + res.send() + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +// change device name +router.put('/api/v1/devices/:deviceId/resources/oc/con', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + res.send({ n: 'New Device Name' }) + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +// resource detail +router.get('/api/v1/devices/:deviceId/resources/light/1', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-light-1.json`), res) + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +// resource detail update +router.put('/api/v1/devices/:deviceId/resources/light/1', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-light-1.json`), res) + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +// resource detail wot +router.get('/api/v1/devices/:deviceId/resources/.well-known/wot', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-well-known-wot.json`), res) + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +// resource detail color +router.get('/api/v1/devices/:deviceId/resources/color', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + + if (resourceColorUpdatedValue) { + loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-color-update.json`), res) + } else { + loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-color.json`), res) + } + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +// resource detail color update +router.put('/api/v1/devices/:deviceId/resources/color', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + resourceColorUpdatedValue = true + loadResponseFromFile(path.join('devices', 'detail', `${req.params['deviceId']}-resources-color-update.json`), res) + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.get('/api/v1/resource-links', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + loadResponseFromFile(path.join('devices', 'detail', `${req.query['device_id_filter']}-resource-links.json`), res) + } catch (e) { + res.status(500).send(e.toString()) + } +}) + +// router.get('/api/v1/provisioning-records', deviceIdCheck, (req, res) => { +// try { +// checkError(req, res) +// loadResponseFromFile(path.join('devices', 'detail', `${req.query['deviceIdFilter']}-provisioning-records.json`), res) +// } catch (e) { +// res.status(500).send(escapeHtml(e.toString())) +// } +// }) + +router.get('/api/v1/signing/records', deviceIdCheck, (req, res) => { + try { + checkError(req, res) + loadResponseFromFile(path.join('devices', 'detail', `${req.query['deviceIdFilter']}-signin-records.json`), res) + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +module.exports = router diff --git a/http-gateway/web/packages/mock-server/src/routes/dps.js b/http-gateway/web/packages/mock-server/src/routes/dps.js new file mode 100644 index 000000000..059e1087e --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/routes/dps.js @@ -0,0 +1,57 @@ +const { checkError, loadResponseStreamFromFile, loadResponseFromFile } = require('../utils') +const get = require('lodash/get') +const path = require('path') +const escapeHtml = require('escape-html') +const express = require('express') + +const router = express.Router() + +router.get('/api/v1/hubs', (req, res) => { + try { + checkError(req, res) + const httpIdFilter = get(req.query, 'idFilter', null) + + // detail configuration page + if (httpIdFilter) { + loadResponseFromFile(path.join('dps', 'linked-hubs', 'detail', `${httpIdFilter}.json`), res) + } else { + loadResponseStreamFromFile(path.join('dps', 'linked-hubs', 'list', `list.json`), res) + } + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.get('/api/v1/enrollment-groups', (req, res) => { + try { + checkError(req, res) + const httpIdFilter = get(req.query, 'idFilter', null) + + // detail configuration page + if (httpIdFilter) { + loadResponseFromFile(path.join('dps', 'enrollment-groups', 'detail', `${httpIdFilter}.json`), res) + } else { + loadResponseStreamFromFile(path.join('dps', 'enrollment-groups', 'list', `list.json`), res) + } + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.get('/api/v1/provisioning-records', (req, res) => { + try { + checkError(req, res) + const httpIdFilter = get(req.query, 'idFilter', null) + + // detail configuration page + if (httpIdFilter) { + loadResponseFromFile(path.join('dps', 'provisioning-records', 'detail', `${httpIdFilter}.json`), res) + } else { + loadResponseStreamFromFile(path.join('dps', 'provisioning-records', 'list', `list.json`), res) + } + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +module.exports = router diff --git a/http-gateway/web/packages/mock-server/src/routes/snippet-service.js b/http-gateway/web/packages/mock-server/src/routes/snippet-service.js new file mode 100644 index 000000000..75386803a --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/routes/snippet-service.js @@ -0,0 +1,62 @@ +const express = require('express') +const { loadResponseStreamFromFile, checkError } = require('../utils') +const path = require('path') +const escapeHtml = require('escape-html') +const get = require('lodash/get') + +const router = express.Router() + +router.get('/api/v1/configurations/applied', (req, res) => { + try { + checkError(req, res) + const httpConfigurationIdFilter = get(req.query, 'httpConfigurationIdFilter', null)?.replace('/all', '') + + // detail configuration page + if (httpConfigurationIdFilter) { + loadResponseStreamFromFile( + path.join('snippet-service', 'applied-configurations', 'list', `httpConfigurationIdFilter-${httpConfigurationIdFilter}.json`), + res + ) + } else { + // res.send([]) + } + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.get('/api/v1/configurations', (req, res) => { + try { + checkError(req, res) + const filter = get(req.query, 'httpIdFilter', null)?.replace('/all', '') + + // detail page + if (filter) { + loadResponseStreamFromFile(path.join('snippet-service', 'configurations', 'detail', `${filter}.json`), res) + } else { + // list page + loadResponseStreamFromFile(path.join('snippet-service', 'configurations', 'list', `list.json`), res) + } + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +router.get('/api/v1/conditions', (req, res) => { + try { + checkError(req, res) + const filter = get(req.query, 'httpIdFilter', null)?.replace('/all', '') + + // detail page + if (filter) { + loadResponseStreamFromFile(path.join('snippet-service', 'conditions', 'detail', `${filter}.json`), res) + } else { + // list page + loadResponseStreamFromFile(path.join('snippet-service', 'conditions', 'list', `list.json`), res) + } + } catch (e) { + res.status(500).send(escapeHtml(e.toString())) + } +}) + +module.exports = router diff --git a/http-gateway/web/packages/mock-server/src/utils.js b/http-gateway/web/packages/mock-server/src/utils.js new file mode 100644 index 000000000..e422fcab1 --- /dev/null +++ b/http-gateway/web/packages/mock-server/src/utils.js @@ -0,0 +1,35 @@ +const { validationResult } = require('express-validator') +const fs = require('fs-extra') + +const checkError = (req, res) => { + const errors = validationResult(req) + if (!errors.isEmpty()) { + return res.status(400).json({ errors: errors.array() }) + } + + console.log(`${req.method}`, req.url) +} + +const loadResponseFromFile = (file, res) => { + const targetDirectory = `${__dirname}/data` + + res.sendFile(file, { root: targetDirectory }) +} + +const loadResponseStreamFromFile = (file, res) => { + const targetDirectory = `${__dirname}/data` + + const dataArray = fs.readJsonSync(`${targetDirectory}/${file}`) + + dataArray.forEach((data, key) => { + res.write(JSON.stringify(data) + `${key === dataArray.length - 1 ? '' : '\n\n'}`) + }) + + res.send() +} + +module.exports = { + checkError, + loadResponseFromFile, + loadResponseStreamFromFile, +} diff --git a/http-gateway/web/packages/shared-ui b/http-gateway/web/packages/shared-ui index 05fb14ee6..efddbe595 160000 --- a/http-gateway/web/packages/shared-ui +++ b/http-gateway/web/packages/shared-ui @@ -1 +1 @@ -Subproject commit 05fb14ee633229500abb840737b581d9b6c6f3f7 +Subproject commit efddbe595bb44a53b5b10eb9e406c74eec6bf141 diff --git a/http-gateway/web/playwright/package-lock.json b/http-gateway/web/playwright/package-lock.json index 99e974b6b..759d51848 100644 --- a/http-gateway/web/playwright/package-lock.json +++ b/http-gateway/web/playwright/package-lock.json @@ -8,9 +8,11 @@ "name": "hub-playwright-test", "version": "1.0.0", "license": "ISC", + "dependencies": { + "axios": "^1.7.2" + }, "devDependencies": { - "@playwright/test": "^1.44.0", - "axios": "^0.24.0" + "@playwright/test": "^1.44.0" } }, "node_modules/@playwright/test": { @@ -28,20 +30,44 @@ "node": ">=16" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", - "dev": true, + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dependencies": { - "follow-redirects": "^1.14.4" + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" } }, "node_modules/follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, "funding": [ { "type": "individual", @@ -57,6 +83,19 @@ } } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -71,6 +110,25 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/playwright": { "version": "1.44.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.0.tgz", @@ -100,6 +158,11 @@ "engines": { "node": ">=16" } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" } }, "dependencies": { @@ -112,20 +175,48 @@ "playwright": "1.44.0" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "axios": { - "version": "0.24.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", - "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", - "dev": true, + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.2.tgz", + "integrity": "sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw==", "requires": { - "follow-redirects": "^1.14.4" + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "follow-redirects": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } }, "fsevents": { "version": "2.3.2", @@ -134,6 +225,19 @@ "dev": true, "optional": true }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, "playwright": { "version": "1.44.0", "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.0.tgz", @@ -149,6 +253,11 @@ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.0.tgz", "integrity": "sha512-ZTbkNpFfYcGWohvTTl+xewITm7EOuqIqex0c7dNZ+aXsbrLj0qI8XlGKfPpipjm0Wny/4Lt4CJsWJk1stVS5qQ==", "dev": true + }, + "proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" } } } diff --git a/http-gateway/web/playwright/package.json b/http-gateway/web/playwright/package.json index 95b91f1f9..dc563308e 100644 --- a/http-gateway/web/playwright/package.json +++ b/http-gateway/web/playwright/package.json @@ -8,13 +8,15 @@ "test": "npx playwright test", "test:ui": "npx playwright test --ui", "test:debug": "npx playwright test --debug", - "test:r": "npx playwright test devices/detail.spec.ts --debug --update-snapshots" + "test:r": "npx playwright test snippet-service/list.spec.ts --debug --update-snapshots" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { - "axios": "^0.24.0", "@playwright/test": "^1.44.0" + }, + "dependencies": { + "axios": "^1.7.2" } } diff --git a/http-gateway/web/playwright/tests/snippet-service/configuratiions/deail.spec.ts b/http-gateway/web/playwright/tests/snippet-service/configuratiions/deail.spec.ts new file mode 100644 index 000000000..a9960dacc --- /dev/null +++ b/http-gateway/web/playwright/tests/snippet-service/configuratiions/deail.spec.ts @@ -0,0 +1,17 @@ +import { test, expect, Page } from '@playwright/test' +import testId from '../../../../src/testId' + +const urlBase = 'http://localhost:3000' + +const openConfigurationItem = async (page: Page) => { + await page.goto(urlBase) + await page.getByTestId(testId.menu.snippetService.link).click() + await page.getByTestId(testId.menu.snippetService.configurations).click() + await page.getByTestId(`${testId.snippetService.configurations.list.table}-row-0`).click() +} + +test('snippet-service-configurations-detail-version', async ({ page }) => { + await openConfigurationItem(page) + + await expect(page.getByTestId(`${testId.snippetService.configurations.detail.versionSelector}`)).toBeVisible() +}) diff --git a/http-gateway/web/playwright/tests/snippet-service/configuratiions/list.spec.ts b/http-gateway/web/playwright/tests/snippet-service/configuratiions/list.spec.ts new file mode 100644 index 000000000..3f65b3d24 --- /dev/null +++ b/http-gateway/web/playwright/tests/snippet-service/configuratiions/list.spec.ts @@ -0,0 +1,13 @@ +import { test, expect } from '@playwright/test' +import testId from '../../../../src/testId' + +const urlBase = 'http://localhost:3000' + +test('snippet-service-configurations-list-open', async ({ page }) => { + await page.goto(urlBase) + await page.getByTestId(testId.menu.snippetService.link).click() + await page.getByTestId(testId.menu.snippetService.configurations).click() + + await expect(page).toHaveTitle(/Configuraions | plgd Dashboard/) + await expect(page).toHaveScreenshot({ fullPage: true, omitBackground: true }) +}) diff --git a/http-gateway/web/src/containers/App/App.i18n.ts b/http-gateway/web/src/containers/App/App.i18n.ts index c48b35d3d..7f8bb7f2a 100644 --- a/http-gateway/web/src/containers/App/App.i18n.ts +++ b/http-gateway/web/src/containers/App/App.i18n.ts @@ -121,4 +121,20 @@ export const messages = defineMessages({ id: 'app.menuConfiguration', defaultMessage: 'Configuration', }, + menuSnippetService: { + id: 'app.menuSnippetService', + defaultMessage: 'Snippet Service', + }, + menuConditions: { + id: 'app.menuConditions', + defaultMessage: 'Conditions', + }, + menuConfigurations: { + id: 'app.menuConfigurations', + defaultMessage: 'Configurations', + }, + menuAppliedConfigurations: { + id: 'app.menuAppliedConfigurations', + defaultMessage: 'Applied Configurations', + }, }) diff --git a/http-gateway/web/src/containers/Common/DetailHeaderLayout/DetailHeaderLayout.tsx b/http-gateway/web/src/containers/Common/DetailHeaderLayout/DetailHeaderLayout.tsx new file mode 100644 index 000000000..f5efa8004 --- /dev/null +++ b/http-gateway/web/src/containers/Common/DetailHeaderLayout/DetailHeaderLayout.tsx @@ -0,0 +1,76 @@ +import React, { FC, useCallback, useState } from 'react' +import isFunction from 'lodash/isFunction' + +import Button from '@shared-ui/components/Atomic/Button' +import { IconTrash } from '@shared-ui/components/Atomic/Icon' +import DeleteModal from '@shared-ui/components/Atomic/Modal/components/DeleteModal' + +import { Props } from './DetailHeaderLayout.types' + +const DetailHeaderLayout: FC = (props) => { + const { customButton, deleteApiMethod, deleteInformation, id, i18n, loading, onDeleteSuccess, onDeleteError, testIds } = props + + const [deleteModal, setDeleteModal] = useState(false) + const [deleting, setDeleting] = useState(false) + + const handleDelete = useCallback(async () => { + try { + setDeleting(true) + + await deleteApiMethod([id]) + + setDeleting(false) + setDeleteModal(false) + + isFunction(onDeleteSuccess) && onDeleteSuccess() + } catch (e: any) { + setDeleting(false) + setDeleteModal(false) + + isFunction(onDeleteError) && onDeleteError(e) + } + }, [deleteApiMethod, id, onDeleteError, onDeleteSuccess]) + + return ( +
+ {customButton} + + setDeleteModal(false), + variant: 'tertiary', + }, + { + dataTestId: testIds?.deleteButtonConfirm, + label: i18n.delete, + loading: deleting, + loadingText: i18n.deleting, + onClick: handleDelete, + variant: 'primary', + }, + ]} + onClose={() => setDeleteModal(false)} + show={deleteModal} + subTitle={i18n.subTitle} + title={i18n.title} + /> +
+ ) +} + +DetailHeaderLayout.displayName = 'DetailHeaderLayout' + +export default DetailHeaderLayout diff --git a/http-gateway/web/src/containers/Common/DetailHeaderLayout/DetailHeaderLayout.types.ts b/http-gateway/web/src/containers/Common/DetailHeaderLayout/DetailHeaderLayout.types.ts new file mode 100644 index 000000000..25875be52 --- /dev/null +++ b/http-gateway/web/src/containers/Common/DetailHeaderLayout/DetailHeaderLayout.types.ts @@ -0,0 +1,27 @@ +import { ReactNode } from 'react' + +import { DeleteInformationType } from '@shared-ui/components/Atomic/Modal/components/DeleteModal/DeleteModal.types' + +export type Props = { + customButton?: ReactNode + deleteApiMethod: (ids: string[]) => Promise + deleteInformation: DeleteInformationType[] + id: string + loading: boolean + i18n: { + cancel: string + delete: string + deleting: string + id: string + name: string + subTitle: string + title: string + } + onDeleteSuccess?: () => void + onDeleteError?: (error: any) => void + testIds?: { + deleteButton?: string + deleteButtonCancel?: string + deleteButtonConfirm?: string + } +} diff --git a/http-gateway/web/src/containers/Common/DetailHeaderLayout/index.ts b/http-gateway/web/src/containers/Common/DetailHeaderLayout/index.ts new file mode 100644 index 000000000..7b4b3ccaa --- /dev/null +++ b/http-gateway/web/src/containers/Common/DetailHeaderLayout/index.ts @@ -0,0 +1,2 @@ +export { default } from './DetailHeaderLayout' +export * from './DetailHeaderLayout' diff --git a/http-gateway/web/src/containers/Common/PageLayout/PageLayout.tsx b/http-gateway/web/src/containers/Common/PageLayout/PageLayout.tsx index 2865aa6a8..c19fc2ac7 100644 --- a/http-gateway/web/src/containers/Common/PageLayout/PageLayout.tsx +++ b/http-gateway/web/src/containers/Common/PageLayout/PageLayout.tsx @@ -3,6 +3,7 @@ import { useIntl } from 'react-intl' import isFunction from 'lodash/isFunction' import ReactDOM from 'react-dom' import { useRecoilState } from 'recoil' +import get from 'lodash/get' import { default as PageLayoutShared } from '@shared-ui/components/Atomic/PageLayout/PageLayout' import Footer from '@shared-ui/components/Layout/Footer' @@ -18,7 +19,7 @@ import { messages as t } from '@/containers/App/App.i18n' const PageLayout = forwardRef((props, ref) => { const { formatMessage: _ } = useIntl() - const { children, breadcrumbs, deviceId, notFound, pendingCommands, innerPortalTarget, size, ...rest } = props + const { children, breadcrumbs, deviceId, notFound, pendingCommands, innerPortalTarget, size, headlineCustomContent, ...rest } = props const { footerExpanded, setFooterExpanded, collapsed } = useContext(AppContext) const [isDomReady, setIsDomReady] = useState(false) @@ -37,7 +38,7 @@ const PageLayout = forwardRef((props, ref) => { collapsed={collapsed} footer={