Compare commits

..

8 Commits

Author SHA1 Message Date
dusanb 8ffc710b6a Merge branch 'ci' into 'main'
MG-1 - Update Docker Image names and setup Continous Delivery

Closes #1

See merge request DAVEEmbeddedSystems/innovation-lab/tlm/tlml/abstract-machines/magistrala!4
2024-03-01 13:45:04 +00:00
Rodney Osodo f762b91669 MG-1 - Update Docker Image names and setup Continous Delivery 2024-03-01 13:45:04 +00:00
dusanb 6e8ca15f56 Merge branch 'kratos-oauth2' into 'main'
NOISSUE - Add Kratos as an OAuth2.0 Provider

See merge request DAVEEmbeddedSystems/innovation-lab/tlm/tlml/abstract-machines/magistrala!6
2024-03-01 13:33:10 +00:00
Rodney Osodo d3fe7d1063 NOISSUE - Add Kratos as an OAuth2.0 Provider 2024-03-01 13:33:09 +00:00
dusanb ad6619f0ac Merge branch 'update-main' into 'main'
NOISSUE - Add Kratos as Users Repository

See merge request DAVEEmbeddedSystems/innovation-lab/tlm/tlml/abstract-machines/magistrala!7
2024-03-01 12:29:48 +00:00
Rodney Osodo 4bee424289 NOISSUE - Add Kratos as Users Repository 2024-03-01 12:29:47 +00:00
dusanb f55d7640eb Merge branch 'migrate-to-gitlab' into 'main'
NOISSUE - Migrate to GitLab

See merge request DAVEEmbeddedSystems/innovation-lab/tlm/tlml/abstract-machines/magistrala!8
2024-03-01 12:15:10 +00:00
Rodney Osodo 221c1212bb NOISSUE - Migrate to GitLab 2024-03-01 12:15:10 +00:00
1281 changed files with 126655 additions and 132102 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0
.git
.github
.gitlab
build
docker
metrics
-15
View File
@@ -1,15 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
# CoAP is temporarily ignored since we don't have tests for it yet.
coverage:
ignore:
- "tools/*"
- "api/grpc/**"
- "cmd/*"
- "coap/**"
- "**/mocks/*"
- "*/middleware/*"
- "pkg/sid/mock.go"
- "pkg/tracing/utils.go"
- "pkg/prometheus/*"
-52
View File
@@ -1,52 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Bug Report
description: File a bug/issue report. Make sure to search to see if an issue already exists for the bug you encountered.
title: "Bug: <title>"
labels: ["bug", "needs-review", "help wanted"]
body:
- type: textarea
attributes:
label: What were you trying to achieve?
description: A clear and concise description of what the bug is.
validations:
required: true
- type: textarea
attributes:
label: What are the expected results?
description: A concise description of what you expected to happen.
validations:
required: true
- type: textarea
attributes:
label: What are the received results?
description: A concise description of what you received.
validations:
required: true
- type: textarea
attributes:
label: Steps To Reproduce
description: What are the steps to reproduce the issue?
placeholder: |
1. In this environment...
2. With this config...
3. Run '...'
4. See error...
validations:
required: false
- type: textarea
attributes:
label: In what environment did you encounter the issue?
description: A concise description of the environment you encountered the issue in.
validations:
required: true
- type: textarea
attributes:
label: Additional information you deem important
description: |
Links? References? Anything that will give us more context about the issue you are encountering!
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false
-11
View File
@@ -1,11 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
blank_issues_enabled: false
contact_links:
- name: Google group
url: https://groups.google.com/forum/#!forum/mainflux
about: Join the Magistrala community on Google group.
- name: Gitter
url: https://gitter.im/mainflux/mainflux
about: Join the Magistrala community on Gitter.
@@ -1,39 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Feature Request
description: File a feature request. Make sure to search to see if a request already exists for the feature you are requesting.
title: "Feature: <title>"
labels: ["enchancement", "needs-review"]
body:
- type: textarea
attributes:
label: Is your feature request related to a problem? Please describe.
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
validations:
required: true
- type: textarea
attributes:
label: Describe the feature you are requesting, as well as the possible use case(s) for it.
description: A clear and concise description of what you want to happen.
validations:
required: true
- type: dropdown
attributes:
label: Indicate the importance of this feature to you.
description: This will help us prioritize the feature request.
options:
- Must-have
- Should-have
- Nice-to-have
validations:
required: true
- type: textarea
attributes:
label: Anything else?
description: |
Links? References? Anything that will give us more context about the feature that you are requesting.
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
validations:
required: false
-43
View File
@@ -1,43 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "./.github/workflows"
target-branch: "main"
schedule:
interval: "weekly"
day: "monday"
time: "06:00"
timezone: "Europe/Paris"
groups:
gh-dependency:
patterns:
- "*"
- package-ecosystem: "gomod"
directory: "/"
target-branch: "main"
schedule:
interval: "weekly"
day: "monday"
time: "06:15"
timezone: "Europe/Paris"
groups:
go-dependency:
patterns:
- "*"
- package-ecosystem: "docker"
directory: "/docker"
target-branch: "main"
schedule:
interval: "weekly"
day: "monday"
time: "06:30"
timezone: "Europe/Paris"
groups:
docker-dependency:
patterns:
- "*"
-181
View File
@@ -1,181 +0,0 @@
<!--
Copyright (c) Abstract Machines
SPDX-License-Identifier: Apache-2.0
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Magistrala API Documentation</title>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.30.3/swagger-ui.css">
<style>
body {
margin: 0;
padding: 0;
}
.topbar {
display: none;
}
.service-selector {
background: #1b1b1b;
padding: 20px;
text-align: center;
}
.service-selector h1 {
color: #fff;
margin: 0 0 15px 0;
font-family: sans-serif;
}
.service-dropdown-container {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
}
.service-dropdown-container label {
color: #fff;
font-family: sans-serif;
font-size: 14px;
font-weight: 500;
}
.service-dropdown {
background: #2d2d2d;
color: white;
border: 1px solid #4990e2;
padding: 10px 40px 10px 15px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
font-weight: 500;
min-width: 200px;
appearance: none;
background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><path fill="%23ffffff" d="M6 9L1 4h10z"/></svg>');
background-repeat: no-repeat;
background-position: right 12px center;
}
.service-dropdown:hover {
background-color: #3a3a3a;
border-color: #357abd;
}
.service-dropdown:focus {
outline: none;
border-color: #4990e2;
box-shadow: 0 0 0 2px rgba(73, 144, 226, 0.3);
}
/* Responsive styles for mobile */
@media (max-width: 768px) {
.service-selector {
padding: 15px 10px;
}
.service-selector h1 {
font-size: 1.5rem;
margin: 0 0 12px 0;
}
.service-dropdown-container {
flex-direction: column;
gap: 8px;
}
.service-dropdown-container label {
font-size: 13px;
}
.service-dropdown {
width: 100%;
max-width: 300px;
min-width: auto;
font-size: 13px;
padding: 8px 35px 8px 12px;
}
}
@media (max-width: 480px) {
.service-selector h1 {
font-size: 1.25rem;
}
.service-dropdown {
max-width: 250px;
}
}
</style>
</head>
<body>
<div class="service-selector">
<h1>Magistrala API Documentation</h1>
<div class="service-dropdown-container">
<label for="serviceDropdown">Select Service:</label>
<select id="serviceDropdown" class="service-dropdown"></select>
</div>
</div>
<div id="swagger-ui"></div>
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.30.3/swagger-ui-bundle.js"></script>
<script src="https://cdn.jsdelivr.net/npm/swagger-ui-dist@5.30.3/swagger-ui-standalone-preset.js"></script>
<script>
// Available API specifications
const APIs = APIS_PLACEHOLDER;
// Get the service from URL query parameter, default to first service
function getServiceFromURL() {
const params = new URLSearchParams(window.location.search);
const service = params.get('service');
return service && APIs.includes(service) ? service : APIs[0];
}
// Update URL with selected service
function updateURL(service) {
const url = new URL(window.location);
url.searchParams.set('service', service);
window.history.pushState({}, '', url);
}
// Create service selector dropdown
function createServiceDropdown() {
const dropdown = document.getElementById('serviceDropdown');
const currentService = getServiceFromURL();
APIs.forEach(api => {
const option = document.createElement('option');
option.value = api;
let serviceName = api.replace('.yaml', '').replace(/^\w/, c => c.toUpperCase());
if (serviceName.toLowerCase() === 'http') {
serviceName = 'HTTP';
}
option.textContent = serviceName;
if (api === currentService) {
option.selected = true;
}
dropdown.appendChild(option);
});
// Handle dropdown change
dropdown.addEventListener('change', (e) => {
const selectedApi = e.target.value;
loadSwaggerUI(selectedApi);
updateURL(selectedApi);
});
}
// Load Swagger UI with specified API spec
function loadSwaggerUI(apiSpec) {
SwaggerUIBundle({
url: apiSpec,
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
});
}
// Initialize
createServiceDropdown();
loadSwaggerUI(getServiceFromURL());
</script>
</body>
</html>
-322
View File
@@ -1,322 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Property Based Tests
on:
push:
branches:
- main
paths:
- ".github/workflows/api-tests.yaml"
- "api/**"
- "internal/atom/**"
- "channels/api/http/**"
- "clients/api/http/**"
- "domains/api/http/**"
- "groups/api/http/**"
- "journal/api/**"
- "users/api/**"
- "bootstrap/api/**"
- "certs/api/http/**"
- "readers/api/http/**"
- "re/**"
- "alarms/**"
- "reports/**"
- "apidocs/openapi/**"
pull_request:
branches:
- main
paths:
- ".github/workflows/api-tests.yaml"
- "api/**"
- "internal/atom/**"
- "channels/api/http/**"
- "clients/api/http/**"
- "domains/api/http/**"
- "groups/api/http/**"
- "journal/api/**"
- "users/api/**"
- "bootstrap/api/**"
- "certs/api/http/**"
- "readers/api/http/**"
- "re/**"
- "alarms/**"
- "reports/**"
- "apidocs/openapi/**"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
ATOM_LOGIN_URL: http://localhost/auth/login
USER_IDENTITY: admin
USER_SECRET: 12345678
DOMAIN_NAME: demo-test
USERS_URL: http://localhost
DOMAIN_URL: http://localhost
CLIENTS_URL: http://localhost
CHANNELS_URL: http://localhost
GROUPS_URL: http://localhost
JOURNAL_URL: http://localhost:9021
BOOTSTRAP_URL: http://localhost:9013
CERTS_URL: http://localhost:9019
READERS_URL: http://localhost:9011
RE_URL: http://localhost:9008
ALARMS_URL: http://localhost:8050
REPORTS_URL: http://localhost:9017
jobs:
api-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "go.sum"
- name: Check for changes in specific paths
uses: dorny/paths-filter@v4
id: changes
with:
filters: |
workflow:
- ".github/workflows/api-tests.yaml"
journal:
- "apidocs/openapi/journal.yaml"
- "journal/api/**"
domains:
- "apidocs/openapi/domains.yaml"
- "internal/atom/**"
- "domains/api/http/**"
clients:
- "apidocs/openapi/clients.yaml"
- "internal/atom/**"
- "clients/api/http/**"
channels:
- "apidocs/openapi/channels.yaml"
- "internal/atom/**"
- "channels/api/http/**"
groups:
- "apidocs/openapi/groups.yaml"
- "internal/atom/**"
- "groups/api/http/**"
users:
- "apidocs/openapi/users.yaml"
- "internal/atom/**"
- "users/api/**"
bootstrap:
- "apidocs/openapi/bootstrap.yaml"
- "bootstrap/api/**"
certs:
- "apidocs/openapi/certs.yaml"
- "certs/api/http/**"
readers:
- "apidocs/openapi/readers.yaml"
- "readers/api/http/**"
re:
- "apidocs/openapi/rules.yaml"
- "re/**"
- "cmd/re/**"
- "internal/atom/**"
alarms:
- "apidocs/openapi/alarms.yaml"
- "alarms/**"
- "cmd/alarms/**"
- "internal/atom/**"
reports:
- "apidocs/openapi/reports.yaml"
- "reports/**"
- "cmd/reports/**"
- "internal/atom/**"
- name: Build images
run: make all -j $(nproc) && make dockers_dev -j $(nproc)
- name: Provision Atom service tokens
run: make provision_atom_tokens
- name: Start containers
run: make run_latest_ci up args="-d" && make run_addons up args="-d"
- name: Wait for services to be ready
run: |
echo "Waiting for services to start..."
sleep 15
# Check if services are responding
for i in {1..30}; do
if curl -f -s http://localhost/health > /dev/null 2>&1; then
echo "Services are ready!"
exit 0
fi
echo "Waiting for services... ($i/30)"
sleep 2
done
echo "Services failed to become ready" >&2
docker compose -f docker/docker-compose.yaml -f docker/docker-compose-ci.yaml --env-file docker/.env --env-file docker/.env.tokens -p "${USER_REPO:-absmach_magistrala}" ps || true
docker logs --tail 100 magistrala-nginx || true
docker logs --tail 100 magistrala-atom || true
docker logs --tail 100 magistrala-atom-bootstrap || true
exit 1
- name: Set access token
run: |
export USER_TOKEN=$(curl -fsS -X POST "$ATOM_LOGIN_URL" -H "Content-Type: application/json" -d "{\"identifier\":\"$USER_IDENTITY\",\"secret\":\"$USER_SECRET\",\"kind\":\"password\"}" | jq -er .token)
echo "USER_TOKEN=$USER_TOKEN" >> $GITHUB_ENV
- name: Run Users API tests
if: (steps.changes.outputs.users == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('users/api/**') != ''
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/users.yaml
base-url: ${{ env.USERS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --exclude-operation-id=requestPasswordReset --phases=examples'
coverage-artifact-name: schema-coverage-users
coverage-pr-comment: false
- name: Run Groups API tests
if: (steps.changes.outputs.groups == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('groups/api/http/**') != ''
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/groups.yaml
base-url: ${{ env.GROUPS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-groups
coverage-pr-comment: false
- name: Run Clients API tests
if: (steps.changes.outputs.clients == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('clients/api/http/**') != ''
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/clients.yaml
base-url: ${{ env.CLIENTS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-clients
coverage-pr-comment: false
- name: Run Channels API tests
if: (steps.changes.outputs.channels == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('channels/api/http/**') != ''
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/channels.yaml
base-url: ${{ env.CHANNELS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-channels
coverage-pr-comment: false
- name: Run Domains API tests
if: (steps.changes.outputs.domains == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('domains/api/http/**') != ''
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/domains.yaml
base-url: ${{ env.DOMAIN_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-domains
coverage-pr-comment: false
- name: Run Journal API tests
if: steps.changes.outputs.journal == 'true' || steps.changes.outputs.workflow == 'true'
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/journal.yaml
base-url: ${{ env.JOURNAL_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-journal
coverage-pr-comment: false
- name: Run Bootstrap API tests
if: (steps.changes.outputs.bootstrap == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('bootstrap/api/**') != ''
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/bootstrap.yaml
base-url: ${{ env.BOOTSTRAP_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-bootstrap
coverage-pr-comment: false
- name: Run Certs API tests
if: (steps.changes.outputs.certs == 'true' || steps.changes.outputs.workflow == 'true') && hashFiles('docker/addons/certs/docker-compose.yaml') != ''
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/certs.yaml
base-url: ${{ env.CERTS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-certs
coverage-pr-comment: false
- name: Run Readers API tests
if: steps.changes.outputs.readers == 'true' || steps.changes.outputs.workflow == 'true'
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/readers.yaml
base-url: ${{ env.READERS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-readers
coverage-pr-comment: false
- name: Run Rules Engine API tests
if: steps.changes.outputs.re == 'true' || steps.changes.outputs.workflow == 'true'
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/rules.yaml
base-url: ${{ env.RE_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-rules
coverage-pr-comment: false
- name: Run Alarms API tests
if: steps.changes.outputs.alarms == 'true' || steps.changes.outputs.workflow == 'true'
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/alarms.yaml
base-url: ${{ env.ALARMS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-alarms
coverage-pr-comment: false
- name: Run Reports API tests
if: steps.changes.outputs.reports == 'true' || steps.changes.outputs.workflow == 'true'
uses: schemathesis/action@v3.0.0
with:
schema: apidocs/openapi/reports.yaml
base-url: ${{ env.REPORTS_URL }}
checks: all
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --suppress-health-check=filter_too_much --exclude-checks=positive_data_acceptance --phases=examples'
coverage-artifact-name: schema-coverage-reports
coverage-pr-comment: false
- name: Stop containers
if: always()
run: make run_latest_ci down args="-v" && make run_addons down args="-v"
-59
View File
@@ -1,59 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Continuous Delivery
on:
push:
branches:
- main
paths-ignore:
- "**/*.md"
- "docs/**"
- ".github/workflows/**"
- "LICENSE"
- "MAINTAINERS"
- "CODEOWNERS"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
lint-and-build:
uses: ./.github/workflows/lint-and-build.yaml
build-and-push:
name: Build and Push Docker Images
runs-on: ubuntu-latest
needs: [lint-and-build]
permissions:
contents: read
packages: write
steps:
- name: Checkout code
uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "go.sum"
- name: Set up Docker Build
uses: docker/setup-buildx-action@v4
- name: Login to GHCR
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker images
run: |
make latest -j $(nproc)
@@ -1,129 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Check the consistency of generated files
on:
pull_request:
branches:
- main
jobs:
check-generated-files:
runs-on: ubuntu-latest
env:
PROTOC_VERSION: "33.0"
PROTOC_GEN_GO_VERSION: "v1.36.11"
PROTOC_GEN_GO_GRPC_VERSION: "v1.6.0"
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Install Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "go.sum"
- name: Set GOBIN
run: echo "GOBIN=$HOME/.local/bin" >> $GITHUB_ENV
- name: Add GOBIN to PATH
run: echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Check for changes in go.mod
run: |
go mod tidy
git diff --exit-code
- name: Check for changes in specific paths
uses: dorny/paths-filter@v4
id: changes
with:
base: main
filters: |
proto:
- ".github/workflows/check-generated-files.yaml"
- "auth.proto"
- "auth/*.pb.go"
- "pkg/messaging/message.proto"
- "pkg/messaging/*.pb.go"
mocks:
- "tools/config/.mockery.yaml"
- ".github/workflows/check-generated-files.yaml"
- "pkg/sdk/sdk.go"
- "users/postgres/clients.go"
- "users/clients.go"
- "pkg/clients/clients.go"
- "pkg/messaging/pubsub.go"
- "clients/postgres/clients.go"
- "clients/clients.go"
- "pkg/authz.go"
- "pkg/authn.go"
- "auth/domains.go"
- "auth/keys.go"
- "auth/service.go"
- "pkg/events/events.go"
- "pkg/groups/groups.go"
- "users/emailer.go"
- "users/hasher.go"
- "journal/journal.go"
- "consumers/notifier.go"
- name: Install Protoc
if: steps.changes.outputs.proto == 'true'
uses: arduino/setup-protoc@v3
with:
version: ${{ env.PROTOC_VERSION }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Go Protobuf Plugins
if: steps.changes.outputs.proto == 'true'
run: |
go install google.golang.org/protobuf/cmd/protoc-gen-go@$PROTOC_GEN_GO_VERSION
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@$PROTOC_GEN_GO_GRPC_VERSION
- name: Check Protobuf is up to Date
if: steps.changes.outputs.proto == 'true'
run: |
for p in $(find . -name "*.pb.go"); do
mv $p $p.tmp
done
make proto
for p in $(find . -name "*.pb.go"); do
if ! cmp -s $p $p.tmp; then
echo "Error: Proto file and generated Go file $p are out of sync!"
echo "Here is the difference:"
diff $p $p.tmp || true
echo "Please run 'make proto' with protoc version $PROTOC_VERSION, protoc-gen-go version $PROTOC_GEN_GO_VERSION and protoc-gen-go-grpc version $PROTOC_GEN_GO_GRPC_VERSION and commit the changes."
exit 1
fi
done
- name: Check Mocks are up to Date
if: steps.changes.outputs.mocks == 'true'
run: |
for f in $(find . -type f -path '*/mocks/*.go' ! -name 'doc.go'); do
mv $f $f.tmp
done
make mocks
check_mock_changes() {
local file_path=$1
local tmp_file_path=$1.tmp
local entity_name=$2
if ! cmp -s "$file_path" "$tmp_file_path"; then
echo "Error: Generated mocks for $entity_name are out of sync!"
echo "Please run 'make mocks' with mockery version $MOCKERY_VERSION and commit the changes."
exit 1
fi
}
for f in $(find . -type f -path '*/mocks/*.go' ! -name 'doc.go'); do
check_mock_changes $f "$f"
done
-37
View File
@@ -1,37 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Check License Header
on:
pull_request:
branches:
- main
jobs:
check-license:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Check License Header
run: |
CHECK=""
for file in $(grep -rl --exclude-dir={.git,build} \
--exclude=\*.{crt,key,pem,zed,hcl,md,json,csv,mod,sum,tmpl,args} \
--exclude={CODEOWNERS,LICENSE,MAINTAINERS,enabled_plugins,rabbitmq.conf} \
.); do
if ! head -n 5 "$file" | grep -q "Copyright (c) Abstract Machines"; then
CHECK="$CHECK $file"
fi
done
if [ "$CHECK" ]; then
echo "License header check failed. Fix the following files:"
echo "$CHECK"
exit 1
else
echo "All files have the correct license header!"
fi
-63
View File
@@ -1,63 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Lint and Build
on:
workflow_call:
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "go.sum"
- name: Run linters
uses: golangci/golangci-lint-action@v9.3.0
with:
version: v2.10.1
args: --config ./tools/config/.golangci.yaml
build:
name: Build All Binaries
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "go.sum"
- name: Build all binaries
run: |
make all -j $(nproc)
compile-check:
name: Compile Check Redis Event Store
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "go.sum"
- name: Compile check
run: |
MG_ES_TYPE=es_redis make all -j $(nproc)
-45
View File
@@ -1,45 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Deploy GitHub Pages
on:
push:
branches:
- main
permissions:
contents: write
jobs:
swagger-ui:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Build Swagger UI
run: |
# Create output directory
mkdir -p swagger-ui
# Copy OpenAPI YAML files and schemas directory
cp apidocs/openapi/*.yaml swagger-ui/
cp -r apidocs/openapi/schemas swagger-ui/
# Get list of YAML files
cd apidocs/openapi
YAML_FILES=$(ls *.yaml | jq -R -s -c 'split("\n")[:-1]')
cd ../..
# Generate index.html from template
sed "s|APIS_PLACEHOLDER|$YAML_FILES|g" .github/swagger-ui-template.html > swagger-ui/index.html
echo "Generated Swagger UI with APIs: $YAML_FILES"
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./swagger-ui
cname: docs.api.magistrala.absmach.eu
-319
View File
@@ -1,319 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: CI Pipeline
on:
push:
branches:
- main
paths-ignore:
- '**/*.md'
- 'docs/**'
- 'LICENSE'
- 'MAINTAINERS'
- 'CODEOWNERS'
pull_request:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint-proto:
name: Lint Proto
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v7
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "go.sum"
- name: Install protolint
run: |
go install github.com/yoheimuta/protolint/cmd/protolint@latest
- name: Lint Protobuf Files
run: |
protolint .
lint-and-build:
needs: [lint-proto]
uses: ./.github/workflows/lint-and-build.yaml
detect-changes:
name: Detect Changes
runs-on: ubuntu-latest
outputs:
modules: ${{ steps.set-matrix.outputs.modules }}
steps:
- name: Checkout
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Check for changes in specific paths
uses: dorny/paths-filter@v4
id: changes
with:
filters: |
workflow:
- ".github/workflows/tests.yaml"
channels:
- "channels/**"
- "pkg/sdk/**"
- "clients/api/grpc/**"
- "groups/api/grpc/**"
- "domains/api/grpc/**"
- "internal/grpc/**"
cli:
- "cli/**"
- "cmd/cli/**"
- "pkg/sdk/**"
clients:
- "clients/**"
- "pkg/ulid/**"
- "pkg/uuid/**"
- "pkg/events/**"
- "groups/api/grpc/**"
- "channels/api/grpc/**"
- "domains/api/grpc/**"
- "internal/grpc/**"
domains:
- "domains/**"
- "internal/grpc/**"
groups:
- "groups/**"
- "pkg/ulid/**"
- "pkg/uuid/**"
- "clients/api/grpc/**"
- "channels/api/grpc/**"
- "domains/api/grpc/**"
- "internal/grpc/**"
internal:
- "internal/**"
journal:
- "journal/**"
- "cmd/journal/**"
- "pkg/events/**"
logger:
- "logger/**"
pkg-errors:
- "pkg/errors/**"
pkg-events:
- "pkg/events/**"
- "pkg/messaging/**"
pkg-grpcclient:
- "pkg/grpcclient/**"
pkg-messaging:
- "pkg/messaging/**"
pkg-sdk:
- "pkg/sdk/**"
- "pkg/errors/**"
- "pkg/groups/**"
- "internal/*"
- "clients/**"
- "users/**"
- "channels/**"
- "domains/**"
- "groups/**"
- "journal/**"
- "api/http/**"
- "re/**"
- "alarms/**"
- "reports/**"
pkg-transformers:
- "pkg/transformers/**"
pkg-ulid:
- "pkg/ulid/**"
pkg-uuid:
- "pkg/uuid/**"
users:
- "users/**"
- "pkg/ulid/**"
- "pkg/uuid/**"
- "pkg/events/**"
notifications:
- "notifications/**"
- "cmd/notifications/**"
- "consumers/notifier.go"
- "pkg/events/**"
api:
- "api/**"
consumers:
- "consumers/**"
- "cmd/postgres-writer/**"
- "cmd/timescale-writer/**"
- "cmd/smpp-notifier/**"
- "cmd/smtp-notifier/**"
readers:
- "readers/**"
- "cmd/postgres-reader/**"
- "cmd/timescale-reader/**"
re:
- "re/**"
- "cmd/re/**"
- "re/api/**"
alarms:
- "alarms/**"
- "cmd/alarms/**"
reports:
- "reports/**"
- "cmd/reports/**"
- name: Set matrix for changed modules
id: set-matrix
run: |
modules=()
if [[ "${{ steps.changes.outputs.workflow }}" == "true" || "${{ steps.changes.outputs.pkg-errors }}" == "true" ]]; then
# If workflow or pkg/errors changed, test everything
modules=("auth" "channels" "cli" "clients" "domains" "groups" "internal" "journal" "logger" "pkg-errors" "pkg-events" "pkg-grpcclient" "pkg-messaging" "pkg-sdk" "pkg-transformers" "pkg-ulid" "pkg-uuid" "users" "notifications" "api" "consumers" "readers" "re" "alarms" "reports")
else
# Add only changed modules
[[ "${{ steps.changes.outputs.auth }}" == "true" ]] && modules+=("auth")
[[ "${{ steps.changes.outputs.channels }}" == "true" ]] && modules+=("channels")
[[ "${{ steps.changes.outputs.cli }}" == "true" ]] && modules+=("cli")
[[ "${{ steps.changes.outputs.clients }}" == "true" ]] && modules+=("clients")
[[ "${{ steps.changes.outputs.domains }}" == "true" ]] && modules+=("domains")
[[ "${{ steps.changes.outputs.groups }}" == "true" ]] && modules+=("groups")
[[ "${{ steps.changes.outputs.internal }}" == "true" ]] && modules+=("internal")
[[ "${{ steps.changes.outputs.journal }}" == "true" ]] && modules+=("journal")
[[ "${{ steps.changes.outputs.logger }}" == "true" ]] && modules+=("logger")
[[ "${{ steps.changes.outputs.pkg-errors }}" == "true" ]] && modules+=("pkg-errors")
[[ "${{ steps.changes.outputs.pkg-events }}" == "true" ]] && modules+=("pkg-events")
[[ "${{ steps.changes.outputs.pkg-grpcclient }}" == "true" ]] && modules+=("pkg-grpcclient")
[[ "${{ steps.changes.outputs.pkg-messaging }}" == "true" ]] && modules+=("pkg-messaging")
[[ "${{ steps.changes.outputs.pkg-sdk }}" == "true" ]] && modules+=("pkg-sdk")
[[ "${{ steps.changes.outputs.pkg-transformers }}" == "true" ]] && modules+=("pkg-transformers")
[[ "${{ steps.changes.outputs.pkg-ulid }}" == "true" ]] && modules+=("pkg-ulid")
[[ "${{ steps.changes.outputs.pkg-uuid }}" == "true" ]] && modules+=("pkg-uuid")
[[ "${{ steps.changes.outputs.users }}" == "true" ]] && modules+=("users")
[[ "${{ steps.changes.outputs.notifications }}" == "true" ]] && modules+=("notifications")
[[ "${{ steps.changes.outputs.api }}" == "true" ]] && modules+=("api")
[[ "${{ steps.changes.outputs.consumers }}" == "true" ]] && modules+=("consumers")
[[ "${{ steps.changes.outputs.readers }}" == "true" ]] && modules+=("readers")
[[ "${{ steps.changes.outputs.re }}" == "true" ]] && modules+=("re")
[[ "${{ steps.changes.outputs.alarms }}" == "true" ]] && modules+=("alarms")
[[ "${{ steps.changes.outputs.reports }}" == "true" ]] && modules+=("reports")
fi
# Convert to JSON array
json_modules=$(printf '%s\n' "${modules[@]}" | jq -R . | jq -s -c .)
echo "modules=$json_modules" >> $GITHUB_OUTPUT
echo "Testing modules: $json_modules"
run-tests:
name: Test ${{ matrix.module }}
runs-on: ubuntu-latest
needs: [lint-and-build, detect-changes]
if: needs.detect-changes.outputs.modules != '[]'
strategy:
fail-fast: true
max-parallel: 20
matrix:
module: ${{ fromJSON(needs.detect-changes.outputs.modules) }}
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version-file: go.mod
cache-dependency-path: "go.sum"
- name: Verify dependencies
run: |
go mod download
go mod verify
- name: Run ${{ matrix.module }} tests
run: |
# Map module names to directories
case "${{ matrix.module }}" in
pkg-errors) dir="pkg/errors" ;;
pkg-events) dir="pkg/events" ;;
pkg-grpcclient) dir="pkg/grpcclient" ;;
pkg-messaging) dir="pkg/messaging" ;;
pkg-sdk) dir="pkg/sdk" ;;
pkg-transformers) dir="pkg/transformers" ;;
pkg-ulid) dir="pkg/ulid" ;;
pkg-uuid) dir="pkg/uuid" ;;
channels) dir="pkg/channels" ;;
clients) dir="pkg/clients" ;;
domains) dir="pkg/domains" ;;
groups) dir="pkg/groups" ;;
*) dir="${{ matrix.module }}" ;;
esac
if [[ ! -d "$dir" ]]; then
echo "Skipping ${{ matrix.module }}; ./$dir is not present in this branch"
echo "mode: atomic" > coverage-${{ matrix.module }}.out
exit 0
fi
go test -mod=readonly --race -v -count=1 -failfast -coverprofile=coverage-${{ matrix.module }}.out ./$dir/...
- name: Upload coverage
uses: actions/upload-artifact@v7
with:
name: coverage-${{ matrix.module }}
path: coverage-${{ matrix.module }}.out
retention-days: 1
upload-coverage:
name: Upload Coverage
runs-on: ubuntu-latest
needs: run-tests
if: always() && needs.run-tests.result != 'cancelled'
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Download all coverage artifacts
uses: actions/download-artifact@v8
with:
pattern: coverage-*
path: coverage
merge-multiple: true
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV }}
directory: ./coverage
files: ./coverage/*.out
fail_ci_if_error: false
verbose: true
-15
View File
@@ -12,18 +12,3 @@ tools/provision/mgconn.toml
# coverage files
coverage
# Schemathesis
.hypothesis
# Ignore Openbao data directory as it contains runtime-generated data
docker/addons/certs/openbao/
# Ignore generated local Atom service tokens.
docker/.env.tokens
# Ignore SeaweedFS data directory as it contains runtime-generated data
docker/data/*
demo-ui
node_modules
+78
View File
@@ -0,0 +1,78 @@
variables:
DOCKER_HOST: tcp://docker:2375/
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
GOLANGCI_LINT_VERSION: "v1.55.2"
PROTOC_VERSION: "25.3"
PROTOC_GEN_VERSION: "v1.32.0"
PROTOC_GRPC_VERSION: "v1.3.0"
stages:
- test
- build
- publish
lint:
image: golang:1.21.6-bookworm
stage: test
before_script:
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin $GOLANGCI_LINT_VERSION
- export PATH=$PATH:$HOME/go/bin
script:
- golangci-lint run -v
test:
image: golang:1.21.6-bookworm
stage: test
before_script:
- go mod download
- make mocks
- mkdir -p coverage
- touch coverage/coverage.out
script:
- go test -v --race -count 1 -tags test -coverprofile=coverage/coverage.out $(go list ./... | grep -v 'consumers\|readers\|events\|cache\|messaging\|postgres\|mongodb\|internal\|opcua\|cmd')
check-generated-files:
image: golang:1.21.6-bookworm
stage: test
before_script:
- apt-get update && apt-get install -y unzip curl
- PROTOC_ZIP=protoc-$PROTOC_VERSION-linux-x86_64.zip
- curl -0L -o $PROTOC_ZIP https://github.com/protocolbuffers/protobuf/releases/download/v$PROTOC_VERSION/$PROTOC_ZIP
- unzip -o $PROTOC_ZIP -d protoc3
- mv protoc3/bin/* /usr/local/bin/
- mv protoc3/include/* /usr/local/include/
- rm -rf $PROTOC_ZIP protoc3
- go install google.golang.org/protobuf/cmd/protoc-gen-go@$PROTOC_GEN_VERSION
- go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@$PROTOC_GRPC_VERSION
- export PATH=$PATH:/usr/local/bin/protoc
- go mod download
script:
- make check-generated-files
build:
image: golang:1.21.6-bookworm
stage: build
before_script:
- go mod download
script:
- MG_MESSAGE_BROKER_TYPE=rabbitmq make mqtt
- MG_ES_TYPE=redis make mqtt
- make all -j $(nproc)
publish:
image: docker:latest
stage: publish
services:
- name: docker:dind
entrypoint: ["env", "-u", "DOCKER_HOST"]
command: ["dockerd-entrypoint.sh"]
before_script:
- apk add --no-cache make go git
- echo $CI_REGISTRY_PASSWORD | docker login $CI_REGISTRY --username $CI_REGISTRY_USER --password-stdin
- go mod download
script:
- make all -j $(nproc)
- MG_DOCKER_IMAGE_NAME_PREFIX=registry.gitlab.com/daveembeddedsystems/innovation-lab/tlm/tlml/abstract-machines/magistrala make latest -j $(nproc)
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+14
View File
@@ -0,0 +1,14 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "docker"
directory: "./docker"
schedule:
interval: "weekly"
+36
View File
@@ -0,0 +1,36 @@
<!---
Please read this!
Before opening a new issue, make sure to search for existing issues and verify the issue you're about to submit isn't a duplicate.
--->
## What were you trying to achieve?
<!-- A clear and concise description of what the bug is. -->
## What are the expected results?
<!-- A concise description of what you expected to happen. -->
## What are the received results?
<!-- A concise description of what actually happened. -->
## Steps to reproduce
<!-- Describe how one can reproduce the issue - this is very important. Please use an ordered list. -->
## In what environment did you encounter the issue?
<!-- Describe the environment you encountered the issue in. -->
## Additional information you deem important
<!-- List any additional information that you think might help us debug the issue.
Links? References? Anything that will give us more context about the issue you are encountering!
You can attach images or log files by clicking this area to highlight it and then dragging files in.
-->
/label ~"type::bug"
+25
View File
@@ -0,0 +1,25 @@
<!---
Please read this!
Before opening a new issue, make sure to search for existing issues and verify the issue you're about to submit isn't a duplicate.
--->
## Is your feature request related to a problem? Please describe?
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
## Describe the feature you'd like
<!-- A clear and concise description of what you want to happen. Add any considered drawbacks. -->
## Describe alternatives you've considered
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
## Indicate the importance of this feature to you.
<!-- How important is this feature to you? How much would you appreciate it? -->
## Additional context
<!-- Is there anything else you can add about the proposal? E.g. links to other issues, PRs, etc. -->
@@ -1,12 +1,9 @@
<!-- Copyright (c) Abstract Machines
SPDX-License-Identifier: Apache-2.0 -->
<!--
Pull request title should be `MG-XXX - description` or `NOISSUE - description` where XXX is ID of the issue that this PR relate to.
Please review the [CONTRIBUTING.md](https://github.com/absmach/magistrala/blob/main/CONTRIBUTING.md) file for detailed contributing guidelines.
Please review the [CONTRIBUTING.md](https://gitlab.com/DAVEEmbeddedSystems/innovation-lab/tlm/tlml/abstract-machines/magistrala/-/blob/main/CONTRIBUTING.md?ref_type=heads) file for detailed contributing guidelines.
For Work In Progress Pull Requests, please use the Draft PR feature, see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for further details.
For Work In Progress Pull Requests, please use the Draft PR feature.
For a timely review/response, please avoid force-pushing additional commits if your PR already received reviews or comments.
@@ -17,17 +14,17 @@ For a timely review/response, please avoid force-pushing additional commits if y
- Update any related documentation.
-->
# What type of PR is this?
## What type of PR is this?
<!--This represents the type of PR you are submitting.
For example:
This is a bug fix because it fixes the following issue: #1234
This is a feature because it adds the following functionality: ...
This is a refactor because it changes the following functionality: ...
This is a documentation update because it updates the following documentation: ...
This is a dependency update because it updates the following dependencies: ...
This is an optimization because it improves the following functionality: ...
This PR is a bug fix because it fixes the following issue: #1234
This PR is a feature because it adds the following functionality: ...
This PR is a refactor because it changes the following functionality: ...
This PR is a documentation update because it updates the following documentation: ...
This PR is a dependency update because it updates the following dependencies: ...
This PR is an optimization because it improves the following functionality: ...
-->
## What does this do?
@@ -45,8 +42,10 @@ For pull requests that relate or close an issue, please include them below. We
For example having the text: "Resolves #1234" would connect the current pull request to issue 1234. And when we merge the pull request, Github will automatically close the issue.
-->
<!--
- Related Issue #
- Resolves #
-->
## Have you included tests for your changes?
+95
View File
@@ -0,0 +1,95 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
run:
timeout: 10m
build-tags:
- "nats"
issues:
max-issues-per-linter: 100
max-same-issues: 100
exclude:
- "string `Usage:\n` has (\\d+) occurrences, make it a constant"
- "string `For example:\n` has (\\d+) occurrences, make it a constant"
linters-settings:
importas:
no-unaliased: true
no-extra-aliases: false
alias:
- pkg: github.com/absmach/callhome/pkg/client
alias: chclient
- pkg: github.com/absmach/magistrala/logger
alias: mglog
- pkg: github.com/absmach/magistrala/pkg/errors/service
alias: svcerr
- pkg: github.com/absmach/magistrala/pkg/errors/repository
alias: repoerr
- pkg: github.com/absmach/magistrala/pkg/sdk/mocks
alias: sdkmocks
gocritic:
enabled-checks:
- captLocal
- singleCaseSwitch
- switchTrue
- importShadow
- httpNoBody
- paramTypeCombine
- emptyStringTest
- builtinShadow
- exposedSyncMutex
disabled-checks:
- appendAssign
enabled-tags:
- diagnostic
disabled-tags:
- performance
- style
- experimental
- opinionated
misspell:
ignore-words:
- "mosquitto"
stylecheck:
checks: ["-ST1000", "-ST1003", "-ST1020", "-ST1021", "-ST1022"]
linters:
disable-all: true
enable:
- gocritic
- gosimple
- errcheck
- govet
- unused
- goconst
- godot
- godox
- ineffassign
- misspell
- stylecheck
- whitespace
- gci
- gofmt
- goimports
- loggercheck
- asasalint
- asciicheck
- bidichk
- contextcheck
- decorder
- dogsled
- errchkjson
- errname
- execinquery
- exportloopref
- ginkgolinter
- gocheckcompilerdirectives
- gofumpt
- goprintffuncname
- importas
- makezero
- mirror
- nakedret
- dupword
-36
View File
@@ -1,36 +0,0 @@
# Adopters
As Magistrala Community grows, we'd like to keep track of Magistrala adopters to grow the community, contact other users, share experiences and best practices.
To accomplish this, we created a public ledger. The list of organizations and users who consider themselves as Magistrala adopters and that **publicly/officially** shared information and/or details of their adoption journey(optional).
Where users themselves directly maintain the list.
## Adding yourself as an adopter
If you are using Magistrala, please consider adding yourself as an adopter with a brief description of your use case by opening a pull request to this file and adding a section describing your adoption of Magistrala technology.
**Please send PRs to add or remove organizations/users**
### Format
```
N: Name of user (company or individual)
D: Short Use Case Description (optional)
L: Link with further information (optional)
T: Type of adaptation: Evaluation, Core Technology, Production Usage (optional)
```
## Requirements
* You must represent the user or organization listed. Do NOT add entries on behalf of other organizations or individuals.
Pull request commit must be [signed](https://docs.github.com/en/github/authenticating-to-github/signing-commits) and auto-checked with [ Developer Certificate of Origin (DCO)](https://probot.github.io/apps/dco/)
* There is no minimum requirement or adaptation size, but we request to list permanent deployments only, i.e., no demo or trial deployments. Commercial or production use is not required. A well-done home lab setup can be equally impressive as a large-scale commercial deployment.
**The list of organizations/users that have publicly shared the usage of Magistrala:**
**Note**: Several other organizations/users couldn't publicly share their usage details but are active project contributors and Magistrala Community members.
## Adopters list (alphabetical)
**Note:** The list is maintained by the users themselves. If you find yourself on this list, and you think it's inappropriate. Please contact [project maintainers](https://github.com/absmach/magistrala/blob/main/MAINTAINERS) and you will be permanently removed from the list.
+19 -37
View File
@@ -1,19 +1,14 @@
# Contributing to Magistrala
The following is a set of guidelines to contribute to Magistrala and its libraries, which are
hosted on the [Abstract Machines Organization](https://github.com/absmach) on GitHub.
The following is a set of guidelines to contribute to Magistrala and its libraries, which are hosted on the [Abstract Machines Organization](https://gitlab.com/DAVEEmbeddedSystems/innovation-lab/tlm/tlml/abstract-machines) on Gitlab.
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0).
By participating, you are expected to uphold this code. Please report unacceptable behavior to
[abuse@absmach.eu](mailto:abuse@absmach.eu).
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0). By participating, you are expected to uphold this code. Please report unacceptable behavior to [abuse@magistrala.com](mailto:abuse@magistrala.com).
## Reporting issues
Reporting issues are a great way to contribute to the project. We are perpetually grateful about a well-written,
thorough bug report.
Reporting issues are a great way to contribute to the project. We are perpetually grateful about a well-written, thorough bug report.
Before raising a new issue, check [our issue
list](https://github.com/absmach/magistrala/issues) to determine if it already contains the
Before raising a new issue, check [our issue list](https://gitlab.com/DAVEEmbeddedSystems/innovation-lab/tlm/tlml/abstract-machines/magistrala/-/issues) to determine if it already contains the
problem that you are facing.
A good bug report shouldn't leave others needing to chase you for more information. Please be as detailed as possible. The following questions might serve as a template for writing a detailed
@@ -27,61 +22,48 @@ report:
## Pull requests
Good pull requests (e.g. patches, improvements, new features) are a fantastic help. They should
remain focused in scope and avoid unrelated commits.
Good pull requests (e.g. patches, improvements, new features) are a fantastic help. They should remain focused in scope and avoid unrelated commits.
**Please ask first** before embarking on any significant pull request (e.g. implementing new features,
refactoring code etc.), otherwise you risk spending a lot of time working on something that the
maintainers might not want to merge into the project.
**Please ask first** before embarking on any significant pull request (e.g. implementing new features, refactoring code etc.), otherwise you risk spending a lot of time working on something that the maintainers might not want to merge into the project.
Please adhere to the coding conventions used throughout the project. If in doubt, consult the
[Effective Go](https://golang.org/doc/effective_go.html) style guide.
Please adhere to the coding conventions used throughout the project. If in doubt, consult the [Effective Go](https://golang.org/doc/effective_go.html) style guide.
To contribute to the project, [fork](https://help.github.com/articles/fork-a-repo/) it,
clone your fork repository, and configure the remotes:
To contribute to the project, clone the repository:
```
git clone https://github.com/<your-username>/magistrala.git
```bash
git clone https://gitlab.com/DAVEEmbeddedSystems/innovation-lab/tlm/tlml/abstract-machines/magistrala.git
cd magistrala
git remote add upstream https://github.com/absmach/magistrala.git
```
If your cloned repository is behind the upstream commits, then get the latest changes from upstream:
```
```bash
git checkout main
git pull --rebase upstream main
```
Create a new topic branch from `main` using the naming convention `MG-[issue-number]`
to help us keep track of your contribution scope:
Create a new topic branch from `main` using the naming convention `MG-[issue-number]` to help us keep track of your contribution scope:
```
```bash
git checkout -b MG-[issue-number]
```
Commit your changes in logical chunks. When you are ready to commit, make sure
to write a Good Commit Message™. Consult the [Erlang's contributing guide](https://github.com/erlang/otp/wiki/Writing-good-commit-messages)
if you're unsure of what constitutes a Good Commit Message™. Use [interactive rebase](https://help.github.com/articles/about-git-rebase)
to group your commits into logical units of work before making it public.
Commit your changes in logical chunks. When you are ready to commit, make sure to write a Good Commit Message™. Consult the [Erlang's contributing guide](https://github.com/erlang/otp/wiki/Writing-good-commit-messages) if you're unsure of what constitutes a Good Commit Message™. Use [interactive rebase](https://docs.gitlab.com/ee/topics/git/git_rebase.html) to group your commits into logical units of work before making it public.
Note that every commit you make must be signed. By signing off your work you indicate that you
are accepting the [Developer Certificate of Origin](https://developercertificate.org/).
Note that every commit you make must be signed. By signing off your work you indicate that you are accepting the [Developer Certificate of Origin](https://developercertificate.org/).
Use your real name (sorry, no pseudonyms or anonymous contributions). If you set your `user.name`
and `user.email` git configs, you can sign your commit automatically with `git commit -s`.
Use your real name (sorry, no pseudonyms or anonymous contributions). If you set your `user.name` and `user.email` git configs, you can sign your commit automatically with `git commit -s`.
Locally merge (or rebase) the upstream development branch into your topic branch:
```
```bash
git pull --rebase upstream main
```
Push your topic branch up to your fork:
```
```bash
git push origin MG-[issue-number]
```
[Open a Pull Request](https://help.github.com/articles/using-pull-requests/) with a clear title
and detailed description.
[Open a Pull Request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) with a clear title and detailed description.
+1 -1
View File
@@ -176,7 +176,7 @@
END OF TERMS AND CONDITIONS
Copyright 2015-2026 Magistrala
Copyright 2015-2020 Magistrala
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
+26 -11
View File
@@ -1,15 +1,30 @@
# Magistrala Maintainers
# Magistrala follows the timeless, highly efficient and totally unfair system
# known as [Benevolent dictator for
# life](https://en.wikipedia.org/wiki/Benevolent_Dictator_for_Life), with
# Drasko DRASKOVIC in the role of BDFL.
Magistrala follows a BDFL model for dead-lock situations; day-to-day decisions happen through discussion and pull requests.
[bdfl]
[[drasko]]
Name = "Drasko Draskovic"
Email = "draasko.draskovic@abstractmachines.fr"
GitHub = "drasko"
## BDFL
# However, this role serves only in dead-lock events, or in a special and very rare cases
# when BDFL completely disagrees with the decisions made.
# In the normal flow of events, decisions on the project design are made through discussions,
# most often on the Pull Requests.
#
# Maintainers have the special role in the project in managing and accepting PRs,
# overall leading the project and making design decisions on the maintained subsystems.
#
# A reference list of all maintainers of the Magistrala project.
- **Drasko Draskovic** — [drasko@absmach.eu](mailto:drasko@absmach.eu) — [GitHub: drasko](https://github.com/drasko)
# ADD YOURSELF HERE IN ALPHABETICAL ORDER
## Maintainers
Add yourself below in alphabetical order.
| Name | Email | GitHub |
| --- | --- | --- |
| Dusan Borovcanin | [dusan.borovcanin@absmach.eu](mailto:dusan.borovcanin@absmach.eu) | [dborovcanin](https://github.com/dborovcanin) |
[maintainers]
[[dusan]]
Name = "Dusan Borovcanin"
Email = "dusan.borovcanin@abstractmachines.fr"
GitHub = "dborovcanin"
+57 -234
View File
@@ -1,61 +1,42 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
override MG_DOCKER_IMAGE_NAME_PREFIX := ghcr.io/absmach/magistrala
MG_DOCKER_VOLUME_NAME_PREFIX ?= magistrala
BUILD_DIR ?= build
SERVICES = atom-bootstrap notifications certs re postgres-writer postgres-reader timescale-writer timescale-reader alarms reports journal fluxmq
TEST_API_SERVICES = journal certs clients users channels groups domains
TEST_API = $(addprefix test_api_,$(TEST_API_SERVICES))
MG_DOCKER_IMAGE_NAME_PREFIX ?= magistrala
BUILD_DIR = build
SERVICES = auth users things http coap ws lora influxdb-writer influxdb-reader mongodb-writer \
mongodb-reader cassandra-writer cassandra-reader postgres-writer postgres-reader timescale-writer timescale-reader cli \
bootstrap opcua twins mqtt provision certs smtp-notifier smpp-notifier invitations
DOCKERS = $(addprefix docker_,$(SERVICES))
DOCKERS_DEV = $(addprefix docker_dev_,$(SERVICES))
CGO_ENABLED ?= 0
GOARCH ?= amd64
GOOS ?= linux
DETECTED_ARCH := $(shell uname -m)
VERSION ?= $(shell git describe --abbrev=0 --tags 2>/dev/null || echo 'unknown')
VERSION ?= $(shell git describe --abbrev=0 --tags)
COMMIT ?= $(shell git rev-parse HEAD)
TIME ?= $(shell date +%F_%T)
USER_REPO ?= $(shell git remote get-url origin | sed -E 's@.*/([^/]+)/([^/.]+)(\.git)?@\1_\2@')
USER_REPO ?= $(shell git remote get-url origin | sed -e 's/.*\/\([^/]*\)\/\([^/]*\).*/\1_\2/' )
empty:=
space:= $(empty) $(empty)
# Docker compose project name should follow this guidelines: https://docs.docker.com/compose/reference/#use--p-to-specify-a-project-name
DOCKER_PROJECT ?= $(shell echo $(subst $(space),,$(USER_REPO)) | sed -E 's/[^a-zA-Z0-9]/_/g' | tr '[:upper:]' '[:lower:]')
DOCKER_COMPOSE_COMMANDS_SUPPORTED := up down config restart
DOCKER_PROJECT ?= $(shell echo $(subst $(space),,$(USER_REPO)) | tr -c -s '[:alnum:][=-=]' '_' | tr '[:upper:]' '[:lower:]')
DOCKER_COMPOSE_COMMANDS_SUPPORTED := up down config
DEFAULT_DOCKER_COMPOSE_COMMAND := up
ATOM_TOKENS_ENV ?= docker/.env.tokens
REQUIRED_ATOM_TOKEN_ENVS := MG_ATOM_TOKEN_FLUXMQ_AUTH MG_ATOM_TOKEN_FLUXMQ_NODE1 MG_ATOM_TOKEN_FLUXMQ_NODE2 MG_ATOM_TOKEN_FLUXMQ_NODE3 MG_ATOM_TOKEN_JOURNAL MG_ATOM_TOKEN_NOTIFICATIONS MG_ATOM_TOKEN_TIMESCALE_READER MG_ATOM_TOKEN_RE MG_ATOM_TOKEN_ALARMS MG_ATOM_TOKEN_REPORTS MG_ATOM_TOKEN_POSTGRES_READER
PROVISION_ATOM_TOKENS ?= false
PROVISION_ATOM_TOKEN_GOALS := provision-atom-tokens
DOCKER_BASE_ENV_FILES := --env-file docker/.env
DOCKER_ENV_FILES = $(if $(filter down,$(DOCKER_COMPOSE_COMMAND)),$(DOCKER_BASE_ENV_FILES),$(DOCKER_BASE_ENV_FILES) --env-file $(ATOM_TOKENS_ENV))
DOCKER_PROVISION_ENV_FILES = $(DOCKER_BASE_ENV_FILES) $(if $(wildcard $(ATOM_TOKENS_ENV)),--env-file $(ATOM_TOKENS_ENV))
HOST_UID := $(shell id -u)
HOST_GID := $(shell id -g)
GRPC_MTLS_CERT_FILES_EXISTS = 0
MOCKERY = $(GOBIN)/mockery
MOCKERY_VERSION=3.6.4
PKG_PROTO_GEN_OUT_DIR=api/grpc
INTERNAL_PROTO_DIR=internal/proto
INTERNAL_PROTO_FILES := $(shell find $(INTERNAL_PROTO_DIR) -name "*.proto" | sed 's|$(INTERNAL_PROTO_DIR)/||')
MOCKERY_VERSION=v2.38.0
ifneq ($(MG_MESSAGE_BROKER_TYPE),)
MG_MESSAGE_BROKER_TYPE := $(MG_MESSAGE_BROKER_TYPE)
MG_MESSAGE_BROKER_TYPE := $(MG_MESSAGE_BROKER_TYPE)
else
MG_MESSAGE_BROKER_TYPE=msg_fluxmq
MG_MESSAGE_BROKER_TYPE=nats
endif
ifneq ($(MG_ES_TYPE),)
MG_ES_TYPE := $(MG_ES_TYPE)
MG_ES_TYPE := $(MG_ES_TYPE)
else
MG_ES_TYPE=es_fluxmq
MG_ES_TYPE=nats
endif
BUILD_TAGS := $(strip $(MG_MESSAGE_BROKER_TYPE) $(MG_ES_TYPE))
define compile_service
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) \
go build -tags "$(BUILD_TAGS)" -ldflags "-s -w \
go build -tags $(MG_MESSAGE_BROKER_TYPE) --tags $(MG_ES_TYPE) -ldflags "-s -w \
-X 'github.com/absmach/magistrala.BuildTime=$(TIME)' \
-X 'github.com/absmach/magistrala.Version=$(VERSION)' \
-X 'github.com/absmach/magistrala.Commit=$(COMMIT)'" \
@@ -73,7 +54,6 @@ define make_docker
--build-arg VERSION=$(VERSION) \
--build-arg COMMIT=$(COMMIT) \
--build-arg TIME=$(TIME) \
--build-arg BUILD_TAGS="$(BUILD_TAGS)" \
--tag=$(MG_DOCKER_IMAGE_NAME_PREFIX)/$(svc) \
-f docker/Dockerfile .
endef
@@ -88,96 +68,16 @@ define make_docker_dev
-f docker/Dockerfile.dev ./build
endef
define require_atom_tokens_env
@if [ -z "$(filter down,$(DOCKER_COMPOSE_COMMAND))" ]; then \
if [ ! -f "$(ATOM_TOKENS_ENV)" ]; then \
echo "Missing $(ATOM_TOKENS_ENV). Run 'make provision_atom_tokens' before starting the Docker Compose stack."; \
exit 2; \
fi; \
missing=""; \
for env_name in $(REQUIRED_ATOM_TOKEN_ENVS); do \
if ! grep -q "^$${env_name}=" "$(ATOM_TOKENS_ENV)"; then \
missing="$${missing} $${env_name}"; \
fi; \
done; \
if [ -n "$${missing}" ]; then \
echo "Missing Atom service token(s) in $(ATOM_TOKENS_ENV):$${missing}. Run 'make provision_atom_tokens' before starting the Docker Compose stack."; \
exit 2; \
fi; \
fi
endef
ADDON_SERVICES = bootstrap cassandra-reader cassandra-writer certs \
influxdb-reader influxdb-writer lora-adapter mongodb-reader mongodb-writer \
opcua-adapter postgres-reader postgres-writer provision smpp-notifier smtp-notifier \
timescale-reader timescale-writer twins
define ensure_atom_tokens_env
@if [ "$(PROVISION_ATOM_TOKENS)" = "true" ] && [ -z "$(filter down,$(DOCKER_COMPOSE_COMMAND))" ]; then \
$(MAKE) provision_atom_tokens; \
elif [ -z "$(filter down,$(DOCKER_COMPOSE_COMMAND))" ]; then \
if [ ! -f "$(ATOM_TOKENS_ENV)" ]; then \
echo "Missing $(ATOM_TOKENS_ENV). Run 'make provision_atom_tokens' before starting the Docker Compose stack."; \
exit 2; \
fi; \
missing=""; \
for env_name in $(REQUIRED_ATOM_TOKEN_ENVS); do \
if ! grep -q "^$${env_name}=" "$(ATOM_TOKENS_ENV)"; then \
missing="$${missing} $${env_name}"; \
fi; \
done; \
if [ -n "$${missing}" ]; then \
echo "Missing Atom service token(s) in $(ATOM_TOKENS_ENV):$${missing}. Run 'make provision_atom_tokens' before starting the Docker Compose stack."; \
exit 2; \
fi; \
fi
endef
define run_with_arch_detection
$(call require_atom_tokens_env)
@echo "Detecting architecture..."
@if [ "$(DETECTED_ARCH)" = "arm64" ] || [ "$(DETECTED_ARCH)" = "aarch64" ]; then \
echo "ARM64 architecture detected."; \
git checkout $(1); \
GOARCH=arm64 $(MAKE) dockers; \
for svc in $(SERVICES); do \
docker tag $(MG_DOCKER_IMAGE_NAME_PREFIX)/$$svc $(MG_DOCKER_IMAGE_NAME_PREFIX)/$$svc:latest; \
done; \
sed -i.bak 's/^MG_RELEASE_TAG=.*/MG_RELEASE_TAG=latest/' docker/.env && rm -f docker/.env.bak; \
docker compose -f docker/docker-compose.yaml $(DOCKER_ENV_FILES) -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args); \
else \
echo "x86_64 architecture detected."; \
git checkout $(1); \
sed -i.bak 's/^MG_RELEASE_TAG=.*/MG_RELEASE_TAG=$(2)/' docker/.env && rm -f docker/.env.bak; \
docker compose -f docker/docker-compose.yaml $(DOCKER_ENV_FILES) -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args); \
fi
endef
ADDON_SERVICES = bootstrap provision postgres-writer postgres-reader
EXTERNAL_SERVICES = prometheus
# Detect OS and architecture for cross-platform compatibility
UNAME_S := $(shell uname -s)
UNAME_M := $(shell uname -m)
# macOS BSD sed vs GNU sed compatibility
ifeq ($(UNAME_S),Darwin)
SED_INPLACE := sed -i ''
else
SED_INPLACE := sed -i
endif
# Apple Silicon (arm64) Docker platform compatibility
# Pre-built images are amd64 only, so we need to use emulation on Apple Silicon
ifeq ($(UNAME_S),Darwin)
ifeq ($(UNAME_M),arm64)
DOCKER_PLATFORM := DOCKER_DEFAULT_PLATFORM=linux/amd64
endif
endif
DOCKER_PLATFORM ?=
EXTERNAL_SERVICES = vault prometheus
ifneq ($(filter run%,$(firstword $(MAKECMDGOALS))),)
temp_args := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
DOCKER_COMPOSE_COMMAND := $(if $(filter $(DOCKER_COMPOSE_COMMANDS_SUPPORTED),$(temp_args)), $(filter $(DOCKER_COMPOSE_COMMANDS_SUPPORTED),$(temp_args)), $(DEFAULT_DOCKER_COMPOSE_COMMAND))
ifneq ($(filter $(PROVISION_ATOM_TOKEN_GOALS),$(temp_args)),)
override PROVISION_ATOM_TOKENS := true
endif
$(eval $(DOCKER_COMPOSE_COMMAND):;@)
endif
@@ -197,18 +97,18 @@ FILTERED_SERVICES = $(filter-out $(RUN_ADDON_ARGS), $(SERVICES))
all: $(SERVICES)
.PHONY: all $(SERVICES) dockers dockers_dev latest release provision_atom_tokens provision-atom-tokens migrate_atom run_latest run_latest_ci run_tls run_stable run_addons grpc_mtls_certs check_mtls check_certs test_api mocks
.PHONY: all $(SERVICES) dockers dockers_dev latest release run run_addons grpc_mtls_certs check_mtls check_certs
clean:
rm -rf ${BUILD_DIR}
cleandocker:
# Stops containers and removes containers, networks, volumes, and images created by up
docker compose -f docker/docker-compose.yaml -p $(DOCKER_PROJECT) down --rmi all -v --remove-orphans
docker compose -f docker/docker-compose.yml -p $(DOCKER_PROJECT) down --rmi all -v --remove-orphans
ifdef pv
# Remove unused volumes
docker volume ls -f name=$(MG_DOCKER_VOLUME_NAME_PREFIX) -f dangling=true -q | xargs -r docker volume rm
docker volume ls -f name=$(MG_DOCKER_IMAGE_NAME_PREFIX) -f dangling=true -q | xargs -r docker volume rm
endif
install:
@@ -216,57 +116,33 @@ install:
cp $$file $(GOBIN)/magistrala-`basename $$file`; \
done
mocks: $(MOCKERY)
@$(MOCKERY) --config ./tools/config/.mockery.yaml
check-generated-files:
$(MAKE) proto
@if git diff --name-only | grep .pb.go; then \
echo "Error generated files are out of sync. Please run 'make proto' and commit the changes."; \
exit 1; \
fi
$(MAKE) mocks
@if git diff --name-only | grep mocks; then \
echo "Error mocks are out of sync. Please run 'make mocks' and commit the changes."; \
exit 1; \
fi
$(MOCKERY):
@mkdir -p $(GOBIN)
@echo ">> installing mockery $(MOCKERY_VERSION)..."
@go install github.com/vektra/mockery/v3@v$(MOCKERY_VERSION)
mocks:
@which mockery > /dev/null || go install github.com/vektra/mockery/v2@$(MOCKERY_VERSION)
@unset MOCKERY_VERSION && go generate ./...
DIRS = consumers readers postgres internal
DIRS = consumers readers events cache messaging postgres internal opcua
test: mocks
mkdir -p coverage
@for dir in $(DIRS); do \
go test -v --race -failfast -count 1 -tags test -coverprofile=coverage/$$dir.out $$(go list ./... | grep $$dir | grep -v 'cmd'); \
done
go test -v --race -failfast -count 1 -tags test -coverprofile=coverage/coverage.out $$(go list ./... | grep -v 'consumers\|readers\|postgres\|internal\|cmd\|middleware')
define test_api_service
$(eval svc=$(subst test_api_,,$(1)))
@which uv > /dev/null || (echo "uv not found, please install it from https://github.com/astral-sh/uv" && exit 1)
@if [ -z "$(USER_TOKEN)" ]; then \
echo "USER_TOKEN is not set"; \
echo "Please set it to a valid token"; \
exit 1; \
fi
@uvx schemathesis run apidocs/openapi/$(svc).yaml \
--checks all \
--url $(2) \
--header "Authorization: Bearer $(USER_TOKEN)" \
--suppress-health-check=filter_too_much \
--exclude-checks=positive_data_acceptance \
--exclude-operation-id=requestPasswordReset \
--phases=examples,stateful
endef
test_api_users: TEST_API_URL := http://localhost:9000
test_api_clients: TEST_API_URL := http://localhost:9000
test_api_domains: TEST_API_URL := http://localhost:9000
test_api_channels: TEST_API_URL := http://localhost:9000
test_api_groups: TEST_API_URL := http://localhost:9000
test_api_certs: TEST_API_URL := http://localhost:9019
test_api_journal: TEST_API_URL := http://localhost:9021
$(TEST_API):
$(call test_api_service,$(@),$(TEST_API_URL))
go test -v --race -count 1 -tags test -coverprofile=coverage/$$dir.out $$(go list ./... | grep $$dir | grep -v 'cmd'); \
done
go test -v --race -count 1 -tags test -coverprofile=coverage/coverage.out $$(go list ./... | grep -v 'consumers\|readers\|events\|cache\|messaging\|postgres\|mongodb\|internal\|opcua\|cmd')
proto:
protoc -I. --go_out=. --go_opt=paths=source_relative pkg/messaging/*.proto
mkdir -p $(PKG_PROTO_GEN_OUT_DIR)
protoc -I $(INTERNAL_PROTO_DIR) --go_out=$(PKG_PROTO_GEN_OUT_DIR) --go_opt=paths=source_relative --go-grpc_out=$(PKG_PROTO_GEN_OUT_DIR) --go-grpc_opt=paths=source_relative $(INTERNAL_PROTO_FILES)
protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./*.proto
$(FILTERED_SERVICES):
$(call compile_service,$(@))
@@ -289,18 +165,10 @@ endef
changelog:
git log $(shell git describe --tags --abbrev=0)..HEAD --pretty=format:"- %s"
latest: dockers
# using dev since it takes less time to build for CI
latest: dockers_dev
$(call docker_push,latest)
publish_arch:
$(MAKE) dockers GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM)
for svc in $(SERVICES); do \
docker tag $(MG_DOCKER_IMAGE_NAME_PREFIX)/$$svc $(MG_DOCKER_IMAGE_NAME_PREFIX)/$$svc:$(VERSION)-$(GOARCH); \
docker tag $(MG_DOCKER_IMAGE_NAME_PREFIX)/$$svc $(MG_DOCKER_IMAGE_NAME_PREFIX)/$$svc:latest-$(GOARCH); \
docker push $(MG_DOCKER_IMAGE_NAME_PREFIX)/$$svc:$(VERSION)-$(GOARCH); \
docker push $(MG_DOCKER_IMAGE_NAME_PREFIX)/$$svc:latest-$(GOARCH); \
done
release:
$(eval version = $(shell git describe --abbrev=0 --tags))
git checkout $(version)
@@ -314,87 +182,42 @@ rundev:
cd scripts && ./run.sh
grpc_mtls_certs:
$(MAKE) -C docker/ssl clients_grpc_certs
provision_atom_tokens:
$(DOCKER_PLATFORM) docker compose -f docker/docker-compose.yaml $(DOCKER_PROVISION_ENV_FILES) -p $(DOCKER_PROJECT) up -d --wait --wait-timeout 120 atom
$(MAKE) docker_atom-bootstrap
$(DOCKER_PLATFORM) docker compose -f docker/docker-compose.yaml $(DOCKER_PROVISION_ENV_FILES) -p $(DOCKER_PROJECT) run --rm --no-deps --user "$(HOST_UID):$(HOST_GID)" -v "$(PWD)/docker:/host/docker" atom-bootstrap provision-tokens --output /host/docker/.env.tokens
provision-atom-tokens:
@:
# Migrate an old Magistrala (v0.30.0 / pre-Atom) deployment into Atom. Runs an
# isolated, collision-free stack, seeds the Atom schema into the run_latest Atom
# volume and loads the data. Default is a dry-run; pass args="--apply" to load,
# args="--verify" to reconcile afterwards.
# make migrate_atom # dry-run
# make migrate_atom args="--apply" # perform the migration
# make migrate_atom args="--apply --fresh-atom" # rebuild Atom schema first
migrate_atom:
DOCKER_PROJECT="$(DOCKER_PROJECT)" tools/atom-migration/migrate.sh $(args)
$(MAKE) -C docker/ssl auth_grpc_certs things_grpc_certs
check_tls:
ifeq ($(GRPC_TLS),true)
@unset GRPC_MTLS
@echo "gRPC TLS is enabled"
$(eval GRPC_MTLS :=)
GRPC_MTLS=
else
$(eval GRPC_TLS :=)
@unset GRPC_TLS
GRPC_TLS=
endif
check_mtls:
ifeq ($(GRPC_MTLS),true)
@unset GRPC_TLS
@echo "gRPC MTLS is enabled"
$(eval GRPC_TLS :=)
GRPC_TLS=
else
$(eval GRPC_MTLS :=)
@unset GRPC_MTLS
GRPC_MTLS=
endif
check_certs: check_mtls check_tls
ifeq ($(GRPC_MTLS_CERT_FILES_EXISTS),0)
ifeq ($(filter true,$(GRPC_MTLS) $(GRPC_TLS)),true)
ifeq ($(filter $(DEFAULT_DOCKER_COMPOSE_COMMAND),$(DOCKER_COMPOSE_COMMAND)),$(DEFAULT_DOCKER_COMPOSE_COMMAND))
$(MAKE) -C docker/ssl clients_grpc_certs
$(MAKE) -C docker/ssl auth_grpc_certs things_grpc_certs
endif
endif
endif
run_latest: check_certs
$(SED_INPLACE) 's/^MG_RELEASE_TAG=.*/MG_RELEASE_TAG=latest/' docker/.env
$(call ensure_atom_tokens_env)
$(DOCKER_PLATFORM) docker compose -f docker/docker-compose.yaml $(DOCKER_ENV_FILES) -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
run_latest_ci: check_certs
$(call require_atom_tokens_env)
$(SED_INPLACE) 's/^MG_RELEASE_TAG=.*/MG_RELEASE_TAG=latest/' docker/.env
$(DOCKER_PLATFORM) docker compose -f docker/docker-compose.yaml -f docker/docker-compose-ci.yaml $(DOCKER_ENV_FILES) -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
run_tls:
@test -n "$(host)" || (echo "Usage: make run_tls host=example.com [email=admin@example.com] [letsencrypt=false] [staging=true] [force=true]" && exit 2)
@if [ "$(or $(letsencrypt),true)" != "false" ] && [ -z "$(email)" ]; then echo "Usage: make run_tls host=example.com email=admin@example.com [letsencrypt=false] [staging=true] [force=true]"; exit 2; fi
MG_PUBLIC_HOST="$(host)" \
MG_LETSENCRYPT_ENABLED="$(or $(letsencrypt),true)" \
MG_LETSENCRYPT_EMAIL="$(email)" \
MG_LETSENCRYPT_STAGING="$(or $(staging),false)" \
MG_LETSENCRYPT_FORCE_RENEWAL="$(or $(force),false)" \
DOCKER_PROJECT="$(DOCKER_PROJECT)" \
./docker/setup-tls.sh
run_stable: check_certs
$(call require_atom_tokens_env)
$(eval version = $(shell git describe --abbrev=0 --tags))
git checkout $(version)
$(SED_INPLACE) 's/^MG_RELEASE_TAG=.*/MG_RELEASE_TAG=$(version)/' docker/.env
$(DOCKER_PLATFORM) docker compose -f docker/docker-compose.yaml $(DOCKER_ENV_FILES) -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
run: check_certs
docker compose -f docker/docker-compose.yml --env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
run_addons: check_certs
$(call require_atom_tokens_env)
$(foreach SVC,$(RUN_ADDON_ARGS),$(if $(filter $(SVC),$(ADDON_SERVICES) $(EXTERNAL_SERVICES)),,$(error Invalid Service $(SVC))))
@$(DOCKER_PLATFORM) docker compose -f docker/docker-compose.yaml $(DOCKER_ENV_FILES) -p $(DOCKER_PROJECT) up -d atom jaeger
@for SVC in $(RUN_ADDON_ARGS); do \
MG_ADDONS_CERTS_PATH_PREFIX="../" $(DOCKER_PLATFORM) docker compose -f docker/addons/$$SVC/docker-compose.yaml -p $(DOCKER_PROJECT) $(DOCKER_ENV_FILES) $(DOCKER_COMPOSE_COMMAND) $(args) & \
MG_ADDONS_CERTS_PATH_PREFIX="../." docker compose -f docker/addons/$$SVC/docker-compose.yml -p $(DOCKER_PROJECT) --env-file ./docker/.env $(DOCKER_COMPOSE_COMMAND) $(args) & \
done
run_live: check_certs
$(call require_atom_tokens_env)
GOPATH=$(go env GOPATH) $(DOCKER_PLATFORM) docker compose -f docker/docker-compose.yaml -f docker/docker-compose-live.yaml $(DOCKER_ENV_FILES) -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
+154 -270
View File
@@ -1,299 +1,183 @@
<div align="center">
# Magistrala
### A Modern IoT Platform Framework for Scalable IoT
[![go report card][grc-badge]][grc-url]
[![coverage][cov-badge]][cov-url]
[![license][license]](LICENSE)
[![chat][gitter-badge]][gitter]
**Made with ❤ by [Abstract Machines](https://absmach.eu/)**
![banner][banner]
[![Build Status](https://github.com/absmach/magistrala/actions/workflows/build.yaml/badge.svg?branch=main)](https://github.com/absmach/magistrala/actions/workflows/build.yaml)
[![Go Report Card](https://goreportcard.com/badge/github.com/absmach/magistrala)](https://goreportcard.com/report/github.com/absmach/magistrala)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/absmach/magistrala)
[![Check License Header](https://github.com/absmach/magistrala/actions/workflows/check-license.yaml/badge.svg?branch=main)](https://github.com/absmach/magistrala/actions/workflows/check-license.yaml)
[![Check Generated Files](https://github.com/absmach/magistrala/actions/workflows/check-generated-files.yaml/badge.svg?branch=main)](https://github.com/absmach/magistrala/actions/workflows/check-generated-files.yaml)
[![Coverage](https://codecov.io/gh/absmach/magistrala/graph/badge.svg?token=nPCEr5nW8S)](https://codecov.io/gh/absmach/magistrala)
[![License](https://img.shields.io/badge/license-Apache%20v2.0-blue.svg)](LICENSE)
[![Matrix](https://img.shields.io/matrix/supermq%3Amatrix.org?label=Chat&style=flat&logo=matrix&logoColor=white)](https://matrix.to/#/#supermq:matrix.org)
Magistrala is modern, scalable, secure, open-source, and patent-free IoT cloud platform written in Go.
[Guide](https://magistrala.absmach.eu/docs/) | [Contributing](CONTRIBUTING.md) | [Website](https://absmach.eu/) | [Chat](https://matrix.to/#/#supermq:matrix.org)
</div>
It accepts user and thing (sensor, actuator, application) connections over various network protocols (i.e. HTTP, MQTT, WebSocket, CoAP), thus making a seamless bridge between them. It is used as the IoT middleware for building complex IoT solutions.
## Introduction 🌍
For more details, check out the [official documentation][docs].
Magistrala is an open-source IoT platform built for engineers who need full control over their messaging, device management, and data pipelines.
## Features
It is built on top of [FluxMQ](https://github.com/absmach/fluxmq), a modern message broker designed for both messaging and event streams. Magistrala provides everything around it: identity, access control, device provisioning, data processing, and observability.
- Multi-protocol connectivity and bridging (HTTP, MQTT, WebSocket and CoAP)
- Device management and provisioning (Zero Touch provisioning)
- Mutual TLS Authentication (mTLS) using X.509 Certificates
- Fine-grained access control (policies, ABAC/RBAC)
- Message persistence (Cassandra, InfluxDB, MongoDB and PostgresSQL)
- Platform logging and instrumentation support (Prometheus and OpenTelemetry)
- Event sourcing
- Container-based deployment using [Docker][docker] and [Kubernetes][kubernetes]
- [LoRaWAN][lora] network integration
- [OPC UA][opcua] integration
- Edge [Agent][agent] and [Export][export] services for remote IoT gateway management and edge computing
- SDK
- CLI
- Small memory footprint and fast execution
- Domain-driven design architecture, high-quality code and test coverage
IoT systems usually involve brokers, databases, rule engines, and custom services. Magistrala does not pretend those pieces disappear. It provides a coherent framework for integrating them into a single system with a consistent model for identity, access control, messaging, and observability.
## Prerequisites
**What it is:**
- An event-driven IoT middleware platform
- A unified control plane for devices, users, and data
- A foundation for building scalable IoT systems
The following are needed to run Magistrala:
**What it is not:**
- Not just an MQTT broker
- Not a black-box SaaS
- Not tied to a single cloud or vendor
- [Docker](https://docs.docker.com/install/) (version 24.0.7)
- [Docker compose](https://docs.docker.com/compose/install/) (version 2.24.0)
---
Developing Magistrala will also require:
## 🧩 IoT Platform Framework
- [Go](https://golang.org/doc/install) (version 1.21)
- [Protobuf](https://github.com/protocolbuffers/protobuf#protocol-compiler-installation) (version 25.1)
We call Magistrala a **framework**, not just a platform.
## Install
It is extremely flexible and lets you build systems the way you want — from simple prototypes to complex, large-scale deployments — without forcing you into rigid patterns.
At the same time, it avoids the typical complexity of many IoT platforms, where you need to learn an entirely new set of concepts before you can even get started.
Magistrala is built around a small number of main concepts:
- users
- clients (devices)
- channels
- messages
- policies
Most engineers are already familiar with these ideas, so you can start building immediately.
You can keep things simple:
- connect devices
- send messages
- store data
Or you can go deeper:
- define complex access control policies
- build event-driven pipelines
- integrate custom processing and automation
Magistrala scales with your needs — simple when you want it, powerful when you need it.
---
## 🚀 Key Benefits
- **A Coherent System, Not a Mess of Integrations**
Build IoT systems from multiple components without ending up with fragmented security, messaging, and operations.
- **Event-Driven at the Core**
Everything is built around events — enabling real-time processing, streaming, and scalable data flows.
- **Protocol-Native, Not Forced Abstractions**
MQTT, HTTP, WebSocket, and CoAP are treated as first-class citizens, each with their own semantics.
- **Security Built Into the Model**
Identity, authentication, and authorization are part of the system design — not bolted on later.
- **Flexible by Design**
Start simple or build complex systems — without changing platforms or rewriting your architecture.
- **Runs Where You Need It**
Cloud, edge, or hybrid — no vendor lock-in, no hidden dependencies.
---
## ✨ Features
Magistrala provides a complete set of building blocks for IoT systems — from device connectivity to data processing and observability — without forcing a rigid architecture.
### 🔐 Identity & Access
- Multi-tenant domains for isolating environments
- Users, roles, and organizational hierarchies
- Fine-grained access control (ABAC + RBAC)
- Mutual TLS (X.509) and JWT-based authentication
- Personal Access Tokens (PATs) with scoping and revocation
### 🔌 Connectivity
- Native support for MQTT, HTTP, WebSocket, and CoAP
- Consistent authentication and authorization across protocols
- Designed for both cloud services and constrained devices
### 📦 Device & Application Model
- Device (client) provisioning and lifecycle management
- Channels for grouping and controlling message flow
- Application-level grouping and sharing of clients
- Simple but flexible communication model
### ⚙️ Processing & Automation
- Rules engine for message processing and routing
- Alarms and triggers for reacting to events
- Scheduled actions for time-based workflows
- Event-driven architecture as the foundation
### 📊 Observability
- Audit logs for tracking system activity
- Metrics and tracing via Prometheus and OpenTelemetry
- Built-in visibility into system behavior and data flows
### 🚀 Deployment & Operations
- Container-native (Docker, Kubernetes)
- Designed for cloud, edge, and hybrid deployments
- Works with external storage and processing systems
- Scales from small setups to production environments
### 🧑‍💻 Developer Experience
- CLI and SDKs for fast integration
- Straightforward APIs and concepts
- Documentation focused on getting you running quickly
---
## Atom Integration Model
Magistrala uses **Atom** as the backend for identity, authorization, and the catalog.
Atom is the source of truth for:
- domains
- users
- clients
- channels
- groups
- roles
- access policies
Magistrala services such as rules, alarms, and reports remain Magistrala services, but they use Atom for identity and authorization.
Current Docker deployments use the Atom image configured by `ATOM_IMAGE` in `docker/.env`. For compatibility with the current Magistrala integration, the generated `MG_ATOM_TOKEN_*` service credentials are unscoped Atom access tokens. Scoped Atom access tokens should not be used for these service env vars until Magistrala stops using owner-wide Atom listing APIs such as `authorizedObjectIds` in service policy paths.
### Core Entity Mapping
| Magistrala concept | Atom concept | Meaning |
|--------------------|--------------|---------|
| Domain | Tenant | Isolation boundary for one organization, project, or environment |
| User | Entity with kind `human` | A person who logs in and uses the UI/API |
| Client | Entity with kind `device` | A device or application that sends/receives data |
| Channel | Resource with kind `channel` | A messaging/data path that clients can publish or subscribe to |
| Group | Group | A collection of users, clients, channels, or other grouped objects |
In simple terms:
```text
MG Domain = Atom Tenant
MG User = Atom Human Entity
MG Client = Atom Device Entity
MG Channel = Atom Channel Resource
MG Group = Atom Group
```
### Actions, Permission Blocks, Roles, and Assignments
Atom access control has these basic parts:
| Atom word | Simple meaning | Example |
|-----------|----------------|---------|
| Action | One permission verb | `read`, `write`, `delete`, `role.manage`, `policy.manage` |
| Permission Block | Where actions apply | all channels in domain `d1` can `read`, `publish` |
| Role | A bundle of permission blocks | `tenant-admin` bundles domain, role, and member access |
| Role Assignment | Who gets a role | give `user1` the `tenant-admin` role |
Read an assignment like this:
```text
Give <who> this <role>.
The role contains permission blocks that say where and what.
```
Example:
```text
Give user1 the tenant-admin role on domain d1.
```
That means:
```text
user1 can use the tenant-admin permissions inside domain d1.
```
### How MG Roles Work With Atom
MG UI shows actions such as:
- read
- update
- delete
- manage roles
- add/remove members
- publish
- subscribe
These are mapped to Atom actions:
| MG action | Atom action |
|-----------|-----------------|
| view/read | `read` |
| create/update/edit/connect | `write` |
| delete/remove | `delete` |
| manage roles | `role.manage` |
| add/remove members or access | `policy.manage` |
| channel publish | `publish` |
| channel subscribe | `subscribe` |
So when MG UI checks:
```text
Can user1 manage roles for client1?
```
Atom checks:
```text
Does user1 have role.manage on client1, or on the domain that contains client1?
```
When MG UI checks:
```text
Can user1 add a member to channel1?
```
Atom checks:
```text
Does user1 have policy.manage on channel1, or on the domain that contains channel1?
```
### Practical Rule
If a user is domain admin, they usually receive a tenant-scoped role in Atom.
That tenant-scoped role can allow them to manage objects inside the domain:
- clients
- channels
- groups
- rules
- alarms
- reports
For narrower access, create object-scoped roles. For example:
```text
Give user2 a reader role only on channel1.
```
Then user2 can read only that channel, not the whole domain.
## Installation
Once the prerequisites are installed, execute the following commands from the project's root:
```bash
git clone https://github.com/absmach/magistrala.git
cd magistrala
make run_latest
docker compose -f docker/docker-compose.yml --env-file docker/.env -p git_github_com_absmach_magistrala_git_ up
```
---
This will bring up the Magistrala docker services and interconnect them. This command can also be executed using the project's included Makefile:
```bash
make run
```
If you want to run services from specific release checkout code from github and make sure that `MG_RELEASE_TAG` in [.env](.env) is being set to match the release version
```bash
git checkout tags/<release_number> -b <release_number>
# e.g. `git checkout tags/0.14.0 -b 0.14.0`
```
Check that `.env` file contains:
```bash
MG_RELEASE_TAG=<release_number>
```
> `docker-compose` should be used for development and testing deployments. For production we suggest using [Kubernetes](https://docs.mainflux.io/kubernetes).
## Usage
The quickest way to start using Magistrala is via the CLI. The latest version can be downloaded from the [official releases page][releases].
It can also be built and used from the project's root directory:
```bash
make cli
./build/cli health <service>
./build/cli version
```
---
Additional details on using the CLI can be found in the [CLI documentation](https://docs.mainflux.io/cli).
## Documentation
Official documentation is hosted at [Magistrala official docs page][docs]. Documentation is auto-generated, checkout the instructions on [official docs repository](https://github.com/mainflux/docs):
If you spot an error or a need for corrections, please let us know - or even better: send us a PR.
## Authors
Main architect and BDFL of Magistrala project is [@drasko][drasko].
Additionally, [@nmarcetic][nikola] and [@janko-isidorovic][janko] assured overall architecture and design, while [@manuio][manu] and [@darkodraskovic][darko] helped with crafting initial implementation and continuously worked on the project evolutions.
Besides them, Magistrala is constantly improved and actively developed by [@anovakovic01][alex], [@dusanb94][dusan], [@srados][sava], [@gsaleh][george], [@blokovi][iva], [@chombium][kole], [@mteodor][mirko], [@rodneyosodo][rodneyosodo] and a large set of contributors.
Maintainers are listed in [MAINTAINERS](MAINTAINERS) file.
The Magistrala team would like to give special thanks to [@mijicd][dejan] for his monumental work on designing and implementing a highly improved and optimized version of the platform, and [@malidukica][dusanm] for his effort on implementing the initial user interface.
## Professional Support
There are many companies offering professional support for the Magistrala system.
If you need this kind of support, best is to reach out to [@drasko][drasko] directly, and he will point you out to the best-matching support team.
## Contributing
Thank you for your interest in Magistrala and the desire to contribute!
1. Take a look at our [open issues](https://github.com/absmach/magistrala/issues). The [good-first-issue](https://github.com/absmach/magistrala/labels/good-first-issue) label is specifically for issues that are great for getting started.
2. Checkout the [contribution guide](CONTRIBUTING.md) to learn more about our style and conventions.
3. Make your changes compatible to our workflow.
## Community
- [Google group][forum]
- [Gitter][gitter]
- [Twitter][twitter]
## License
Apache-2.0
[Apache-2.0](LICENSE)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fmainflux%2Fmainflux.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fmainflux%2Fmainflux?ref=badge_large)
## Data Collection for Magistrala
Magistrala is committed to continuously improving its services and ensuring a seamless experience for its users. To achieve this, we collect certain data from your deployments. Rest assured, this data is collected solely for the purpose of enhancing Magistrala and is not used with any malicious intent. The deployment summary can be found on our [website][callhome].
The collected data includes:
- **IP Address** - Used for approximate location information on deployments.
- **Services Used** - To understand which features are popular and prioritize future developments.
- **Last Seen Time** - To ensure the stability and availability of Magistrala.
- **Magistrala Version** - To track the software version and deliver relevant updates.
We take your privacy and data security seriously. All data collected is handled in accordance with our stringent privacy policies and industry best practices.
Data collection is on by default and can be disabled by setting the env variable:
`MG_SEND_TELEMETRY=false`
By utilizing Magistrala, you actively contribute to its improvement. Together, we can build a more robust and efficient IoT platform. Thank you for your trust in Magistrala!
[banner]: https://github.com/mainflux/docs/blob/master/docs/img/gopherBanner.jpg
[docs]: https://docs.mainflux.io
[docker]: https://www.docker.com
[forum]: https://groups.google.com/forum/#!forum/mainflux
[gitter]: https://gitter.im/absmach/magistrala?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[gitter-badge]: https://badges.gitter.im/Join%20Chat.svg
[grc-badge]: https://goreportcard.com/badge/github.com/absmach/magistrala
[grc-url]: https://goreportcard.com/report/github.com/absmach/magistrala
[cov-badge]: https://codecov.io/gh/absmach/magistrala/graph/badge.svg?token=SEMDAO3L09
[cov-url]: https://codecov.io/gh/absmach/magistrala
[license]: https://img.shields.io/badge/license-Apache%20v2.0-blue.svg
[twitter]: https://twitter.com/mainflux
[lora]: https://lora-alliance.org/
[opcua]: https://opcfoundation.org/about/opc-technologies/opc-ua/
[agent]: https://github.com/mainflux/agent
[export]: https://github.com/mainflux/export
[kubernetes]: https://kubernetes.io/
[releases]: https://github.com/absmach/magistrala/releases
[drasko]: https://github.com/drasko
[nikola]: https://github.com/nmarcetic
[dejan]: https://github.com/mijicd
[manu]: https://github.com/manuIO
[darko]: https://github.com/darkodraskovic
[janko]: https://github.com/janko-isidorovic
[alex]: https://github.com/anovakovic01
[dusan]: https://github.com/dborovcanin
[sava]: https://github.com/srados
[george]: https://github.com/gesaleh
[iva]: https://github.com/blokovi
[kole]: https://github.com/chombium
[dusanm]: https://github.com/malidukica
[mirko]: https://github.com/mteodor
[rodneyosodo]: https://github.com/rodneyosodo
[callhome]: https://deployments.mainflux.io
-193
View File
@@ -1,193 +0,0 @@
# Alarms
The Alarms service stores, manages and exposes alarms raised by rules and device activity. It consumes alarm events from the message broker, persists them to PostgreSQL, and provides an HTTP API for listing, viewing, updating, and deleting alarms with full authn/authz, metrics, and tracing support.
## Configuration
The service is configured using the following environment variables (values shown are from [docker/.env](https://github.com/absmach/magistrala/blob/main/docker/.env) as consumed by [docker/docker-compose.yaml](https://github.com/absmach/magistrala/blob/main/docker/docker-compose.yaml)):
| Variable | Description | Default |
| --- | --- | --- |
| `MG_ALARMS_LOG_LEVEL` | Log level for the service | `debug` |
| `MG_ALARMS_HTTP_HOST` | HTTP host to bind | `alarms` |
| `MG_ALARMS_HTTP_PORT` | HTTP port to bind | `8050` |
| `MG_ALARMS_HTTP_SERVER_CERT` | Path to PEM-encoded HTTPS server certificate | "" |
| `MG_ALARMS_HTTP_SERVER_KEY` | Path to PEM-encoded HTTPS server key | "" |
| `MG_ALARMS_DB_HOST` | PostgreSQL host | `alarms-db` |
| `MG_ALARMS_DB_PORT` | PostgreSQL port | `5432` |
| `MG_ALARMS_DB_USER` | PostgreSQL user | `magistrala` |
| `MG_ALARMS_DB_PASS` | PostgreSQL password | `magistrala` |
| `MG_ALARMS_DB_NAME` | PostgreSQL database name | `alarms` |
| `MG_ALARMS_DB_SSL_MODE` | PostgreSQL SSL mode | `disable` |
| `MG_ALARMS_DB_SSL_CERT` | PostgreSQL SSL client cert | "" |
| `MG_ALARMS_DB_SSL_KEY` | PostgreSQL SSL client key | "" |
| `MG_ALARMS_DB_SSL_ROOT_CERT` | PostgreSQL SSL root cert | "" |
| `MG_ALARMS_INSTANCE_ID` | Instance ID for tracing/health | "" |
| `MG_MESSAGE_BROKER_URL` | Message broker URL for alarm ingestion | `nats://nats:4222` |
| `MG_JAEGER_URL` | Jaeger collector endpoint | `http://jaeger:4318/v1/traces` |
| `MG_JAEGER_TRACE_RATIO` | Trace sampling ratio | `1.0` |
| `ATOM_URL` | Atom HTTP endpoint | `http://atom:8080` |
| `ATOM_JWKS_URL` | Atom JWKS endpoint for JWT verification | `http://atom:8080/.well-known/jwks.json` |
| `ATOM_SERVICE_TOKEN` | Atom service token for authorization checks | "" |
| `ATOM_ADMIN_USERNAME` | Atom admin login fallback when no service token is configured | `atom-admin` |
| `ATOM_ADMIN_SECRET` | Atom admin secret fallback when no service token is configured | `change-me` |
| `ATOM_TIMEOUT` | Atom request timeout | `5s` |
| `MG_ALLOW_UNVERIFIED_USER` | Allow unverified users to access | `true` |
## Features
- **Alarm ingestion**: Consumes alarms from the message broker and persists them to PostgreSQL.
- **Stateful updates**: Updates assignee, acknowledgment, resolution, and metadata fields.
- **Filtering and paging**: Lists alarms by domain, rule, channel, client, subtopic, status, severity, and time range.
- **Observability**: `/metrics` Prometheus endpoint and Jaeger tracing support.
- **Auth and authorization**: Authn/authz enforced through Atom JWT verification and PDP checks while alarm records stay in PostgreSQL.
## Architecture
### Runtime flow
1. The message broker publishes alarm events under the `alarms.>` subject.
2. The Alarms consumer decodes the event payload, enriches it with message metadata, validates it, and calls `CreateAlarm`.
3. The repository writes to PostgreSQL while deduplicating repeated active alarms with the same severity.
4. The HTTP API exposes list/view/update/delete operations with authn/authz, metrics, and tracing middleware.
### Components
- **HTTP API**: `alarms/api` exposes REST endpoints and health/metrics handlers.
- **Service layer**: `alarms/service.go` validates requests and coordinates repository operations.
- **Repository**: `alarms/postgres/alarms.go` implements persistence and filtering.
- **Consumer**: `alarms/consumer` processes broker messages and creates alarms.
- **Message broker**: `alarms/brokers` uses NATS JetStream with stream `alarms` and subject `alarms.>`.
- **Migrations**: `alarms/postgres/init.go` defines the alarms schema and indexes.
### Alarms table
Defined in `alarms/postgres/init.go`:
| Column | Type | Description |
| --- | --- | --- |
| `id` | `VARCHAR(36)` | Alarm UUID (primary key) |
| `rule_id` | `VARCHAR(36)` | Rule ID that triggered the alarm |
| `domain_id` | `VARCHAR(36)` | Domain ID |
| `channel_id` | `VARCHAR(36)` | Channel ID |
| `subtopic` | `TEXT` | Subtopic associated with the alarm |
| `client_id` | `VARCHAR(36)` | Client ID |
| `measurement` | `TEXT` | Measurement name |
| `value` | `TEXT` | Measured value |
| `unit` | `TEXT` | Measurement unit |
| `threshold` | `TEXT` | Threshold value |
| `cause` | `TEXT` | Cause/description |
| `status` | `SMALLINT` | 0 = active, 1 = cleared |
| `severity` | `SMALLINT` | Severity (0-100) |
| `assignee_id` | `VARCHAR(36)` | Assignee ID |
| `created_at` | `TIMESTAMPTZ` | Creation timestamp |
| `updated_at` | `TIMESTAMPTZ` | Last update timestamp |
| `updated_by` | `VARCHAR(36)` | User who updated |
| `assigned_at` | `TIMESTAMPTZ` | When assigned |
| `assigned_by` | `VARCHAR(36)` | Who assigned |
| `acknowledged_at` | `TIMESTAMPTZ` | When acknowledged |
| `acknowledged_by` | `VARCHAR(36)` | Who acknowledged |
| `resolved_at` | `TIMESTAMPTZ` | When resolved |
| `resolved_by` | `VARCHAR(36)` | Who resolved |
| `metadata` | `JSONB` | Custom metadata |
Index: `idx_alarms_state (domain_id, rule_id, channel_id, subtopic, client_id, measurement, created_at DESC)`
## Deployment
### Build and run locally
```bash
make alarms
MG_ALARMS_LOG_LEVEL=debug \
MG_ALARMS_HTTP_PORT=8050 \
MG_ALARMS_DB_HOST=localhost \
MG_ALARMS_DB_PORT=5432 \
MG_ALARMS_DB_USER=magistrala \
MG_ALARMS_DB_PASS=magistrala \
MG_ALARMS_DB_NAME=alarms \
MG_MESSAGE_BROKER_URL=nats://localhost:4222 \
MG_AUTH_GRPC_URL=localhost:7001 \
MG_AUTH_GRPC_TIMEOUT=300s \
MG_DOMAINS_GRPC_URL=localhost:7003 \
MG_DOMAINS_GRPC_TIMEOUT=300s \
./build/alarms
```
### Docker Compose
The service is available as a Docker container. Refer to [docker/docker-compose.yaml](https://github.com/absmach/magistrala/blob/main/docker/docker-compose.yaml) for the `alarms` and `alarms-db` services and their environment variables. For a full local stack, make sure the auth, domains, and message broker services are also running.
```bash
docker compose -f docker/docker-compose.yaml up alarms alarms-db
```
### Health check
```bash
curl -X GET http://localhost:8050/health \
-H "accept: application/health+json"
```
## Testing
```bash
go test ./alarms/...
```
## Usage
The Alarms service supports the following operations:
| Operation | Method & Path | Description |
| --- | --- | --- |
| `listAlarms` | `GET /{domainID}/alarms` | List alarms with filters |
| `viewAlarm` | `GET /{domainID}/alarms/{alarmID}` | Retrieve a single alarm |
| `updateAlarm` | `PUT /{domainID}/alarms/{alarmID}` | Update alarm status/assignee/metadata |
| `deleteAlarm` | `DELETE /{domainID}/alarms/{alarmID}` | Delete an alarm |
| `health` | `GET /health` | Service health check |
Alarm creation is driven by message broker events and is not exposed as an HTTP endpoint.
### Example: List alarms
```bash
curl -X GET "http://localhost:8050/<domainID>/alarms?limit=10&offset=0&status=active&severity=50" \
-H "Authorization: Bearer <your_access_token>"
```
### Example: View an alarm
```bash
curl -X GET http://localhost:8050/<domainID>/alarms/<alarmID> \
-H "Authorization: Bearer <your_access_token>"
```
### Example: Update an alarm
```bash
curl -X PUT http://localhost:8050/<domainID>/alarms/<alarmID> \
-H "Authorization: Bearer <your_access_token>" \
-H "Content-Type: application/json" \
-d '{
"status": "cleared",
"assignee_id": "<userID>",
"severity": 40,
"metadata": { "note": "cleared after inspection" }
}'
```
### Example: Delete an alarm
```bash
curl -X DELETE http://localhost:8050/<domainID>/alarms/<alarmID> \
-H "Authorization: Bearer <your_access_token>"
```
### Example: Health check
```bash
curl -X GET http://localhost:8050/health \
-H "accept: application/health+json"
```
-123
View File
@@ -1,123 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package alarms
import (
"context"
"errors"
"time"
"github.com/absmach/magistrala/pkg/authn"
)
const SeverityMax uint8 = 100
var ErrInvalidSeverity = errors.New("invalid severity. Must be between 0 and 100")
type Metadata map[string]any
// Alarm represents an alarm instance.
type Alarm struct {
ID string `json:"id"`
RuleID string `json:"rule_id"`
DomainID string `json:"domain_id"`
ChannelID string `json:"channel_id"`
ClientID string `json:"client_id"`
Subtopic string `json:"subtopic"`
Status Status `json:"status"`
Measurement string `json:"measurement"`
Value string `json:"value"`
Unit string `json:"unit"`
Threshold string `json:"threshold"`
Cause string `json:"cause"`
Severity uint8 `json:"severity"`
AssigneeID string `json:"assignee_id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
UpdatedBy string `json:"updated_by"`
AssignedAt time.Time `json:"assigned_at,omitempty"`
AssignedBy string `json:"assigned_by,omitempty"`
AcknowledgedAt time.Time `json:"acknowledged_at,omitempty"`
AcknowledgedBy string `json:"acknowledged_by,omitempty"`
ResolvedAt time.Time `json:"resolved_at,omitempty"`
ResolvedBy string `json:"resolved_by,omitempty"`
Metadata Metadata `json:"metadata,omitempty"`
}
type AlarmsPage struct {
Offset uint64 `json:"offset"`
Limit uint64 `json:"limit"`
Total uint64 `json:"total"`
Alarms []Alarm `json:"alarms"`
}
type PageMetadata struct {
Offset uint64 `json:"offset" db:"offset"`
Limit uint64 `json:"limit" db:"limit"`
DomainID string `json:"domain_id" db:"domain_id"`
RuleID string `json:"rule_id" db:"rule_id"`
RuleIDs []string `json:"rule_ids" db:"rule_ids"`
ChannelID string `json:"channel_id" db:"channel_id"`
ClientID string `json:"client_id" db:"client_id"`
Subtopic string `json:"subtopic" db:"subtopic"`
Measurement string `json:"measurement" db:"measurement"`
Dir string `json:"dir" db:"dir"`
Order string `json:"order" db:"order"`
Status Status `json:"status" db:"status"`
CreatedFrom time.Time `json:"created_from" db:"created_from"`
CreatedTo time.Time `json:"created_to" db:"created_to"`
AssigneeID string `json:"assignee_id" db:"assignee_id"`
Severity uint8 `json:"severity" db:"severity"`
UpdatedBy string `json:"updated_by" db:"updated_by"`
AssignedBy string `json:"assigned_by" db:"assigned_by"`
AcknowledgedBy string `json:"acknowledged_by" db:"acknowledged_by"`
ResolvedBy string `json:"resolved_by" db:"resolved_by"`
UserID string `json:"user_id" db:"user_id"`
}
func (a Alarm) Validate() error {
if a.RuleID == "" {
return errors.New("rule_id is required")
}
if a.DomainID == "" {
return errors.New("domain_id is required")
}
if a.ChannelID == "" {
return errors.New("channel_id is required")
}
if a.ClientID == "" {
return errors.New("client_id is required")
}
if a.Measurement == "" {
return errors.New("measurement is required")
}
if a.Value == "" {
return errors.New("value is required")
}
if a.Cause == "" {
return errors.New("cause is required")
}
if a.Severity > SeverityMax {
return ErrInvalidSeverity
}
return nil
}
// Service specifies an API that must be fulfilled by the domain service.
type Service interface {
CreateAlarm(ctx context.Context, alarm Alarm) (Alarm, error)
UpdateAlarm(ctx context.Context, session authn.Session, alarm Alarm) (Alarm, error)
ViewAlarm(ctx context.Context, session authn.Session, id string) (Alarm, error)
ListAlarms(ctx context.Context, session authn.Session, pm PageMetadata) (AlarmsPage, error)
DeleteAlarm(ctx context.Context, session authn.Session, id string) error
}
type Repository interface {
CreateAlarm(ctx context.Context, alarm Alarm) (Alarm, error)
UpdateAlarm(ctx context.Context, alarm Alarm) (Alarm, error)
ViewAlarm(ctx context.Context, alarmID, domainID string) (Alarm, error)
ListAllAlarms(ctx context.Context, pm PageMetadata) (AlarmsPage, error)
DeleteAlarm(ctx context.Context, id string) error
}
-173
View File
@@ -1,173 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package alarms_test
import (
"fmt"
"testing"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/internal/testsutil"
"github.com/absmach/magistrala/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestValidateAlarms(t *testing.T) {
cases := []struct {
desc string
alarm alarms.Alarm
err error
}{
{
desc: "valid alarm",
alarm: alarms.Alarm{
RuleID: testsutil.GenerateUUID(t),
DomainID: testsutil.GenerateUUID(t),
ChannelID: testsutil.GenerateUUID(t),
ClientID: testsutil.GenerateUUID(t),
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
},
err: nil,
},
{
desc: "missing rule_id",
alarm: alarms.Alarm{
DomainID: testsutil.GenerateUUID(t),
ChannelID: testsutil.GenerateUUID(t),
ClientID: testsutil.GenerateUUID(t),
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
},
err: errors.New("rule_id is required"),
},
{
desc: "missing domain_id",
alarm: alarms.Alarm{
RuleID: testsutil.GenerateUUID(t),
ChannelID: testsutil.GenerateUUID(t),
ClientID: testsutil.GenerateUUID(t),
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
},
err: errors.New("domain_id is required"),
},
{
desc: "missing channel_id",
alarm: alarms.Alarm{
RuleID: testsutil.GenerateUUID(t),
DomainID: testsutil.GenerateUUID(t),
ClientID: testsutil.GenerateUUID(t),
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
},
err: errors.New("channel_id is required"),
},
{
desc: "missing client_id",
alarm: alarms.Alarm{
RuleID: testsutil.GenerateUUID(t),
DomainID: testsutil.GenerateUUID(t),
ChannelID: testsutil.GenerateUUID(t),
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
},
err: errors.New("client_id is required"),
},
{
desc: "missing measurement",
alarm: alarms.Alarm{
RuleID: testsutil.GenerateUUID(t),
DomainID: testsutil.GenerateUUID(t),
ChannelID: testsutil.GenerateUUID(t),
ClientID: testsutil.GenerateUUID(t),
Subtopic: "subtopic",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
},
err: errors.New("measurement is required"),
},
{
desc: "missing value",
alarm: alarms.Alarm{
RuleID: testsutil.GenerateUUID(t),
DomainID: testsutil.GenerateUUID(t),
ChannelID: testsutil.GenerateUUID(t),
ClientID: testsutil.GenerateUUID(t),
Subtopic: "subtopic",
Measurement: "measurement",
Unit: "unit",
Cause: "cause",
Severity: 100,
},
err: errors.New("value is required"),
},
{
desc: "missing cause",
alarm: alarms.Alarm{
RuleID: testsutil.GenerateUUID(t),
DomainID: testsutil.GenerateUUID(t),
ChannelID: testsutil.GenerateUUID(t),
ClientID: testsutil.GenerateUUID(t),
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Severity: 100,
},
err: errors.New("cause is required"),
},
{
desc: "higher severity",
alarm: alarms.Alarm{
RuleID: testsutil.GenerateUUID(t),
DomainID: testsutil.GenerateUUID(t),
ChannelID: testsutil.GenerateUUID(t),
ClientID: testsutil.GenerateUUID(t),
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: alarms.SeverityMax + 1,
},
err: alarms.ErrInvalidSeverity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
err := tc.alarm.Validate()
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
})
}
}
-104
View File
@@ -1,104 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
import (
"context"
"github.com/absmach/magistrala/alarms"
apiutil "github.com/absmach/magistrala/api/http/util"
"github.com/absmach/magistrala/pkg/authn"
"github.com/absmach/magistrala/pkg/errors"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
"github.com/go-kit/kit/endpoint"
)
func updateAlarmEndpoint(svc alarms.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(updateAlarmReq)
if err := req.validate(); err != nil {
return alarmRes{}, errors.Wrap(apiutil.ErrValidation, err)
}
session, ok := ctx.Value(authn.SessionKey).(authn.Session)
if !ok {
return alarmRes{}, svcerr.ErrAuthorization
}
alarm, err := svc.UpdateAlarm(ctx, session, req.Alarm)
if err != nil {
return alarmRes{}, err
}
return alarmRes{
Alarm: alarm,
}, nil
}
}
func viewAlarmEndpoint(svc alarms.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(alarmReq)
if err := req.validate(); err != nil {
return alarmRes{}, errors.Wrap(apiutil.ErrValidation, err)
}
session, ok := ctx.Value(authn.SessionKey).(authn.Session)
if !ok {
return alarmRes{}, svcerr.ErrAuthorization
}
alarm, err := svc.ViewAlarm(ctx, session, req.ID)
if err != nil {
return alarmRes{}, err
}
return alarmRes{
Alarm: alarm,
}, nil
}
}
func listAlarmsEndpoint(svc alarms.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(listAlarmsReq)
if err := req.validate(); err != nil {
return alarmsPageRes{}, errors.Wrap(apiutil.ErrValidation, err)
}
session, ok := ctx.Value(authn.SessionKey).(authn.Session)
if !ok {
return alarmsPageRes{}, svcerr.ErrAuthorization
}
alarms, err := svc.ListAlarms(ctx, session, req.PageMetadata)
if err != nil {
return alarmsPageRes{}, err
}
return alarmsPageRes{
AlarmsPage: alarms,
}, nil
}
}
func deleteAlarmEndpoint(svc alarms.Service) endpoint.Endpoint {
return func(ctx context.Context, request any) (any, error) {
req := request.(alarmReq)
if err := req.validate(); err != nil {
return alarmRes{}, errors.Wrap(apiutil.ErrValidation, err)
}
session, ok := ctx.Value(authn.SessionKey).(authn.Session)
if !ok {
return alarmRes{}, svcerr.ErrAuthorization
}
if err := svc.DeleteAlarm(ctx, session, req.ID); err != nil {
return alarmRes{}, err
}
return alarmRes{deleted: true}, nil
}
}
-59
View File
@@ -1,59 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
import (
"errors"
"github.com/absmach/magistrala/alarms"
api "github.com/absmach/magistrala/api/http"
apiutil "github.com/absmach/magistrala/api/http/util"
)
type alarmReq struct {
alarms.Alarm `json:",inline"`
}
func (req alarmReq) validate() error {
if req.Alarm.ID == "" {
return errors.New("missing alarm id")
}
return nil
}
type updateAlarmReq struct {
alarms.Alarm `json:",inline"`
}
func (req updateAlarmReq) validate() error {
if req.Alarm.ID == "" {
return errors.New("missing alarm id")
}
if req.Alarm.AssigneeID == "" && req.Alarm.AcknowledgedBy == "" && req.Alarm.ResolvedBy == "" && len(req.Alarm.Metadata) == 0 {
return errors.New("at least one of assignee_id, acknowledged_by, resolved_by, or metadata must be set")
}
return nil
}
type listAlarmsReq struct {
alarms.PageMetadata
}
func (req listAlarmsReq) validate() error {
if req.Limit > api.MaxLimitSize || req.Limit < 1 {
return apiutil.ErrLimitSize
}
if req.Order != "" && req.Order != api.UpdatedAtOrder && req.Order != api.CreatedAtOrder {
return apiutil.ErrInvalidOrder
}
if req.Dir != api.AscDir && req.Dir != api.DescDir {
return apiutil.ErrInvalidDirection
}
return nil
}
-70
View File
@@ -1,70 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
import (
"fmt"
"net/http"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/alarms"
)
var (
_ magistrala.Response = (*alarmRes)(nil)
_ magistrala.Response = (*alarmsPageRes)(nil)
)
type alarmRes struct {
alarms.Alarm `json:",inline"`
created bool
deleted bool
}
func (res alarmRes) Headers() map[string]string {
switch {
case res.created:
return map[string]string{
"Location": fmt.Sprintf("/%s/alarms/%s", res.DomainID, res.ID),
}
default:
return map[string]string{}
}
}
func (res alarmRes) Code() int {
switch {
case res.created:
return http.StatusCreated
case res.deleted:
return http.StatusNoContent
default:
return http.StatusOK
}
}
func (res alarmRes) Empty() bool {
switch {
case res.deleted:
return true
default:
return false
}
}
type alarmsPageRes struct {
alarms.AlarmsPage `json:",inline"`
}
func (res alarmsPageRes) Headers() map[string]string {
return map[string]string{}
}
func (res alarmsPageRes) Code() int {
return http.StatusOK
}
func (res alarmsPageRes) Empty() bool {
return false
}
-209
View File
@@ -1,209 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
import (
"context"
"encoding/json"
"log/slog"
"math"
"net/http"
"strings"
"time"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/alarms"
api "github.com/absmach/magistrala/api/http"
apiutil "github.com/absmach/magistrala/api/http/util"
smqauthn "github.com/absmach/magistrala/pkg/authn"
"github.com/absmach/magistrala/pkg/errors"
"github.com/go-chi/chi/v5"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
func MakeHandler(svc alarms.Service, logger *slog.Logger, idp magistrala.IDProvider, instanceID string, authn smqauthn.AuthNMiddleware) http.Handler {
opts := []kithttp.ServerOption{
kithttp.ServerErrorEncoder(apiutil.LoggingErrorEncoder(logger, api.EncodeError)),
}
mux := chi.NewRouter()
mux.Route("/{domainID}/alarms", func(r chi.Router) {
r.Group(func(r chi.Router) {
r.Use(authn.WithOptions(smqauthn.WithDomainCheck(true)).Middleware())
r.Use(api.RequestIDMiddleware(idp))
r.Get("/", otelhttp.NewHandler(kithttp.NewServer(
listAlarmsEndpoint(svc),
decodeListAlarmsReq,
api.EncodeResponse,
opts...,
), "list_alarms").ServeHTTP)
r.Route("/{alarmID}", func(r chi.Router) {
r.Get("/", otelhttp.NewHandler(kithttp.NewServer(
viewAlarmEndpoint(svc),
decodeAlarmReq,
api.EncodeResponse,
opts...,
), "get_alarm").ServeHTTP)
r.Put("/", otelhttp.NewHandler(kithttp.NewServer(
updateAlarmEndpoint(svc),
decodeUpdateAlarmReq,
api.EncodeResponse,
opts...,
), "update_alarm").ServeHTTP)
r.Delete("/", otelhttp.NewHandler(kithttp.NewServer(
deleteAlarmEndpoint(svc),
decodeAlarmReq,
api.EncodeResponse,
opts...,
), "delete_alarm").ServeHTTP)
})
})
})
mux.Get("/health", magistrala.Health("alarms", instanceID))
mux.Handle("/metrics", promhttp.Handler())
return mux
}
func decodeListAlarmsReq(_ context.Context, r *http.Request) (any, error) {
offset, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset)
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
limit, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit)
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
domainID, err := apiutil.ReadStringQuery(r, "domain_id", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
channelID, err := apiutil.ReadStringQuery(r, "channel_id", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
clientID, err := apiutil.ReadStringQuery(r, "client_id", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
subtopic, err := apiutil.ReadStringQuery(r, "subtopic", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
ruleID, err := apiutil.ReadStringQuery(r, "rule_id", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
s, err := apiutil.ReadStringQuery(r, api.StatusKey, alarms.All)
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
status, err := alarms.ToStatus(s)
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
assigneeID, err := apiutil.ReadStringQuery(r, "assignee_id", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
serverity, err := apiutil.ReadNumQuery(r, "severity", uint64(math.MaxUint8))
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
updatedBy, err := apiutil.ReadStringQuery(r, "updated_by", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
assignedBy, err := apiutil.ReadStringQuery(r, "assigned_by", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
acknowledgedBy, err := apiutil.ReadStringQuery(r, "acknowledged_by", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
resolvedBy, err := apiutil.ReadStringQuery(r, "resolved_by", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
cfrom, err := apiutil.ReadStringQuery(r, "created_from", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
cto, err := apiutil.ReadStringQuery(r, "created_to", "")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
order, err := apiutil.ReadStringQuery(r, api.OrderKey, api.DefOrder)
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
dir, err := apiutil.ReadStringQuery(r, api.DirKey, "desc")
if err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
var createdFrom, createdTo time.Time
if cfrom != "" {
if createdFrom, err = time.Parse(time.RFC3339, cfrom); err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
}
if cto != "" {
if createdTo, err = time.Parse(time.RFC3339, cto); err != nil {
return listAlarmsReq{}, errors.Wrap(apiutil.ErrValidation, err)
}
}
return listAlarmsReq{
PageMetadata: alarms.PageMetadata{
Offset: offset,
Limit: limit,
DomainID: domainID,
ChannelID: channelID,
ClientID: clientID,
Subtopic: subtopic,
RuleID: ruleID,
Status: status,
AssigneeID: assigneeID,
ResolvedBy: resolvedBy,
Severity: uint8(serverity),
UpdatedBy: updatedBy,
AcknowledgedBy: acknowledgedBy,
AssignedBy: assignedBy,
CreatedFrom: createdFrom,
CreatedTo: createdTo,
Dir: dir,
Order: order,
},
}, nil
}
func decodeAlarmReq(_ context.Context, r *http.Request) (any, error) {
return alarmReq{
Alarm: alarms.Alarm{
ID: chi.URLParam(r, "alarmID"),
},
}, nil
}
func decodeUpdateAlarmReq(_ context.Context, r *http.Request) (any, error) {
if !strings.Contains(r.Header.Get("Content-Type"), api.ContentType) {
return updateAlarmReq{}, apiutil.ErrUnsupportedContentType
}
req := updateAlarmReq{}
if err := json.NewDecoder(r.Body).Decode(&req.Alarm); err != nil {
return updateAlarmReq{}, errors.Wrap(apiutil.ErrMalformedRequestBody, err)
}
req.Alarm.ID = chi.URLParam(r, "alarmID")
return req, nil
}
-53
View File
@@ -1,53 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
//go:build msg_fluxmq
// +build msg_fluxmq
package brokers
import (
"context"
"log/slog"
"time"
"github.com/absmach/magistrala/pkg/messaging"
broker "github.com/absmach/magistrala/pkg/messaging/fluxmq"
"github.com/nats-io/nats.go/jetstream"
)
const (
AllTopic = "alarms/#"
prefix = "alarms"
)
var cfg = jetstream.StreamConfig{
Name: "alarms",
Description: "Magistrala stream alarms",
Subjects: []string{"alarms/#"},
Retention: jetstream.LimitsPolicy,
MaxMsgsPerSubject: 1e6,
MaxAge: time.Hour * 24,
MaxMsgSize: 1024 * 1024,
Discard: jetstream.DiscardOld,
Storage: jetstream.FileStorage,
}
func NewPubSub(ctx context.Context, url string, logger *slog.Logger) (messaging.PubSub, error) {
pb, err := broker.NewPubSub(ctx, url, logger, broker.Prefix(prefix), broker.JSStreamConfig(cfg), broker.ConnectionName("alarms-msg-pubsub"))
if err != nil {
return nil, err
}
return pb, nil
}
func NewPublisher(ctx context.Context, url string) (messaging.Publisher, error) {
pb, err := broker.NewPublisher(ctx, url, broker.Prefix(prefix), broker.JSStreamConfig(cfg), broker.ConnectionName("alarms-msg-pub"))
if err != nil {
return nil, err
}
return pb, nil
}
-53
View File
@@ -1,53 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
//go:build !msg_fluxmq && !msg_rabbitmq && !rabbitmq
// +build !msg_fluxmq,!msg_rabbitmq,!rabbitmq
package brokers
import (
"context"
"log/slog"
"time"
"github.com/absmach/magistrala/pkg/messaging"
broker "github.com/absmach/magistrala/pkg/messaging/nats"
"github.com/nats-io/nats.go/jetstream"
)
const (
AllTopic = "alarms/#"
prefix = "alarms"
)
var cfg = jetstream.StreamConfig{
Name: "alarms",
Description: "Magistrala stream alarms",
Subjects: []string{"alarms.>"},
Retention: jetstream.LimitsPolicy,
MaxMsgsPerSubject: 1e6,
MaxAge: time.Hour * 24,
MaxMsgSize: 1024 * 1024,
Discard: jetstream.DiscardOld,
Storage: jetstream.FileStorage,
}
func NewPubSub(ctx context.Context, url string, logger *slog.Logger) (messaging.PubSub, error) {
pb, err := broker.NewPubSub(ctx, url, logger, broker.Prefix(prefix), broker.JSStreamConfig(cfg))
if err != nil {
return nil, err
}
return pb, nil
}
func NewPublisher(ctx context.Context, url string) (messaging.Publisher, error) {
pb, err := broker.NewPublisher(ctx, url, broker.Prefix(prefix), broker.JSStreamConfig(cfg))
if err != nil {
return nil, err
}
return pb, nil
}
-57
View File
@@ -1,57 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package consumer
import (
"bytes"
"context"
"encoding/gob"
"log/slog"
"time"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/pkg/errors"
"github.com/absmach/magistrala/pkg/messaging"
)
var errFailedToDecode = errors.New("failed to decode alarm")
type handler struct {
svc alarms.Service
logger *slog.Logger
}
func NewHandler(svc alarms.Service, logger *slog.Logger) messaging.MessageHandler {
return &handler{svc: svc, logger: logger}
}
func (h handler) Handle(msg *messaging.Message) (err error) {
if msg == nil {
return errors.New("message is empty")
}
if msg.GetPayload() == nil {
return errors.New("message payload is empty")
}
var alarm alarms.Alarm
if err := gob.NewDecoder(bytes.NewReader(msg.GetPayload())).Decode(&alarm); err != nil {
return messaging.NewError(errors.Wrap(errFailedToDecode, err), messaging.Term)
}
alarm.DomainID = msg.GetDomain()
alarm.ChannelID = msg.GetChannel()
alarm.ClientID = msg.ClientIdentity()
alarm.Subtopic = msg.GetSubtopic()
alarm.CreatedAt = time.Unix(0, int64(msg.GetCreated()))
if err := alarm.Validate(); err != nil {
return err
}
_, err = h.svc.CreateAlarm(context.Background(), alarm)
return err
}
func (h handler) Cancel() error {
return nil
}
-6
View File
@@ -1,6 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package alarms contains domain concept definitions needed to support
// Alarms service feature, i.e. create, read, update, and delete alarms.
package alarms
-322
View File
@@ -1,322 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package middleware
import (
"context"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/alarms/operations"
"github.com/absmach/magistrala/auth"
"github.com/absmach/magistrala/internal/atom"
"github.com/absmach/magistrala/pkg/authn"
smqauthz "github.com/absmach/magistrala/pkg/authz"
"github.com/absmach/magistrala/pkg/errors"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
"github.com/absmach/magistrala/pkg/permissions"
"github.com/absmach/magistrala/pkg/policies"
)
var (
errDomainUpdateAlarms = errors.New("not authorized to update alarms in domain")
errDomainDeleteAlarms = errors.New("not authorized to delete alarms in domain")
errDomainViewAlarms = errors.New("not authorized to view alarms in domain")
)
type authorizationMiddleware struct {
svc alarms.Service
authz smqauthz.Authorization
atomAuthz atom.Authorizer
entitiesOps permissions.EntitiesOperations[permissions.Operation]
}
var _ alarms.Service = (*authorizationMiddleware)(nil)
const (
atomObjectKindResource = "resource"
atomObjectTypeResourceRule = "resource:" + atom.KindRule
atomAuthorizedRulePageLimit = 100
)
type atomAuthorizedObjectLister interface {
AuthorizedObjectIDs(ctx context.Context, q atom.AuthorizedObjectIDsQuery) (atom.AuthorizedObjectIDs, error)
}
func NewAuthorizationMiddleware(svc alarms.Service, authz smqauthz.Authorization, entitiesOps permissions.EntitiesOperations[permissions.Operation]) (alarms.Service, error) {
if err := entitiesOps.Validate(); err != nil {
return nil, err
}
return &authorizationMiddleware{
svc: svc,
authz: authz,
entitiesOps: entitiesOps,
}, nil
}
func NewAtomAuthorizationMiddleware(svc alarms.Service, authz atom.Authorizer, entitiesOps permissions.EntitiesOperations[permissions.Operation]) (alarms.Service, error) {
if err := entitiesOps.Validate(); err != nil {
return nil, err
}
return &authorizationMiddleware{
svc: svc,
atomAuthz: authz,
entitiesOps: entitiesOps,
}, nil
}
func (am *authorizationMiddleware) CreateAlarm(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error) {
return am.svc.CreateAlarm(ctx, alarm)
}
func (am *authorizationMiddleware) UpdateAlarm(ctx context.Context, session authn.Session, alarm alarms.Alarm) (alarms.Alarm, error) {
current, err := am.svc.ViewAlarm(ctx, session, alarm.ID)
if err != nil {
return alarms.Alarm{}, err
}
if len(alarm.Metadata) > 0 {
if err := am.authorizeAlarmOrRule(ctx, operations.OpUpdateAlarm, session, current); err != nil {
return alarms.Alarm{}, errors.Wrap(errDomainUpdateAlarms, err)
}
}
if alarm.AssigneeID != "" {
if err := am.authorizeAlarmOrRule(ctx, operations.OpAssignAlarm, session, current); err != nil {
return alarms.Alarm{}, errors.Wrap(errDomainUpdateAlarms, err)
}
if am.atomAuthz == nil {
domainUserID := auth.EncodeDomainUserID(session.DomainID, alarm.AssigneeID)
if err := am.authz.Authorize(ctx, smqauthz.PolicyReq{
Domain: session.DomainID,
SubjectType: policies.UserType,
SubjectKind: policies.UsersKind,
Subject: domainUserID,
Permission: policies.MembershipPermission,
ObjectType: policies.DomainType,
Object: session.DomainID,
}, nil); err != nil {
return alarms.Alarm{}, err
}
}
}
if alarm.AcknowledgedBy != "" {
if err := am.authorizeAlarmOrRule(ctx, operations.OpAcknowledgeAlarm, session, current); err != nil {
return alarms.Alarm{}, errors.Wrap(errDomainUpdateAlarms, err)
}
}
if alarm.ResolvedBy != "" {
if err := am.authorizeAlarmOrRule(ctx, operations.OpResolveAlarm, session, current); err != nil {
return alarms.Alarm{}, errors.Wrap(errDomainUpdateAlarms, err)
}
}
return am.svc.UpdateAlarm(ctx, session, alarm)
}
func (am *authorizationMiddleware) DeleteAlarm(ctx context.Context, session authn.Session, id string) error {
alarm, err := am.svc.ViewAlarm(ctx, session, id)
if err != nil {
return err
}
if err := am.authorizeAlarmOrRule(ctx, operations.OpDeleteAlarm, session, alarm); err != nil {
return errors.Wrap(errDomainDeleteAlarms, err)
}
return am.svc.DeleteAlarm(ctx, session, id)
}
func (am *authorizationMiddleware) ListAlarms(ctx context.Context, session authn.Session, pm alarms.PageMetadata) (alarms.AlarmsPage, error) {
if pm.DomainID == "" {
pm.DomainID = session.DomainID
}
switch err := am.checkSuperAdmin(ctx, session); {
case err == nil:
session.SuperAdmin = true
case errors.Contains(err, svcerr.ErrSuperAdminAction):
if err := am.authorizeTenantAlarm(ctx, operations.OpViewAlarm, session); err != nil {
if pm.RuleID != "" {
if ruleErr := am.authorizeRuleAlarmRead(ctx, session, pm.RuleID); ruleErr != nil {
return alarms.AlarmsPage{}, errors.Wrap(errDomainViewAlarms, err)
}
break
}
ruleIDs, ruleErr := am.authorizedReadableRuleIDs(ctx, session)
if ruleErr != nil {
return alarms.AlarmsPage{}, errors.Wrap(errDomainViewAlarms, err)
}
if len(ruleIDs) == 0 {
return alarms.AlarmsPage{
Offset: pm.Offset,
Limit: pm.Limit,
Alarms: []alarms.Alarm{},
}, nil
}
pm.RuleIDs = ruleIDs
}
default:
return alarms.AlarmsPage{}, err
}
return am.svc.ListAlarms(ctx, session, pm)
}
func (am *authorizationMiddleware) ViewAlarm(ctx context.Context, session authn.Session, id string) (alarms.Alarm, error) {
alarm, err := am.svc.ViewAlarm(ctx, session, id)
if err != nil {
return alarms.Alarm{}, err
}
if err := am.authorizeViewAlarm(ctx, session, alarm); err != nil {
return alarms.Alarm{}, errors.Wrap(errDomainViewAlarms, err)
}
return alarm, nil
}
func (am *authorizationMiddleware) authorizeAlarmOrRule(ctx context.Context, op permissions.Operation, session authn.Session, alarm alarms.Alarm) error {
tenantErr := am.authorizeTenantAlarm(ctx, op, session)
if tenantErr == nil {
return nil
}
if alarm.RuleID == "" {
return tenantErr
}
if err := am.authorize(ctx, op, session, policies.RulesType, alarm.RuleID, atom.KindRule); err != nil {
return tenantErr
}
return nil
}
func (am *authorizationMiddleware) authorizeViewAlarm(ctx context.Context, session authn.Session, alarm alarms.Alarm) error {
tenantErr := am.authorizeTenantAlarm(ctx, operations.OpViewAlarm, session)
if tenantErr == nil {
return nil
}
if alarm.RuleID == "" {
return tenantErr
}
if err := am.authorizeRuleAlarmRead(ctx, session, alarm.RuleID); err != nil {
return tenantErr
}
return nil
}
func (am *authorizationMiddleware) authorizeTenantAlarm(ctx context.Context, op permissions.Operation, session authn.Session) error {
return am.authorize(ctx, op, session, policies.DomainType, session.DomainID, atom.KindAlarm)
}
func (am *authorizationMiddleware) authorizeRuleAlarmRead(ctx context.Context, session authn.Session, ruleID string) error {
if am.atomAuthz != nil {
return am.authorize(ctx, operations.OpViewAlarm, session, policies.RulesType, ruleID, atom.KindRule)
}
perm, err := am.entitiesOps.GetPermission(operations.EntityType, operations.OpViewAlarm)
if err != nil {
return err
}
pr := smqauthz.PolicyReq{
Domain: session.DomainID,
SubjectType: policies.UserType,
SubjectKind: policies.UsersKind,
Subject: session.DomainUserID,
Object: ruleID,
ObjectType: policies.RulesType,
Permission: perm.String(),
}
return am.authz.Authorize(ctx, pr, nil)
}
func (am *authorizationMiddleware) authorizedReadableRuleIDs(ctx context.Context, session authn.Session) ([]string, error) {
lister, ok := am.atomAuthz.(atomAuthorizedObjectLister)
if !ok {
return nil, errors.ErrAuthorization
}
perm, err := am.entitiesOps.GetPermission(operations.EntityType, operations.OpViewAlarm)
if err != nil {
return nil, err
}
var ids []string
for offset := uint64(0); ; offset += atomAuthorizedRulePageLimit {
page, err := lister.AuthorizedObjectIDs(ctx, atom.AuthorizedObjectIDsQuery{
SubjectID: atom.SubjectID(session),
Action: atom.CapabilityName(perm.String()),
ObjectKind: atomObjectKindResource,
ObjectType: atomObjectTypeResourceRule,
TenantID: session.DomainID,
Limit: atomAuthorizedRulePageLimit,
Offset: offset,
})
if err != nil {
return nil, err
}
ids = append(ids, page.IDs...)
if uint64(len(page.IDs)) < atomAuthorizedRulePageLimit || offset+uint64(len(page.IDs)) >= page.Total {
break
}
}
return ids, nil
}
func (am *authorizationMiddleware) authorize(ctx context.Context, op permissions.Operation, session authn.Session, objType, obj, resourceKind string) error {
perm, err := am.entitiesOps.GetPermission(operations.EntityType, op)
if err != nil {
return err
}
if am.atomAuthz != nil {
return atom.Authorize(ctx, am.atomAuthz, session, perm.String(), objType, obj, resourceKind)
}
pr := smqauthz.PolicyReq{
Domain: session.DomainID,
SubjectType: policies.UserType,
SubjectKind: policies.UsersKind,
Subject: session.DomainUserID,
Object: obj,
ObjectType: objType,
Permission: perm.String(),
}
var pat *smqauthz.PATReq
if session.PatID != "" {
opName := am.entitiesOps.OperationName(operations.EntityType, op)
pat = &smqauthz.PATReq{
UserID: session.UserID,
PatID: session.PatID,
EntityID: auth.AnyIDs,
EntityType: auth.RulesType.String(),
Operation: opName,
Domain: session.DomainID,
}
}
if err := am.authz.Authorize(ctx, pr, pat); err != nil {
return err
}
return nil
}
func (am *authorizationMiddleware) checkSuperAdmin(ctx context.Context, session authn.Session) error {
if session.Role != authn.SuperAdminRole {
return svcerr.ErrSuperAdminAction
}
if am.atomAuthz != nil {
return atom.Authorize(ctx, am.atomAuthz, session, policies.AdminPermission, policies.PlatformType, policies.MagistralaObject, policies.PlatformType)
}
if err := am.authz.Authorize(ctx, smqauthz.PolicyReq{
SubjectType: policies.UserType,
Subject: session.UserID,
Permission: policies.AdminPermission,
ObjectType: policies.PlatformType,
Object: policies.MagistralaObject,
}, nil); err != nil {
return err
}
return nil
}
-224
View File
@@ -1,224 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package middleware
import (
"context"
"testing"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/alarms/mocks"
"github.com/absmach/magistrala/alarms/operations"
"github.com/absmach/magistrala/internal/atom"
"github.com/absmach/magistrala/pkg/authn"
"github.com/absmach/magistrala/pkg/permissions"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
type recordingAtomAuthorizer struct {
allowed bool
allow func(atom.AuthzRequest) bool
authorized atom.AuthorizedObjectIDs
reqs []atom.AuthzRequest
queries []atom.AuthorizedObjectIDsQuery
}
func (a *recordingAtomAuthorizer) CheckAuthz(_ context.Context, req atom.AuthzRequest) (atom.AuthzResponse, error) {
a.reqs = append(a.reqs, req)
if a.allow != nil {
return atom.AuthzResponse{Allowed: a.allow(req)}, nil
}
return atom.AuthzResponse{Allowed: a.allowed}, nil
}
func (a *recordingAtomAuthorizer) AuthorizedObjectIDs(_ context.Context, q atom.AuthorizedObjectIDsQuery) (atom.AuthorizedObjectIDs, error) {
a.queries = append(a.queries, q)
return a.authorized, nil
}
func TestListAlarmsAuthorizesTenantAlarmReader(t *testing.T) {
svc := mocks.NewService(t)
pm := alarms.PageMetadata{Limit: 10}
expectedPM := pm
expectedPM.DomainID = "domain-1"
session := authn.Session{UserID: "user-1", DomainID: "domain-1", DomainUserID: "domain-1_user-1"}
authz := &recordingAtomAuthorizer{allowed: true}
wrapped, err := NewAtomAuthorizationMiddleware(svc, authz, testEntitiesOps(t))
require.NoError(t, err)
svc.On("ListAlarms", mock.Anything, session, expectedPM).Return(alarms.AlarmsPage{Limit: 10}, nil).Once()
page, err := wrapped.ListAlarms(context.Background(), session, pm)
require.NoError(t, err)
assert.Equal(t, uint64(10), page.Limit)
require.Len(t, authz.reqs, 1)
assert.Equal(t, atom.AuthzRequest{
SubjectID: "user-1",
Action: "alarm_read",
ResourceID: "",
ObjectKind: "tenant",
ObjectID: "domain-1",
Context: map[string]any{
"domain_id": "domain-1",
"legacy_object_type": "domain",
},
}, authz.reqs[0])
}
func TestListAlarmsFiltersToReadableRulesWhenTenantAlarmReadDenied(t *testing.T) {
svc := mocks.NewService(t)
pm := alarms.PageMetadata{Limit: 10}
expectedPM := pm
expectedPM.DomainID = "domain-1"
expectedPM.RuleIDs = []string{"rule-1", "rule-2"}
authz := &recordingAtomAuthorizer{
allowed: false,
authorized: atom.AuthorizedObjectIDs{IDs: []string{"rule-1", "rule-2"}, Total: 2},
}
wrapped, err := NewAtomAuthorizationMiddleware(svc, authz, testEntitiesOps(t))
require.NoError(t, err)
svc.On("ListAlarms", mock.Anything, authn.Session{UserID: "user-1", DomainID: "domain-1"}, expectedPM).Return(alarms.AlarmsPage{Limit: 10}, nil).Once()
_, err = wrapped.ListAlarms(context.Background(), authn.Session{UserID: "user-1", DomainID: "domain-1"}, pm)
require.NoError(t, err)
require.Len(t, authz.reqs, 1)
assert.Equal(t, "alarm_read", authz.reqs[0].Action)
assert.Equal(t, "tenant", authz.reqs[0].ObjectKind)
require.Len(t, authz.queries, 1)
assert.Equal(t, atom.AuthorizedObjectIDsQuery{
SubjectID: "user-1",
Action: "alarm_read",
ObjectKind: "resource",
ObjectType: "resource:rule",
TenantID: "domain-1",
Limit: 100,
}, authz.queries[0])
}
func TestListAlarmsWithRuleFilterAuthorizesRuleRead(t *testing.T) {
svc := mocks.NewService(t)
pm := alarms.PageMetadata{Limit: 10, RuleID: "rule-1"}
expectedPM := pm
expectedPM.DomainID = "domain-1"
session := authn.Session{UserID: "user-1", DomainID: "domain-1"}
authz := &recordingAtomAuthorizer{
allow: func(req atom.AuthzRequest) bool {
return req.Action == "alarm_read" && req.ObjectKind == "resource" && req.ObjectID == "rule-1"
},
}
wrapped, err := NewAtomAuthorizationMiddleware(svc, authz, testEntitiesOps(t))
require.NoError(t, err)
svc.On("ListAlarms", mock.Anything, session, expectedPM).Return(alarms.AlarmsPage{Limit: 10}, nil).Once()
_, err = wrapped.ListAlarms(context.Background(), session, pm)
require.NoError(t, err)
require.Len(t, authz.reqs, 2)
assert.Equal(t, "alarm_read", authz.reqs[0].Action)
assert.Equal(t, "alarm_read", authz.reqs[1].Action)
assert.Equal(t, "resource", authz.reqs[1].ObjectKind)
assert.Equal(t, "rules", authz.reqs[1].Context["legacy_object_type"])
}
func TestListAlarmsSuperAdminSkipsListAuthorization(t *testing.T) {
svc := mocks.NewService(t)
pm := alarms.PageMetadata{Limit: 10}
expectedPM := pm
expectedPM.DomainID = "domain-1"
session := authn.Session{UserID: "admin-1", DomainID: "domain-1", Role: authn.SuperAdminRole}
authz := &recordingAtomAuthorizer{allowed: true}
wrapped, err := NewAtomAuthorizationMiddleware(svc, authz, testEntitiesOps(t))
require.NoError(t, err)
svc.On("ListAlarms", mock.Anything, mock.MatchedBy(func(s authn.Session) bool {
return s.SuperAdmin
}), expectedPM).Return(alarms.AlarmsPage{Limit: 10}, nil).Once()
_, err = wrapped.ListAlarms(context.Background(), session, pm)
require.NoError(t, err)
require.Len(t, authz.reqs, 1)
assert.Equal(t, "manage", authz.reqs[0].Action)
}
func TestAcknowledgeAlarmAuthorizesRuleAlarmActionWhenTenantDenied(t *testing.T) {
svc := mocks.NewService(t)
session := authn.Session{UserID: "user-1", DomainID: "domain-1"}
current := alarms.Alarm{ID: "alarm-1", RuleID: "rule-1", DomainID: "domain-1"}
update := alarms.Alarm{ID: "alarm-1", AcknowledgedBy: "user-1"}
authz := &recordingAtomAuthorizer{
allow: func(req atom.AuthzRequest) bool {
return req.Action == "alarm_acknowledge" && req.ObjectKind == "resource" && req.ObjectID == "rule-1"
},
}
wrapped, err := NewAtomAuthorizationMiddleware(svc, authz, testEntitiesOps(t))
require.NoError(t, err)
svc.On("ViewAlarm", mock.Anything, session, "alarm-1").Return(current, nil).Once()
svc.On("UpdateAlarm", mock.Anything, session, update).Return(update, nil).Once()
_, err = wrapped.UpdateAlarm(context.Background(), session, update)
require.NoError(t, err)
require.Len(t, authz.reqs, 2)
assert.Equal(t, atom.AuthzRequest{
SubjectID: "user-1",
Action: "alarm_acknowledge",
ResourceID: "",
ObjectKind: "tenant",
ObjectID: "domain-1",
Context: map[string]any{
"domain_id": "domain-1",
"legacy_object_type": "domain",
},
}, authz.reqs[0])
assert.Equal(t, atom.AuthzRequest{
SubjectID: "user-1",
Action: "alarm_acknowledge",
ResourceID: "rule-1",
ObjectKind: "resource",
ObjectID: "rule-1",
Context: map[string]any{
"domain_id": "domain-1",
"legacy_object_type": "rules",
},
}, authz.reqs[1])
}
func testEntitiesOps(t *testing.T) permissions.EntitiesOperations[permissions.Operation] {
t.Helper()
details := operations.OperationDetails()
perms := make(map[string]permissions.Permission, len(details))
for op, detail := range details {
if detail.PermissionRequired {
perms[detail.Name] = testPermission(op, detail.Name)
}
}
entitiesOps, err := permissions.NewEntitiesOperations(
permissions.EntitiesPermission{operations.EntityType: perms},
permissions.EntitiesOperationDetails[permissions.Operation]{operations.EntityType: details},
)
require.NoError(t, err)
return entitiesOps
}
func testPermission(op permissions.Operation, fallback string) permissions.Permission {
switch op {
case operations.OpViewAlarm, operations.OpListAlarms:
return "alarm_read_permission"
case operations.OpUpdateAlarm:
return "alarm_update_permission"
case operations.OpDeleteAlarm:
return "alarm_delete_permission"
case operations.OpAssignAlarm:
return "alarm_assign_permission"
case operations.OpAcknowledgeAlarm:
return "alarm_acknowledge_permission"
case operations.OpResolveAlarm:
return "alarm_resolve_permission"
default:
return permissions.Permission(fallback)
}
}
-6
View File
@@ -1,6 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package middleware provides middleware for the alarms service.
// This is logging, metrics, and tracing middleware.
package middleware
-155
View File
@@ -1,155 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package middleware
import (
"context"
"log/slog"
"time"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/pkg/authn"
"github.com/go-chi/chi/v5/middleware"
)
type loggingMiddleware struct {
logger *slog.Logger
service alarms.Service
}
var _ alarms.Service = (*loggingMiddleware)(nil)
func NewLoggingMiddleware(logger *slog.Logger, service alarms.Service) alarms.Service {
return &loggingMiddleware{
logger: logger,
service: service,
}
}
func (lm *loggingMiddleware) CreateAlarm(ctx context.Context, alarm alarms.Alarm) (created alarms.Alarm, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("request_id", middleware.GetReqID(ctx)),
slog.Group("alarm",
slog.String("rule_id", alarm.RuleID),
slog.String("domain_id", alarm.DomainID),
slog.String("channel_id", alarm.ChannelID),
slog.String("client_id", alarm.ClientID),
slog.String("subtopic", alarm.Subtopic),
slog.String("measurement", alarm.Measurement),
slog.String("value", alarm.Value),
slog.String("unit", alarm.Unit),
slog.Uint64("status", uint64(alarm.Status)),
slog.Uint64("severity", uint64(alarm.Severity)),
slog.String("threshold", alarm.Threshold),
slog.String("cause", alarm.Cause),
),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("Create alarm failed", args...)
return
}
if created.ID != "" {
lm.logger.Info("Create alarm completed successfully", args...)
}
}(time.Now())
return lm.service.CreateAlarm(ctx, alarm)
}
func (lm *loggingMiddleware) UpdateAlarm(ctx context.Context, session authn.Session, alarm alarms.Alarm) (dba alarms.Alarm, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("request_id", middleware.GetReqID(ctx)),
slog.Group("alarm",
slog.String("id", dba.ID),
slog.String("rule_id", dba.RuleID),
slog.String("domain_id", dba.DomainID),
slog.String("channel_id", dba.ChannelID),
slog.String("client_id", dba.ClientID),
slog.String("subtopic", dba.Subtopic),
slog.String("measurement", dba.Measurement),
slog.String("value", dba.Value),
slog.String("unit", dba.Unit),
slog.String("status", dba.Status.String()),
slog.Uint64("severity", uint64(dba.Severity)),
slog.String("threshold", dba.Threshold),
slog.String("cause", dba.Cause),
),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("Update alarm failed", args...)
return
}
lm.logger.Info("Update alarm completed successfully", args...)
}(time.Now())
return lm.service.UpdateAlarm(ctx, session, alarm)
}
func (lm *loggingMiddleware) ViewAlarm(ctx context.Context, session authn.Session, id string) (dba alarms.Alarm, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("request_id", middleware.GetReqID(ctx)),
slog.String("id", id),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("View alarm failed", args...)
return
}
lm.logger.Info("View alarm completed successfully", args...)
}(time.Now())
return lm.service.ViewAlarm(ctx, session, id)
}
func (lm *loggingMiddleware) ListAlarms(ctx context.Context, session authn.Session, pm alarms.PageMetadata) (dbp alarms.AlarmsPage, err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("request_id", middleware.GetReqID(ctx)),
slog.Int("offset", int(pm.Offset)),
slog.Int("limit", int(pm.Limit)),
slog.String("rule_id", pm.RuleID),
slog.String("domain_id", pm.DomainID),
slog.String("channel_id", pm.ChannelID),
slog.String("client_id", pm.ClientID),
slog.String("subtopic", pm.Subtopic),
slog.String("status", pm.Status.String()),
slog.Uint64("severity", uint64(pm.Severity)),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("List alarms failed", args...)
return
}
lm.logger.Info("List alarms completed successfully", args...)
}(time.Now())
return lm.service.ListAlarms(ctx, session, pm)
}
func (lm *loggingMiddleware) DeleteAlarm(ctx context.Context, session authn.Session, id string) (err error) {
defer func(begin time.Time) {
args := []any{
slog.String("duration", time.Since(begin).String()),
slog.String("request_id", middleware.GetReqID(ctx)),
slog.String("id", id),
}
if err != nil {
args = append(args, slog.Any("error", err))
lm.logger.Warn("Delete alarm failed", args...)
return
}
lm.logger.Info("Delete alarm completed successfully", args...)
}(time.Now())
return lm.service.DeleteAlarm(ctx, session, id)
}
-74
View File
@@ -1,74 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package middleware
import (
"context"
"time"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/pkg/authn"
"github.com/go-kit/kit/metrics"
)
type metricsMiddleware struct {
counter metrics.Counter
latency metrics.Histogram
service alarms.Service
}
var _ alarms.Service = (*metricsMiddleware)(nil)
func NewMetricsMiddleware(counter metrics.Counter, latency metrics.Histogram, service alarms.Service) alarms.Service {
return &metricsMiddleware{
counter: counter,
latency: latency,
service: service,
}
}
func (mm *metricsMiddleware) CreateAlarm(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error) {
defer func(begin time.Time) {
mm.counter.With("method", "create_alarm").Add(1)
mm.latency.With("method", "create_alarm").Observe(time.Since(begin).Seconds())
}(time.Now())
return mm.service.CreateAlarm(ctx, alarm)
}
func (mm *metricsMiddleware) UpdateAlarm(ctx context.Context, session authn.Session, alarm alarms.Alarm) (alarms.Alarm, error) {
defer func(begin time.Time) {
mm.counter.With("method", "update_alarm").Add(1)
mm.latency.With("method", "update_alarm").Observe(time.Since(begin).Seconds())
}(time.Now())
return mm.service.UpdateAlarm(ctx, session, alarm)
}
func (mm *metricsMiddleware) ViewAlarm(ctx context.Context, session authn.Session, id string) (alarms.Alarm, error) {
defer func(begin time.Time) {
mm.counter.With("method", "get_alarm").Add(1)
mm.latency.With("method", "get_alarm").Observe(time.Since(begin).Seconds())
}(time.Now())
return mm.service.ViewAlarm(ctx, session, id)
}
func (mm *metricsMiddleware) ListAlarms(ctx context.Context, session authn.Session, pm alarms.PageMetadata) (alarms.AlarmsPage, error) {
defer func(begin time.Time) {
mm.counter.With("method", "list_alarms").Add(1)
mm.latency.With("method", "list_alarms").Observe(time.Since(begin).Seconds())
}(time.Now())
return mm.service.ListAlarms(ctx, session, pm)
}
func (mm *metricsMiddleware) DeleteAlarm(ctx context.Context, session authn.Session, id string) error {
defer func(begin time.Time) {
mm.counter.With("method", "delete_alarm").Add(1)
mm.latency.With("method", "delete_alarm").Observe(time.Since(begin).Seconds())
}(time.Now())
return mm.service.DeleteAlarm(ctx, session, id)
}
-84
View File
@@ -1,84 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package middleware
import (
"context"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/pkg/authn"
smqTracing "github.com/absmach/magistrala/pkg/tracing"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
type tracingMiddleware struct {
tracer trace.Tracer
svc alarms.Service
}
var _ alarms.Service = (*tracingMiddleware)(nil)
func NewTracingMiddleware(tracer trace.Tracer, svc alarms.Service) alarms.Service {
return &tracingMiddleware{
tracer: tracer,
svc: svc,
}
}
func (tm *tracingMiddleware) CreateAlarm(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error) {
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "create_alarm", trace.WithAttributes(
attribute.String("rule_id", alarm.RuleID),
attribute.String("measurement", alarm.Measurement),
attribute.String("value", alarm.Value),
attribute.String("unit", alarm.Unit),
attribute.String("cause", alarm.Cause),
attribute.String("status", alarm.Status.String()),
))
defer span.End()
return tm.svc.CreateAlarm(ctx, alarm)
}
func (tm *tracingMiddleware) UpdateAlarm(ctx context.Context, session authn.Session, alarm alarms.Alarm) (alarms.Alarm, error) {
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "update_alarm", trace.WithAttributes(
attribute.String("rule_id", alarm.RuleID),
attribute.String("measurement", alarm.Measurement),
attribute.String("value", alarm.Value),
attribute.String("unit", alarm.Unit),
attribute.String("cause", alarm.Cause),
attribute.String("status", alarm.Status.String()),
))
defer span.End()
return tm.svc.UpdateAlarm(ctx, session, alarm)
}
func (tm *tracingMiddleware) ViewAlarm(ctx context.Context, session authn.Session, id string) (alarms.Alarm, error) {
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "get_alarm", trace.WithAttributes(
attribute.String("id", id),
))
defer span.End()
return tm.svc.ViewAlarm(ctx, session, id)
}
func (tm *tracingMiddleware) ListAlarms(ctx context.Context, session authn.Session, pm alarms.PageMetadata) (alarms.AlarmsPage, error) {
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "list_alarms", trace.WithAttributes(
attribute.Int("offset", int(pm.Offset)),
attribute.Int("limit", int(pm.Limit)),
))
defer span.End()
return tm.svc.ListAlarms(ctx, session, pm)
}
func (tm *tracingMiddleware) DeleteAlarm(ctx context.Context, session authn.Session, id string) error {
ctx, span := smqTracing.StartSpan(ctx, tm.tracer, "delete_alarm", trace.WithAttributes(
attribute.String("id", id),
))
defer span.End()
return tm.svc.DeleteAlarm(ctx, session, id)
}
-370
View File
@@ -1,370 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks
import (
"context"
"github.com/absmach/magistrala/alarms"
mock "github.com/stretchr/testify/mock"
)
// NewRepository creates a new instance of Repository. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewRepository(t interface {
mock.TestingT
Cleanup(func())
}) *Repository {
mock := &Repository{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// Repository is an autogenerated mock type for the Repository type
type Repository struct {
mock.Mock
}
type Repository_Expecter struct {
mock *mock.Mock
}
func (_m *Repository) EXPECT() *Repository_Expecter {
return &Repository_Expecter{mock: &_m.Mock}
}
// CreateAlarm provides a mock function for the type Repository
func (_mock *Repository) CreateAlarm(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error) {
ret := _mock.Called(ctx, alarm)
if len(ret) == 0 {
panic("no return value specified for CreateAlarm")
}
var r0 alarms.Alarm
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, alarms.Alarm) (alarms.Alarm, error)); ok {
return returnFunc(ctx, alarm)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, alarms.Alarm) alarms.Alarm); ok {
r0 = returnFunc(ctx, alarm)
} else {
r0 = ret.Get(0).(alarms.Alarm)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, alarms.Alarm) error); ok {
r1 = returnFunc(ctx, alarm)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Repository_CreateAlarm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateAlarm'
type Repository_CreateAlarm_Call struct {
*mock.Call
}
// CreateAlarm is a helper method to define mock.On call
// - ctx context.Context
// - alarm alarms.Alarm
func (_e *Repository_Expecter) CreateAlarm(ctx interface{}, alarm interface{}) *Repository_CreateAlarm_Call {
return &Repository_CreateAlarm_Call{Call: _e.mock.On("CreateAlarm", ctx, alarm)}
}
func (_c *Repository_CreateAlarm_Call) Run(run func(ctx context.Context, alarm alarms.Alarm)) *Repository_CreateAlarm_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 alarms.Alarm
if args[1] != nil {
arg1 = args[1].(alarms.Alarm)
}
run(
arg0,
arg1,
)
})
return _c
}
func (_c *Repository_CreateAlarm_Call) Return(alarm1 alarms.Alarm, err error) *Repository_CreateAlarm_Call {
_c.Call.Return(alarm1, err)
return _c
}
func (_c *Repository_CreateAlarm_Call) RunAndReturn(run func(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error)) *Repository_CreateAlarm_Call {
_c.Call.Return(run)
return _c
}
// DeleteAlarm provides a mock function for the type Repository
func (_mock *Repository) DeleteAlarm(ctx context.Context, id string) error {
ret := _mock.Called(ctx, id)
if len(ret) == 0 {
panic("no return value specified for DeleteAlarm")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(context.Context, string) error); ok {
r0 = returnFunc(ctx, id)
} else {
r0 = ret.Error(0)
}
return r0
}
// Repository_DeleteAlarm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteAlarm'
type Repository_DeleteAlarm_Call struct {
*mock.Call
}
// DeleteAlarm is a helper method to define mock.On call
// - ctx context.Context
// - id string
func (_e *Repository_Expecter) DeleteAlarm(ctx interface{}, id interface{}) *Repository_DeleteAlarm_Call {
return &Repository_DeleteAlarm_Call{Call: _e.mock.On("DeleteAlarm", ctx, id)}
}
func (_c *Repository_DeleteAlarm_Call) Run(run func(ctx context.Context, id string)) *Repository_DeleteAlarm_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
run(
arg0,
arg1,
)
})
return _c
}
func (_c *Repository_DeleteAlarm_Call) Return(err error) *Repository_DeleteAlarm_Call {
_c.Call.Return(err)
return _c
}
func (_c *Repository_DeleteAlarm_Call) RunAndReturn(run func(ctx context.Context, id string) error) *Repository_DeleteAlarm_Call {
_c.Call.Return(run)
return _c
}
// ListAllAlarms provides a mock function for the type Repository
func (_mock *Repository) ListAllAlarms(ctx context.Context, pm alarms.PageMetadata) (alarms.AlarmsPage, error) {
ret := _mock.Called(ctx, pm)
if len(ret) == 0 {
panic("no return value specified for ListAllAlarms")
}
var r0 alarms.AlarmsPage
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, alarms.PageMetadata) (alarms.AlarmsPage, error)); ok {
return returnFunc(ctx, pm)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, alarms.PageMetadata) alarms.AlarmsPage); ok {
r0 = returnFunc(ctx, pm)
} else {
r0 = ret.Get(0).(alarms.AlarmsPage)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, alarms.PageMetadata) error); ok {
r1 = returnFunc(ctx, pm)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Repository_ListAllAlarms_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListAllAlarms'
type Repository_ListAllAlarms_Call struct {
*mock.Call
}
// ListAllAlarms is a helper method to define mock.On call
// - ctx context.Context
// - pm alarms.PageMetadata
func (_e *Repository_Expecter) ListAllAlarms(ctx interface{}, pm interface{}) *Repository_ListAllAlarms_Call {
return &Repository_ListAllAlarms_Call{Call: _e.mock.On("ListAllAlarms", ctx, pm)}
}
func (_c *Repository_ListAllAlarms_Call) Run(run func(ctx context.Context, pm alarms.PageMetadata)) *Repository_ListAllAlarms_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 alarms.PageMetadata
if args[1] != nil {
arg1 = args[1].(alarms.PageMetadata)
}
run(
arg0,
arg1,
)
})
return _c
}
func (_c *Repository_ListAllAlarms_Call) Return(alarmsPage alarms.AlarmsPage, err error) *Repository_ListAllAlarms_Call {
_c.Call.Return(alarmsPage, err)
return _c
}
func (_c *Repository_ListAllAlarms_Call) RunAndReturn(run func(ctx context.Context, pm alarms.PageMetadata) (alarms.AlarmsPage, error)) *Repository_ListAllAlarms_Call {
_c.Call.Return(run)
return _c
}
// UpdateAlarm provides a mock function for the type Repository
func (_mock *Repository) UpdateAlarm(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error) {
ret := _mock.Called(ctx, alarm)
if len(ret) == 0 {
panic("no return value specified for UpdateAlarm")
}
var r0 alarms.Alarm
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, alarms.Alarm) (alarms.Alarm, error)); ok {
return returnFunc(ctx, alarm)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, alarms.Alarm) alarms.Alarm); ok {
r0 = returnFunc(ctx, alarm)
} else {
r0 = ret.Get(0).(alarms.Alarm)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, alarms.Alarm) error); ok {
r1 = returnFunc(ctx, alarm)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Repository_UpdateAlarm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateAlarm'
type Repository_UpdateAlarm_Call struct {
*mock.Call
}
// UpdateAlarm is a helper method to define mock.On call
// - ctx context.Context
// - alarm alarms.Alarm
func (_e *Repository_Expecter) UpdateAlarm(ctx interface{}, alarm interface{}) *Repository_UpdateAlarm_Call {
return &Repository_UpdateAlarm_Call{Call: _e.mock.On("UpdateAlarm", ctx, alarm)}
}
func (_c *Repository_UpdateAlarm_Call) Run(run func(ctx context.Context, alarm alarms.Alarm)) *Repository_UpdateAlarm_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 alarms.Alarm
if args[1] != nil {
arg1 = args[1].(alarms.Alarm)
}
run(
arg0,
arg1,
)
})
return _c
}
func (_c *Repository_UpdateAlarm_Call) Return(alarm1 alarms.Alarm, err error) *Repository_UpdateAlarm_Call {
_c.Call.Return(alarm1, err)
return _c
}
func (_c *Repository_UpdateAlarm_Call) RunAndReturn(run func(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error)) *Repository_UpdateAlarm_Call {
_c.Call.Return(run)
return _c
}
// ViewAlarm provides a mock function for the type Repository
func (_mock *Repository) ViewAlarm(ctx context.Context, alarmID string, domainID string) (alarms.Alarm, error) {
ret := _mock.Called(ctx, alarmID, domainID)
if len(ret) == 0 {
panic("no return value specified for ViewAlarm")
}
var r0 alarms.Alarm
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) (alarms.Alarm, error)); ok {
return returnFunc(ctx, alarmID, domainID)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, string, string) alarms.Alarm); ok {
r0 = returnFunc(ctx, alarmID, domainID)
} else {
r0 = ret.Get(0).(alarms.Alarm)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, string, string) error); ok {
r1 = returnFunc(ctx, alarmID, domainID)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Repository_ViewAlarm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ViewAlarm'
type Repository_ViewAlarm_Call struct {
*mock.Call
}
// ViewAlarm is a helper method to define mock.On call
// - ctx context.Context
// - alarmID string
// - domainID string
func (_e *Repository_Expecter) ViewAlarm(ctx interface{}, alarmID interface{}, domainID interface{}) *Repository_ViewAlarm_Call {
return &Repository_ViewAlarm_Call{Call: _e.mock.On("ViewAlarm", ctx, alarmID, domainID)}
}
func (_c *Repository_ViewAlarm_Call) Run(run func(ctx context.Context, alarmID string, domainID string)) *Repository_ViewAlarm_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 string
if args[1] != nil {
arg1 = args[1].(string)
}
var arg2 string
if args[2] != nil {
arg2 = args[2].(string)
}
run(
arg0,
arg1,
arg2,
)
})
return _c
}
func (_c *Repository_ViewAlarm_Call) Return(alarm alarms.Alarm, err error) *Repository_ViewAlarm_Call {
_c.Call.Return(alarm, err)
return _c
}
func (_c *Repository_ViewAlarm_Call) RunAndReturn(run func(ctx context.Context, alarmID string, domainID string) (alarms.Alarm, error)) *Repository_ViewAlarm_Call {
_c.Call.Return(run)
return _c
}
-389
View File
@@ -1,389 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by mockery; DO NOT EDIT.
// github.com/vektra/mockery
// template: testify
package mocks
import (
"context"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/pkg/authn"
mock "github.com/stretchr/testify/mock"
)
// NewService creates a new instance of Service. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
// The first argument is typically a *testing.T value.
func NewService(t interface {
mock.TestingT
Cleanup(func())
}) *Service {
mock := &Service{}
mock.Mock.Test(t)
t.Cleanup(func() { mock.AssertExpectations(t) })
return mock
}
// Service is an autogenerated mock type for the Service type
type Service struct {
mock.Mock
}
type Service_Expecter struct {
mock *mock.Mock
}
func (_m *Service) EXPECT() *Service_Expecter {
return &Service_Expecter{mock: &_m.Mock}
}
// CreateAlarm provides a mock function for the type Service
func (_mock *Service) CreateAlarm(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error) {
ret := _mock.Called(ctx, alarm)
if len(ret) == 0 {
panic("no return value specified for CreateAlarm")
}
var r0 alarms.Alarm
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, alarms.Alarm) (alarms.Alarm, error)); ok {
return returnFunc(ctx, alarm)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, alarms.Alarm) alarms.Alarm); ok {
r0 = returnFunc(ctx, alarm)
} else {
r0 = ret.Get(0).(alarms.Alarm)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, alarms.Alarm) error); ok {
r1 = returnFunc(ctx, alarm)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Service_CreateAlarm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateAlarm'
type Service_CreateAlarm_Call struct {
*mock.Call
}
// CreateAlarm is a helper method to define mock.On call
// - ctx context.Context
// - alarm alarms.Alarm
func (_e *Service_Expecter) CreateAlarm(ctx interface{}, alarm interface{}) *Service_CreateAlarm_Call {
return &Service_CreateAlarm_Call{Call: _e.mock.On("CreateAlarm", ctx, alarm)}
}
func (_c *Service_CreateAlarm_Call) Run(run func(ctx context.Context, alarm alarms.Alarm)) *Service_CreateAlarm_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 alarms.Alarm
if args[1] != nil {
arg1 = args[1].(alarms.Alarm)
}
run(
arg0,
arg1,
)
})
return _c
}
func (_c *Service_CreateAlarm_Call) Return(alarm1 alarms.Alarm, err error) *Service_CreateAlarm_Call {
_c.Call.Return(alarm1, err)
return _c
}
func (_c *Service_CreateAlarm_Call) RunAndReturn(run func(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error)) *Service_CreateAlarm_Call {
_c.Call.Return(run)
return _c
}
// DeleteAlarm provides a mock function for the type Service
func (_mock *Service) DeleteAlarm(ctx context.Context, session authn.Session, id string) error {
ret := _mock.Called(ctx, session, id)
if len(ret) == 0 {
panic("no return value specified for DeleteAlarm")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(context.Context, authn.Session, string) error); ok {
r0 = returnFunc(ctx, session, id)
} else {
r0 = ret.Error(0)
}
return r0
}
// Service_DeleteAlarm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'DeleteAlarm'
type Service_DeleteAlarm_Call struct {
*mock.Call
}
// DeleteAlarm is a helper method to define mock.On call
// - ctx context.Context
// - session authn.Session
// - id string
func (_e *Service_Expecter) DeleteAlarm(ctx interface{}, session interface{}, id interface{}) *Service_DeleteAlarm_Call {
return &Service_DeleteAlarm_Call{Call: _e.mock.On("DeleteAlarm", ctx, session, id)}
}
func (_c *Service_DeleteAlarm_Call) Run(run func(ctx context.Context, session authn.Session, id string)) *Service_DeleteAlarm_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 authn.Session
if args[1] != nil {
arg1 = args[1].(authn.Session)
}
var arg2 string
if args[2] != nil {
arg2 = args[2].(string)
}
run(
arg0,
arg1,
arg2,
)
})
return _c
}
func (_c *Service_DeleteAlarm_Call) Return(err error) *Service_DeleteAlarm_Call {
_c.Call.Return(err)
return _c
}
func (_c *Service_DeleteAlarm_Call) RunAndReturn(run func(ctx context.Context, session authn.Session, id string) error) *Service_DeleteAlarm_Call {
_c.Call.Return(run)
return _c
}
// ListAlarms provides a mock function for the type Service
func (_mock *Service) ListAlarms(ctx context.Context, session authn.Session, pm alarms.PageMetadata) (alarms.AlarmsPage, error) {
ret := _mock.Called(ctx, session, pm)
if len(ret) == 0 {
panic("no return value specified for ListAlarms")
}
var r0 alarms.AlarmsPage
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, authn.Session, alarms.PageMetadata) (alarms.AlarmsPage, error)); ok {
return returnFunc(ctx, session, pm)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, authn.Session, alarms.PageMetadata) alarms.AlarmsPage); ok {
r0 = returnFunc(ctx, session, pm)
} else {
r0 = ret.Get(0).(alarms.AlarmsPage)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, authn.Session, alarms.PageMetadata) error); ok {
r1 = returnFunc(ctx, session, pm)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Service_ListAlarms_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListAlarms'
type Service_ListAlarms_Call struct {
*mock.Call
}
// ListAlarms is a helper method to define mock.On call
// - ctx context.Context
// - session authn.Session
// - pm alarms.PageMetadata
func (_e *Service_Expecter) ListAlarms(ctx interface{}, session interface{}, pm interface{}) *Service_ListAlarms_Call {
return &Service_ListAlarms_Call{Call: _e.mock.On("ListAlarms", ctx, session, pm)}
}
func (_c *Service_ListAlarms_Call) Run(run func(ctx context.Context, session authn.Session, pm alarms.PageMetadata)) *Service_ListAlarms_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 authn.Session
if args[1] != nil {
arg1 = args[1].(authn.Session)
}
var arg2 alarms.PageMetadata
if args[2] != nil {
arg2 = args[2].(alarms.PageMetadata)
}
run(
arg0,
arg1,
arg2,
)
})
return _c
}
func (_c *Service_ListAlarms_Call) Return(alarmsPage alarms.AlarmsPage, err error) *Service_ListAlarms_Call {
_c.Call.Return(alarmsPage, err)
return _c
}
func (_c *Service_ListAlarms_Call) RunAndReturn(run func(ctx context.Context, session authn.Session, pm alarms.PageMetadata) (alarms.AlarmsPage, error)) *Service_ListAlarms_Call {
_c.Call.Return(run)
return _c
}
// UpdateAlarm provides a mock function for the type Service
func (_mock *Service) UpdateAlarm(ctx context.Context, session authn.Session, alarm alarms.Alarm) (alarms.Alarm, error) {
ret := _mock.Called(ctx, session, alarm)
if len(ret) == 0 {
panic("no return value specified for UpdateAlarm")
}
var r0 alarms.Alarm
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, authn.Session, alarms.Alarm) (alarms.Alarm, error)); ok {
return returnFunc(ctx, session, alarm)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, authn.Session, alarms.Alarm) alarms.Alarm); ok {
r0 = returnFunc(ctx, session, alarm)
} else {
r0 = ret.Get(0).(alarms.Alarm)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, authn.Session, alarms.Alarm) error); ok {
r1 = returnFunc(ctx, session, alarm)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Service_UpdateAlarm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateAlarm'
type Service_UpdateAlarm_Call struct {
*mock.Call
}
// UpdateAlarm is a helper method to define mock.On call
// - ctx context.Context
// - session authn.Session
// - alarm alarms.Alarm
func (_e *Service_Expecter) UpdateAlarm(ctx interface{}, session interface{}, alarm interface{}) *Service_UpdateAlarm_Call {
return &Service_UpdateAlarm_Call{Call: _e.mock.On("UpdateAlarm", ctx, session, alarm)}
}
func (_c *Service_UpdateAlarm_Call) Run(run func(ctx context.Context, session authn.Session, alarm alarms.Alarm)) *Service_UpdateAlarm_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 authn.Session
if args[1] != nil {
arg1 = args[1].(authn.Session)
}
var arg2 alarms.Alarm
if args[2] != nil {
arg2 = args[2].(alarms.Alarm)
}
run(
arg0,
arg1,
arg2,
)
})
return _c
}
func (_c *Service_UpdateAlarm_Call) Return(alarm1 alarms.Alarm, err error) *Service_UpdateAlarm_Call {
_c.Call.Return(alarm1, err)
return _c
}
func (_c *Service_UpdateAlarm_Call) RunAndReturn(run func(ctx context.Context, session authn.Session, alarm alarms.Alarm) (alarms.Alarm, error)) *Service_UpdateAlarm_Call {
_c.Call.Return(run)
return _c
}
// ViewAlarm provides a mock function for the type Service
func (_mock *Service) ViewAlarm(ctx context.Context, session authn.Session, id string) (alarms.Alarm, error) {
ret := _mock.Called(ctx, session, id)
if len(ret) == 0 {
panic("no return value specified for ViewAlarm")
}
var r0 alarms.Alarm
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, authn.Session, string) (alarms.Alarm, error)); ok {
return returnFunc(ctx, session, id)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, authn.Session, string) alarms.Alarm); ok {
r0 = returnFunc(ctx, session, id)
} else {
r0 = ret.Get(0).(alarms.Alarm)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, authn.Session, string) error); ok {
r1 = returnFunc(ctx, session, id)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Service_ViewAlarm_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ViewAlarm'
type Service_ViewAlarm_Call struct {
*mock.Call
}
// ViewAlarm is a helper method to define mock.On call
// - ctx context.Context
// - session authn.Session
// - id string
func (_e *Service_Expecter) ViewAlarm(ctx interface{}, session interface{}, id interface{}) *Service_ViewAlarm_Call {
return &Service_ViewAlarm_Call{Call: _e.mock.On("ViewAlarm", ctx, session, id)}
}
func (_c *Service_ViewAlarm_Call) Run(run func(ctx context.Context, session authn.Session, id string)) *Service_ViewAlarm_Call {
_c.Call.Run(func(args mock.Arguments) {
var arg0 context.Context
if args[0] != nil {
arg0 = args[0].(context.Context)
}
var arg1 authn.Session
if args[1] != nil {
arg1 = args[1].(authn.Session)
}
var arg2 string
if args[2] != nil {
arg2 = args[2].(string)
}
run(
arg0,
arg1,
arg2,
)
})
return _c
}
func (_c *Service_ViewAlarm_Call) Return(alarm alarms.Alarm, err error) *Service_ViewAlarm_Call {
_c.Call.Return(alarm, err)
return _c
}
func (_c *Service_ViewAlarm_Call) RunAndReturn(run func(ctx context.Context, session authn.Session, id string) (alarms.Alarm, error)) *Service_ViewAlarm_Call {
_c.Call.Return(run)
return _c
}
-52
View File
@@ -1,52 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package operations
import "github.com/absmach/magistrala/pkg/permissions"
const EntityType = "alarm"
// Alarm Operations.
const (
OpViewAlarm permissions.Operation = iota
OpDeleteAlarm
OpListAlarms
OpAssignAlarm
OpAcknowledgeAlarm
OpResolveAlarm
OpUpdateAlarm
)
func OperationDetails() map[permissions.Operation]permissions.OperationDetails {
return map[permissions.Operation]permissions.OperationDetails{
OpViewAlarm: {
Name: "view",
PermissionRequired: true,
},
OpDeleteAlarm: {
Name: "delete",
PermissionRequired: true,
},
OpListAlarms: {
Name: "list",
PermissionRequired: true,
},
OpAssignAlarm: {
Name: "alarm_assign",
PermissionRequired: true,
},
OpAcknowledgeAlarm: {
Name: "alarm_acknowledge",
PermissionRequired: true,
},
OpResolveAlarm: {
Name: "alarm_resolve",
PermissionRequired: true,
},
OpUpdateAlarm: {
Name: "update",
PermissionRequired: true,
},
}
}
-510
View File
@@ -1,510 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package postgres
import (
"context"
"database/sql"
"encoding/json"
"fmt"
"math"
"strings"
"time"
"github.com/absmach/magistrala/alarms"
api "github.com/absmach/magistrala/api/http"
"github.com/absmach/magistrala/pkg/errors"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
"github.com/absmach/magistrala/pkg/postgres"
"github.com/jmoiron/sqlx"
)
const alarmColumns = `alarms.id, alarms.rule_id, alarms.domain_id, alarms.channel_id, alarms.client_id, alarms.subtopic, alarms.measurement, alarms.value, alarms.unit,
alarms.threshold, alarms.cause, alarms.status, alarms.severity, alarms.assignee_id, alarms.created_at, alarms.updated_at, alarms.updated_by, alarms.assigned_at,
alarms.assigned_by, alarms.acknowledged_at, alarms.acknowledged_by, alarms.resolved_at, alarms.resolved_by, alarms.metadata`
type repository struct {
db *sqlx.DB
}
var _ alarms.Repository = (*repository)(nil)
func NewAlarmsRepo(db *sqlx.DB) alarms.Repository {
return &repository{db: db}
}
func (r *repository) CreateAlarm(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error) {
query := `
WITH existing AS (
SELECT status, severity
FROM alarms
WHERE domain_id = :domain_id
AND rule_id = :rule_id
AND channel_id = :channel_id
AND client_id = :client_id
AND subtopic = :subtopic
AND measurement = :measurement
AND created_at <= :created_at
ORDER BY created_at DESC
LIMIT 1
)
INSERT INTO alarms (
id, rule_id, domain_id, channel_id, client_id, subtopic, measurement,
value, unit, threshold, cause, status, severity, assignee_id,
created_at, updated_at, updated_by, assigned_at, assigned_by,
acknowledged_at, acknowledged_by, resolved_at, resolved_by, metadata
)
SELECT
:id, :rule_id, :domain_id, :channel_id, :client_id, :subtopic, :measurement,
:value, :unit, :threshold, :cause, :status, :severity, :assignee_id,
:created_at, :updated_at, :updated_by, :assigned_at, :assigned_by,
:acknowledged_at, :acknowledged_by, :resolved_at, :resolved_by, :metadata
WHERE (
EXISTS (
SELECT 1 FROM existing
WHERE existing.status IS DISTINCT FROM :status
OR (:status = 0 AND existing.status = 0 AND existing.severity IS DISTINCT FROM :severity)
)
OR (
NOT EXISTS (SELECT 1 FROM existing) AND :status = 0
)
)
RETURNING
id, rule_id, domain_id, channel_id, client_id, subtopic, measurement,
value, unit, threshold, cause, status, severity, created_at,
assignee_id, updated_at, updated_by, assigned_at, assigned_by,
acknowledged_at, acknowledged_by, resolved_at, resolved_by, metadata
;
`
dba, err := toDBAlarm(alarm)
if err != nil {
return alarms.Alarm{}, errors.Wrap(repoerr.ErrCreateEntity, err)
}
row, err := r.db.NamedQueryContext(ctx, query, dba)
if err != nil {
return alarms.Alarm{}, postgres.HandleError(repoerr.ErrCreateEntity, err)
}
defer row.Close()
if !row.Next() {
return alarms.Alarm{}, repoerr.ErrNotFound
}
dba = dbAlarm{}
if err := row.StructScan(&dba); err != nil {
return alarms.Alarm{}, errors.Wrap(repoerr.ErrCreateEntity, err)
}
return toAlarm(dba)
}
func (r *repository) UpdateAlarm(ctx context.Context, alarm alarms.Alarm) (alarms.Alarm, error) {
var query []string
var upq string
if alarm.Status != 0 {
query = append(query, "status = :status,")
}
if alarm.AssigneeID != "" {
query = append(query, "assignee_id = :assignee_id,")
}
if !alarm.AssignedAt.IsZero() {
query = append(query, "assigned_at = :assigned_at,")
}
if alarm.AssignedBy != "" {
query = append(query, "assigned_by = :assigned_by,")
}
if alarm.AcknowledgedBy != "" {
query = append(query, "acknowledged_by = :acknowledged_by,")
}
if !alarm.AcknowledgedAt.IsZero() {
query = append(query, "acknowledged_at = :acknowledged_at,")
}
if alarm.ResolvedBy != "" {
query = append(query, "resolved_by = :resolved_by,")
}
if !alarm.ResolvedAt.IsZero() {
query = append(query, "resolved_at = :resolved_at,")
}
if alarm.Metadata != nil {
query = append(query, "metadata = :metadata,")
}
if len(query) > 0 {
upq = strings.Join(query, " ")
}
q := fmt.Sprintf(`UPDATE alarms SET %s updated_by = :updated_by, updated_at = :updated_at WHERE id = :id
RETURNING id, rule_id, domain_id, channel_id, client_id, subtopic, measurement, value, unit, threshold,
cause, status, severity, assignee_id, assigned_at, assigned_by, acknowledged_at, acknowledged_by,
resolved_by, resolved_at, metadata, created_at, updated_by, updated_at;`, upq)
dba, err := toDBAlarm(alarm)
if err != nil {
return alarms.Alarm{}, errors.Wrap(repoerr.ErrUpdateEntity, err)
}
row, err := r.db.NamedQueryContext(ctx, q, dba)
if err != nil {
return alarms.Alarm{}, postgres.HandleError(repoerr.ErrUpdateEntity, err)
}
defer row.Close()
if !row.Next() {
return alarms.Alarm{}, repoerr.ErrNotFound
}
dba = dbAlarm{}
if err := row.StructScan(&dba); err != nil {
return alarms.Alarm{}, errors.Wrap(repoerr.ErrUpdateEntity, err)
}
return toAlarm(dba)
}
func (r *repository) ViewAlarm(ctx context.Context, alarmID, domainID string) (alarms.Alarm, error) {
query := `SELECT * FROM alarms WHERE id = :id AND domain_id = :domain_id;`
row, err := r.db.NamedQueryContext(ctx, query, map[string]any{
"id": alarmID, "domain_id": domainID,
})
if err != nil {
return alarms.Alarm{}, postgres.HandleError(repoerr.ErrViewEntity, err)
}
defer row.Close()
if !row.Next() {
return alarms.Alarm{}, repoerr.ErrNotFound
}
dba := dbAlarm{}
if err := row.StructScan(&dba); err != nil {
return alarms.Alarm{}, errors.Wrap(repoerr.ErrViewEntity, err)
}
alarm, err := toAlarm(dba)
if err != nil {
return alarms.Alarm{}, errors.Wrap(repoerr.ErrViewEntity, err)
}
return alarm, nil
}
func (r *repository) ListAllAlarms(ctx context.Context, pm alarms.PageMetadata) (alarms.AlarmsPage, error) {
query, err := pageQuery(pm)
if err != nil {
return alarms.AlarmsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
}
comQuery := fmt.Sprintf(`SELECT %s FROM alarms %s`, alarmColumns, query)
return r.alarmsPage(ctx, comQuery, pm)
}
func (r *repository) alarmsPage(ctx context.Context, comQuery string, pm alarms.PageMetadata) (alarms.AlarmsPage, error) {
dir := api.DescDir
if pm.Dir == api.AscDir {
dir = api.AscDir
}
var orderClause string
switch pm.Order {
case api.CreatedAtOrder:
orderClause = fmt.Sprintf("ORDER BY created_at %s, id %s", dir, dir)
default:
orderClause = fmt.Sprintf("ORDER BY COALESCE(updated_at, created_at) %s, id %s", dir, dir)
}
q := fmt.Sprintf(`SELECT * FROM (%s) AS sub_query %s LIMIT :limit OFFSET :offset;`, comQuery, orderClause)
cq := fmt.Sprintf(`SELECT COUNT(*) AS total_count FROM (%s) AS sub_query;`, comQuery)
rows, err := r.db.NamedQueryContext(ctx, q, pm)
if err != nil {
return alarms.AlarmsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
}
defer rows.Close()
var items []alarms.Alarm
for rows.Next() {
dba := dbAlarm{}
if err := rows.StructScan(&dba); err != nil {
return alarms.AlarmsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
}
a, err := toAlarm(dba)
if err != nil {
return alarms.AlarmsPage{}, err
}
items = append(items, a)
}
total, err := postgres.Total(ctx, r.db, cq, pm)
if err != nil {
return alarms.AlarmsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
}
return alarms.AlarmsPage{
Total: total,
Offset: pm.Offset,
Limit: pm.Limit,
Alarms: items,
}, nil
}
func (r *repository) DeleteAlarm(ctx context.Context, id string) error {
query := `DELETE FROM alarms WHERE id = :id;`
result, err := r.db.NamedExecContext(ctx, query, map[string]any{"id": id})
if err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return errors.Wrap(repoerr.ErrRemoveEntity, err)
}
if rowsAffected == 0 {
return repoerr.ErrNotFound
}
return nil
}
type dbAlarm struct {
ID string `db:"id"`
RuleID string `db:"rule_id"`
DomainID string `db:"domain_id"`
ChannelID string `db:"channel_id"`
ClientID string `db:"client_id"`
Subtopic string `db:"subtopic"`
Measurement string `db:"measurement"`
Value string `db:"value"`
Unit string `db:"unit"`
Cause string `db:"cause"`
Threshold string `db:"threshold"`
Status alarms.Status `db:"status"`
Severity uint8 `db:"severity"`
AssigneeID string `db:"assignee_id"`
CreatedAt time.Time `db:"created_at"`
UpdatedAt sql.NullTime `db:"updated_at,omitempty"`
UpdatedBy *string `db:"updated_by,omitempty"`
AssignedAt sql.NullTime `db:"assigned_at,omitempty"`
AssignedBy *string `db:"assigned_by,omitempty"`
AcknowledgedAt sql.NullTime `db:"acknowledged_at,omitempty"`
AcknowledgedBy *string `db:"acknowledged_by,omitempty"`
ResolvedAt sql.NullTime `db:"resolved_at,omitempty"`
ResolvedBy *string `db:"resolved_by,omitempty"`
Metadata []byte `db:"metadata,omitempty"`
}
func toDBAlarm(a alarms.Alarm) (dbAlarm, error) {
if a.CreatedAt.IsZero() {
a.CreatedAt = time.Now()
}
var updatedBy *string
if a.UpdatedBy != "" {
updatedBy = &a.UpdatedBy
}
var updatedAt sql.NullTime
if a.UpdatedAt != (time.Time{}) {
updatedAt = sql.NullTime{Time: a.UpdatedAt, Valid: true}
}
var acknowledgedBy *string
if a.AcknowledgedBy != "" {
acknowledgedBy = &a.AcknowledgedBy
}
var acknowledgedAt sql.NullTime
if a.AcknowledgedAt != (time.Time{}) {
acknowledgedAt = sql.NullTime{Time: a.AcknowledgedAt, Valid: true}
}
var resolvedBy *string
if a.ResolvedBy != "" {
resolvedBy = &a.ResolvedBy
}
var resolvedAt sql.NullTime
if a.ResolvedAt != (time.Time{}) {
resolvedAt = sql.NullTime{Time: a.ResolvedAt, Valid: true}
}
var assignedBy *string
if a.AssignedBy != "" {
assignedBy = &a.AssignedBy
}
var assignedAt sql.NullTime
if a.AssignedAt != (time.Time{}) {
assignedAt = sql.NullTime{Time: a.AssignedAt, Valid: true}
}
metadata := []byte("{}")
if len(a.Metadata) > 0 {
b, err := json.Marshal(a.Metadata)
if err != nil {
return dbAlarm{}, errors.Wrap(repoerr.ErrMalformedEntity, err)
}
metadata = b
}
return dbAlarm{
ID: a.ID,
RuleID: a.RuleID,
DomainID: a.DomainID,
ChannelID: a.ChannelID,
ClientID: a.ClientID,
Subtopic: a.Subtopic,
Measurement: a.Measurement,
Value: a.Value,
Unit: a.Unit,
Cause: a.Cause,
Threshold: a.Threshold,
Status: a.Status,
Severity: a.Severity,
AssigneeID: a.AssigneeID,
CreatedAt: a.CreatedAt,
UpdatedAt: updatedAt,
UpdatedBy: updatedBy,
AssignedAt: assignedAt,
AssignedBy: assignedBy,
AcknowledgedAt: acknowledgedAt,
AcknowledgedBy: acknowledgedBy,
ResolvedAt: resolvedAt,
ResolvedBy: resolvedBy,
Metadata: metadata,
}, nil
}
func toAlarm(dbr dbAlarm) (alarms.Alarm, error) {
var updatedBy string
if dbr.UpdatedBy != nil {
updatedBy = *dbr.UpdatedBy
}
var updatedAt time.Time
if dbr.UpdatedAt.Valid {
updatedAt = dbr.UpdatedAt.Time
}
var assignedBy string
if dbr.AssignedBy != nil {
assignedBy = *dbr.AssignedBy
}
var assignedAt time.Time
if dbr.AssignedAt.Valid {
assignedAt = dbr.AssignedAt.Time
}
var acknowledgedBy string
if dbr.AcknowledgedBy != nil {
acknowledgedBy = *dbr.AcknowledgedBy
}
var acknowledgedAt time.Time
if dbr.AcknowledgedAt.Valid {
acknowledgedAt = dbr.AcknowledgedAt.Time
}
var resolvedBy string
if dbr.ResolvedBy != nil {
resolvedBy = *dbr.ResolvedBy
}
var resolvedAt time.Time
if dbr.ResolvedAt.Valid {
resolvedAt = dbr.ResolvedAt.Time
}
var metadata map[string]any
if len(dbr.Metadata) > 0 {
err := json.Unmarshal(dbr.Metadata, &metadata)
if err != nil {
return alarms.Alarm{}, errors.Wrap(repoerr.ErrMalformedEntity, err)
}
}
return alarms.Alarm{
ID: dbr.ID,
RuleID: dbr.RuleID,
DomainID: dbr.DomainID,
ChannelID: dbr.ChannelID,
ClientID: dbr.ClientID,
Subtopic: dbr.Subtopic,
Measurement: dbr.Measurement,
Value: dbr.Value,
Unit: dbr.Unit,
Threshold: dbr.Threshold,
Cause: dbr.Cause,
Status: dbr.Status,
Severity: dbr.Severity,
AssigneeID: dbr.AssigneeID,
CreatedAt: dbr.CreatedAt,
UpdatedAt: updatedAt,
UpdatedBy: updatedBy,
AssignedAt: assignedAt,
AssignedBy: assignedBy,
AcknowledgedAt: acknowledgedAt,
AcknowledgedBy: acknowledgedBy,
ResolvedAt: resolvedAt,
ResolvedBy: resolvedBy,
Metadata: metadata,
}, nil
}
func pageQuery(pm alarms.PageMetadata) (string, error) {
query := pageQueryConditions(pm)
var emq string
if len(query) > 0 {
emq = fmt.Sprintf("WHERE %s", strings.Join(query, " AND "))
}
return emq, nil
}
func pageQueryConditions(pm alarms.PageMetadata) []string {
var query []string
if pm.DomainID != "" {
query = append(query, "alarms.domain_id = :domain_id")
}
if pm.RuleID != "" {
query = append(query, "alarms.rule_id = :rule_id")
}
if len(pm.RuleIDs) > 0 {
query = append(query, "alarms.rule_id = ANY(:rule_ids)")
}
if pm.ChannelID != "" {
query = append(query, "alarms.channel_id = :channel_id")
}
if pm.Subtopic != "" {
query = append(query, "alarms.subtopic = :subtopic")
}
if pm.ClientID != "" {
query = append(query, "alarms.client_id = :client_id")
}
if pm.Measurement != "" {
query = append(query, "alarms.measurement = :measurement")
}
if pm.Status != alarms.AllStatus {
query = append(query, "alarms.status = :status")
}
if pm.Severity != math.MaxUint8 {
query = append(query, "alarms.severity = :severity")
}
if pm.AssigneeID != "" {
query = append(query, "alarms.assignee_id = :assignee_id")
}
if pm.UpdatedBy != "" {
query = append(query, "alarms.updated_by = :updated_by")
}
if pm.ResolvedBy != "" {
query = append(query, "alarms.resolved_by = :resolved_by")
}
if pm.AcknowledgedBy != "" {
query = append(query, "alarms.acknowledged_by = :acknowledged_by")
}
if pm.AssignedBy != "" {
query = append(query, "alarms.assigned_by = :assigned_by")
}
if !pm.CreatedFrom.IsZero() {
query = append(query, "alarms.created_at >= :created_from")
}
if !pm.CreatedTo.IsZero() {
query = append(query, "alarms.created_at <= :created_to")
}
return query
}
-481
View File
@@ -1,481 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package postgres_test
import (
"context"
"fmt"
"strings"
"testing"
"time"
"github.com/0x6flab/namegenerator"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/alarms/postgres"
"github.com/absmach/magistrala/pkg/errors"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
"github.com/absmach/magistrala/pkg/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
var (
namegen = namegenerator.NewGenerator()
idProvider = uuid.New()
)
func TestCreateAlarm(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
alarm := alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Subtopic: namegen.Generate(),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
cases := []struct {
desc string
alarm alarms.Alarm
err error
}{
{
desc: "valid alarm",
alarm: alarm,
err: nil,
},
{
desc: "duplicate alarm",
alarm: alarm,
err: repoerr.ErrNotFound,
},
{
desc: "missing rule id",
alarm: alarms.Alarm{
ID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Subtopic: namegen.Generate(),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
},
err: repoerr.ErrCreateEntity,
},
{
desc: "invalid alarm",
alarm: alarms.Alarm{
ID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Subtopic: namegen.Generate(),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": make(chan int),
},
},
err: repoerr.ErrCreateEntity,
},
{
desc: "empty alarm",
alarm: alarms.Alarm{},
err: repoerr.ErrCreateEntity,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
alarm, err := repo.CreateAlarm(context.Background(), tc.alarm)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
assert.NotEmpty(t, alarm.ID)
assert.Equal(t, tc.alarm.RuleID, alarm.RuleID)
assert.Equal(t, tc.alarm.Measurement, alarm.Measurement)
assert.Equal(t, tc.alarm.Value, alarm.Value)
assert.Equal(t, tc.alarm.Unit, alarm.Unit)
assert.Equal(t, tc.alarm.Cause, alarm.Cause)
assert.Equal(t, tc.alarm.Status, alarm.Status)
assert.Equal(t, tc.alarm.DomainID, alarm.DomainID)
assert.Equal(t, tc.alarm.AssigneeID, alarm.AssigneeID)
assert.Equal(t, tc.alarm.Metadata, alarm.Metadata)
})
}
}
func TestUpdateAlarm(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
alarm := alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
alarm, err := repo.CreateAlarm(context.Background(), alarm)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
cases := []struct {
desc string
alarm alarms.Alarm
err error
}{
{
desc: "valid alarm",
alarm: alarms.Alarm{
ID: alarm.ID,
Status: alarms.ClearedStatus,
DomainID: alarm.DomainID,
AssigneeID: generateUUID(t),
AssignedBy: generateUUID(t),
AssignedAt: time.Now().UTC(),
AcknowledgedBy: generateUUID(t),
AcknowledgedAt: time.Now().UTC(),
CreatedAt: alarm.CreatedAt,
UpdatedAt: time.Now().UTC(),
UpdatedBy: generateUUID(t),
ResolvedAt: time.Now().UTC(),
ResolvedBy: generateUUID(t),
Metadata: map[string]any{
"key": "value",
},
},
err: nil,
},
{
desc: "non existing alarm",
alarm: alarms.Alarm{
ID: generateUUID(t),
},
err: repoerr.ErrNotFound,
},
{
desc: "invalid alarm",
alarm: alarms.Alarm{
ID: alarm.ID,
RuleID: generateUUID(t),
Status: 0,
DomainID: generateUUID(t),
AssigneeID: strings.Repeat("a", 40),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
},
err: repoerr.ErrMalformedEntity,
},
{
desc: "empty alarm",
alarm: alarms.Alarm{},
err: repoerr.ErrNotFound,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
alarm, err := repo.UpdateAlarm(context.Background(), tc.alarm)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
assert.NotEmpty(t, alarm.ID)
assert.Equal(t, tc.alarm.Status, alarm.Status)
assert.Equal(t, tc.alarm.DomainID, alarm.DomainID)
assert.Equal(t, tc.alarm.AssigneeID, alarm.AssigneeID)
assert.Equal(t, tc.alarm.UpdatedBy, alarm.UpdatedBy)
assert.Equal(t, tc.alarm.ResolvedBy, alarm.ResolvedBy)
assert.Equal(t, tc.alarm.AcknowledgedBy, alarm.AcknowledgedBy)
assert.Equal(t, tc.alarm.Metadata, alarm.Metadata)
})
}
}
func TestViewAlarm(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
alarm := alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
alarm, err := repo.CreateAlarm(context.Background(), alarm)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
cases := []struct {
desc string
id string
domainID string
err error
}{
{
desc: "valid alarm",
id: alarm.ID,
domainID: alarm.DomainID,
err: nil,
},
{
desc: "non existing alarm id",
id: generateUUID(t),
domainID: alarm.DomainID,
err: repoerr.ErrNotFound,
},
{
desc: "non existing domain id",
id: alarm.ID,
domainID: generateUUID(t),
err: repoerr.ErrNotFound,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
alarm, err := repo.ViewAlarm(context.Background(), tc.id, tc.domainID)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
assert.NotEmpty(t, alarm.ID)
assert.Equal(t, tc.id, alarm.ID)
})
}
}
func TestListAlarms(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
items := make([]alarms.Alarm, 1000)
for i := range 1000 {
items[i] = alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
alarm, err := repo.CreateAlarm(context.Background(), items[i])
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
items[i].ID = alarm.ID
}
cases := []struct {
desc string
pm alarms.PageMetadata
response []alarms.Alarm
err error
}{
{
desc: "valid page",
pm: alarms.PageMetadata{
Offset: 0,
Limit: 10,
},
response: items[:10],
err: nil,
},
{
desc: "offset and limit",
pm: alarms.PageMetadata{
Offset: 10,
Limit: 50,
},
response: items[10:60],
err: nil,
},
{
desc: "empty page",
pm: alarms.PageMetadata{},
response: []alarms.Alarm{},
err: nil,
},
{
desc: "invalid page",
pm: alarms.PageMetadata{
Offset: 1000,
Limit: 10,
},
response: []alarms.Alarm{},
err: nil,
},
{
desc: "invalid assignee id",
pm: alarms.PageMetadata{
Offset: 0,
Limit: 10,
AssigneeID: generateUUID(t),
},
response: []alarms.Alarm{},
err: nil,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
alarms, err := repo.ListAllAlarms(context.Background(), tc.pm)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
assert.Equal(t, len(tc.response), len(alarms.Alarms))
})
}
}
func TestDeleteAlarm(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
alarm := alarms.Alarm{
ID: generateUUID(t),
RuleID: generateUUID(t),
DomainID: generateUUID(t),
ChannelID: generateUUID(t),
ClientID: generateUUID(t),
Measurement: namegen.Generate(),
Value: namegen.Generate(),
Unit: namegen.Generate(),
Threshold: namegen.Generate(),
Cause: namegen.Generate(),
Status: 0,
AssigneeID: generateUUID(t),
CreatedAt: time.Now().UTC(),
Metadata: map[string]any{
"key": "value",
},
}
alarm, err := repo.CreateAlarm(context.Background(), alarm)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
cases := []struct {
desc string
id string
err error
}{
{
desc: "valid alarm",
id: alarm.ID,
err: nil,
},
{
desc: "non existing alarm",
id: generateUUID(t),
err: repoerr.ErrNotFound,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
err := repo.DeleteAlarm(context.Background(), tc.id)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
assert.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
})
}
}
func generateUUID(t *testing.T) string {
ulid, err := idProvider.ID()
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
return ulid
}
-55
View File
@@ -1,55 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package postgres
import (
_ "github.com/jackc/pgx/v5/stdlib" // required for SQL access
migrate "github.com/rubenv/sql-migrate"
)
// Migration of Alarms service.
func Migration() (*migrate.MemoryMigrationSource, error) {
alarmsMigration := &migrate.MemoryMigrationSource{
Migrations: []*migrate.Migration{
{
Id: "alarms_01",
// VARCHAR(36) for columns with IDs as UUIDS have a maximum of 36 characters
Up: []string{
`CREATE TABLE IF NOT EXISTS alarms (
id VARCHAR(36) PRIMARY KEY,
rule_id VARCHAR(36) NOT NULL CHECK (length(rule_id) > 0),
domain_id VARCHAR(36) NOT NULL,
channel_id VARCHAR(36) NOT NULL,
subtopic TEXT NOT NULL,
client_id VARCHAR(36) NOT NULL,
measurement TEXT NOT NULL,
value TEXT NOT NULL,
unit TEXT NOT NULL,
threshold TEXT NOT NULL,
cause TEXT NOT NULL,
status SMALLINT NOT NULL DEFAULT 0 CHECK (status >= 0),
severity SMALLINT NOT NULL DEFAULT 0 CHECK (severity >= 0),
assignee_id VARCHAR(36),
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NULL,
updated_by VARCHAR(36) NULL,
assigned_at TIMESTAMPTZ NULL,
assigned_by VARCHAR(36) NULL,
acknowledged_at TIMESTAMPTZ NULL,
acknowledged_by VARCHAR(36) NULL,
resolved_at TIMESTAMPTZ NULL,
resolved_by VARCHAR(36) NULL,
metadata JSONB
);`,
"CREATE INDEX IF NOT EXISTS idx_alarms_state ON alarms (domain_id, rule_id, channel_id, subtopic, client_id, measurement, created_at DESC);",
},
Down: []string{
`DROP TABLE IF EXISTS alarms`,
},
},
},
}
return alarmsMigration, nil
}
-72
View File
@@ -1,72 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package alarms
import (
"context"
"time"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/pkg/authn"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
)
type service struct {
idp magistrala.IDProvider
repo Repository
}
var _ Service = (*service)(nil)
func NewService(idp magistrala.IDProvider, repo Repository) Service {
return &service{
idp: idp,
repo: repo,
}
}
func (s *service) CreateAlarm(ctx context.Context, alarm Alarm) (Alarm, error) {
id, err := s.idp.ID()
if err != nil {
return Alarm{}, err
}
alarm.ID = id
if alarm.CreatedAt.IsZero() {
alarm.CreatedAt = time.Now()
}
if err := alarm.Validate(); err != nil {
return Alarm{}, err
}
created, err := s.repo.CreateAlarm(ctx, alarm)
if err != nil && err != repoerr.ErrNotFound {
return Alarm{}, err
}
if err == repoerr.ErrNotFound {
return Alarm{}, nil
}
return created, nil
}
func (s *service) ViewAlarm(ctx context.Context, session authn.Session, alarmID string) (Alarm, error) {
return s.repo.ViewAlarm(ctx, alarmID, session.DomainID)
}
func (s *service) ListAlarms(ctx context.Context, session authn.Session, pm PageMetadata) (AlarmsPage, error) {
pm.DomainID = session.DomainID
return s.repo.ListAllAlarms(ctx, pm)
}
func (s *service) DeleteAlarm(ctx context.Context, session authn.Session, alarmID string) error {
return s.repo.DeleteAlarm(ctx, alarmID)
}
func (s *service) UpdateAlarm(ctx context.Context, session authn.Session, alarm Alarm) (Alarm, error) {
alarm.UpdatedAt = time.Now()
alarm.UpdatedBy = session.UserID
return s.repo.UpdateAlarm(ctx, alarm)
}
-254
View File
@@ -1,254 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package alarms_test
import (
"context"
"fmt"
"testing"
"time"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/magistrala/alarms/mocks"
"github.com/absmach/magistrala/pkg/authn"
"github.com/absmach/magistrala/pkg/errors"
repoerr "github.com/absmach/magistrala/pkg/errors/repository"
"github.com/absmach/magistrala/pkg/uuid"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
var idp = uuid.New()
func newService(t *testing.T, repo *mocks.Repository) alarms.Service {
return alarms.NewService(idp, repo)
}
func TestCreateAlarm(t *testing.T) {
repo := new(mocks.Repository)
svc := newService(t, repo)
ts := time.Now()
cases := []struct {
desc string
alarm alarms.Alarm
err error
}{
{
desc: "valid alarm",
alarm: alarms.Alarm{
RuleID: "rule-id",
DomainID: "domain-id",
ChannelID: "channel-id",
ClientID: "client-id",
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
CreatedAt: ts,
},
err: nil,
},
{
desc: "missing rule_id",
alarm: alarms.Alarm{
DomainID: "domain-id",
ChannelID: "channel-id",
ClientID: "client-id",
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
CreatedAt: ts,
},
err: errors.New("rule_id is required"),
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
repoCall := repo.On("CreateAlarm", context.Background(), mock.Anything).Return(tc.alarm, tc.err)
_, err := svc.CreateAlarm(context.Background(), tc.alarm)
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
repoCall.Unset()
})
}
}
func TestViewAlarm(t *testing.T) {
repo := new(mocks.Repository)
svc := newService(t, repo)
cases := []struct {
desc string
id string
domainID string
err error
}{
{
desc: "valid alarm",
id: "alarm-id",
domainID: "domain-id",
err: nil,
},
{
desc: "non existing alarm id",
id: "alarm-id",
domainID: "domain-id",
err: repoerr.ErrNotFound,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
s := authn.Session{DomainID: tc.domainID}
repoCall := repo.On("ViewAlarm", context.Background(), tc.id, tc.domainID).Return(alarms.Alarm{}, tc.err)
_, err := svc.ViewAlarm(context.Background(), s, tc.id)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
repoCall.Unset()
})
}
}
func TestUpdateAlarm(t *testing.T) {
repo := new(mocks.Repository)
svc := newService(t, repo)
cases := []struct {
desc string
alarm alarms.Alarm
err error
}{
{
desc: "valid alarm",
alarm: alarms.Alarm{
RuleID: "rule-id",
DomainID: "domain-id",
ChannelID: "channel-id",
ClientID: "client-id",
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
},
err: nil,
},
{
desc: "non existing alarm",
alarm: alarms.Alarm{
RuleID: "rule-id",
DomainID: "domain-id",
ChannelID: "channel-id",
ClientID: "client-id",
Subtopic: "subtopic",
Measurement: "measurement",
Value: "value",
Unit: "unit",
Cause: "cause",
Severity: 100,
},
err: repoerr.ErrNotFound,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
s := authn.Session{DomainID: tc.alarm.DomainID}
repoCall := repo.On("UpdateAlarm", context.Background(), mock.Anything).Return(tc.alarm, tc.err)
_, err := svc.UpdateAlarm(context.Background(), s, tc.alarm)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
repoCall.Unset()
})
}
}
func TestListAlarms(t *testing.T) {
repo := new(mocks.Repository)
svc := newService(t, repo)
cases := []struct {
desc string
pm alarms.PageMetadata
page alarms.AlarmsPage
err error
}{
{
desc: "valid page",
pm: alarms.PageMetadata{
Offset: 0,
Limit: 10,
},
page: alarms.AlarmsPage{
Offset: 0,
Limit: 10,
Total: 10,
Alarms: []alarms.Alarm{},
},
err: nil,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
s := authn.Session{DomainID: tc.pm.DomainID}
repoCall := repo.On("ListAllAlarms", context.Background(), tc.pm).Return(tc.page, tc.err)
_, err := svc.ListAlarms(context.Background(), s, tc.pm)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
repoCall.Unset()
})
}
}
func TestDeleteAlarm(t *testing.T) {
repo := new(mocks.Repository)
svc := newService(t, repo)
cases := []struct {
desc string
id string
err error
}{
{
desc: "valid alarm",
id: "alarm-id",
err: nil,
},
{
desc: "non existing alarm",
id: "alarm-id",
err: repoerr.ErrNotFound,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
s := authn.Session{DomainID: tc.id}
repoCall := repo.On("DeleteAlarm", context.Background(), tc.id).Return(tc.err)
err := svc.DeleteAlarm(context.Background(), s, tc.id)
if tc.err != nil {
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
return
}
repoCall.Unset()
})
}
}
-70
View File
@@ -1,70 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package alarms
import (
"encoding/json"
"strings"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
)
type Status uint8
const (
ActiveStatus Status = iota
ClearedStatus
// AllStatus is used for querying purposes to list alarms irrespective
// of their status. It is never stored in the database as the actual
// Alarm status and should always be the largest value in this enumeration.
AllStatus
)
const (
Active = "active"
Cleared = "cleared"
Unknown = "unknown"
All = "all"
)
// String converts alarm status to string literal.
func (s Status) String() string {
switch s {
case ActiveStatus:
return Active
case ClearedStatus:
return Cleared
default:
return Unknown
}
}
// ToStatus converts string value to a valid Alarm status.
func ToStatus(status string) (Status, error) {
switch strings.ToLower(status) {
case Active:
return ActiveStatus, nil
case Cleared:
return ClearedStatus, nil
case All:
return AllStatus, nil
default:
return Status(0), svcerr.ErrInvalidStatus
}
}
// Custom Marshaller for Alarm.
func (s Status) MarshalJSON() ([]byte, error) {
return json.Marshal(s.String())
}
// Custom Unmarshaler for Alarm.
func (s *Status) UnmarshalJSON(data []byte) error {
str := strings.Trim(string(data), "\"")
val, err := ToStatus(str)
*s = val
return err
}
@@ -2,23 +2,23 @@
# SPDX-License-Identifier: Apache-2.0
asyncapi: '2.6.0'
id: 'https://github.com/absmach/magistrala/blob/main/api/asyncapi/mqtt.yaml'
id: 'https://github.com/absmach/magistrala/blob/master/api/asyncapi/mqtt.yml'
info:
title: Magistrala MQTT Adapter
version: '0.18.0'
version: '1.0.0'
contact:
name: Magistrala Team
url: 'https://github.com/absmach/magistrala'
email: info@absmach.eu
email: info@mainflux.com
description: |
MQTT adapter provides an MQTT API for sending messages through the platform. MQTT adapter uses [mProxy](https://github.com/absmach/mproxy) for proxying traffic between client and MQTT broker.
Additionally, the MQTT adapter and the message broker are replicating the traffic between brokers.
license:
name: Apache 2.0
url: 'https://github.com/absmach/magistrala/blob/main/LICENSE'
url: 'https://github.com/absmach/magistrala/blob/master/LICENSE'
defaultContentType: application/json
servers:
@@ -33,23 +33,19 @@ servers:
enum:
- '1883'
- '8883'
security:
security:
- user-password: []
channels:
/m/{domainPrefix}/c/{channelPrefix}/{subtopic}:
channels/{channelID}/messages/{subtopic}:
parameters:
domainPrefix:
$ref: '#/components/parameters/domainPrefix'
in: path
required: true
channelPrefix:
$ref: '#/components/parameters/channelPrefix'
channelID:
$ref: '#/components/parameters/channelID'
in: path
required: true
subtopic:
$ref: '#/components/parameters/subtopic'
in: path
in: path
required: false
publish:
@@ -91,26 +87,23 @@ components:
```
parameters:
domainPrefix:
description: ID or route of the domain associated with the channel and client.
schema:
type: string
channelPrefix:
description: ID or route of the channel connected to the Client ID defined in the username.
channelID:
description: Channel ID connected to the Thing ID defined in the username.
schema:
type: string
format: uuid
subtopic:
description: Arbitrary message subtopic.
schema:
type: string
default: ''
securitySchemes:
user-password:
type: userPassword
description: |
username is client ID connected to the channel defined in the mqtt topic and
password is client secret corresponding to the client ID
username is thing ID connected to the channel defined in the mqtt topic and
password is thing key corresponding to the thing ID
operationTraits:
mqtt:
@@ -2,18 +2,18 @@
# SPDX-License-Identifier: Apache-2.0
asyncapi: 2.6.0
id: 'https://github.com/absmach/magistrala/blob/main/api/asyncapi/websocket.yaml'
id: 'https://github.com/absmach/magistrala/blob/master/api/asyncapi/websocket.yml'
info:
title: Magistrala WebSocket adapter
description: WebSocket adapter provides a WebSocket API for sending messages through communication channels. WebSocket adapter uses [mProxy](https://github.com/absmach/mproxy) for proxying traffic between client and MQTT broker.
version: '0.18.0'
version: '1.0.0'
contact:
name: Magistrala Team
url: 'https://github.com/absmach/magistrala'
email: info@absmach.eu
email: info@mainflux.com
license:
name: Apache 2.0
url: 'https://github.com/absmach/magistrala/blob/main/LICENSE'
url: 'https://github.com/absmach/magistrala/blob/master/LICENSE'
tags:
- name: WebSocket
defaultContentType: application/json
@@ -29,17 +29,13 @@ servers:
default: localhost
port:
description: Magistrala WebSocket Adapter port
default: '8008'
default: '8186'
channels:
'm/{domainPrefix}/c/{channelPrefix}/{subtopic}':
'channels/{channelID}/messages/{subtopic}':
parameters:
domainPrefix:
$ref: '#/components/parameters/domainPrefix'
in: path
required: true
channelPrefix:
$ref: '#/components/parameters/channelPrefix'
channelID:
$ref: '#/components/parameters/channelID'
in: path
required: true
subtopic:
@@ -129,14 +125,11 @@ components:
```
parameters:
domainPrefix:
description: ID or route of the domain associated with the channel and client.
schema:
type: string
channelPrefix:
description: ID or route of the channel connected to the Client ID defined in the username.
channelID:
description: Channel ID connected to the Thing ID defined in the username.
schema:
type: string
format: uuid
subtopic:
description: Arbitrary message subtopic.
schema:
@@ -148,4 +141,4 @@ components:
scheme: bearer
bearerFormat: uuid
description: |
* Client access: "Authorization: Client <client_key>"
* Thing access: "Authorization: Thing <thing_key>"
-551
View File
@@ -1,551 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: auth/v1/auth.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type AuthNReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthNReq) Reset() {
*x = AuthNReq{}
mi := &file_auth_v1_auth_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthNReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthNReq) ProtoMessage() {}
func (x *AuthNReq) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthNReq.ProtoReflect.Descriptor instead.
func (*AuthNReq) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{0}
}
func (x *AuthNReq) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
type AuthNRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
UserRole uint32 `protobuf:"varint,3,opt,name=user_role,json=userRole,proto3" json:"user_role,omitempty"`
Verified bool `protobuf:"varint,4,opt,name=verified,proto3" json:"verified,omitempty"`
TokenType uint32 `protobuf:"varint,5,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthNRes) Reset() {
*x = AuthNRes{}
mi := &file_auth_v1_auth_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthNRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthNRes) ProtoMessage() {}
func (x *AuthNRes) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthNRes.ProtoReflect.Descriptor instead.
func (*AuthNRes) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{1}
}
func (x *AuthNRes) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *AuthNRes) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *AuthNRes) GetUserRole() uint32 {
if x != nil {
return x.UserRole
}
return 0
}
func (x *AuthNRes) GetVerified() bool {
if x != nil {
return x.Verified
}
return false
}
func (x *AuthNRes) GetTokenType() uint32 {
if x != nil {
return x.TokenType
}
return 0
}
type PolicyReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Domain string `protobuf:"bytes,1,opt,name=domain,proto3" json:"domain,omitempty"`
SubjectType string `protobuf:"bytes,2,opt,name=subject_type,json=subjectType,proto3" json:"subject_type,omitempty"`
SubjectKind string `protobuf:"bytes,3,opt,name=subject_kind,json=subjectKind,proto3" json:"subject_kind,omitempty"`
SubjectRelation string `protobuf:"bytes,4,opt,name=subject_relation,json=subjectRelation,proto3" json:"subject_relation,omitempty"`
Subject string `protobuf:"bytes,5,opt,name=subject,proto3" json:"subject,omitempty"`
Relation string `protobuf:"bytes,6,opt,name=relation,proto3" json:"relation,omitempty"`
Permission string `protobuf:"bytes,7,opt,name=permission,proto3" json:"permission,omitempty"`
Object string `protobuf:"bytes,8,opt,name=object,proto3" json:"object,omitempty"`
ObjectType string `protobuf:"bytes,9,opt,name=object_type,json=objectType,proto3" json:"object_type,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PolicyReq) Reset() {
*x = PolicyReq{}
mi := &file_auth_v1_auth_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PolicyReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PolicyReq) ProtoMessage() {}
func (x *PolicyReq) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PolicyReq.ProtoReflect.Descriptor instead.
func (*PolicyReq) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{2}
}
func (x *PolicyReq) GetDomain() string {
if x != nil {
return x.Domain
}
return ""
}
func (x *PolicyReq) GetSubjectType() string {
if x != nil {
return x.SubjectType
}
return ""
}
func (x *PolicyReq) GetSubjectKind() string {
if x != nil {
return x.SubjectKind
}
return ""
}
func (x *PolicyReq) GetSubjectRelation() string {
if x != nil {
return x.SubjectRelation
}
return ""
}
func (x *PolicyReq) GetSubject() string {
if x != nil {
return x.Subject
}
return ""
}
func (x *PolicyReq) GetRelation() string {
if x != nil {
return x.Relation
}
return ""
}
func (x *PolicyReq) GetPermission() string {
if x != nil {
return x.Permission
}
return ""
}
func (x *PolicyReq) GetObject() string {
if x != nil {
return x.Object
}
return ""
}
func (x *PolicyReq) GetObjectType() string {
if x != nil {
return x.ObjectType
}
return ""
}
type PATReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
PatId string `protobuf:"bytes,1,opt,name=pat_id,json=patId,proto3" json:"pat_id,omitempty"`
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
Operation string `protobuf:"bytes,3,opt,name=operation,proto3" json:"operation,omitempty"`
UserId string `protobuf:"bytes,4,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
EntityId string `protobuf:"bytes,5,opt,name=entity_id,json=entityId,proto3" json:"entity_id,omitempty"`
EntityType string `protobuf:"bytes,6,opt,name=entity_type,json=entityType,proto3" json:"entity_type,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PATReq) Reset() {
*x = PATReq{}
mi := &file_auth_v1_auth_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PATReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PATReq) ProtoMessage() {}
func (x *PATReq) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PATReq.ProtoReflect.Descriptor instead.
func (*PATReq) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{3}
}
func (x *PATReq) GetPatId() string {
if x != nil {
return x.PatId
}
return ""
}
func (x *PATReq) GetDomain() string {
if x != nil {
return x.Domain
}
return ""
}
func (x *PATReq) GetOperation() string {
if x != nil {
return x.Operation
}
return ""
}
func (x *PATReq) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *PATReq) GetEntityId() string {
if x != nil {
return x.EntityId
}
return ""
}
func (x *PATReq) GetEntityType() string {
if x != nil {
return x.EntityType
}
return ""
}
type AuthZReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
PolicyReq *PolicyReq `protobuf:"bytes,1,opt,name=policy_req,json=policyReq,proto3" json:"policy_req,omitempty"`
PatReq *PATReq `protobuf:"bytes,2,opt,name=pat_req,json=patReq,proto3,oneof" json:"pat_req,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthZReq) Reset() {
*x = AuthZReq{}
mi := &file_auth_v1_auth_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthZReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthZReq) ProtoMessage() {}
func (x *AuthZReq) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthZReq.ProtoReflect.Descriptor instead.
func (*AuthZReq) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{4}
}
func (x *AuthZReq) GetPolicyReq() *PolicyReq {
if x != nil {
return x.PolicyReq
}
return nil
}
func (x *AuthZReq) GetPatReq() *PATReq {
if x != nil {
return x.PatReq
}
return nil
}
type AuthZRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthZRes) Reset() {
*x = AuthZRes{}
mi := &file_auth_v1_auth_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthZRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthZRes) ProtoMessage() {}
func (x *AuthZRes) ProtoReflect() protoreflect.Message {
mi := &file_auth_v1_auth_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthZRes.ProtoReflect.Descriptor instead.
func (*AuthZRes) Descriptor() ([]byte, []int) {
return file_auth_v1_auth_proto_rawDescGZIP(), []int{5}
}
func (x *AuthZRes) GetAuthorized() bool {
if x != nil {
return x.Authorized
}
return false
}
func (x *AuthZRes) GetId() string {
if x != nil {
return x.Id
}
return ""
}
var File_auth_v1_auth_proto protoreflect.FileDescriptor
const file_auth_v1_auth_proto_rawDesc = "" +
"\n" +
"\x12auth/v1/auth.proto\x12\aauth.v1\" \n" +
"\bAuthNReq\x12\x14\n" +
"\x05token\x18\x01 \x01(\tR\x05token\"\x8b\x01\n" +
"\bAuthNRes\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x17\n" +
"\auser_id\x18\x02 \x01(\tR\x06userId\x12\x1b\n" +
"\tuser_role\x18\x03 \x01(\rR\buserRole\x12\x1a\n" +
"\bverified\x18\x04 \x01(\bR\bverified\x12\x1d\n" +
"\n" +
"token_type\x18\x05 \x01(\rR\ttokenType\"\xa3\x02\n" +
"\tPolicyReq\x12\x16\n" +
"\x06domain\x18\x01 \x01(\tR\x06domain\x12!\n" +
"\fsubject_type\x18\x02 \x01(\tR\vsubjectType\x12!\n" +
"\fsubject_kind\x18\x03 \x01(\tR\vsubjectKind\x12)\n" +
"\x10subject_relation\x18\x04 \x01(\tR\x0fsubjectRelation\x12\x18\n" +
"\asubject\x18\x05 \x01(\tR\asubject\x12\x1a\n" +
"\brelation\x18\x06 \x01(\tR\brelation\x12\x1e\n" +
"\n" +
"permission\x18\a \x01(\tR\n" +
"permission\x12\x16\n" +
"\x06object\x18\b \x01(\tR\x06object\x12\x1f\n" +
"\vobject_type\x18\t \x01(\tR\n" +
"objectType\"\xac\x01\n" +
"\x06PATReq\x12\x15\n" +
"\x06pat_id\x18\x01 \x01(\tR\x05patId\x12\x16\n" +
"\x06domain\x18\x02 \x01(\tR\x06domain\x12\x1c\n" +
"\toperation\x18\x03 \x01(\tR\toperation\x12\x17\n" +
"\auser_id\x18\x04 \x01(\tR\x06userId\x12\x1b\n" +
"\tentity_id\x18\x05 \x01(\tR\bentityId\x12\x1f\n" +
"\ventity_type\x18\x06 \x01(\tR\n" +
"entityType\"x\n" +
"\bAuthZReq\x121\n" +
"\n" +
"policy_req\x18\x01 \x01(\v2\x12.auth.v1.PolicyReqR\tpolicyReq\x12-\n" +
"\apat_req\x18\x02 \x01(\v2\x0f.auth.v1.PATReqH\x00R\x06patReq\x88\x01\x01B\n" +
"\n" +
"\b_pat_req\":\n" +
"\bAuthZRes\x12\x1e\n" +
"\n" +
"authorized\x18\x01 \x01(\bR\n" +
"authorized\x12\x0e\n" +
"\x02id\x18\x02 \x01(\tR\x02id2z\n" +
"\vAuthService\x123\n" +
"\tAuthorize\x12\x11.auth.v1.AuthZReq\x1a\x11.auth.v1.AuthZRes\"\x00\x126\n" +
"\fAuthenticate\x12\x11.auth.v1.AuthNReq\x1a\x11.auth.v1.AuthNRes\"\x00B0Z.github.com/absmach/magistrala/api/grpc/auth/v1b\x06proto3"
var (
file_auth_v1_auth_proto_rawDescOnce sync.Once
file_auth_v1_auth_proto_rawDescData []byte
)
func file_auth_v1_auth_proto_rawDescGZIP() []byte {
file_auth_v1_auth_proto_rawDescOnce.Do(func() {
file_auth_v1_auth_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_auth_v1_auth_proto_rawDesc), len(file_auth_v1_auth_proto_rawDesc)))
})
return file_auth_v1_auth_proto_rawDescData
}
var file_auth_v1_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_auth_v1_auth_proto_goTypes = []any{
(*AuthNReq)(nil), // 0: auth.v1.AuthNReq
(*AuthNRes)(nil), // 1: auth.v1.AuthNRes
(*PolicyReq)(nil), // 2: auth.v1.PolicyReq
(*PATReq)(nil), // 3: auth.v1.PATReq
(*AuthZReq)(nil), // 4: auth.v1.AuthZReq
(*AuthZRes)(nil), // 5: auth.v1.AuthZRes
}
var file_auth_v1_auth_proto_depIdxs = []int32{
2, // 0: auth.v1.AuthZReq.policy_req:type_name -> auth.v1.PolicyReq
3, // 1: auth.v1.AuthZReq.pat_req:type_name -> auth.v1.PATReq
4, // 2: auth.v1.AuthService.Authorize:input_type -> auth.v1.AuthZReq
0, // 3: auth.v1.AuthService.Authenticate:input_type -> auth.v1.AuthNReq
5, // 4: auth.v1.AuthService.Authorize:output_type -> auth.v1.AuthZRes
1, // 5: auth.v1.AuthService.Authenticate:output_type -> auth.v1.AuthNRes
4, // [4:6] is the sub-list for method output_type
2, // [2:4] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_auth_v1_auth_proto_init() }
func file_auth_v1_auth_proto_init() {
if File_auth_v1_auth_proto != nil {
return
}
file_auth_v1_auth_proto_msgTypes[4].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_auth_v1_auth_proto_rawDesc), len(file_auth_v1_auth_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_auth_v1_auth_proto_goTypes,
DependencyIndexes: file_auth_v1_auth_proto_depIdxs,
MessageInfos: file_auth_v1_auth_proto_msgTypes,
}.Build()
File_auth_v1_auth_proto = out.File
file_auth_v1_auth_proto_goTypes = nil
file_auth_v1_auth_proto_depIdxs = nil
}
-168
View File
@@ -1,168 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.0
// source: auth/v1/auth.proto
package v1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
AuthService_Authorize_FullMethodName = "/auth.v1.AuthService/Authorize"
AuthService_Authenticate_FullMethodName = "/auth.v1.AuthService/Authenticate"
)
// AuthServiceClient is the client API for AuthService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// AuthService is a service that provides authentication
// and authorization functionalities for Magistrala services.
type AuthServiceClient interface {
Authorize(ctx context.Context, in *AuthZReq, opts ...grpc.CallOption) (*AuthZRes, error)
Authenticate(ctx context.Context, in *AuthNReq, opts ...grpc.CallOption) (*AuthNRes, error)
}
type authServiceClient struct {
cc grpc.ClientConnInterface
}
func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient {
return &authServiceClient{cc}
}
func (c *authServiceClient) Authorize(ctx context.Context, in *AuthZReq, opts ...grpc.CallOption) (*AuthZRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AuthZRes)
err := c.cc.Invoke(ctx, AuthService_Authorize_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *authServiceClient) Authenticate(ctx context.Context, in *AuthNReq, opts ...grpc.CallOption) (*AuthNRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AuthNRes)
err := c.cc.Invoke(ctx, AuthService_Authenticate_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// AuthServiceServer is the server API for AuthService service.
// All implementations must embed UnimplementedAuthServiceServer
// for forward compatibility.
//
// AuthService is a service that provides authentication
// and authorization functionalities for Magistrala services.
type AuthServiceServer interface {
Authorize(context.Context, *AuthZReq) (*AuthZRes, error)
Authenticate(context.Context, *AuthNReq) (*AuthNRes, error)
mustEmbedUnimplementedAuthServiceServer()
}
// UnimplementedAuthServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedAuthServiceServer struct{}
func (UnimplementedAuthServiceServer) Authorize(context.Context, *AuthZReq) (*AuthZRes, error) {
return nil, status.Error(codes.Unimplemented, "method Authorize not implemented")
}
func (UnimplementedAuthServiceServer) Authenticate(context.Context, *AuthNReq) (*AuthNRes, error) {
return nil, status.Error(codes.Unimplemented, "method Authenticate not implemented")
}
func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {}
func (UnimplementedAuthServiceServer) testEmbeddedByValue() {}
// UnsafeAuthServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to AuthServiceServer will
// result in compilation errors.
type UnsafeAuthServiceServer interface {
mustEmbedUnimplementedAuthServiceServer()
}
func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) {
// If the following call panics, it indicates UnimplementedAuthServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&AuthService_ServiceDesc, srv)
}
func _AuthService_Authorize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthZReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).Authorize(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_Authorize_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).Authorize(ctx, req.(*AuthZReq))
}
return interceptor(ctx, in, info, handler)
}
func _AuthService_Authenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthNReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(AuthServiceServer).Authenticate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: AuthService_Authenticate_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(AuthServiceServer).Authenticate(ctx, req.(*AuthNReq))
}
return interceptor(ctx, in, info, handler)
}
// AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var AuthService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "auth.v1.AuthService",
HandlerType: (*AuthServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Authorize",
Handler: _AuthService_Authorize_Handler,
},
{
MethodName: "Authenticate",
Handler: _AuthService_Authenticate_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "auth/v1/auth.proto",
}
-228
View File
@@ -1,228 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: certs/v1/certs.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type EntityReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
SerialNumber string `protobuf:"bytes,1,opt,name=serial_number,json=serialNumber,proto3" json:"serial_number,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *EntityReq) Reset() {
*x = EntityReq{}
mi := &file_certs_v1_certs_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *EntityReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EntityReq) ProtoMessage() {}
func (x *EntityReq) ProtoReflect() protoreflect.Message {
mi := &file_certs_v1_certs_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use EntityReq.ProtoReflect.Descriptor instead.
func (*EntityReq) Descriptor() ([]byte, []int) {
return file_certs_v1_certs_proto_rawDescGZIP(), []int{0}
}
func (x *EntityReq) GetSerialNumber() string {
if x != nil {
return x.SerialNumber
}
return ""
}
type EntityRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
EntityId string `protobuf:"bytes,1,opt,name=entity_id,json=entityId,proto3" json:"entity_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *EntityRes) Reset() {
*x = EntityRes{}
mi := &file_certs_v1_certs_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *EntityRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EntityRes) ProtoMessage() {}
func (x *EntityRes) ProtoReflect() protoreflect.Message {
mi := &file_certs_v1_certs_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use EntityRes.ProtoReflect.Descriptor instead.
func (*EntityRes) Descriptor() ([]byte, []int) {
return file_certs_v1_certs_proto_rawDescGZIP(), []int{1}
}
func (x *EntityRes) GetEntityId() string {
if x != nil {
return x.EntityId
}
return ""
}
type RevokeReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
EntityId string `protobuf:"bytes,1,opt,name=entity_id,json=entityId,proto3" json:"entity_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RevokeReq) Reset() {
*x = RevokeReq{}
mi := &file_certs_v1_certs_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RevokeReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RevokeReq) ProtoMessage() {}
func (x *RevokeReq) ProtoReflect() protoreflect.Message {
mi := &file_certs_v1_certs_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RevokeReq.ProtoReflect.Descriptor instead.
func (*RevokeReq) Descriptor() ([]byte, []int) {
return file_certs_v1_certs_proto_rawDescGZIP(), []int{2}
}
func (x *RevokeReq) GetEntityId() string {
if x != nil {
return x.EntityId
}
return ""
}
var File_certs_v1_certs_proto protoreflect.FileDescriptor
const file_certs_v1_certs_proto_rawDesc = "" +
"\n" +
"\x14certs/v1/certs.proto\x12\rabsmach.certs\x1a\x1bgoogle/protobuf/empty.proto\"0\n" +
"\tEntityReq\x12#\n" +
"\rserial_number\x18\x01 \x01(\tR\fserialNumber\"(\n" +
"\tEntityRes\x12\x1b\n" +
"\tentity_id\x18\x01 \x01(\tR\bentityId\"(\n" +
"\tRevokeReq\x12\x1b\n" +
"\tentity_id\x18\x01 \x01(\tR\bentityId2\x96\x01\n" +
"\fCertsService\x12C\n" +
"\vGetEntityID\x12\x18.absmach.certs.EntityReq\x1a\x18.absmach.certs.EntityRes\"\x00\x12A\n" +
"\vRevokeCerts\x12\x18.absmach.certs.RevokeReq\x1a\x16.google.protobuf.Empty\"\x00B1Z/github.com/absmach/magistrala/api/grpc/certs/v1b\x06proto3"
var (
file_certs_v1_certs_proto_rawDescOnce sync.Once
file_certs_v1_certs_proto_rawDescData []byte
)
func file_certs_v1_certs_proto_rawDescGZIP() []byte {
file_certs_v1_certs_proto_rawDescOnce.Do(func() {
file_certs_v1_certs_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_certs_v1_certs_proto_rawDesc), len(file_certs_v1_certs_proto_rawDesc)))
})
return file_certs_v1_certs_proto_rawDescData
}
var file_certs_v1_certs_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_certs_v1_certs_proto_goTypes = []any{
(*EntityReq)(nil), // 0: absmach.certs.EntityReq
(*EntityRes)(nil), // 1: absmach.certs.EntityRes
(*RevokeReq)(nil), // 2: absmach.certs.RevokeReq
(*emptypb.Empty)(nil), // 3: google.protobuf.Empty
}
var file_certs_v1_certs_proto_depIdxs = []int32{
0, // 0: absmach.certs.CertsService.GetEntityID:input_type -> absmach.certs.EntityReq
2, // 1: absmach.certs.CertsService.RevokeCerts:input_type -> absmach.certs.RevokeReq
1, // 2: absmach.certs.CertsService.GetEntityID:output_type -> absmach.certs.EntityRes
3, // 3: absmach.certs.CertsService.RevokeCerts:output_type -> google.protobuf.Empty
2, // [2:4] is the sub-list for method output_type
0, // [0:2] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_certs_v1_certs_proto_init() }
func file_certs_v1_certs_proto_init() {
if File_certs_v1_certs_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_certs_v1_certs_proto_rawDesc), len(file_certs_v1_certs_proto_rawDesc)),
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_certs_v1_certs_proto_goTypes,
DependencyIndexes: file_certs_v1_certs_proto_depIdxs,
MessageInfos: file_certs_v1_certs_proto_msgTypes,
}.Build()
File_certs_v1_certs_proto = out.File
file_certs_v1_certs_proto_goTypes = nil
file_certs_v1_certs_proto_depIdxs = nil
}
-163
View File
@@ -1,163 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.0
// source: certs/v1/certs.proto
package v1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
emptypb "google.golang.org/protobuf/types/known/emptypb"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
CertsService_GetEntityID_FullMethodName = "/absmach.certs.CertsService/GetEntityID"
CertsService_RevokeCerts_FullMethodName = "/absmach.certs.CertsService/RevokeCerts"
)
// CertsServiceClient is the client API for CertsService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type CertsServiceClient interface {
GetEntityID(ctx context.Context, in *EntityReq, opts ...grpc.CallOption) (*EntityRes, error)
RevokeCerts(ctx context.Context, in *RevokeReq, opts ...grpc.CallOption) (*emptypb.Empty, error)
}
type certsServiceClient struct {
cc grpc.ClientConnInterface
}
func NewCertsServiceClient(cc grpc.ClientConnInterface) CertsServiceClient {
return &certsServiceClient{cc}
}
func (c *certsServiceClient) GetEntityID(ctx context.Context, in *EntityReq, opts ...grpc.CallOption) (*EntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(EntityRes)
err := c.cc.Invoke(ctx, CertsService_GetEntityID_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *certsServiceClient) RevokeCerts(ctx context.Context, in *RevokeReq, opts ...grpc.CallOption) (*emptypb.Empty, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(emptypb.Empty)
err := c.cc.Invoke(ctx, CertsService_RevokeCerts_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// CertsServiceServer is the server API for CertsService service.
// All implementations must embed UnimplementedCertsServiceServer
// for forward compatibility.
type CertsServiceServer interface {
GetEntityID(context.Context, *EntityReq) (*EntityRes, error)
RevokeCerts(context.Context, *RevokeReq) (*emptypb.Empty, error)
mustEmbedUnimplementedCertsServiceServer()
}
// UnimplementedCertsServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedCertsServiceServer struct{}
func (UnimplementedCertsServiceServer) GetEntityID(context.Context, *EntityReq) (*EntityRes, error) {
return nil, status.Error(codes.Unimplemented, "method GetEntityID not implemented")
}
func (UnimplementedCertsServiceServer) RevokeCerts(context.Context, *RevokeReq) (*emptypb.Empty, error) {
return nil, status.Error(codes.Unimplemented, "method RevokeCerts not implemented")
}
func (UnimplementedCertsServiceServer) mustEmbedUnimplementedCertsServiceServer() {}
func (UnimplementedCertsServiceServer) testEmbeddedByValue() {}
// UnsafeCertsServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to CertsServiceServer will
// result in compilation errors.
type UnsafeCertsServiceServer interface {
mustEmbedUnimplementedCertsServiceServer()
}
func RegisterCertsServiceServer(s grpc.ServiceRegistrar, srv CertsServiceServer) {
// If the following call panics, it indicates UnimplementedCertsServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&CertsService_ServiceDesc, srv)
}
func _CertsService_GetEntityID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(EntityReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CertsServiceServer).GetEntityID(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CertsService_GetEntityID_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CertsServiceServer).GetEntityID(ctx, req.(*EntityReq))
}
return interceptor(ctx, in, info, handler)
}
func _CertsService_RevokeCerts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RevokeReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CertsServiceServer).RevokeCerts(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CertsService_RevokeCerts_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CertsServiceServer).RevokeCerts(ctx, req.(*RevokeReq))
}
return interceptor(ctx, in, info, handler)
}
// CertsService_ServiceDesc is the grpc.ServiceDesc for CertsService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var CertsService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "absmach.certs.CertsService",
HandlerType: (*CertsServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "GetEntityID",
Handler: _CertsService_GetEntityID_Handler,
},
{
MethodName: "RevokeCerts",
Handler: _CertsService_RevokeCerts_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "certs/v1/certs.proto",
}
-402
View File
@@ -1,402 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: channels/v1/channels.proto
package v1
import (
v1 "github.com/absmach/magistrala/api/grpc/common/v1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type RemoveClientConnectionsReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RemoveClientConnectionsReq) Reset() {
*x = RemoveClientConnectionsReq{}
mi := &file_channels_v1_channels_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RemoveClientConnectionsReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveClientConnectionsReq) ProtoMessage() {}
func (x *RemoveClientConnectionsReq) ProtoReflect() protoreflect.Message {
mi := &file_channels_v1_channels_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RemoveClientConnectionsReq.ProtoReflect.Descriptor instead.
func (*RemoveClientConnectionsReq) Descriptor() ([]byte, []int) {
return file_channels_v1_channels_proto_rawDescGZIP(), []int{0}
}
func (x *RemoveClientConnectionsReq) GetClientId() string {
if x != nil {
return x.ClientId
}
return ""
}
type RemoveClientConnectionsRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RemoveClientConnectionsRes) Reset() {
*x = RemoveClientConnectionsRes{}
mi := &file_channels_v1_channels_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RemoveClientConnectionsRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveClientConnectionsRes) ProtoMessage() {}
func (x *RemoveClientConnectionsRes) ProtoReflect() protoreflect.Message {
mi := &file_channels_v1_channels_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RemoveClientConnectionsRes.ProtoReflect.Descriptor instead.
func (*RemoveClientConnectionsRes) Descriptor() ([]byte, []int) {
return file_channels_v1_channels_proto_rawDescGZIP(), []int{1}
}
type UnsetParentGroupFromChannelsReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
ParentGroupId string `protobuf:"bytes,1,opt,name=parent_group_id,json=parentGroupId,proto3" json:"parent_group_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnsetParentGroupFromChannelsReq) Reset() {
*x = UnsetParentGroupFromChannelsReq{}
mi := &file_channels_v1_channels_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UnsetParentGroupFromChannelsReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnsetParentGroupFromChannelsReq) ProtoMessage() {}
func (x *UnsetParentGroupFromChannelsReq) ProtoReflect() protoreflect.Message {
mi := &file_channels_v1_channels_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UnsetParentGroupFromChannelsReq.ProtoReflect.Descriptor instead.
func (*UnsetParentGroupFromChannelsReq) Descriptor() ([]byte, []int) {
return file_channels_v1_channels_proto_rawDescGZIP(), []int{2}
}
func (x *UnsetParentGroupFromChannelsReq) GetParentGroupId() string {
if x != nil {
return x.ParentGroupId
}
return ""
}
type UnsetParentGroupFromChannelsRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnsetParentGroupFromChannelsRes) Reset() {
*x = UnsetParentGroupFromChannelsRes{}
mi := &file_channels_v1_channels_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UnsetParentGroupFromChannelsRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnsetParentGroupFromChannelsRes) ProtoMessage() {}
func (x *UnsetParentGroupFromChannelsRes) ProtoReflect() protoreflect.Message {
mi := &file_channels_v1_channels_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UnsetParentGroupFromChannelsRes.ProtoReflect.Descriptor instead.
func (*UnsetParentGroupFromChannelsRes) Descriptor() ([]byte, []int) {
return file_channels_v1_channels_proto_rawDescGZIP(), []int{3}
}
type AuthzReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
DomainId string `protobuf:"bytes,1,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
ClientId string `protobuf:"bytes,2,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
ClientType string `protobuf:"bytes,3,opt,name=client_type,json=clientType,proto3" json:"client_type,omitempty"`
ChannelId string `protobuf:"bytes,4,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
Type uint32 `protobuf:"varint,5,opt,name=type,proto3" json:"type,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthzReq) Reset() {
*x = AuthzReq{}
mi := &file_channels_v1_channels_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthzReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthzReq) ProtoMessage() {}
func (x *AuthzReq) ProtoReflect() protoreflect.Message {
mi := &file_channels_v1_channels_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthzReq.ProtoReflect.Descriptor instead.
func (*AuthzReq) Descriptor() ([]byte, []int) {
return file_channels_v1_channels_proto_rawDescGZIP(), []int{4}
}
func (x *AuthzReq) GetDomainId() string {
if x != nil {
return x.DomainId
}
return ""
}
func (x *AuthzReq) GetClientId() string {
if x != nil {
return x.ClientId
}
return ""
}
func (x *AuthzReq) GetClientType() string {
if x != nil {
return x.ClientType
}
return ""
}
func (x *AuthzReq) GetChannelId() string {
if x != nil {
return x.ChannelId
}
return ""
}
func (x *AuthzReq) GetType() uint32 {
if x != nil {
return x.Type
}
return 0
}
type AuthzRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthzRes) Reset() {
*x = AuthzRes{}
mi := &file_channels_v1_channels_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthzRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthzRes) ProtoMessage() {}
func (x *AuthzRes) ProtoReflect() protoreflect.Message {
mi := &file_channels_v1_channels_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthzRes.ProtoReflect.Descriptor instead.
func (*AuthzRes) Descriptor() ([]byte, []int) {
return file_channels_v1_channels_proto_rawDescGZIP(), []int{5}
}
func (x *AuthzRes) GetAuthorized() bool {
if x != nil {
return x.Authorized
}
return false
}
var File_channels_v1_channels_proto protoreflect.FileDescriptor
const file_channels_v1_channels_proto_rawDesc = "" +
"\n" +
"\x1achannels/v1/channels.proto\x12\vchannels.v1\x1a\x16common/v1/common.proto\"9\n" +
"\x1aRemoveClientConnectionsReq\x12\x1b\n" +
"\tclient_id\x18\x01 \x01(\tR\bclientId\"\x1c\n" +
"\x1aRemoveClientConnectionsRes\"I\n" +
"\x1fUnsetParentGroupFromChannelsReq\x12&\n" +
"\x0fparent_group_id\x18\x01 \x01(\tR\rparentGroupId\"!\n" +
"\x1fUnsetParentGroupFromChannelsRes\"\x98\x01\n" +
"\bAuthzReq\x12\x1b\n" +
"\tdomain_id\x18\x01 \x01(\tR\bdomainId\x12\x1b\n" +
"\tclient_id\x18\x02 \x01(\tR\bclientId\x12\x1f\n" +
"\vclient_type\x18\x03 \x01(\tR\n" +
"clientType\x12\x1d\n" +
"\n" +
"channel_id\x18\x04 \x01(\tR\tchannelId\x12\x12\n" +
"\x04type\x18\x05 \x01(\rR\x04type\"*\n" +
"\bAuthzRes\x12\x1e\n" +
"\n" +
"authorized\x18\x01 \x01(\bR\n" +
"authorized2\xe1\x03\n" +
"\x0fChannelsService\x12;\n" +
"\tAuthorize\x12\x15.channels.v1.AuthzReq\x1a\x15.channels.v1.AuthzRes\"\x00\x12m\n" +
"\x17RemoveClientConnections\x12'.channels.v1.RemoveClientConnectionsReq\x1a'.channels.v1.RemoveClientConnectionsRes\"\x00\x12|\n" +
"\x1cUnsetParentGroupFromChannels\x12,.channels.v1.UnsetParentGroupFromChannelsReq\x1a,.channels.v1.UnsetParentGroupFromChannelsRes\"\x00\x12N\n" +
"\x0eRetrieveEntity\x12\x1c.common.v1.RetrieveEntityReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00\x12T\n" +
"\x11RetrieveIDByRoute\x12\x1f.common.v1.RetrieveIDByRouteReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00B4Z2github.com/absmach/magistrala/api/grpc/channels/v1b\x06proto3"
var (
file_channels_v1_channels_proto_rawDescOnce sync.Once
file_channels_v1_channels_proto_rawDescData []byte
)
func file_channels_v1_channels_proto_rawDescGZIP() []byte {
file_channels_v1_channels_proto_rawDescOnce.Do(func() {
file_channels_v1_channels_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_channels_v1_channels_proto_rawDesc), len(file_channels_v1_channels_proto_rawDesc)))
})
return file_channels_v1_channels_proto_rawDescData
}
var file_channels_v1_channels_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_channels_v1_channels_proto_goTypes = []any{
(*RemoveClientConnectionsReq)(nil), // 0: channels.v1.RemoveClientConnectionsReq
(*RemoveClientConnectionsRes)(nil), // 1: channels.v1.RemoveClientConnectionsRes
(*UnsetParentGroupFromChannelsReq)(nil), // 2: channels.v1.UnsetParentGroupFromChannelsReq
(*UnsetParentGroupFromChannelsRes)(nil), // 3: channels.v1.UnsetParentGroupFromChannelsRes
(*AuthzReq)(nil), // 4: channels.v1.AuthzReq
(*AuthzRes)(nil), // 5: channels.v1.AuthzRes
(*v1.RetrieveEntityReq)(nil), // 6: common.v1.RetrieveEntityReq
(*v1.RetrieveIDByRouteReq)(nil), // 7: common.v1.RetrieveIDByRouteReq
(*v1.RetrieveEntityRes)(nil), // 8: common.v1.RetrieveEntityRes
}
var file_channels_v1_channels_proto_depIdxs = []int32{
4, // 0: channels.v1.ChannelsService.Authorize:input_type -> channels.v1.AuthzReq
0, // 1: channels.v1.ChannelsService.RemoveClientConnections:input_type -> channels.v1.RemoveClientConnectionsReq
2, // 2: channels.v1.ChannelsService.UnsetParentGroupFromChannels:input_type -> channels.v1.UnsetParentGroupFromChannelsReq
6, // 3: channels.v1.ChannelsService.RetrieveEntity:input_type -> common.v1.RetrieveEntityReq
7, // 4: channels.v1.ChannelsService.RetrieveIDByRoute:input_type -> common.v1.RetrieveIDByRouteReq
5, // 5: channels.v1.ChannelsService.Authorize:output_type -> channels.v1.AuthzRes
1, // 6: channels.v1.ChannelsService.RemoveClientConnections:output_type -> channels.v1.RemoveClientConnectionsRes
3, // 7: channels.v1.ChannelsService.UnsetParentGroupFromChannels:output_type -> channels.v1.UnsetParentGroupFromChannelsRes
8, // 8: channels.v1.ChannelsService.RetrieveEntity:output_type -> common.v1.RetrieveEntityRes
8, // 9: channels.v1.ChannelsService.RetrieveIDByRoute:output_type -> common.v1.RetrieveEntityRes
5, // [5:10] is the sub-list for method output_type
0, // [0:5] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_channels_v1_channels_proto_init() }
func file_channels_v1_channels_proto_init() {
if File_channels_v1_channels_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_channels_v1_channels_proto_rawDesc), len(file_channels_v1_channels_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_channels_v1_channels_proto_goTypes,
DependencyIndexes: file_channels_v1_channels_proto_depIdxs,
MessageInfos: file_channels_v1_channels_proto_msgTypes,
}.Build()
File_channels_v1_channels_proto = out.File
file_channels_v1_channels_proto_goTypes = nil
file_channels_v1_channels_proto_depIdxs = nil
}
-277
View File
@@ -1,277 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.0
// source: channels/v1/channels.proto
package v1
import (
context "context"
v1 "github.com/absmach/magistrala/api/grpc/common/v1"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
ChannelsService_Authorize_FullMethodName = "/channels.v1.ChannelsService/Authorize"
ChannelsService_RemoveClientConnections_FullMethodName = "/channels.v1.ChannelsService/RemoveClientConnections"
ChannelsService_UnsetParentGroupFromChannels_FullMethodName = "/channels.v1.ChannelsService/UnsetParentGroupFromChannels"
ChannelsService_RetrieveEntity_FullMethodName = "/channels.v1.ChannelsService/RetrieveEntity"
ChannelsService_RetrieveIDByRoute_FullMethodName = "/channels.v1.ChannelsService/RetrieveIDByRoute"
)
// ChannelsServiceClient is the client API for ChannelsService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type ChannelsServiceClient interface {
Authorize(ctx context.Context, in *AuthzReq, opts ...grpc.CallOption) (*AuthzRes, error)
RemoveClientConnections(ctx context.Context, in *RemoveClientConnectionsReq, opts ...grpc.CallOption) (*RemoveClientConnectionsRes, error)
UnsetParentGroupFromChannels(ctx context.Context, in *UnsetParentGroupFromChannelsReq, opts ...grpc.CallOption) (*UnsetParentGroupFromChannelsRes, error)
RetrieveEntity(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
RetrieveIDByRoute(ctx context.Context, in *v1.RetrieveIDByRouteReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
}
type channelsServiceClient struct {
cc grpc.ClientConnInterface
}
func NewChannelsServiceClient(cc grpc.ClientConnInterface) ChannelsServiceClient {
return &channelsServiceClient{cc}
}
func (c *channelsServiceClient) Authorize(ctx context.Context, in *AuthzReq, opts ...grpc.CallOption) (*AuthzRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AuthzRes)
err := c.cc.Invoke(ctx, ChannelsService_Authorize_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *channelsServiceClient) RemoveClientConnections(ctx context.Context, in *RemoveClientConnectionsReq, opts ...grpc.CallOption) (*RemoveClientConnectionsRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RemoveClientConnectionsRes)
err := c.cc.Invoke(ctx, ChannelsService_RemoveClientConnections_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *channelsServiceClient) UnsetParentGroupFromChannels(ctx context.Context, in *UnsetParentGroupFromChannelsReq, opts ...grpc.CallOption) (*UnsetParentGroupFromChannelsRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UnsetParentGroupFromChannelsRes)
err := c.cc.Invoke(ctx, ChannelsService_UnsetParentGroupFromChannels_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *channelsServiceClient) RetrieveEntity(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntityRes)
err := c.cc.Invoke(ctx, ChannelsService_RetrieveEntity_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *channelsServiceClient) RetrieveIDByRoute(ctx context.Context, in *v1.RetrieveIDByRouteReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntityRes)
err := c.cc.Invoke(ctx, ChannelsService_RetrieveIDByRoute_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ChannelsServiceServer is the server API for ChannelsService service.
// All implementations must embed UnimplementedChannelsServiceServer
// for forward compatibility.
type ChannelsServiceServer interface {
Authorize(context.Context, *AuthzReq) (*AuthzRes, error)
RemoveClientConnections(context.Context, *RemoveClientConnectionsReq) (*RemoveClientConnectionsRes, error)
UnsetParentGroupFromChannels(context.Context, *UnsetParentGroupFromChannelsReq) (*UnsetParentGroupFromChannelsRes, error)
RetrieveEntity(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error)
RetrieveIDByRoute(context.Context, *v1.RetrieveIDByRouteReq) (*v1.RetrieveEntityRes, error)
mustEmbedUnimplementedChannelsServiceServer()
}
// UnimplementedChannelsServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedChannelsServiceServer struct{}
func (UnimplementedChannelsServiceServer) Authorize(context.Context, *AuthzReq) (*AuthzRes, error) {
return nil, status.Error(codes.Unimplemented, "method Authorize not implemented")
}
func (UnimplementedChannelsServiceServer) RemoveClientConnections(context.Context, *RemoveClientConnectionsReq) (*RemoveClientConnectionsRes, error) {
return nil, status.Error(codes.Unimplemented, "method RemoveClientConnections not implemented")
}
func (UnimplementedChannelsServiceServer) UnsetParentGroupFromChannels(context.Context, *UnsetParentGroupFromChannelsReq) (*UnsetParentGroupFromChannelsRes, error) {
return nil, status.Error(codes.Unimplemented, "method UnsetParentGroupFromChannels not implemented")
}
func (UnimplementedChannelsServiceServer) RetrieveEntity(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Error(codes.Unimplemented, "method RetrieveEntity not implemented")
}
func (UnimplementedChannelsServiceServer) RetrieveIDByRoute(context.Context, *v1.RetrieveIDByRouteReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Error(codes.Unimplemented, "method RetrieveIDByRoute not implemented")
}
func (UnimplementedChannelsServiceServer) mustEmbedUnimplementedChannelsServiceServer() {}
func (UnimplementedChannelsServiceServer) testEmbeddedByValue() {}
// UnsafeChannelsServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ChannelsServiceServer will
// result in compilation errors.
type UnsafeChannelsServiceServer interface {
mustEmbedUnimplementedChannelsServiceServer()
}
func RegisterChannelsServiceServer(s grpc.ServiceRegistrar, srv ChannelsServiceServer) {
// If the following call panics, it indicates UnimplementedChannelsServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&ChannelsService_ServiceDesc, srv)
}
func _ChannelsService_Authorize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthzReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ChannelsServiceServer).Authorize(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ChannelsService_Authorize_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ChannelsServiceServer).Authorize(ctx, req.(*AuthzReq))
}
return interceptor(ctx, in, info, handler)
}
func _ChannelsService_RemoveClientConnections_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RemoveClientConnectionsReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ChannelsServiceServer).RemoveClientConnections(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ChannelsService_RemoveClientConnections_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ChannelsServiceServer).RemoveClientConnections(ctx, req.(*RemoveClientConnectionsReq))
}
return interceptor(ctx, in, info, handler)
}
func _ChannelsService_UnsetParentGroupFromChannels_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UnsetParentGroupFromChannelsReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ChannelsServiceServer).UnsetParentGroupFromChannels(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ChannelsService_UnsetParentGroupFromChannels_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ChannelsServiceServer).UnsetParentGroupFromChannels(ctx, req.(*UnsetParentGroupFromChannelsReq))
}
return interceptor(ctx, in, info, handler)
}
func _ChannelsService_RetrieveEntity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveEntityReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ChannelsServiceServer).RetrieveEntity(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ChannelsService_RetrieveEntity_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ChannelsServiceServer).RetrieveEntity(ctx, req.(*v1.RetrieveEntityReq))
}
return interceptor(ctx, in, info, handler)
}
func _ChannelsService_RetrieveIDByRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveIDByRouteReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ChannelsServiceServer).RetrieveIDByRoute(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ChannelsService_RetrieveIDByRoute_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ChannelsServiceServer).RetrieveIDByRoute(ctx, req.(*v1.RetrieveIDByRouteReq))
}
return interceptor(ctx, in, info, handler)
}
// ChannelsService_ServiceDesc is the grpc.ServiceDesc for ChannelsService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ChannelsService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "channels.v1.ChannelsService",
HandlerType: (*ChannelsServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Authorize",
Handler: _ChannelsService_Authorize_Handler,
},
{
MethodName: "RemoveClientConnections",
Handler: _ChannelsService_RemoveClientConnections_Handler,
},
{
MethodName: "UnsetParentGroupFromChannels",
Handler: _ChannelsService_UnsetParentGroupFromChannels_Handler,
},
{
MethodName: "RetrieveEntity",
Handler: _ChannelsService_RetrieveEntity_Handler,
},
{
MethodName: "RetrieveIDByRoute",
Handler: _ChannelsService_RetrieveIDByRoute_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "channels/v1/channels.proto",
}
-384
View File
@@ -1,384 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: clients/v1/clients.proto
package v1
import (
v1 "github.com/absmach/magistrala/api/grpc/common/v1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type AuthnReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthnReq) Reset() {
*x = AuthnReq{}
mi := &file_clients_v1_clients_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthnReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthnReq) ProtoMessage() {}
func (x *AuthnReq) ProtoReflect() protoreflect.Message {
mi := &file_clients_v1_clients_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthnReq.ProtoReflect.Descriptor instead.
func (*AuthnReq) Descriptor() ([]byte, []int) {
return file_clients_v1_clients_proto_rawDescGZIP(), []int{0}
}
func (x *AuthnReq) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
type AuthnRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Authenticated bool `protobuf:"varint,1,opt,name=authenticated,proto3" json:"authenticated,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AuthnRes) Reset() {
*x = AuthnRes{}
mi := &file_clients_v1_clients_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AuthnRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AuthnRes) ProtoMessage() {}
func (x *AuthnRes) ProtoReflect() protoreflect.Message {
mi := &file_clients_v1_clients_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AuthnRes.ProtoReflect.Descriptor instead.
func (*AuthnRes) Descriptor() ([]byte, []int) {
return file_clients_v1_clients_proto_rawDescGZIP(), []int{1}
}
func (x *AuthnRes) GetAuthenticated() bool {
if x != nil {
return x.Authenticated
}
return false
}
func (x *AuthnRes) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type RemoveChannelConnectionsReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
ChannelId string `protobuf:"bytes,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RemoveChannelConnectionsReq) Reset() {
*x = RemoveChannelConnectionsReq{}
mi := &file_clients_v1_clients_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RemoveChannelConnectionsReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveChannelConnectionsReq) ProtoMessage() {}
func (x *RemoveChannelConnectionsReq) ProtoReflect() protoreflect.Message {
mi := &file_clients_v1_clients_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RemoveChannelConnectionsReq.ProtoReflect.Descriptor instead.
func (*RemoveChannelConnectionsReq) Descriptor() ([]byte, []int) {
return file_clients_v1_clients_proto_rawDescGZIP(), []int{2}
}
func (x *RemoveChannelConnectionsReq) GetChannelId() string {
if x != nil {
return x.ChannelId
}
return ""
}
type RemoveChannelConnectionsRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RemoveChannelConnectionsRes) Reset() {
*x = RemoveChannelConnectionsRes{}
mi := &file_clients_v1_clients_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RemoveChannelConnectionsRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveChannelConnectionsRes) ProtoMessage() {}
func (x *RemoveChannelConnectionsRes) ProtoReflect() protoreflect.Message {
mi := &file_clients_v1_clients_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RemoveChannelConnectionsRes.ProtoReflect.Descriptor instead.
func (*RemoveChannelConnectionsRes) Descriptor() ([]byte, []int) {
return file_clients_v1_clients_proto_rawDescGZIP(), []int{3}
}
type UnsetParentGroupFromClientReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
ParentGroupId string `protobuf:"bytes,1,opt,name=parent_group_id,json=parentGroupId,proto3" json:"parent_group_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnsetParentGroupFromClientReq) Reset() {
*x = UnsetParentGroupFromClientReq{}
mi := &file_clients_v1_clients_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UnsetParentGroupFromClientReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnsetParentGroupFromClientReq) ProtoMessage() {}
func (x *UnsetParentGroupFromClientReq) ProtoReflect() protoreflect.Message {
mi := &file_clients_v1_clients_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UnsetParentGroupFromClientReq.ProtoReflect.Descriptor instead.
func (*UnsetParentGroupFromClientReq) Descriptor() ([]byte, []int) {
return file_clients_v1_clients_proto_rawDescGZIP(), []int{4}
}
func (x *UnsetParentGroupFromClientReq) GetParentGroupId() string {
if x != nil {
return x.ParentGroupId
}
return ""
}
type UnsetParentGroupFromClientRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UnsetParentGroupFromClientRes) Reset() {
*x = UnsetParentGroupFromClientRes{}
mi := &file_clients_v1_clients_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UnsetParentGroupFromClientRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UnsetParentGroupFromClientRes) ProtoMessage() {}
func (x *UnsetParentGroupFromClientRes) ProtoReflect() protoreflect.Message {
mi := &file_clients_v1_clients_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UnsetParentGroupFromClientRes.ProtoReflect.Descriptor instead.
func (*UnsetParentGroupFromClientRes) Descriptor() ([]byte, []int) {
return file_clients_v1_clients_proto_rawDescGZIP(), []int{5}
}
var File_clients_v1_clients_proto protoreflect.FileDescriptor
const file_clients_v1_clients_proto_rawDesc = "" +
"\n" +
"\x18clients/v1/clients.proto\x12\n" +
"clients.v1\x1a\x16common/v1/common.proto\" \n" +
"\bAuthnReq\x12\x14\n" +
"\x05token\x18\x01 \x01(\tR\x05token\"@\n" +
"\bAuthnRes\x12$\n" +
"\rauthenticated\x18\x01 \x01(\bR\rauthenticated\x12\x0e\n" +
"\x02id\x18\x02 \x01(\tR\x02id\"<\n" +
"\x1bRemoveChannelConnectionsReq\x12\x1d\n" +
"\n" +
"channel_id\x18\x01 \x01(\tR\tchannelId\"\x1d\n" +
"\x1bRemoveChannelConnectionsRes\"G\n" +
"\x1dUnsetParentGroupFromClientReq\x12&\n" +
"\x0fparent_group_id\x18\x01 \x01(\tR\rparentGroupId\"\x1f\n" +
"\x1dUnsetParentGroupFromClientRes2\x83\x05\n" +
"\x0eClientsService\x12<\n" +
"\fAuthenticate\x12\x14.clients.v1.AuthnReq\x1a\x14.clients.v1.AuthnRes\"\x00\x12N\n" +
"\x0eRetrieveEntity\x12\x1c.common.v1.RetrieveEntityReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00\x12T\n" +
"\x10RetrieveEntities\x12\x1e.common.v1.RetrieveEntitiesReq\x1a\x1e.common.v1.RetrieveEntitiesRes\"\x00\x12N\n" +
"\x0eAddConnections\x12\x1c.common.v1.AddConnectionsReq\x1a\x1c.common.v1.AddConnectionsRes\"\x00\x12W\n" +
"\x11RemoveConnections\x12\x1f.common.v1.RemoveConnectionsReq\x1a\x1f.common.v1.RemoveConnectionsRes\"\x00\x12n\n" +
"\x18RemoveChannelConnections\x12'.clients.v1.RemoveChannelConnectionsReq\x1a'.clients.v1.RemoveChannelConnectionsRes\"\x00\x12t\n" +
"\x1aUnsetParentGroupFromClient\x12).clients.v1.UnsetParentGroupFromClientReq\x1a).clients.v1.UnsetParentGroupFromClientRes\"\x00B3Z1github.com/absmach/magistrala/api/grpc/clients/v1b\x06proto3"
var (
file_clients_v1_clients_proto_rawDescOnce sync.Once
file_clients_v1_clients_proto_rawDescData []byte
)
func file_clients_v1_clients_proto_rawDescGZIP() []byte {
file_clients_v1_clients_proto_rawDescOnce.Do(func() {
file_clients_v1_clients_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_clients_v1_clients_proto_rawDesc), len(file_clients_v1_clients_proto_rawDesc)))
})
return file_clients_v1_clients_proto_rawDescData
}
var file_clients_v1_clients_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_clients_v1_clients_proto_goTypes = []any{
(*AuthnReq)(nil), // 0: clients.v1.AuthnReq
(*AuthnRes)(nil), // 1: clients.v1.AuthnRes
(*RemoveChannelConnectionsReq)(nil), // 2: clients.v1.RemoveChannelConnectionsReq
(*RemoveChannelConnectionsRes)(nil), // 3: clients.v1.RemoveChannelConnectionsRes
(*UnsetParentGroupFromClientReq)(nil), // 4: clients.v1.UnsetParentGroupFromClientReq
(*UnsetParentGroupFromClientRes)(nil), // 5: clients.v1.UnsetParentGroupFromClientRes
(*v1.RetrieveEntityReq)(nil), // 6: common.v1.RetrieveEntityReq
(*v1.RetrieveEntitiesReq)(nil), // 7: common.v1.RetrieveEntitiesReq
(*v1.AddConnectionsReq)(nil), // 8: common.v1.AddConnectionsReq
(*v1.RemoveConnectionsReq)(nil), // 9: common.v1.RemoveConnectionsReq
(*v1.RetrieveEntityRes)(nil), // 10: common.v1.RetrieveEntityRes
(*v1.RetrieveEntitiesRes)(nil), // 11: common.v1.RetrieveEntitiesRes
(*v1.AddConnectionsRes)(nil), // 12: common.v1.AddConnectionsRes
(*v1.RemoveConnectionsRes)(nil), // 13: common.v1.RemoveConnectionsRes
}
var file_clients_v1_clients_proto_depIdxs = []int32{
0, // 0: clients.v1.ClientsService.Authenticate:input_type -> clients.v1.AuthnReq
6, // 1: clients.v1.ClientsService.RetrieveEntity:input_type -> common.v1.RetrieveEntityReq
7, // 2: clients.v1.ClientsService.RetrieveEntities:input_type -> common.v1.RetrieveEntitiesReq
8, // 3: clients.v1.ClientsService.AddConnections:input_type -> common.v1.AddConnectionsReq
9, // 4: clients.v1.ClientsService.RemoveConnections:input_type -> common.v1.RemoveConnectionsReq
2, // 5: clients.v1.ClientsService.RemoveChannelConnections:input_type -> clients.v1.RemoveChannelConnectionsReq
4, // 6: clients.v1.ClientsService.UnsetParentGroupFromClient:input_type -> clients.v1.UnsetParentGroupFromClientReq
1, // 7: clients.v1.ClientsService.Authenticate:output_type -> clients.v1.AuthnRes
10, // 8: clients.v1.ClientsService.RetrieveEntity:output_type -> common.v1.RetrieveEntityRes
11, // 9: clients.v1.ClientsService.RetrieveEntities:output_type -> common.v1.RetrieveEntitiesRes
12, // 10: clients.v1.ClientsService.AddConnections:output_type -> common.v1.AddConnectionsRes
13, // 11: clients.v1.ClientsService.RemoveConnections:output_type -> common.v1.RemoveConnectionsRes
3, // 12: clients.v1.ClientsService.RemoveChannelConnections:output_type -> clients.v1.RemoveChannelConnectionsRes
5, // 13: clients.v1.ClientsService.UnsetParentGroupFromClient:output_type -> clients.v1.UnsetParentGroupFromClientRes
7, // [7:14] is the sub-list for method output_type
0, // [0:7] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_clients_v1_clients_proto_init() }
func file_clients_v1_clients_proto_init() {
if File_clients_v1_clients_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_clients_v1_clients_proto_rawDesc), len(file_clients_v1_clients_proto_rawDesc)),
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_clients_v1_clients_proto_goTypes,
DependencyIndexes: file_clients_v1_clients_proto_depIdxs,
MessageInfos: file_clients_v1_clients_proto_msgTypes,
}.Build()
File_clients_v1_clients_proto = out.File
file_clients_v1_clients_proto_goTypes = nil
file_clients_v1_clients_proto_depIdxs = nil
}
-361
View File
@@ -1,361 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.0
// source: clients/v1/clients.proto
package v1
import (
context "context"
v1 "github.com/absmach/magistrala/api/grpc/common/v1"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
ClientsService_Authenticate_FullMethodName = "/clients.v1.ClientsService/Authenticate"
ClientsService_RetrieveEntity_FullMethodName = "/clients.v1.ClientsService/RetrieveEntity"
ClientsService_RetrieveEntities_FullMethodName = "/clients.v1.ClientsService/RetrieveEntities"
ClientsService_AddConnections_FullMethodName = "/clients.v1.ClientsService/AddConnections"
ClientsService_RemoveConnections_FullMethodName = "/clients.v1.ClientsService/RemoveConnections"
ClientsService_RemoveChannelConnections_FullMethodName = "/clients.v1.ClientsService/RemoveChannelConnections"
ClientsService_UnsetParentGroupFromClient_FullMethodName = "/clients.v1.ClientsService/UnsetParentGroupFromClient"
)
// ClientsServiceClient is the client API for ClientsService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// ClientsService is a service that provides clients
// authorization functionalities for Magistrala services.
type ClientsServiceClient interface {
// Authorize checks if the client is authorized to perform
Authenticate(ctx context.Context, in *AuthnReq, opts ...grpc.CallOption) (*AuthnRes, error)
RetrieveEntity(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
RetrieveEntities(ctx context.Context, in *v1.RetrieveEntitiesReq, opts ...grpc.CallOption) (*v1.RetrieveEntitiesRes, error)
AddConnections(ctx context.Context, in *v1.AddConnectionsReq, opts ...grpc.CallOption) (*v1.AddConnectionsRes, error)
RemoveConnections(ctx context.Context, in *v1.RemoveConnectionsReq, opts ...grpc.CallOption) (*v1.RemoveConnectionsRes, error)
RemoveChannelConnections(ctx context.Context, in *RemoveChannelConnectionsReq, opts ...grpc.CallOption) (*RemoveChannelConnectionsRes, error)
UnsetParentGroupFromClient(ctx context.Context, in *UnsetParentGroupFromClientReq, opts ...grpc.CallOption) (*UnsetParentGroupFromClientRes, error)
}
type clientsServiceClient struct {
cc grpc.ClientConnInterface
}
func NewClientsServiceClient(cc grpc.ClientConnInterface) ClientsServiceClient {
return &clientsServiceClient{cc}
}
func (c *clientsServiceClient) Authenticate(ctx context.Context, in *AuthnReq, opts ...grpc.CallOption) (*AuthnRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(AuthnRes)
err := c.cc.Invoke(ctx, ClientsService_Authenticate_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *clientsServiceClient) RetrieveEntity(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntityRes)
err := c.cc.Invoke(ctx, ClientsService_RetrieveEntity_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *clientsServiceClient) RetrieveEntities(ctx context.Context, in *v1.RetrieveEntitiesReq, opts ...grpc.CallOption) (*v1.RetrieveEntitiesRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntitiesRes)
err := c.cc.Invoke(ctx, ClientsService_RetrieveEntities_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *clientsServiceClient) AddConnections(ctx context.Context, in *v1.AddConnectionsReq, opts ...grpc.CallOption) (*v1.AddConnectionsRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.AddConnectionsRes)
err := c.cc.Invoke(ctx, ClientsService_AddConnections_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *clientsServiceClient) RemoveConnections(ctx context.Context, in *v1.RemoveConnectionsReq, opts ...grpc.CallOption) (*v1.RemoveConnectionsRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RemoveConnectionsRes)
err := c.cc.Invoke(ctx, ClientsService_RemoveConnections_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *clientsServiceClient) RemoveChannelConnections(ctx context.Context, in *RemoveChannelConnectionsReq, opts ...grpc.CallOption) (*RemoveChannelConnectionsRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RemoveChannelConnectionsRes)
err := c.cc.Invoke(ctx, ClientsService_RemoveChannelConnections_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *clientsServiceClient) UnsetParentGroupFromClient(ctx context.Context, in *UnsetParentGroupFromClientReq, opts ...grpc.CallOption) (*UnsetParentGroupFromClientRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(UnsetParentGroupFromClientRes)
err := c.cc.Invoke(ctx, ClientsService_UnsetParentGroupFromClient_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ClientsServiceServer is the server API for ClientsService service.
// All implementations must embed UnimplementedClientsServiceServer
// for forward compatibility.
//
// ClientsService is a service that provides clients
// authorization functionalities for Magistrala services.
type ClientsServiceServer interface {
// Authorize checks if the client is authorized to perform
Authenticate(context.Context, *AuthnReq) (*AuthnRes, error)
RetrieveEntity(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error)
RetrieveEntities(context.Context, *v1.RetrieveEntitiesReq) (*v1.RetrieveEntitiesRes, error)
AddConnections(context.Context, *v1.AddConnectionsReq) (*v1.AddConnectionsRes, error)
RemoveConnections(context.Context, *v1.RemoveConnectionsReq) (*v1.RemoveConnectionsRes, error)
RemoveChannelConnections(context.Context, *RemoveChannelConnectionsReq) (*RemoveChannelConnectionsRes, error)
UnsetParentGroupFromClient(context.Context, *UnsetParentGroupFromClientReq) (*UnsetParentGroupFromClientRes, error)
mustEmbedUnimplementedClientsServiceServer()
}
// UnimplementedClientsServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedClientsServiceServer struct{}
func (UnimplementedClientsServiceServer) Authenticate(context.Context, *AuthnReq) (*AuthnRes, error) {
return nil, status.Error(codes.Unimplemented, "method Authenticate not implemented")
}
func (UnimplementedClientsServiceServer) RetrieveEntity(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Error(codes.Unimplemented, "method RetrieveEntity not implemented")
}
func (UnimplementedClientsServiceServer) RetrieveEntities(context.Context, *v1.RetrieveEntitiesReq) (*v1.RetrieveEntitiesRes, error) {
return nil, status.Error(codes.Unimplemented, "method RetrieveEntities not implemented")
}
func (UnimplementedClientsServiceServer) AddConnections(context.Context, *v1.AddConnectionsReq) (*v1.AddConnectionsRes, error) {
return nil, status.Error(codes.Unimplemented, "method AddConnections not implemented")
}
func (UnimplementedClientsServiceServer) RemoveConnections(context.Context, *v1.RemoveConnectionsReq) (*v1.RemoveConnectionsRes, error) {
return nil, status.Error(codes.Unimplemented, "method RemoveConnections not implemented")
}
func (UnimplementedClientsServiceServer) RemoveChannelConnections(context.Context, *RemoveChannelConnectionsReq) (*RemoveChannelConnectionsRes, error) {
return nil, status.Error(codes.Unimplemented, "method RemoveChannelConnections not implemented")
}
func (UnimplementedClientsServiceServer) UnsetParentGroupFromClient(context.Context, *UnsetParentGroupFromClientReq) (*UnsetParentGroupFromClientRes, error) {
return nil, status.Error(codes.Unimplemented, "method UnsetParentGroupFromClient not implemented")
}
func (UnimplementedClientsServiceServer) mustEmbedUnimplementedClientsServiceServer() {}
func (UnimplementedClientsServiceServer) testEmbeddedByValue() {}
// UnsafeClientsServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ClientsServiceServer will
// result in compilation errors.
type UnsafeClientsServiceServer interface {
mustEmbedUnimplementedClientsServiceServer()
}
func RegisterClientsServiceServer(s grpc.ServiceRegistrar, srv ClientsServiceServer) {
// If the following call panics, it indicates UnimplementedClientsServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&ClientsService_ServiceDesc, srv)
}
func _ClientsService_Authenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthnReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClientsServiceServer).Authenticate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ClientsService_Authenticate_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClientsServiceServer).Authenticate(ctx, req.(*AuthnReq))
}
return interceptor(ctx, in, info, handler)
}
func _ClientsService_RetrieveEntity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveEntityReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClientsServiceServer).RetrieveEntity(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ClientsService_RetrieveEntity_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClientsServiceServer).RetrieveEntity(ctx, req.(*v1.RetrieveEntityReq))
}
return interceptor(ctx, in, info, handler)
}
func _ClientsService_RetrieveEntities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveEntitiesReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClientsServiceServer).RetrieveEntities(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ClientsService_RetrieveEntities_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClientsServiceServer).RetrieveEntities(ctx, req.(*v1.RetrieveEntitiesReq))
}
return interceptor(ctx, in, info, handler)
}
func _ClientsService_AddConnections_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.AddConnectionsReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClientsServiceServer).AddConnections(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ClientsService_AddConnections_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClientsServiceServer).AddConnections(ctx, req.(*v1.AddConnectionsReq))
}
return interceptor(ctx, in, info, handler)
}
func _ClientsService_RemoveConnections_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RemoveConnectionsReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClientsServiceServer).RemoveConnections(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ClientsService_RemoveConnections_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClientsServiceServer).RemoveConnections(ctx, req.(*v1.RemoveConnectionsReq))
}
return interceptor(ctx, in, info, handler)
}
func _ClientsService_RemoveChannelConnections_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RemoveChannelConnectionsReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClientsServiceServer).RemoveChannelConnections(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ClientsService_RemoveChannelConnections_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClientsServiceServer).RemoveChannelConnections(ctx, req.(*RemoveChannelConnectionsReq))
}
return interceptor(ctx, in, info, handler)
}
func _ClientsService_UnsetParentGroupFromClient_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UnsetParentGroupFromClientReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClientsServiceServer).UnsetParentGroupFromClient(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ClientsService_UnsetParentGroupFromClient_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClientsServiceServer).UnsetParentGroupFromClient(ctx, req.(*UnsetParentGroupFromClientReq))
}
return interceptor(ctx, in, info, handler)
}
// ClientsService_ServiceDesc is the grpc.ServiceDesc for ClientsService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ClientsService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "clients.v1.ClientsService",
HandlerType: (*ClientsServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Authenticate",
Handler: _ClientsService_Authenticate_Handler,
},
{
MethodName: "RetrieveEntity",
Handler: _ClientsService_RetrieveEntity_Handler,
},
{
MethodName: "RetrieveEntities",
Handler: _ClientsService_RetrieveEntities_Handler,
},
{
MethodName: "AddConnections",
Handler: _ClientsService_AddConnections_Handler,
},
{
MethodName: "RemoveConnections",
Handler: _ClientsService_RemoveConnections_Handler,
},
{
MethodName: "RemoveChannelConnections",
Handler: _ClientsService_RemoveChannelConnections_Handler,
},
{
MethodName: "UnsetParentGroupFromClient",
Handler: _ClientsService_UnsetParentGroupFromClient_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "clients/v1/clients.proto",
}
-691
View File
@@ -1,691 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: common/v1/common.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type RetrieveEntitiesReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RetrieveEntitiesReq) Reset() {
*x = RetrieveEntitiesReq{}
mi := &file_common_v1_common_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RetrieveEntitiesReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RetrieveEntitiesReq) ProtoMessage() {}
func (x *RetrieveEntitiesReq) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RetrieveEntitiesReq.ProtoReflect.Descriptor instead.
func (*RetrieveEntitiesReq) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{0}
}
func (x *RetrieveEntitiesReq) GetIds() []string {
if x != nil {
return x.Ids
}
return nil
}
type RetrieveEntitiesRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"`
Limit uint64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"`
Offset uint64 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"`
Entities []*EntityBasic `protobuf:"bytes,4,rep,name=entities,proto3" json:"entities,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RetrieveEntitiesRes) Reset() {
*x = RetrieveEntitiesRes{}
mi := &file_common_v1_common_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RetrieveEntitiesRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RetrieveEntitiesRes) ProtoMessage() {}
func (x *RetrieveEntitiesRes) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RetrieveEntitiesRes.ProtoReflect.Descriptor instead.
func (*RetrieveEntitiesRes) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{1}
}
func (x *RetrieveEntitiesRes) GetTotal() uint64 {
if x != nil {
return x.Total
}
return 0
}
func (x *RetrieveEntitiesRes) GetLimit() uint64 {
if x != nil {
return x.Limit
}
return 0
}
func (x *RetrieveEntitiesRes) GetOffset() uint64 {
if x != nil {
return x.Offset
}
return 0
}
func (x *RetrieveEntitiesRes) GetEntities() []*EntityBasic {
if x != nil {
return x.Entities
}
return nil
}
type RetrieveEntityReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RetrieveEntityReq) Reset() {
*x = RetrieveEntityReq{}
mi := &file_common_v1_common_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RetrieveEntityReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RetrieveEntityReq) ProtoMessage() {}
func (x *RetrieveEntityReq) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RetrieveEntityReq.ProtoReflect.Descriptor instead.
func (*RetrieveEntityReq) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{2}
}
func (x *RetrieveEntityReq) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type RetrieveEntityRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Entity *EntityBasic `protobuf:"bytes,1,opt,name=entity,proto3" json:"entity,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RetrieveEntityRes) Reset() {
*x = RetrieveEntityRes{}
mi := &file_common_v1_common_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RetrieveEntityRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RetrieveEntityRes) ProtoMessage() {}
func (x *RetrieveEntityRes) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RetrieveEntityRes.ProtoReflect.Descriptor instead.
func (*RetrieveEntityRes) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{3}
}
func (x *RetrieveEntityRes) GetEntity() *EntityBasic {
if x != nil {
return x.Entity
}
return nil
}
type EntityBasic struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
DomainId string `protobuf:"bytes,2,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
ParentGroupId string `protobuf:"bytes,3,opt,name=parent_group_id,json=parentGroupId,proto3" json:"parent_group_id,omitempty"`
Status uint32 `protobuf:"varint,4,opt,name=status,proto3" json:"status,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *EntityBasic) Reset() {
*x = EntityBasic{}
mi := &file_common_v1_common_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *EntityBasic) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EntityBasic) ProtoMessage() {}
func (x *EntityBasic) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use EntityBasic.ProtoReflect.Descriptor instead.
func (*EntityBasic) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{4}
}
func (x *EntityBasic) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *EntityBasic) GetDomainId() string {
if x != nil {
return x.DomainId
}
return ""
}
func (x *EntityBasic) GetParentGroupId() string {
if x != nil {
return x.ParentGroupId
}
return ""
}
func (x *EntityBasic) GetStatus() uint32 {
if x != nil {
return x.Status
}
return 0
}
type AddConnectionsReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Connections []*Connection `protobuf:"bytes,1,rep,name=connections,proto3" json:"connections,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AddConnectionsReq) Reset() {
*x = AddConnectionsReq{}
mi := &file_common_v1_common_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AddConnectionsReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AddConnectionsReq) ProtoMessage() {}
func (x *AddConnectionsReq) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AddConnectionsReq.ProtoReflect.Descriptor instead.
func (*AddConnectionsReq) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{5}
}
func (x *AddConnectionsReq) GetConnections() []*Connection {
if x != nil {
return x.Connections
}
return nil
}
type AddConnectionsRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AddConnectionsRes) Reset() {
*x = AddConnectionsRes{}
mi := &file_common_v1_common_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AddConnectionsRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AddConnectionsRes) ProtoMessage() {}
func (x *AddConnectionsRes) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use AddConnectionsRes.ProtoReflect.Descriptor instead.
func (*AddConnectionsRes) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{6}
}
func (x *AddConnectionsRes) GetOk() bool {
if x != nil {
return x.Ok
}
return false
}
type RemoveConnectionsReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Connections []*Connection `protobuf:"bytes,1,rep,name=connections,proto3" json:"connections,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RemoveConnectionsReq) Reset() {
*x = RemoveConnectionsReq{}
mi := &file_common_v1_common_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RemoveConnectionsReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveConnectionsReq) ProtoMessage() {}
func (x *RemoveConnectionsReq) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RemoveConnectionsReq.ProtoReflect.Descriptor instead.
func (*RemoveConnectionsReq) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{7}
}
func (x *RemoveConnectionsReq) GetConnections() []*Connection {
if x != nil {
return x.Connections
}
return nil
}
type RemoveConnectionsRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RemoveConnectionsRes) Reset() {
*x = RemoveConnectionsRes{}
mi := &file_common_v1_common_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RemoveConnectionsRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RemoveConnectionsRes) ProtoMessage() {}
func (x *RemoveConnectionsRes) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[8]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RemoveConnectionsRes.ProtoReflect.Descriptor instead.
func (*RemoveConnectionsRes) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{8}
}
func (x *RemoveConnectionsRes) GetOk() bool {
if x != nil {
return x.Ok
}
return false
}
type Connection struct {
state protoimpl.MessageState `protogen:"open.v1"`
ClientId string `protobuf:"bytes,1,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
ChannelId string `protobuf:"bytes,2,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
DomainId string `protobuf:"bytes,3,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
Type uint32 `protobuf:"varint,4,opt,name=type,proto3" json:"type,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Connection) Reset() {
*x = Connection{}
mi := &file_common_v1_common_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Connection) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Connection) ProtoMessage() {}
func (x *Connection) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[9]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Connection.ProtoReflect.Descriptor instead.
func (*Connection) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{9}
}
func (x *Connection) GetClientId() string {
if x != nil {
return x.ClientId
}
return ""
}
func (x *Connection) GetChannelId() string {
if x != nil {
return x.ChannelId
}
return ""
}
func (x *Connection) GetDomainId() string {
if x != nil {
return x.DomainId
}
return ""
}
func (x *Connection) GetType() uint32 {
if x != nil {
return x.Type
}
return 0
}
type RetrieveIDByRouteReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Route string `protobuf:"bytes,1,opt,name=route,proto3" json:"route,omitempty"`
DomainId string `protobuf:"bytes,2,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RetrieveIDByRouteReq) Reset() {
*x = RetrieveIDByRouteReq{}
mi := &file_common_v1_common_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RetrieveIDByRouteReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RetrieveIDByRouteReq) ProtoMessage() {}
func (x *RetrieveIDByRouteReq) ProtoReflect() protoreflect.Message {
mi := &file_common_v1_common_proto_msgTypes[10]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RetrieveIDByRouteReq.ProtoReflect.Descriptor instead.
func (*RetrieveIDByRouteReq) Descriptor() ([]byte, []int) {
return file_common_v1_common_proto_rawDescGZIP(), []int{10}
}
func (x *RetrieveIDByRouteReq) GetRoute() string {
if x != nil {
return x.Route
}
return ""
}
func (x *RetrieveIDByRouteReq) GetDomainId() string {
if x != nil {
return x.DomainId
}
return ""
}
var File_common_v1_common_proto protoreflect.FileDescriptor
const file_common_v1_common_proto_rawDesc = "" +
"\n" +
"\x16common/v1/common.proto\x12\tcommon.v1\"'\n" +
"\x13RetrieveEntitiesReq\x12\x10\n" +
"\x03ids\x18\x01 \x03(\tR\x03ids\"\x8d\x01\n" +
"\x13RetrieveEntitiesRes\x12\x14\n" +
"\x05total\x18\x01 \x01(\x04R\x05total\x12\x14\n" +
"\x05limit\x18\x02 \x01(\x04R\x05limit\x12\x16\n" +
"\x06offset\x18\x03 \x01(\x04R\x06offset\x122\n" +
"\bentities\x18\x04 \x03(\v2\x16.common.v1.EntityBasicR\bentities\"#\n" +
"\x11RetrieveEntityReq\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\"C\n" +
"\x11RetrieveEntityRes\x12.\n" +
"\x06entity\x18\x01 \x01(\v2\x16.common.v1.EntityBasicR\x06entity\"z\n" +
"\vEntityBasic\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x1b\n" +
"\tdomain_id\x18\x02 \x01(\tR\bdomainId\x12&\n" +
"\x0fparent_group_id\x18\x03 \x01(\tR\rparentGroupId\x12\x16\n" +
"\x06status\x18\x04 \x01(\rR\x06status\"L\n" +
"\x11AddConnectionsReq\x127\n" +
"\vconnections\x18\x01 \x03(\v2\x15.common.v1.ConnectionR\vconnections\"#\n" +
"\x11AddConnectionsRes\x12\x0e\n" +
"\x02ok\x18\x01 \x01(\bR\x02ok\"O\n" +
"\x14RemoveConnectionsReq\x127\n" +
"\vconnections\x18\x01 \x03(\v2\x15.common.v1.ConnectionR\vconnections\"&\n" +
"\x14RemoveConnectionsRes\x12\x0e\n" +
"\x02ok\x18\x01 \x01(\bR\x02ok\"y\n" +
"\n" +
"Connection\x12\x1b\n" +
"\tclient_id\x18\x01 \x01(\tR\bclientId\x12\x1d\n" +
"\n" +
"channel_id\x18\x02 \x01(\tR\tchannelId\x12\x1b\n" +
"\tdomain_id\x18\x03 \x01(\tR\bdomainId\x12\x12\n" +
"\x04type\x18\x04 \x01(\rR\x04type\"I\n" +
"\x14RetrieveIDByRouteReq\x12\x14\n" +
"\x05route\x18\x01 \x01(\tR\x05route\x12\x1b\n" +
"\tdomain_id\x18\x02 \x01(\tR\bdomainIdB2Z0github.com/absmach/magistrala/api/grpc/common/v1b\x06proto3"
var (
file_common_v1_common_proto_rawDescOnce sync.Once
file_common_v1_common_proto_rawDescData []byte
)
func file_common_v1_common_proto_rawDescGZIP() []byte {
file_common_v1_common_proto_rawDescOnce.Do(func() {
file_common_v1_common_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_common_v1_common_proto_rawDesc), len(file_common_v1_common_proto_rawDesc)))
})
return file_common_v1_common_proto_rawDescData
}
var file_common_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_common_v1_common_proto_goTypes = []any{
(*RetrieveEntitiesReq)(nil), // 0: common.v1.RetrieveEntitiesReq
(*RetrieveEntitiesRes)(nil), // 1: common.v1.RetrieveEntitiesRes
(*RetrieveEntityReq)(nil), // 2: common.v1.RetrieveEntityReq
(*RetrieveEntityRes)(nil), // 3: common.v1.RetrieveEntityRes
(*EntityBasic)(nil), // 4: common.v1.EntityBasic
(*AddConnectionsReq)(nil), // 5: common.v1.AddConnectionsReq
(*AddConnectionsRes)(nil), // 6: common.v1.AddConnectionsRes
(*RemoveConnectionsReq)(nil), // 7: common.v1.RemoveConnectionsReq
(*RemoveConnectionsRes)(nil), // 8: common.v1.RemoveConnectionsRes
(*Connection)(nil), // 9: common.v1.Connection
(*RetrieveIDByRouteReq)(nil), // 10: common.v1.RetrieveIDByRouteReq
}
var file_common_v1_common_proto_depIdxs = []int32{
4, // 0: common.v1.RetrieveEntitiesRes.entities:type_name -> common.v1.EntityBasic
4, // 1: common.v1.RetrieveEntityRes.entity:type_name -> common.v1.EntityBasic
9, // 2: common.v1.AddConnectionsReq.connections:type_name -> common.v1.Connection
9, // 3: common.v1.RemoveConnectionsReq.connections:type_name -> common.v1.Connection
4, // [4:4] is the sub-list for method output_type
4, // [4:4] is the sub-list for method input_type
4, // [4:4] is the sub-list for extension type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
}
func init() { file_common_v1_common_proto_init() }
func file_common_v1_common_proto_init() {
if File_common_v1_common_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_v1_common_proto_rawDesc), len(file_common_v1_common_proto_rawDesc)),
NumEnums: 0,
NumMessages: 11,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_common_v1_common_proto_goTypes,
DependencyIndexes: file_common_v1_common_proto_depIdxs,
MessageInfos: file_common_v1_common_proto_msgTypes,
}.Build()
File_common_v1_common_proto = out.File
file_common_v1_common_proto_goTypes = nil
file_common_v1_common_proto_depIdxs = nil
}
-187
View File
@@ -1,187 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: domains/v1/domains.proto
package v1
import (
v1 "github.com/absmach/magistrala/api/grpc/common/v1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type DeleteUserRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteUserRes) Reset() {
*x = DeleteUserRes{}
mi := &file_domains_v1_domains_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteUserRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteUserRes) ProtoMessage() {}
func (x *DeleteUserRes) ProtoReflect() protoreflect.Message {
mi := &file_domains_v1_domains_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteUserRes.ProtoReflect.Descriptor instead.
func (*DeleteUserRes) Descriptor() ([]byte, []int) {
return file_domains_v1_domains_proto_rawDescGZIP(), []int{0}
}
func (x *DeleteUserRes) GetDeleted() bool {
if x != nil {
return x.Deleted
}
return false
}
type DeleteUserReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteUserReq) Reset() {
*x = DeleteUserReq{}
mi := &file_domains_v1_domains_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteUserReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteUserReq) ProtoMessage() {}
func (x *DeleteUserReq) ProtoReflect() protoreflect.Message {
mi := &file_domains_v1_domains_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteUserReq.ProtoReflect.Descriptor instead.
func (*DeleteUserReq) Descriptor() ([]byte, []int) {
return file_domains_v1_domains_proto_rawDescGZIP(), []int{1}
}
func (x *DeleteUserReq) GetId() string {
if x != nil {
return x.Id
}
return ""
}
var File_domains_v1_domains_proto protoreflect.FileDescriptor
const file_domains_v1_domains_proto_rawDesc = "" +
"\n" +
"\x18domains/v1/domains.proto\x12\n" +
"domains.v1\x1a\x16common/v1/common.proto\")\n" +
"\rDeleteUserRes\x12\x18\n" +
"\adeleted\x18\x01 \x01(\bR\adeleted\"\x1f\n" +
"\rDeleteUserReq\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id2\x87\x02\n" +
"\x0eDomainsService\x12O\n" +
"\x15DeleteUserFromDomains\x12\x19.domains.v1.DeleteUserReq\x1a\x19.domains.v1.DeleteUserRes\"\x00\x12N\n" +
"\x0eRetrieveStatus\x12\x1c.common.v1.RetrieveEntityReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00\x12T\n" +
"\x11RetrieveIDByRoute\x12\x1f.common.v1.RetrieveIDByRouteReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00B8Z6github.com/absmach/magistrala/internal/grpc/domains/v1b\x06proto3"
var (
file_domains_v1_domains_proto_rawDescOnce sync.Once
file_domains_v1_domains_proto_rawDescData []byte
)
func file_domains_v1_domains_proto_rawDescGZIP() []byte {
file_domains_v1_domains_proto_rawDescOnce.Do(func() {
file_domains_v1_domains_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_domains_v1_domains_proto_rawDesc), len(file_domains_v1_domains_proto_rawDesc)))
})
return file_domains_v1_domains_proto_rawDescData
}
var file_domains_v1_domains_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_domains_v1_domains_proto_goTypes = []any{
(*DeleteUserRes)(nil), // 0: domains.v1.DeleteUserRes
(*DeleteUserReq)(nil), // 1: domains.v1.DeleteUserReq
(*v1.RetrieveEntityReq)(nil), // 2: common.v1.RetrieveEntityReq
(*v1.RetrieveIDByRouteReq)(nil), // 3: common.v1.RetrieveIDByRouteReq
(*v1.RetrieveEntityRes)(nil), // 4: common.v1.RetrieveEntityRes
}
var file_domains_v1_domains_proto_depIdxs = []int32{
1, // 0: domains.v1.DomainsService.DeleteUserFromDomains:input_type -> domains.v1.DeleteUserReq
2, // 1: domains.v1.DomainsService.RetrieveStatus:input_type -> common.v1.RetrieveEntityReq
3, // 2: domains.v1.DomainsService.RetrieveIDByRoute:input_type -> common.v1.RetrieveIDByRouteReq
0, // 3: domains.v1.DomainsService.DeleteUserFromDomains:output_type -> domains.v1.DeleteUserRes
4, // 4: domains.v1.DomainsService.RetrieveStatus:output_type -> common.v1.RetrieveEntityRes
4, // 5: domains.v1.DomainsService.RetrieveIDByRoute:output_type -> common.v1.RetrieveEntityRes
3, // [3:6] is the sub-list for method output_type
0, // [0:3] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_domains_v1_domains_proto_init() }
func file_domains_v1_domains_proto_init() {
if File_domains_v1_domains_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_domains_v1_domains_proto_rawDesc), len(file_domains_v1_domains_proto_rawDesc)),
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_domains_v1_domains_proto_goTypes,
DependencyIndexes: file_domains_v1_domains_proto_depIdxs,
MessageInfos: file_domains_v1_domains_proto_msgTypes,
}.Build()
File_domains_v1_domains_proto = out.File
file_domains_v1_domains_proto_goTypes = nil
file_domains_v1_domains_proto_depIdxs = nil
}
-207
View File
@@ -1,207 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.0
// source: domains/v1/domains.proto
package v1
import (
context "context"
v1 "github.com/absmach/magistrala/api/grpc/common/v1"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
DomainsService_DeleteUserFromDomains_FullMethodName = "/domains.v1.DomainsService/DeleteUserFromDomains"
DomainsService_RetrieveStatus_FullMethodName = "/domains.v1.DomainsService/RetrieveStatus"
DomainsService_RetrieveIDByRoute_FullMethodName = "/domains.v1.DomainsService/RetrieveIDByRoute"
)
// DomainsServiceClient is the client API for DomainsService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// DomainsService is a service that provides access to
// domains functionalities for Magistrala services.
type DomainsServiceClient interface {
DeleteUserFromDomains(ctx context.Context, in *DeleteUserReq, opts ...grpc.CallOption) (*DeleteUserRes, error)
RetrieveStatus(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
RetrieveIDByRoute(ctx context.Context, in *v1.RetrieveIDByRouteReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
}
type domainsServiceClient struct {
cc grpc.ClientConnInterface
}
func NewDomainsServiceClient(cc grpc.ClientConnInterface) DomainsServiceClient {
return &domainsServiceClient{cc}
}
func (c *domainsServiceClient) DeleteUserFromDomains(ctx context.Context, in *DeleteUserReq, opts ...grpc.CallOption) (*DeleteUserRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DeleteUserRes)
err := c.cc.Invoke(ctx, DomainsService_DeleteUserFromDomains_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *domainsServiceClient) RetrieveStatus(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntityRes)
err := c.cc.Invoke(ctx, DomainsService_RetrieveStatus_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *domainsServiceClient) RetrieveIDByRoute(ctx context.Context, in *v1.RetrieveIDByRouteReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntityRes)
err := c.cc.Invoke(ctx, DomainsService_RetrieveIDByRoute_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// DomainsServiceServer is the server API for DomainsService service.
// All implementations must embed UnimplementedDomainsServiceServer
// for forward compatibility.
//
// DomainsService is a service that provides access to
// domains functionalities for Magistrala services.
type DomainsServiceServer interface {
DeleteUserFromDomains(context.Context, *DeleteUserReq) (*DeleteUserRes, error)
RetrieveStatus(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error)
RetrieveIDByRoute(context.Context, *v1.RetrieveIDByRouteReq) (*v1.RetrieveEntityRes, error)
mustEmbedUnimplementedDomainsServiceServer()
}
// UnimplementedDomainsServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedDomainsServiceServer struct{}
func (UnimplementedDomainsServiceServer) DeleteUserFromDomains(context.Context, *DeleteUserReq) (*DeleteUserRes, error) {
return nil, status.Error(codes.Unimplemented, "method DeleteUserFromDomains not implemented")
}
func (UnimplementedDomainsServiceServer) RetrieveStatus(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Error(codes.Unimplemented, "method RetrieveStatus not implemented")
}
func (UnimplementedDomainsServiceServer) RetrieveIDByRoute(context.Context, *v1.RetrieveIDByRouteReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Error(codes.Unimplemented, "method RetrieveIDByRoute not implemented")
}
func (UnimplementedDomainsServiceServer) mustEmbedUnimplementedDomainsServiceServer() {}
func (UnimplementedDomainsServiceServer) testEmbeddedByValue() {}
// UnsafeDomainsServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to DomainsServiceServer will
// result in compilation errors.
type UnsafeDomainsServiceServer interface {
mustEmbedUnimplementedDomainsServiceServer()
}
func RegisterDomainsServiceServer(s grpc.ServiceRegistrar, srv DomainsServiceServer) {
// If the following call panics, it indicates UnimplementedDomainsServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&DomainsService_ServiceDesc, srv)
}
func _DomainsService_DeleteUserFromDomains_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteUserReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainsServiceServer).DeleteUserFromDomains(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: DomainsService_DeleteUserFromDomains_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainsServiceServer).DeleteUserFromDomains(ctx, req.(*DeleteUserReq))
}
return interceptor(ctx, in, info, handler)
}
func _DomainsService_RetrieveStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveEntityReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainsServiceServer).RetrieveStatus(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: DomainsService_RetrieveStatus_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainsServiceServer).RetrieveStatus(ctx, req.(*v1.RetrieveEntityReq))
}
return interceptor(ctx, in, info, handler)
}
func _DomainsService_RetrieveIDByRoute_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveIDByRouteReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DomainsServiceServer).RetrieveIDByRoute(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: DomainsService_RetrieveIDByRoute_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DomainsServiceServer).RetrieveIDByRoute(ctx, req.(*v1.RetrieveIDByRouteReq))
}
return interceptor(ctx, in, info, handler)
}
// DomainsService_ServiceDesc is the grpc.ServiceDesc for DomainsService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var DomainsService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "domains.v1.DomainsService",
HandlerType: (*DomainsServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "DeleteUserFromDomains",
Handler: _DomainsService_DeleteUserFromDomains_Handler,
},
{
MethodName: "RetrieveStatus",
Handler: _DomainsService_RetrieveStatus_Handler,
},
{
MethodName: "RetrieveIDByRoute",
Handler: _DomainsService_RetrieveIDByRoute_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "domains/v1/domains.proto",
}
-70
View File
@@ -1,70 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: groups/v1/groups.proto
package v1
import (
v1 "github.com/absmach/magistrala/api/grpc/common/v1"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
var File_groups_v1_groups_proto protoreflect.FileDescriptor
const file_groups_v1_groups_proto_rawDesc = "" +
"\n" +
"\x16groups/v1/groups.proto\x12\tgroups.v1\x1a\x16common/v1/common.proto2_\n" +
"\rGroupsService\x12N\n" +
"\x0eRetrieveEntity\x12\x1c.common.v1.RetrieveEntityReq\x1a\x1c.common.v1.RetrieveEntityRes\"\x00B2Z0github.com/absmach/magistrala/api/grpc/groups/v1b\x06proto3"
var file_groups_v1_groups_proto_goTypes = []any{
(*v1.RetrieveEntityReq)(nil), // 0: common.v1.RetrieveEntityReq
(*v1.RetrieveEntityRes)(nil), // 1: common.v1.RetrieveEntityRes
}
var file_groups_v1_groups_proto_depIdxs = []int32{
0, // 0: groups.v1.GroupsService.RetrieveEntity:input_type -> common.v1.RetrieveEntityReq
1, // 1: groups.v1.GroupsService.RetrieveEntity:output_type -> common.v1.RetrieveEntityRes
1, // [1:2] is the sub-list for method output_type
0, // [0:1] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_groups_v1_groups_proto_init() }
func file_groups_v1_groups_proto_init() {
if File_groups_v1_groups_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_groups_v1_groups_proto_rawDesc), len(file_groups_v1_groups_proto_rawDesc)),
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_groups_v1_groups_proto_goTypes,
DependencyIndexes: file_groups_v1_groups_proto_depIdxs,
}.Build()
File_groups_v1_groups_proto = out.File
file_groups_v1_groups_proto_goTypes = nil
file_groups_v1_groups_proto_depIdxs = nil
}
-131
View File
@@ -1,131 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.0
// source: groups/v1/groups.proto
package v1
import (
context "context"
v1 "github.com/absmach/magistrala/api/grpc/common/v1"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
GroupsService_RetrieveEntity_FullMethodName = "/groups.v1.GroupsService/RetrieveEntity"
)
// GroupsServiceClient is the client API for GroupsService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// GroupssService is a service that provides groups
// functionalities for Magistrala services.
type GroupsServiceClient interface {
RetrieveEntity(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error)
}
type groupsServiceClient struct {
cc grpc.ClientConnInterface
}
func NewGroupsServiceClient(cc grpc.ClientConnInterface) GroupsServiceClient {
return &groupsServiceClient{cc}
}
func (c *groupsServiceClient) RetrieveEntity(ctx context.Context, in *v1.RetrieveEntityReq, opts ...grpc.CallOption) (*v1.RetrieveEntityRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(v1.RetrieveEntityRes)
err := c.cc.Invoke(ctx, GroupsService_RetrieveEntity_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// GroupsServiceServer is the server API for GroupsService service.
// All implementations must embed UnimplementedGroupsServiceServer
// for forward compatibility.
//
// GroupssService is a service that provides groups
// functionalities for Magistrala services.
type GroupsServiceServer interface {
RetrieveEntity(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error)
mustEmbedUnimplementedGroupsServiceServer()
}
// UnimplementedGroupsServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedGroupsServiceServer struct{}
func (UnimplementedGroupsServiceServer) RetrieveEntity(context.Context, *v1.RetrieveEntityReq) (*v1.RetrieveEntityRes, error) {
return nil, status.Error(codes.Unimplemented, "method RetrieveEntity not implemented")
}
func (UnimplementedGroupsServiceServer) mustEmbedUnimplementedGroupsServiceServer() {}
func (UnimplementedGroupsServiceServer) testEmbeddedByValue() {}
// UnsafeGroupsServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to GroupsServiceServer will
// result in compilation errors.
type UnsafeGroupsServiceServer interface {
mustEmbedUnimplementedGroupsServiceServer()
}
func RegisterGroupsServiceServer(s grpc.ServiceRegistrar, srv GroupsServiceServer) {
// If the following call panics, it indicates UnimplementedGroupsServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&GroupsService_ServiceDesc, srv)
}
func _GroupsService_RetrieveEntity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(v1.RetrieveEntityReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(GroupsServiceServer).RetrieveEntity(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: GroupsService_RetrieveEntity_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(GroupsServiceServer).RetrieveEntity(ctx, req.(*v1.RetrieveEntityReq))
}
return interceptor(ctx, in, info, handler)
}
// GroupsService_ServiceDesc is the grpc.ServiceDesc for GroupsService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var GroupsService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "groups.v1.GroupsService",
HandlerType: (*GroupsServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "RetrieveEntity",
Handler: _GroupsService_RetrieveEntity_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "groups/v1/groups.proto",
}
-884
View File
@@ -1,884 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v7.35.1
// source: readers/v1/readers.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Aggregation defines supported data aggregations.
type Aggregation int32
const (
Aggregation_AGGREGATION_UNSPECIFIED Aggregation = 0
Aggregation_AGGREGATION_MAX Aggregation = 1
Aggregation_AGGREGATION_MIN Aggregation = 2
Aggregation_AGGREGATION_SUM Aggregation = 3
Aggregation_AGGREGATION_COUNT Aggregation = 4
Aggregation_AGGREGATION_AVG Aggregation = 5
)
// Enum value maps for Aggregation.
var (
Aggregation_name = map[int32]string{
0: "AGGREGATION_UNSPECIFIED",
1: "AGGREGATION_MAX",
2: "AGGREGATION_MIN",
3: "AGGREGATION_SUM",
4: "AGGREGATION_COUNT",
5: "AGGREGATION_AVG",
}
Aggregation_value = map[string]int32{
"AGGREGATION_UNSPECIFIED": 0,
"AGGREGATION_MAX": 1,
"AGGREGATION_MIN": 2,
"AGGREGATION_SUM": 3,
"AGGREGATION_COUNT": 4,
"AGGREGATION_AVG": 5,
}
)
func (x Aggregation) Enum() *Aggregation {
p := new(Aggregation)
*p = x
return p
}
func (x Aggregation) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Aggregation) Descriptor() protoreflect.EnumDescriptor {
return file_readers_v1_readers_proto_enumTypes[0].Descriptor()
}
func (Aggregation) Type() protoreflect.EnumType {
return &file_readers_v1_readers_proto_enumTypes[0]
}
func (x Aggregation) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Aggregation.Descriptor instead.
func (Aggregation) EnumDescriptor() ([]byte, []int) {
return file_readers_v1_readers_proto_rawDescGZIP(), []int{0}
}
type PageMetadata struct {
state protoimpl.MessageState `protogen:"open.v1"`
Limit uint64 `protobuf:"varint,1,opt,name=limit,proto3" json:"limit,omitempty"`
Offset uint64 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
Protocol string `protobuf:"bytes,3,opt,name=protocol,proto3" json:"protocol,omitempty"`
Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"`
Value float64 `protobuf:"fixed64,5,opt,name=value,proto3" json:"value,omitempty"`
Publisher string `protobuf:"bytes,6,opt,name=publisher,proto3" json:"publisher,omitempty"`
BoolValue bool `protobuf:"varint,7,opt,name=bool_value,json=boolValue,proto3" json:"bool_value,omitempty"`
StringValue string `protobuf:"bytes,8,opt,name=string_value,json=stringValue,proto3" json:"string_value,omitempty"`
DataValue string `protobuf:"bytes,9,opt,name=data_value,json=dataValue,proto3" json:"data_value,omitempty"`
From float64 `protobuf:"fixed64,10,opt,name=from,proto3" json:"from,omitempty"`
To float64 `protobuf:"fixed64,11,opt,name=to,proto3" json:"to,omitempty"`
Subtopic string `protobuf:"bytes,12,opt,name=subtopic,proto3" json:"subtopic,omitempty"`
Interval string `protobuf:"bytes,13,opt,name=interval,proto3" json:"interval,omitempty"`
Read bool `protobuf:"varint,14,opt,name=read,proto3" json:"read,omitempty"`
Aggregation Aggregation `protobuf:"varint,15,opt,name=aggregation,proto3,enum=readers.v1.Aggregation" json:"aggregation,omitempty"`
Comparator string `protobuf:"bytes,16,opt,name=comparator,proto3" json:"comparator,omitempty"`
Format string `protobuf:"bytes,17,opt,name=format,proto3" json:"format,omitempty"`
Order string `protobuf:"bytes,18,opt,name=order,proto3" json:"order,omitempty"`
Dir string `protobuf:"bytes,19,opt,name=dir,proto3" json:"dir,omitempty"`
Publishers []string `protobuf:"bytes,20,rep,name=publishers,proto3" json:"publishers,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *PageMetadata) Reset() {
*x = PageMetadata{}
mi := &file_readers_v1_readers_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *PageMetadata) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*PageMetadata) ProtoMessage() {}
func (x *PageMetadata) ProtoReflect() protoreflect.Message {
mi := &file_readers_v1_readers_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use PageMetadata.ProtoReflect.Descriptor instead.
func (*PageMetadata) Descriptor() ([]byte, []int) {
return file_readers_v1_readers_proto_rawDescGZIP(), []int{0}
}
func (x *PageMetadata) GetLimit() uint64 {
if x != nil {
return x.Limit
}
return 0
}
func (x *PageMetadata) GetOffset() uint64 {
if x != nil {
return x.Offset
}
return 0
}
func (x *PageMetadata) GetProtocol() string {
if x != nil {
return x.Protocol
}
return ""
}
func (x *PageMetadata) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *PageMetadata) GetValue() float64 {
if x != nil {
return x.Value
}
return 0
}
func (x *PageMetadata) GetPublisher() string {
if x != nil {
return x.Publisher
}
return ""
}
func (x *PageMetadata) GetBoolValue() bool {
if x != nil {
return x.BoolValue
}
return false
}
func (x *PageMetadata) GetStringValue() string {
if x != nil {
return x.StringValue
}
return ""
}
func (x *PageMetadata) GetDataValue() string {
if x != nil {
return x.DataValue
}
return ""
}
func (x *PageMetadata) GetFrom() float64 {
if x != nil {
return x.From
}
return 0
}
func (x *PageMetadata) GetTo() float64 {
if x != nil {
return x.To
}
return 0
}
func (x *PageMetadata) GetSubtopic() string {
if x != nil {
return x.Subtopic
}
return ""
}
func (x *PageMetadata) GetInterval() string {
if x != nil {
return x.Interval
}
return ""
}
func (x *PageMetadata) GetRead() bool {
if x != nil {
return x.Read
}
return false
}
func (x *PageMetadata) GetAggregation() Aggregation {
if x != nil {
return x.Aggregation
}
return Aggregation_AGGREGATION_UNSPECIFIED
}
func (x *PageMetadata) GetComparator() string {
if x != nil {
return x.Comparator
}
return ""
}
func (x *PageMetadata) GetFormat() string {
if x != nil {
return x.Format
}
return ""
}
func (x *PageMetadata) GetOrder() string {
if x != nil {
return x.Order
}
return ""
}
func (x *PageMetadata) GetDir() string {
if x != nil {
return x.Dir
}
return ""
}
func (x *PageMetadata) GetPublishers() []string {
if x != nil {
return x.Publishers
}
return nil
}
type ReadMessagesRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"`
PageMetadata *PageMetadata `protobuf:"bytes,2,opt,name=page_metadata,json=pageMetadata,proto3" json:"page_metadata,omitempty"`
Messages []*Message `protobuf:"bytes,3,rep,name=messages,proto3" json:"messages,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ReadMessagesRes) Reset() {
*x = ReadMessagesRes{}
mi := &file_readers_v1_readers_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ReadMessagesRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ReadMessagesRes) ProtoMessage() {}
func (x *ReadMessagesRes) ProtoReflect() protoreflect.Message {
mi := &file_readers_v1_readers_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ReadMessagesRes.ProtoReflect.Descriptor instead.
func (*ReadMessagesRes) Descriptor() ([]byte, []int) {
return file_readers_v1_readers_proto_rawDescGZIP(), []int{1}
}
func (x *ReadMessagesRes) GetTotal() uint64 {
if x != nil {
return x.Total
}
return 0
}
func (x *ReadMessagesRes) GetPageMetadata() *PageMetadata {
if x != nil {
return x.PageMetadata
}
return nil
}
func (x *ReadMessagesRes) GetMessages() []*Message {
if x != nil {
return x.Messages
}
return nil
}
type Message struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Types that are valid to be assigned to Payload:
//
// *Message_Senml
// *Message_Json
Payload isMessage_Payload `protobuf_oneof:"payload"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Message) Reset() {
*x = Message{}
mi := &file_readers_v1_readers_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Message) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Message) ProtoMessage() {}
func (x *Message) ProtoReflect() protoreflect.Message {
mi := &file_readers_v1_readers_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Message.ProtoReflect.Descriptor instead.
func (*Message) Descriptor() ([]byte, []int) {
return file_readers_v1_readers_proto_rawDescGZIP(), []int{2}
}
func (x *Message) GetPayload() isMessage_Payload {
if x != nil {
return x.Payload
}
return nil
}
func (x *Message) GetSenml() *SenMLMessage {
if x != nil {
if x, ok := x.Payload.(*Message_Senml); ok {
return x.Senml
}
}
return nil
}
func (x *Message) GetJson() *JsonMessage {
if x != nil {
if x, ok := x.Payload.(*Message_Json); ok {
return x.Json
}
}
return nil
}
type isMessage_Payload interface {
isMessage_Payload()
}
type Message_Senml struct {
Senml *SenMLMessage `protobuf:"bytes,1,opt,name=senml,proto3,oneof"`
}
type Message_Json struct {
Json *JsonMessage `protobuf:"bytes,2,opt,name=json,proto3,oneof"`
}
func (*Message_Senml) isMessage_Payload() {}
func (*Message_Json) isMessage_Payload() {}
type BaseMessage struct {
state protoimpl.MessageState `protogen:"open.v1"`
Channel string `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"`
Subtopic string `protobuf:"bytes,2,opt,name=subtopic,proto3" json:"subtopic,omitempty"`
Publisher string `protobuf:"bytes,3,opt,name=publisher,proto3" json:"publisher,omitempty"`
Protocol string `protobuf:"bytes,4,opt,name=protocol,proto3" json:"protocol,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *BaseMessage) Reset() {
*x = BaseMessage{}
mi := &file_readers_v1_readers_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *BaseMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*BaseMessage) ProtoMessage() {}
func (x *BaseMessage) ProtoReflect() protoreflect.Message {
mi := &file_readers_v1_readers_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use BaseMessage.ProtoReflect.Descriptor instead.
func (*BaseMessage) Descriptor() ([]byte, []int) {
return file_readers_v1_readers_proto_rawDescGZIP(), []int{3}
}
func (x *BaseMessage) GetChannel() string {
if x != nil {
return x.Channel
}
return ""
}
func (x *BaseMessage) GetSubtopic() string {
if x != nil {
return x.Subtopic
}
return ""
}
func (x *BaseMessage) GetPublisher() string {
if x != nil {
return x.Publisher
}
return ""
}
func (x *BaseMessage) GetProtocol() string {
if x != nil {
return x.Protocol
}
return ""
}
type SenMLMessage struct {
state protoimpl.MessageState `protogen:"open.v1"`
Base *BaseMessage `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Unit string `protobuf:"bytes,3,opt,name=unit,proto3" json:"unit,omitempty"`
Time float64 `protobuf:"fixed64,4,opt,name=time,proto3" json:"time,omitempty"`
UpdateTime float64 `protobuf:"fixed64,5,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty"`
Value *float64 `protobuf:"fixed64,6,opt,name=value,proto3,oneof" json:"value,omitempty"`
StringValue *string `protobuf:"bytes,7,opt,name=string_value,json=stringValue,proto3,oneof" json:"string_value,omitempty"`
DataValue *string `protobuf:"bytes,8,opt,name=data_value,json=dataValue,proto3,oneof" json:"data_value,omitempty"`
BoolValue *bool `protobuf:"varint,9,opt,name=bool_value,json=boolValue,proto3,oneof" json:"bool_value,omitempty"`
Sum *float64 `protobuf:"fixed64,10,opt,name=sum,proto3,oneof" json:"sum,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SenMLMessage) Reset() {
*x = SenMLMessage{}
mi := &file_readers_v1_readers_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SenMLMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SenMLMessage) ProtoMessage() {}
func (x *SenMLMessage) ProtoReflect() protoreflect.Message {
mi := &file_readers_v1_readers_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SenMLMessage.ProtoReflect.Descriptor instead.
func (*SenMLMessage) Descriptor() ([]byte, []int) {
return file_readers_v1_readers_proto_rawDescGZIP(), []int{4}
}
func (x *SenMLMessage) GetBase() *BaseMessage {
if x != nil {
return x.Base
}
return nil
}
func (x *SenMLMessage) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *SenMLMessage) GetUnit() string {
if x != nil {
return x.Unit
}
return ""
}
func (x *SenMLMessage) GetTime() float64 {
if x != nil {
return x.Time
}
return 0
}
func (x *SenMLMessage) GetUpdateTime() float64 {
if x != nil {
return x.UpdateTime
}
return 0
}
func (x *SenMLMessage) GetValue() float64 {
if x != nil && x.Value != nil {
return *x.Value
}
return 0
}
func (x *SenMLMessage) GetStringValue() string {
if x != nil && x.StringValue != nil {
return *x.StringValue
}
return ""
}
func (x *SenMLMessage) GetDataValue() string {
if x != nil && x.DataValue != nil {
return *x.DataValue
}
return ""
}
func (x *SenMLMessage) GetBoolValue() bool {
if x != nil && x.BoolValue != nil {
return *x.BoolValue
}
return false
}
func (x *SenMLMessage) GetSum() float64 {
if x != nil && x.Sum != nil {
return *x.Sum
}
return 0
}
type JsonMessage struct {
state protoimpl.MessageState `protogen:"open.v1"`
Base *BaseMessage `protobuf:"bytes,1,opt,name=base,proto3" json:"base,omitempty"`
Created int64 `protobuf:"varint,2,opt,name=created,proto3" json:"created,omitempty"`
Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *JsonMessage) Reset() {
*x = JsonMessage{}
mi := &file_readers_v1_readers_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *JsonMessage) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*JsonMessage) ProtoMessage() {}
func (x *JsonMessage) ProtoReflect() protoreflect.Message {
mi := &file_readers_v1_readers_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use JsonMessage.ProtoReflect.Descriptor instead.
func (*JsonMessage) Descriptor() ([]byte, []int) {
return file_readers_v1_readers_proto_rawDescGZIP(), []int{5}
}
func (x *JsonMessage) GetBase() *BaseMessage {
if x != nil {
return x.Base
}
return nil
}
func (x *JsonMessage) GetCreated() int64 {
if x != nil {
return x.Created
}
return 0
}
func (x *JsonMessage) GetPayload() []byte {
if x != nil {
return x.Payload
}
return nil
}
type ReadMessagesReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
ChannelId string `protobuf:"bytes,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
DomainId string `protobuf:"bytes,2,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"`
PageMetadata *PageMetadata `protobuf:"bytes,3,opt,name=page_metadata,json=pageMetadata,proto3" json:"page_metadata,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ReadMessagesReq) Reset() {
*x = ReadMessagesReq{}
mi := &file_readers_v1_readers_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ReadMessagesReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ReadMessagesReq) ProtoMessage() {}
func (x *ReadMessagesReq) ProtoReflect() protoreflect.Message {
mi := &file_readers_v1_readers_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ReadMessagesReq.ProtoReflect.Descriptor instead.
func (*ReadMessagesReq) Descriptor() ([]byte, []int) {
return file_readers_v1_readers_proto_rawDescGZIP(), []int{6}
}
func (x *ReadMessagesReq) GetChannelId() string {
if x != nil {
return x.ChannelId
}
return ""
}
func (x *ReadMessagesReq) GetDomainId() string {
if x != nil {
return x.DomainId
}
return ""
}
func (x *ReadMessagesReq) GetPageMetadata() *PageMetadata {
if x != nil {
return x.PageMetadata
}
return nil
}
var File_readers_v1_readers_proto protoreflect.FileDescriptor
const file_readers_v1_readers_proto_rawDesc = "" +
"\n" +
"\x18readers/v1/readers.proto\x12\n" +
"readers.v1\"\xac\x04\n" +
"\fPageMetadata\x12\x14\n" +
"\x05limit\x18\x01 \x01(\x04R\x05limit\x12\x16\n" +
"\x06offset\x18\x02 \x01(\x04R\x06offset\x12\x1a\n" +
"\bprotocol\x18\x03 \x01(\tR\bprotocol\x12\x12\n" +
"\x04name\x18\x04 \x01(\tR\x04name\x12\x14\n" +
"\x05value\x18\x05 \x01(\x01R\x05value\x12\x1c\n" +
"\tpublisher\x18\x06 \x01(\tR\tpublisher\x12\x1d\n" +
"\n" +
"bool_value\x18\a \x01(\bR\tboolValue\x12!\n" +
"\fstring_value\x18\b \x01(\tR\vstringValue\x12\x1d\n" +
"\n" +
"data_value\x18\t \x01(\tR\tdataValue\x12\x12\n" +
"\x04from\x18\n" +
" \x01(\x01R\x04from\x12\x0e\n" +
"\x02to\x18\v \x01(\x01R\x02to\x12\x1a\n" +
"\bsubtopic\x18\f \x01(\tR\bsubtopic\x12\x1a\n" +
"\binterval\x18\r \x01(\tR\binterval\x12\x12\n" +
"\x04read\x18\x0e \x01(\bR\x04read\x129\n" +
"\vaggregation\x18\x0f \x01(\x0e2\x17.readers.v1.AggregationR\vaggregation\x12\x1e\n" +
"\n" +
"comparator\x18\x10 \x01(\tR\n" +
"comparator\x12\x16\n" +
"\x06format\x18\x11 \x01(\tR\x06format\x12\x14\n" +
"\x05order\x18\x12 \x01(\tR\x05order\x12\x10\n" +
"\x03dir\x18\x13 \x01(\tR\x03dir\x12\x1e\n" +
"\n" +
"publishers\x18\x14 \x03(\tR\n" +
"publishers\"\x97\x01\n" +
"\x0fReadMessagesRes\x12\x14\n" +
"\x05total\x18\x01 \x01(\x04R\x05total\x12=\n" +
"\rpage_metadata\x18\x02 \x01(\v2\x18.readers.v1.PageMetadataR\fpageMetadata\x12/\n" +
"\bmessages\x18\x03 \x03(\v2\x13.readers.v1.MessageR\bmessages\"u\n" +
"\aMessage\x120\n" +
"\x05senml\x18\x01 \x01(\v2\x18.readers.v1.SenMLMessageH\x00R\x05senml\x12-\n" +
"\x04json\x18\x02 \x01(\v2\x17.readers.v1.JsonMessageH\x00R\x04jsonB\t\n" +
"\apayload\"}\n" +
"\vBaseMessage\x12\x18\n" +
"\achannel\x18\x01 \x01(\tR\achannel\x12\x1a\n" +
"\bsubtopic\x18\x02 \x01(\tR\bsubtopic\x12\x1c\n" +
"\tpublisher\x18\x03 \x01(\tR\tpublisher\x12\x1a\n" +
"\bprotocol\x18\x04 \x01(\tR\bprotocol\"\xfb\x02\n" +
"\fSenMLMessage\x12+\n" +
"\x04base\x18\x01 \x01(\v2\x17.readers.v1.BaseMessageR\x04base\x12\x12\n" +
"\x04name\x18\x02 \x01(\tR\x04name\x12\x12\n" +
"\x04unit\x18\x03 \x01(\tR\x04unit\x12\x12\n" +
"\x04time\x18\x04 \x01(\x01R\x04time\x12\x1f\n" +
"\vupdate_time\x18\x05 \x01(\x01R\n" +
"updateTime\x12\x19\n" +
"\x05value\x18\x06 \x01(\x01H\x00R\x05value\x88\x01\x01\x12&\n" +
"\fstring_value\x18\a \x01(\tH\x01R\vstringValue\x88\x01\x01\x12\"\n" +
"\n" +
"data_value\x18\b \x01(\tH\x02R\tdataValue\x88\x01\x01\x12\"\n" +
"\n" +
"bool_value\x18\t \x01(\bH\x03R\tboolValue\x88\x01\x01\x12\x15\n" +
"\x03sum\x18\n" +
" \x01(\x01H\x04R\x03sum\x88\x01\x01B\b\n" +
"\x06_valueB\x0f\n" +
"\r_string_valueB\r\n" +
"\v_data_valueB\r\n" +
"\v_bool_valueB\x06\n" +
"\x04_sum\"n\n" +
"\vJsonMessage\x12+\n" +
"\x04base\x18\x01 \x01(\v2\x17.readers.v1.BaseMessageR\x04base\x12\x18\n" +
"\acreated\x18\x02 \x01(\x03R\acreated\x12\x18\n" +
"\apayload\x18\x03 \x01(\fR\apayload\"\x8c\x01\n" +
"\x0fReadMessagesReq\x12\x1d\n" +
"\n" +
"channel_id\x18\x01 \x01(\tR\tchannelId\x12\x1b\n" +
"\tdomain_id\x18\x02 \x01(\tR\bdomainId\x12=\n" +
"\rpage_metadata\x18\x03 \x01(\v2\x18.readers.v1.PageMetadataR\fpageMetadata*\x95\x01\n" +
"\vAggregation\x12\x1b\n" +
"\x17AGGREGATION_UNSPECIFIED\x10\x00\x12\x13\n" +
"\x0fAGGREGATION_MAX\x10\x01\x12\x13\n" +
"\x0fAGGREGATION_MIN\x10\x02\x12\x13\n" +
"\x0fAGGREGATION_SUM\x10\x03\x12\x15\n" +
"\x11AGGREGATION_COUNT\x10\x04\x12\x13\n" +
"\x0fAGGREGATION_AVG\x10\x052\\\n" +
"\x0eReadersService\x12J\n" +
"\fReadMessages\x12\x1b.readers.v1.ReadMessagesReq\x1a\x1b.readers.v1.ReadMessagesRes\"\x00B3Z1github.com/absmach/magistrala/api/grpc/readers/v1b\x06proto3"
var (
file_readers_v1_readers_proto_rawDescOnce sync.Once
file_readers_v1_readers_proto_rawDescData []byte
)
func file_readers_v1_readers_proto_rawDescGZIP() []byte {
file_readers_v1_readers_proto_rawDescOnce.Do(func() {
file_readers_v1_readers_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_readers_v1_readers_proto_rawDesc), len(file_readers_v1_readers_proto_rawDesc)))
})
return file_readers_v1_readers_proto_rawDescData
}
var file_readers_v1_readers_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_readers_v1_readers_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_readers_v1_readers_proto_goTypes = []any{
(Aggregation)(0), // 0: readers.v1.Aggregation
(*PageMetadata)(nil), // 1: readers.v1.PageMetadata
(*ReadMessagesRes)(nil), // 2: readers.v1.ReadMessagesRes
(*Message)(nil), // 3: readers.v1.Message
(*BaseMessage)(nil), // 4: readers.v1.BaseMessage
(*SenMLMessage)(nil), // 5: readers.v1.SenMLMessage
(*JsonMessage)(nil), // 6: readers.v1.JsonMessage
(*ReadMessagesReq)(nil), // 7: readers.v1.ReadMessagesReq
}
var file_readers_v1_readers_proto_depIdxs = []int32{
0, // 0: readers.v1.PageMetadata.aggregation:type_name -> readers.v1.Aggregation
1, // 1: readers.v1.ReadMessagesRes.page_metadata:type_name -> readers.v1.PageMetadata
3, // 2: readers.v1.ReadMessagesRes.messages:type_name -> readers.v1.Message
5, // 3: readers.v1.Message.senml:type_name -> readers.v1.SenMLMessage
6, // 4: readers.v1.Message.json:type_name -> readers.v1.JsonMessage
4, // 5: readers.v1.SenMLMessage.base:type_name -> readers.v1.BaseMessage
4, // 6: readers.v1.JsonMessage.base:type_name -> readers.v1.BaseMessage
1, // 7: readers.v1.ReadMessagesReq.page_metadata:type_name -> readers.v1.PageMetadata
7, // 8: readers.v1.ReadersService.ReadMessages:input_type -> readers.v1.ReadMessagesReq
2, // 9: readers.v1.ReadersService.ReadMessages:output_type -> readers.v1.ReadMessagesRes
9, // [9:10] is the sub-list for method output_type
8, // [8:9] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_readers_v1_readers_proto_init() }
func file_readers_v1_readers_proto_init() {
if File_readers_v1_readers_proto != nil {
return
}
file_readers_v1_readers_proto_msgTypes[2].OneofWrappers = []any{
(*Message_Senml)(nil),
(*Message_Json)(nil),
}
file_readers_v1_readers_proto_msgTypes[4].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_readers_v1_readers_proto_rawDesc), len(file_readers_v1_readers_proto_rawDesc)),
NumEnums: 1,
NumMessages: 7,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_readers_v1_readers_proto_goTypes,
DependencyIndexes: file_readers_v1_readers_proto_depIdxs,
EnumInfos: file_readers_v1_readers_proto_enumTypes,
MessageInfos: file_readers_v1_readers_proto_msgTypes,
}.Build()
File_readers_v1_readers_proto = out.File
file_readers_v1_readers_proto_goTypes = nil
file_readers_v1_readers_proto_depIdxs = nil
}
-130
View File
@@ -1,130 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.0
// source: readers/v1/readers.proto
package v1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
ReadersService_ReadMessages_FullMethodName = "/readers.v1.ReadersService/ReadMessages"
)
// ReadersServiceClient is the client API for ReadersService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// ReadersService is a service that provides access to
// readers functionalities for Magistrala services.
type ReadersServiceClient interface {
ReadMessages(ctx context.Context, in *ReadMessagesReq, opts ...grpc.CallOption) (*ReadMessagesRes, error)
}
type readersServiceClient struct {
cc grpc.ClientConnInterface
}
func NewReadersServiceClient(cc grpc.ClientConnInterface) ReadersServiceClient {
return &readersServiceClient{cc}
}
func (c *readersServiceClient) ReadMessages(ctx context.Context, in *ReadMessagesReq, opts ...grpc.CallOption) (*ReadMessagesRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ReadMessagesRes)
err := c.cc.Invoke(ctx, ReadersService_ReadMessages_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ReadersServiceServer is the server API for ReadersService service.
// All implementations must embed UnimplementedReadersServiceServer
// for forward compatibility.
//
// ReadersService is a service that provides access to
// readers functionalities for Magistrala services.
type ReadersServiceServer interface {
ReadMessages(context.Context, *ReadMessagesReq) (*ReadMessagesRes, error)
mustEmbedUnimplementedReadersServiceServer()
}
// UnimplementedReadersServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedReadersServiceServer struct{}
func (UnimplementedReadersServiceServer) ReadMessages(context.Context, *ReadMessagesReq) (*ReadMessagesRes, error) {
return nil, status.Error(codes.Unimplemented, "method ReadMessages not implemented")
}
func (UnimplementedReadersServiceServer) mustEmbedUnimplementedReadersServiceServer() {}
func (UnimplementedReadersServiceServer) testEmbeddedByValue() {}
// UnsafeReadersServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ReadersServiceServer will
// result in compilation errors.
type UnsafeReadersServiceServer interface {
mustEmbedUnimplementedReadersServiceServer()
}
func RegisterReadersServiceServer(s grpc.ServiceRegistrar, srv ReadersServiceServer) {
// If the following call panics, it indicates UnimplementedReadersServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&ReadersService_ServiceDesc, srv)
}
func _ReadersService_ReadMessages_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ReadMessagesReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ReadersServiceServer).ReadMessages(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ReadersService_ReadMessages_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ReadersServiceServer).ReadMessages(ctx, req.(*ReadMessagesReq))
}
return interceptor(ctx, in, info, handler)
}
// ReadersService_ServiceDesc is the grpc.ServiceDesc for ReadersService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ReadersService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "readers.v1.ReadersService",
HandlerType: (*ReadersServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ReadMessages",
Handler: _ReadersService_ReadMessages_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "readers/v1/readers.proto",
}
-547
View File
@@ -1,547 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: token/v1/token.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type IssueReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
UserRole uint32 `protobuf:"varint,2,opt,name=user_role,json=userRole,proto3" json:"user_role,omitempty"`
Type uint32 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"`
Verified bool `protobuf:"varint,4,opt,name=verified,proto3" json:"verified,omitempty"`
Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *IssueReq) Reset() {
*x = IssueReq{}
mi := &file_token_v1_token_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *IssueReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*IssueReq) ProtoMessage() {}
func (x *IssueReq) ProtoReflect() protoreflect.Message {
mi := &file_token_v1_token_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use IssueReq.ProtoReflect.Descriptor instead.
func (*IssueReq) Descriptor() ([]byte, []int) {
return file_token_v1_token_proto_rawDescGZIP(), []int{0}
}
func (x *IssueReq) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *IssueReq) GetUserRole() uint32 {
if x != nil {
return x.UserRole
}
return 0
}
func (x *IssueReq) GetType() uint32 {
if x != nil {
return x.Type
}
return 0
}
func (x *IssueReq) GetVerified() bool {
if x != nil {
return x.Verified
}
return false
}
func (x *IssueReq) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
type RefreshReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
Verified bool `protobuf:"varint,2,opt,name=verified,proto3" json:"verified,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RefreshReq) Reset() {
*x = RefreshReq{}
mi := &file_token_v1_token_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RefreshReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RefreshReq) ProtoMessage() {}
func (x *RefreshReq) ProtoReflect() protoreflect.Message {
mi := &file_token_v1_token_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RefreshReq.ProtoReflect.Descriptor instead.
func (*RefreshReq) Descriptor() ([]byte, []int) {
return file_token_v1_token_proto_rawDescGZIP(), []int{1}
}
func (x *RefreshReq) GetRefreshToken() string {
if x != nil {
return x.RefreshToken
}
return ""
}
func (x *RefreshReq) GetVerified() bool {
if x != nil {
return x.Verified
}
return false
}
type RevokeReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
TokenId string `protobuf:"bytes,1,opt,name=token_id,json=tokenId,proto3" json:"token_id,omitempty"`
UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RevokeReq) Reset() {
*x = RevokeReq{}
mi := &file_token_v1_token_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RevokeReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RevokeReq) ProtoMessage() {}
func (x *RevokeReq) ProtoReflect() protoreflect.Message {
mi := &file_token_v1_token_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RevokeReq.ProtoReflect.Descriptor instead.
func (*RevokeReq) Descriptor() ([]byte, []int) {
return file_token_v1_token_proto_rawDescGZIP(), []int{2}
}
func (x *RevokeReq) GetTokenId() string {
if x != nil {
return x.TokenId
}
return ""
}
func (x *RevokeReq) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
// If a token is not carrying any information itself, the type
// field can be used to determine how to validate the token.
// Also, different tokens can be encoded in different ways.
type Token struct {
state protoimpl.MessageState `protogen:"open.v1"`
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
RefreshToken *string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3,oneof" json:"refresh_token,omitempty"`
AccessType string `protobuf:"bytes,3,opt,name=access_type,json=accessType,proto3" json:"access_type,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Token) Reset() {
*x = Token{}
mi := &file_token_v1_token_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Token) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Token) ProtoMessage() {}
func (x *Token) ProtoReflect() protoreflect.Message {
mi := &file_token_v1_token_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Token.ProtoReflect.Descriptor instead.
func (*Token) Descriptor() ([]byte, []int) {
return file_token_v1_token_proto_rawDescGZIP(), []int{3}
}
func (x *Token) GetAccessToken() string {
if x != nil {
return x.AccessToken
}
return ""
}
func (x *Token) GetRefreshToken() string {
if x != nil && x.RefreshToken != nil {
return *x.RefreshToken
}
return ""
}
func (x *Token) GetAccessType() string {
if x != nil {
return x.AccessType
}
return ""
}
type RevokeRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RevokeRes) Reset() {
*x = RevokeRes{}
mi := &file_token_v1_token_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RevokeRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RevokeRes) ProtoMessage() {}
func (x *RevokeRes) ProtoReflect() protoreflect.Message {
mi := &file_token_v1_token_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RevokeRes.ProtoReflect.Descriptor instead.
func (*RevokeRes) Descriptor() ([]byte, []int) {
return file_token_v1_token_proto_rawDescGZIP(), []int{4}
}
type ListUserRefreshTokensReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListUserRefreshTokensReq) Reset() {
*x = ListUserRefreshTokensReq{}
mi := &file_token_v1_token_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListUserRefreshTokensReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListUserRefreshTokensReq) ProtoMessage() {}
func (x *ListUserRefreshTokensReq) ProtoReflect() protoreflect.Message {
mi := &file_token_v1_token_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListUserRefreshTokensReq.ProtoReflect.Descriptor instead.
func (*ListUserRefreshTokensReq) Descriptor() ([]byte, []int) {
return file_token_v1_token_proto_rawDescGZIP(), []int{5}
}
func (x *ListUserRefreshTokensReq) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
type ListUserRefreshTokensRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
RefreshTokens []*RefreshToken `protobuf:"bytes,1,rep,name=refresh_tokens,json=refreshTokens,proto3" json:"refresh_tokens,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListUserRefreshTokensRes) Reset() {
*x = ListUserRefreshTokensRes{}
mi := &file_token_v1_token_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListUserRefreshTokensRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListUserRefreshTokensRes) ProtoMessage() {}
func (x *ListUserRefreshTokensRes) ProtoReflect() protoreflect.Message {
mi := &file_token_v1_token_proto_msgTypes[6]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListUserRefreshTokensRes.ProtoReflect.Descriptor instead.
func (*ListUserRefreshTokensRes) Descriptor() ([]byte, []int) {
return file_token_v1_token_proto_rawDescGZIP(), []int{6}
}
func (x *ListUserRefreshTokensRes) GetRefreshTokens() []*RefreshToken {
if x != nil {
return x.RefreshTokens
}
return nil
}
type RefreshToken struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RefreshToken) Reset() {
*x = RefreshToken{}
mi := &file_token_v1_token_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RefreshToken) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RefreshToken) ProtoMessage() {}
func (x *RefreshToken) ProtoReflect() protoreflect.Message {
mi := &file_token_v1_token_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RefreshToken.ProtoReflect.Descriptor instead.
func (*RefreshToken) Descriptor() ([]byte, []int) {
return file_token_v1_token_proto_rawDescGZIP(), []int{7}
}
func (x *RefreshToken) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *RefreshToken) GetDescription() string {
if x != nil {
return x.Description
}
return ""
}
var File_token_v1_token_proto protoreflect.FileDescriptor
const file_token_v1_token_proto_rawDesc = "" +
"\n" +
"\x14token/v1/token.proto\x12\btoken.v1\"\x92\x01\n" +
"\bIssueReq\x12\x17\n" +
"\auser_id\x18\x01 \x01(\tR\x06userId\x12\x1b\n" +
"\tuser_role\x18\x02 \x01(\rR\buserRole\x12\x12\n" +
"\x04type\x18\x03 \x01(\rR\x04type\x12\x1a\n" +
"\bverified\x18\x04 \x01(\bR\bverified\x12 \n" +
"\vdescription\x18\x05 \x01(\tR\vdescription\"M\n" +
"\n" +
"RefreshReq\x12#\n" +
"\rrefresh_token\x18\x01 \x01(\tR\frefreshToken\x12\x1a\n" +
"\bverified\x18\x02 \x01(\bR\bverified\"?\n" +
"\tRevokeReq\x12\x19\n" +
"\btoken_id\x18\x01 \x01(\tR\atokenId\x12\x17\n" +
"\auser_id\x18\x02 \x01(\tR\x06userId\"\x87\x01\n" +
"\x05Token\x12!\n" +
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12(\n" +
"\rrefresh_token\x18\x02 \x01(\tH\x00R\frefreshToken\x88\x01\x01\x12\x1f\n" +
"\vaccess_type\x18\x03 \x01(\tR\n" +
"accessTypeB\x10\n" +
"\x0e_refresh_token\"\v\n" +
"\tRevokeRes\"3\n" +
"\x18ListUserRefreshTokensReq\x12\x17\n" +
"\auser_id\x18\x01 \x01(\tR\x06userId\"Y\n" +
"\x18ListUserRefreshTokensRes\x12=\n" +
"\x0erefresh_tokens\x18\x01 \x03(\v2\x16.token.v1.RefreshTokenR\rrefreshTokens\"@\n" +
"\fRefreshToken\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12 \n" +
"\vdescription\x18\x02 \x01(\tR\vdescription2\x8b\x02\n" +
"\fTokenService\x12.\n" +
"\x05Issue\x12\x12.token.v1.IssueReq\x1a\x0f.token.v1.Token\"\x00\x122\n" +
"\aRefresh\x12\x14.token.v1.RefreshReq\x1a\x0f.token.v1.Token\"\x00\x124\n" +
"\x06Revoke\x12\x13.token.v1.RevokeReq\x1a\x13.token.v1.RevokeRes\"\x00\x12a\n" +
"\x15ListUserRefreshTokens\x12\".token.v1.ListUserRefreshTokensReq\x1a\".token.v1.ListUserRefreshTokensRes\"\x00B1Z/github.com/absmach/magistrala/api/grpc/token/v1b\x06proto3"
var (
file_token_v1_token_proto_rawDescOnce sync.Once
file_token_v1_token_proto_rawDescData []byte
)
func file_token_v1_token_proto_rawDescGZIP() []byte {
file_token_v1_token_proto_rawDescOnce.Do(func() {
file_token_v1_token_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_token_v1_token_proto_rawDesc), len(file_token_v1_token_proto_rawDesc)))
})
return file_token_v1_token_proto_rawDescData
}
var file_token_v1_token_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_token_v1_token_proto_goTypes = []any{
(*IssueReq)(nil), // 0: token.v1.IssueReq
(*RefreshReq)(nil), // 1: token.v1.RefreshReq
(*RevokeReq)(nil), // 2: token.v1.RevokeReq
(*Token)(nil), // 3: token.v1.Token
(*RevokeRes)(nil), // 4: token.v1.RevokeRes
(*ListUserRefreshTokensReq)(nil), // 5: token.v1.ListUserRefreshTokensReq
(*ListUserRefreshTokensRes)(nil), // 6: token.v1.ListUserRefreshTokensRes
(*RefreshToken)(nil), // 7: token.v1.RefreshToken
}
var file_token_v1_token_proto_depIdxs = []int32{
7, // 0: token.v1.ListUserRefreshTokensRes.refresh_tokens:type_name -> token.v1.RefreshToken
0, // 1: token.v1.TokenService.Issue:input_type -> token.v1.IssueReq
1, // 2: token.v1.TokenService.Refresh:input_type -> token.v1.RefreshReq
2, // 3: token.v1.TokenService.Revoke:input_type -> token.v1.RevokeReq
5, // 4: token.v1.TokenService.ListUserRefreshTokens:input_type -> token.v1.ListUserRefreshTokensReq
3, // 5: token.v1.TokenService.Issue:output_type -> token.v1.Token
3, // 6: token.v1.TokenService.Refresh:output_type -> token.v1.Token
4, // 7: token.v1.TokenService.Revoke:output_type -> token.v1.RevokeRes
6, // 8: token.v1.TokenService.ListUserRefreshTokens:output_type -> token.v1.ListUserRefreshTokensRes
5, // [5:9] is the sub-list for method output_type
1, // [1:5] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_token_v1_token_proto_init() }
func file_token_v1_token_proto_init() {
if File_token_v1_token_proto != nil {
return
}
file_token_v1_token_proto_msgTypes[3].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_token_v1_token_proto_rawDesc), len(file_token_v1_token_proto_rawDesc)),
NumEnums: 0,
NumMessages: 8,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_token_v1_token_proto_goTypes,
DependencyIndexes: file_token_v1_token_proto_depIdxs,
MessageInfos: file_token_v1_token_proto_msgTypes,
}.Build()
File_token_v1_token_proto = out.File
file_token_v1_token_proto_goTypes = nil
file_token_v1_token_proto_depIdxs = nil
}
-238
View File
@@ -1,238 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.0
// source: token/v1/token.proto
package v1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
TokenService_Issue_FullMethodName = "/token.v1.TokenService/Issue"
TokenService_Refresh_FullMethodName = "/token.v1.TokenService/Refresh"
TokenService_Revoke_FullMethodName = "/token.v1.TokenService/Revoke"
TokenService_ListUserRefreshTokens_FullMethodName = "/token.v1.TokenService/ListUserRefreshTokens"
)
// TokenServiceClient is the client API for TokenService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type TokenServiceClient interface {
Issue(ctx context.Context, in *IssueReq, opts ...grpc.CallOption) (*Token, error)
Refresh(ctx context.Context, in *RefreshReq, opts ...grpc.CallOption) (*Token, error)
Revoke(ctx context.Context, in *RevokeReq, opts ...grpc.CallOption) (*RevokeRes, error)
ListUserRefreshTokens(ctx context.Context, in *ListUserRefreshTokensReq, opts ...grpc.CallOption) (*ListUserRefreshTokensRes, error)
}
type tokenServiceClient struct {
cc grpc.ClientConnInterface
}
func NewTokenServiceClient(cc grpc.ClientConnInterface) TokenServiceClient {
return &tokenServiceClient{cc}
}
func (c *tokenServiceClient) Issue(ctx context.Context, in *IssueReq, opts ...grpc.CallOption) (*Token, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Token)
err := c.cc.Invoke(ctx, TokenService_Issue_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *tokenServiceClient) Refresh(ctx context.Context, in *RefreshReq, opts ...grpc.CallOption) (*Token, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Token)
err := c.cc.Invoke(ctx, TokenService_Refresh_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *tokenServiceClient) Revoke(ctx context.Context, in *RevokeReq, opts ...grpc.CallOption) (*RevokeRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RevokeRes)
err := c.cc.Invoke(ctx, TokenService_Revoke_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *tokenServiceClient) ListUserRefreshTokens(ctx context.Context, in *ListUserRefreshTokensReq, opts ...grpc.CallOption) (*ListUserRefreshTokensRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListUserRefreshTokensRes)
err := c.cc.Invoke(ctx, TokenService_ListUserRefreshTokens_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// TokenServiceServer is the server API for TokenService service.
// All implementations must embed UnimplementedTokenServiceServer
// for forward compatibility.
type TokenServiceServer interface {
Issue(context.Context, *IssueReq) (*Token, error)
Refresh(context.Context, *RefreshReq) (*Token, error)
Revoke(context.Context, *RevokeReq) (*RevokeRes, error)
ListUserRefreshTokens(context.Context, *ListUserRefreshTokensReq) (*ListUserRefreshTokensRes, error)
mustEmbedUnimplementedTokenServiceServer()
}
// UnimplementedTokenServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedTokenServiceServer struct{}
func (UnimplementedTokenServiceServer) Issue(context.Context, *IssueReq) (*Token, error) {
return nil, status.Error(codes.Unimplemented, "method Issue not implemented")
}
func (UnimplementedTokenServiceServer) Refresh(context.Context, *RefreshReq) (*Token, error) {
return nil, status.Error(codes.Unimplemented, "method Refresh not implemented")
}
func (UnimplementedTokenServiceServer) Revoke(context.Context, *RevokeReq) (*RevokeRes, error) {
return nil, status.Error(codes.Unimplemented, "method Revoke not implemented")
}
func (UnimplementedTokenServiceServer) ListUserRefreshTokens(context.Context, *ListUserRefreshTokensReq) (*ListUserRefreshTokensRes, error) {
return nil, status.Error(codes.Unimplemented, "method ListUserRefreshTokens not implemented")
}
func (UnimplementedTokenServiceServer) mustEmbedUnimplementedTokenServiceServer() {}
func (UnimplementedTokenServiceServer) testEmbeddedByValue() {}
// UnsafeTokenServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to TokenServiceServer will
// result in compilation errors.
type UnsafeTokenServiceServer interface {
mustEmbedUnimplementedTokenServiceServer()
}
func RegisterTokenServiceServer(s grpc.ServiceRegistrar, srv TokenServiceServer) {
// If the following call panics, it indicates UnimplementedTokenServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&TokenService_ServiceDesc, srv)
}
func _TokenService_Issue_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(IssueReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TokenServiceServer).Issue(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TokenService_Issue_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TokenServiceServer).Issue(ctx, req.(*IssueReq))
}
return interceptor(ctx, in, info, handler)
}
func _TokenService_Refresh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RefreshReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TokenServiceServer).Refresh(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TokenService_Refresh_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TokenServiceServer).Refresh(ctx, req.(*RefreshReq))
}
return interceptor(ctx, in, info, handler)
}
func _TokenService_Revoke_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RevokeReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TokenServiceServer).Revoke(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TokenService_Revoke_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TokenServiceServer).Revoke(ctx, req.(*RevokeReq))
}
return interceptor(ctx, in, info, handler)
}
func _TokenService_ListUserRefreshTokens_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListUserRefreshTokensReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(TokenServiceServer).ListUserRefreshTokens(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: TokenService_ListUserRefreshTokens_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(TokenServiceServer).ListUserRefreshTokens(ctx, req.(*ListUserRefreshTokensReq))
}
return interceptor(ctx, in, info, handler)
}
// TokenService_ServiceDesc is the grpc.ServiceDesc for TokenService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var TokenService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "token.v1.TokenService",
HandlerType: (*TokenServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Issue",
Handler: _TokenService_Issue_Handler,
},
{
MethodName: "Refresh",
Handler: _TokenService_Refresh_Handler,
},
{
MethodName: "Revoke",
Handler: _TokenService_Revoke_Handler,
},
{
MethodName: "ListUserRefreshTokens",
Handler: _TokenService_ListUserRefreshTokens_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "token/v1/token.proto",
}
-428
View File
@@ -1,428 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.0
// source: users/v1/users.proto
package v1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
structpb "google.golang.org/protobuf/types/known/structpb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type RetrieveUsersReq struct {
state protoimpl.MessageState `protogen:"open.v1"`
Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"`
Offset uint64 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"`
Limit uint64 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RetrieveUsersReq) Reset() {
*x = RetrieveUsersReq{}
mi := &file_users_v1_users_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RetrieveUsersReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RetrieveUsersReq) ProtoMessage() {}
func (x *RetrieveUsersReq) ProtoReflect() protoreflect.Message {
mi := &file_users_v1_users_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RetrieveUsersReq.ProtoReflect.Descriptor instead.
func (*RetrieveUsersReq) Descriptor() ([]byte, []int) {
return file_users_v1_users_proto_rawDescGZIP(), []int{0}
}
func (x *RetrieveUsersReq) GetIds() []string {
if x != nil {
return x.Ids
}
return nil
}
func (x *RetrieveUsersReq) GetOffset() uint64 {
if x != nil {
return x.Offset
}
return 0
}
func (x *RetrieveUsersReq) GetLimit() uint64 {
if x != nil {
return x.Limit
}
return 0
}
type RetrieveUsersRes struct {
state protoimpl.MessageState `protogen:"open.v1"`
Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"`
Limit uint64 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"`
Offset uint64 `protobuf:"varint,3,opt,name=offset,proto3" json:"offset,omitempty"`
Users []*User `protobuf:"bytes,4,rep,name=users,proto3" json:"users,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RetrieveUsersRes) Reset() {
*x = RetrieveUsersRes{}
mi := &file_users_v1_users_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RetrieveUsersRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RetrieveUsersRes) ProtoMessage() {}
func (x *RetrieveUsersRes) ProtoReflect() protoreflect.Message {
mi := &file_users_v1_users_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RetrieveUsersRes.ProtoReflect.Descriptor instead.
func (*RetrieveUsersRes) Descriptor() ([]byte, []int) {
return file_users_v1_users_proto_rawDescGZIP(), []int{1}
}
func (x *RetrieveUsersRes) GetTotal() uint64 {
if x != nil {
return x.Total
}
return 0
}
func (x *RetrieveUsersRes) GetLimit() uint64 {
if x != nil {
return x.Limit
}
return 0
}
func (x *RetrieveUsersRes) GetOffset() uint64 {
if x != nil {
return x.Offset
}
return 0
}
func (x *RetrieveUsersRes) GetUsers() []*User {
if x != nil {
return x.Users
}
return nil
}
type User struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
FirstName string `protobuf:"bytes,2,opt,name=first_name,json=firstName,proto3" json:"first_name,omitempty"`
LastName string `protobuf:"bytes,3,opt,name=last_name,json=lastName,proto3" json:"last_name,omitempty"`
Tags []string `protobuf:"bytes,4,rep,name=tags,proto3" json:"tags,omitempty"`
Metadata *structpb.Struct `protobuf:"bytes,5,opt,name=metadata,proto3" json:"metadata,omitempty"`
PrivateMetadata *structpb.Struct `protobuf:"bytes,6,opt,name=private_metadata,json=privateMetadata,proto3" json:"private_metadata,omitempty"`
Status uint32 `protobuf:"varint,7,opt,name=status,proto3" json:"status,omitempty"`
Role uint32 `protobuf:"varint,8,opt,name=role,proto3" json:"role,omitempty"`
ProfilePicture string `protobuf:"bytes,9,opt,name=profile_picture,json=profilePicture,proto3" json:"profile_picture,omitempty"`
Username string `protobuf:"bytes,10,opt,name=username,proto3" json:"username,omitempty"`
Email string `protobuf:"bytes,11,opt,name=email,proto3" json:"email,omitempty"`
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,12,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,13,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
UpdatedBy string `protobuf:"bytes,14,opt,name=updated_by,json=updatedBy,proto3" json:"updated_by,omitempty"`
VerifiedAt *timestamppb.Timestamp `protobuf:"bytes,15,opt,name=verified_at,json=verifiedAt,proto3" json:"verified_at,omitempty"`
AuthProvider string `protobuf:"bytes,16,opt,name=auth_provider,json=authProvider,proto3" json:"auth_provider,omitempty"`
Permissions []string `protobuf:"bytes,17,rep,name=permissions,proto3" json:"permissions,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *User) Reset() {
*x = User{}
mi := &file_users_v1_users_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *User) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*User) ProtoMessage() {}
func (x *User) ProtoReflect() protoreflect.Message {
mi := &file_users_v1_users_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use User.ProtoReflect.Descriptor instead.
func (*User) Descriptor() ([]byte, []int) {
return file_users_v1_users_proto_rawDescGZIP(), []int{2}
}
func (x *User) GetId() string {
if x != nil {
return x.Id
}
return ""
}
func (x *User) GetFirstName() string {
if x != nil {
return x.FirstName
}
return ""
}
func (x *User) GetLastName() string {
if x != nil {
return x.LastName
}
return ""
}
func (x *User) GetTags() []string {
if x != nil {
return x.Tags
}
return nil
}
func (x *User) GetMetadata() *structpb.Struct {
if x != nil {
return x.Metadata
}
return nil
}
func (x *User) GetPrivateMetadata() *structpb.Struct {
if x != nil {
return x.PrivateMetadata
}
return nil
}
func (x *User) GetStatus() uint32 {
if x != nil {
return x.Status
}
return 0
}
func (x *User) GetRole() uint32 {
if x != nil {
return x.Role
}
return 0
}
func (x *User) GetProfilePicture() string {
if x != nil {
return x.ProfilePicture
}
return ""
}
func (x *User) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *User) GetEmail() string {
if x != nil {
return x.Email
}
return ""
}
func (x *User) GetCreatedAt() *timestamppb.Timestamp {
if x != nil {
return x.CreatedAt
}
return nil
}
func (x *User) GetUpdatedAt() *timestamppb.Timestamp {
if x != nil {
return x.UpdatedAt
}
return nil
}
func (x *User) GetUpdatedBy() string {
if x != nil {
return x.UpdatedBy
}
return ""
}
func (x *User) GetVerifiedAt() *timestamppb.Timestamp {
if x != nil {
return x.VerifiedAt
}
return nil
}
func (x *User) GetAuthProvider() string {
if x != nil {
return x.AuthProvider
}
return ""
}
func (x *User) GetPermissions() []string {
if x != nil {
return x.Permissions
}
return nil
}
var File_users_v1_users_proto protoreflect.FileDescriptor
const file_users_v1_users_proto_rawDesc = "" +
"\n" +
"\x14users/v1/users.proto\x12\busers.v1\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"R\n" +
"\x10RetrieveUsersReq\x12\x10\n" +
"\x03ids\x18\x01 \x03(\tR\x03ids\x12\x16\n" +
"\x06offset\x18\x02 \x01(\x04R\x06offset\x12\x14\n" +
"\x05limit\x18\x03 \x01(\x04R\x05limit\"|\n" +
"\x10RetrieveUsersRes\x12\x14\n" +
"\x05total\x18\x01 \x01(\x04R\x05total\x12\x14\n" +
"\x05limit\x18\x02 \x01(\x04R\x05limit\x12\x16\n" +
"\x06offset\x18\x03 \x01(\x04R\x06offset\x12$\n" +
"\x05users\x18\x04 \x03(\v2\x0e.users.v1.UserR\x05users\"\xff\x04\n" +
"\x04User\x12\x0e\n" +
"\x02id\x18\x01 \x01(\tR\x02id\x12\x1d\n" +
"\n" +
"first_name\x18\x02 \x01(\tR\tfirstName\x12\x1b\n" +
"\tlast_name\x18\x03 \x01(\tR\blastName\x12\x12\n" +
"\x04tags\x18\x04 \x03(\tR\x04tags\x123\n" +
"\bmetadata\x18\x05 \x01(\v2\x17.google.protobuf.StructR\bmetadata\x12B\n" +
"\x10private_metadata\x18\x06 \x01(\v2\x17.google.protobuf.StructR\x0fprivateMetadata\x12\x16\n" +
"\x06status\x18\a \x01(\rR\x06status\x12\x12\n" +
"\x04role\x18\b \x01(\rR\x04role\x12'\n" +
"\x0fprofile_picture\x18\t \x01(\tR\x0eprofilePicture\x12\x1a\n" +
"\busername\x18\n" +
" \x01(\tR\busername\x12\x14\n" +
"\x05email\x18\v \x01(\tR\x05email\x129\n" +
"\n" +
"created_at\x18\f \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x129\n" +
"\n" +
"updated_at\x18\r \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x1d\n" +
"\n" +
"updated_by\x18\x0e \x01(\tR\tupdatedBy\x12;\n" +
"\vverified_at\x18\x0f \x01(\v2\x1a.google.protobuf.TimestampR\n" +
"verifiedAt\x12#\n" +
"\rauth_provider\x18\x10 \x01(\tR\fauthProvider\x12 \n" +
"\vpermissions\x18\x11 \x03(\tR\vpermissions2Y\n" +
"\fUsersService\x12I\n" +
"\rRetrieveUsers\x12\x1a.users.v1.RetrieveUsersReq\x1a\x1a.users.v1.RetrieveUsersRes\"\x00B1Z/github.com/absmach/magistrala/api/grpc/users/v1b\x06proto3"
var (
file_users_v1_users_proto_rawDescOnce sync.Once
file_users_v1_users_proto_rawDescData []byte
)
func file_users_v1_users_proto_rawDescGZIP() []byte {
file_users_v1_users_proto_rawDescOnce.Do(func() {
file_users_v1_users_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_users_v1_users_proto_rawDesc), len(file_users_v1_users_proto_rawDesc)))
})
return file_users_v1_users_proto_rawDescData
}
var file_users_v1_users_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_users_v1_users_proto_goTypes = []any{
(*RetrieveUsersReq)(nil), // 0: users.v1.RetrieveUsersReq
(*RetrieveUsersRes)(nil), // 1: users.v1.RetrieveUsersRes
(*User)(nil), // 2: users.v1.User
(*structpb.Struct)(nil), // 3: google.protobuf.Struct
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
}
var file_users_v1_users_proto_depIdxs = []int32{
2, // 0: users.v1.RetrieveUsersRes.users:type_name -> users.v1.User
3, // 1: users.v1.User.metadata:type_name -> google.protobuf.Struct
3, // 2: users.v1.User.private_metadata:type_name -> google.protobuf.Struct
4, // 3: users.v1.User.created_at:type_name -> google.protobuf.Timestamp
4, // 4: users.v1.User.updated_at:type_name -> google.protobuf.Timestamp
4, // 5: users.v1.User.verified_at:type_name -> google.protobuf.Timestamp
0, // 6: users.v1.UsersService.RetrieveUsers:input_type -> users.v1.RetrieveUsersReq
1, // 7: users.v1.UsersService.RetrieveUsers:output_type -> users.v1.RetrieveUsersRes
7, // [7:8] is the sub-list for method output_type
6, // [6:7] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_users_v1_users_proto_init() }
func file_users_v1_users_proto_init() {
if File_users_v1_users_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_users_v1_users_proto_rawDesc), len(file_users_v1_users_proto_rawDesc)),
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_users_v1_users_proto_goTypes,
DependencyIndexes: file_users_v1_users_proto_depIdxs,
MessageInfos: file_users_v1_users_proto_msgTypes,
}.Build()
File_users_v1_users_proto = out.File
file_users_v1_users_proto_goTypes = nil
file_users_v1_users_proto_depIdxs = nil
}
-130
View File
@@ -1,130 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.0
// - protoc v6.33.0
// source: users/v1/users.proto
package v1
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
UsersService_RetrieveUsers_FullMethodName = "/users.v1.UsersService/RetrieveUsers"
)
// UsersServiceClient is the client API for UsersService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
//
// UsersService exposes user-related functionality over gRPC.
type UsersServiceClient interface {
// RetrieveUsers fetches users for the provided IDs.
RetrieveUsers(ctx context.Context, in *RetrieveUsersReq, opts ...grpc.CallOption) (*RetrieveUsersRes, error)
}
type usersServiceClient struct {
cc grpc.ClientConnInterface
}
func NewUsersServiceClient(cc grpc.ClientConnInterface) UsersServiceClient {
return &usersServiceClient{cc}
}
func (c *usersServiceClient) RetrieveUsers(ctx context.Context, in *RetrieveUsersReq, opts ...grpc.CallOption) (*RetrieveUsersRes, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RetrieveUsersRes)
err := c.cc.Invoke(ctx, UsersService_RetrieveUsers_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// UsersServiceServer is the server API for UsersService service.
// All implementations must embed UnimplementedUsersServiceServer
// for forward compatibility.
//
// UsersService exposes user-related functionality over gRPC.
type UsersServiceServer interface {
// RetrieveUsers fetches users for the provided IDs.
RetrieveUsers(context.Context, *RetrieveUsersReq) (*RetrieveUsersRes, error)
mustEmbedUnimplementedUsersServiceServer()
}
// UnimplementedUsersServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedUsersServiceServer struct{}
func (UnimplementedUsersServiceServer) RetrieveUsers(context.Context, *RetrieveUsersReq) (*RetrieveUsersRes, error) {
return nil, status.Error(codes.Unimplemented, "method RetrieveUsers not implemented")
}
func (UnimplementedUsersServiceServer) mustEmbedUnimplementedUsersServiceServer() {}
func (UnimplementedUsersServiceServer) testEmbeddedByValue() {}
// UnsafeUsersServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to UsersServiceServer will
// result in compilation errors.
type UnsafeUsersServiceServer interface {
mustEmbedUnimplementedUsersServiceServer()
}
func RegisterUsersServiceServer(s grpc.ServiceRegistrar, srv UsersServiceServer) {
// If the following call panics, it indicates UnimplementedUsersServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&UsersService_ServiceDesc, srv)
}
func _UsersService_RetrieveUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RetrieveUsersReq)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(UsersServiceServer).RetrieveUsers(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: UsersService_RetrieveUsers_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(UsersServiceServer).RetrieveUsers(ctx, req.(*RetrieveUsersReq))
}
return interceptor(ctx, in, info, handler)
}
// UsersService_ServiceDesc is the grpc.ServiceDesc for UsersService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var UsersService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "users.v1.UsersService",
HandlerType: (*UsersServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "RetrieveUsers",
Handler: _UsersService_RetrieveUsers_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "users/v1/users.proto",
}
-242
View File
@@ -1,242 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package http
import (
"context"
"encoding/json"
"net/http"
"net/mail"
"regexp"
"strings"
"github.com/absmach/magistrala"
apiutil "github.com/absmach/magistrala/api/http/util"
"github.com/absmach/magistrala/pkg/errors"
"github.com/gofrs/uuid/v5"
)
const (
OffsetKey = "offset"
DirKey = "dir"
OrderKey = "order"
LimitKey = "limit"
OnlyTotal = "only_total"
NameOrder = "name"
IDOrder = "id"
AscDir = "asc"
DescDir = "desc"
UpdatedAtOrder = "updated_at"
CreatedAtOrder = "created_at"
MetadataKey = "metadata"
NameKey = "name"
TagKey = "tag"
TagsKey = "tags"
StatusKey = "status"
ClientKey = "client"
ChannelKey = "channel"
ConnTypeKey = "connection_type"
GroupKey = "group"
DomainKey = "domain"
StartLevelKey = "start_level"
EndLevelKey = "end_level"
TreeKey = "tree"
ParentKey = "parent_id"
LevelKey = "level"
RootGroupKey = "root_group"
TokenKey = "token"
SubjectKey = "subject"
ObjectKey = "object"
RolesKey = "roles"
ActionKey = "action"
ActionsKey = "actions"
RoleIDKey = "role_id"
RoleNameKey = "role_name"
AccessProviderIDKey = "access_provider_id"
AccessTypeKey = "access_type"
UsernameKey = "username"
UserKey = "user"
EmailKey = "email"
FirstNameKey = "first_name"
LastNameKey = "last_name"
DefTotal = uint64(100)
DefOffset = 0
DefOrder = "updated_at"
DefDir = "desc"
DefLimit = 10
DefLevel = 0
DefStartLevel = 1
DefEndLevel = 0
DefStatus = "enabled"
DefClientStatus = "enabled"
DefUserStatus = "enabled"
DefGroupStatus = "enabled"
// ContentType represents JSON content type.
ContentType = "application/json"
// MaxNameSize limits name size to prevent making them too complex.
MaxLimitSize = 100
MaxNameSize = 1024
MaxIDSize = 36
)
var (
nameRegExp = regexp.MustCompile(`^[a-z0-9][a-z0-9_-]{34}[a-z0-9]$`)
routeRegExp = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9_-]{0,35}$`)
userNameRegExp = regexp.MustCompile(`^[a-zA-Z0-9][a-zA-Z0-9_-]{0,31}$`)
errUnreadableName = errors.New("name containing double underscores or double dashes not allowed")
)
// ValidateUUID validates UUID format.
func ValidateUUID(extID string) (err error) {
id, err := uuid.FromString(extID)
if id.String() != extID || err != nil {
return apiutil.ErrInvalidIDFormat
}
return nil
}
func ValidateEmail(email string) (err error) {
if _, err := mail.ParseAddress(email); err != nil {
return apiutil.ErrInvalidEmail
}
return nil
}
// ValidateName validates name format.
func ValidateName(id string) error {
if !nameRegExp.MatchString(id) {
return apiutil.ErrInvalidNameFormat
}
// Names containing double underscores or double dashes are invalid due to similarity concerns.
if strings.Contains(id, "__") || strings.Contains(id, "--") {
return errors.Wrap(apiutil.ErrInvalidNameFormat, errUnreadableName)
}
return nil
}
// ValidateRoute validates route format.
func ValidateRoute(route string) error {
if !routeRegExp.MatchString(route) {
return apiutil.ErrInvalidRouteFormat
}
if strings.Contains(route, "__") || strings.Contains(route, "--") {
return errors.Wrap(apiutil.ErrInvalidRouteFormat, errUnreadableName)
}
return nil
}
// ValidateUserName validates user name format.
func ValidateUserName(name string) error {
if !userNameRegExp.MatchString(name) {
return apiutil.ErrInvalidUsername
}
if strings.Contains(name, "__") || strings.Contains(name, "--") {
return errors.Wrap(apiutil.ErrInvalidUsername, errUnreadableName)
}
return nil
}
// EncodeResponse encodes successful response.
func EncodeResponse(_ context.Context, w http.ResponseWriter, response any) error {
if ar, ok := response.(magistrala.Response); ok {
for k, v := range ar.Headers() {
w.Header().Set(k, v)
}
w.Header().Set("Content-Type", ContentType)
w.WriteHeader(ar.Code())
if ar.Empty() {
return nil
}
}
return json.NewEncoder(w).Encode(response)
}
// EncodeError encodes an error response.
func EncodeError(_ context.Context, err error, w http.ResponseWriter) {
w.Header().Set("Content-Type", ContentType)
if sdkErr, ok := err.(errors.SDKError); ok {
w.WriteHeader(sdkErr.StatusCode())
if err := json.NewEncoder(w).Encode(sdkErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
}
if errors.Contains(err, errors.ErrAuthentication) {
w.WriteHeader(http.StatusUnauthorized)
if err := json.NewEncoder(w).Encode(err); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
}
if errors.Contains(err, errors.ErrAuthorization) {
w.WriteHeader(http.StatusForbidden)
if err := json.NewEncoder(w).Encode(err); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
}
switch retErr := err.(type) {
case *errors.RequestError:
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(retErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
case *errors.AuthNError:
w.WriteHeader(http.StatusUnauthorized)
if err := json.NewEncoder(w).Encode(retErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
case *errors.AuthZError:
w.WriteHeader(http.StatusForbidden)
if err := json.NewEncoder(w).Encode(retErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
case *errors.MediaTypeError:
w.WriteHeader(http.StatusUnsupportedMediaType)
if err := json.NewEncoder(w).Encode(retErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
case *errors.ServiceError:
w.WriteHeader(http.StatusUnprocessableEntity)
if err := json.NewEncoder(w).Encode(retErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
case *errors.NotFoundError:
w.WriteHeader(http.StatusNotFound)
if err := json.NewEncoder(w).Encode(retErr); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
return
case *errors.InternalError:
w.WriteHeader(http.StatusInternalServerError)
return
default:
w.WriteHeader(http.StatusInternalServerError)
}
}
-27
View File
@@ -1,27 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package http
import (
"context"
"net/http"
"github.com/absmach/magistrala"
"github.com/go-chi/chi/v5/middleware"
)
func RequestIDMiddleware(idp magistrala.IDProvider) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestID, err := idp.ID()
if err != nil {
EncodeError(r.Context(), err, w)
return
}
ctx := context.WithValue(r.Context(), middleware.RequestIDKey, requestID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
-280
View File
@@ -1,280 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package util
import "github.com/absmach/magistrala/pkg/errors"
// Errors defined in this file are used by the LoggingErrorEncoder decorator
// to distinguish and log API request validation errors and avoid that service
// errors are logged twice.
var (
// ErrValidation indicates that an error was returned by the API.
ErrValidation = errors.NewRequestError("something went wrong with the request")
// ErrBearerToken indicates missing or invalid bearer user token.
ErrBearerToken = errors.NewAuthNError("missing or invalid bearer user token")
// ErrBearerKey indicates missing or invalid bearer entity key.
ErrBearerKey = errors.NewAuthNError("missing or invalid bearer entity key")
// ErrMissingID indicates missing entity ID.
ErrMissingID = errors.NewRequestError("missing entity id")
// ErrMissingEntityID indicates missing entity ID.
ErrMissingEntityID = errors.NewRequestError("missing entity id")
// ErrMissingClientID indicates missing client ID.
ErrMissingClientID = errors.NewRequestError("missing client id")
// ErrMissingChannelID indicates missing client ID.
ErrMissingChannelID = errors.NewRequestError("missing channel id")
// ErrMissingConnectionType indicates missing connection tpye.
ErrMissingConnectionType = errors.NewRequestError("missing connection type")
// ErrMissingParentGroupID indicates missing parent group ID.
ErrMissingParentGroupID = errors.NewRequestError("missing parent group id")
// ErrMissingChildrenGroupIDs indicates missing children group IDs.
ErrMissingChildrenGroupIDs = errors.NewRequestError("missing children group ids")
// ErrSelfParentingNotAllowed indicates child id is same as parent id.
ErrSelfParentingNotAllowed = errors.NewRequestError("self parenting not allowed")
// ErrInvalidChildGroupID indicates invalid child group ID.
ErrInvalidChildGroupID = errors.NewRequestError("invalid child group id")
// ErrInvalidAuthKey indicates invalid auth key.
ErrInvalidAuthKey = errors.New("invalid auth key")
// ErrInvalidIDFormat indicates an invalid ID format.
ErrInvalidIDFormat = errors.NewRequestError("invalid id format provided")
// ErrNameSize indicates that name size exceeds the max.
ErrNameSize = errors.NewRequestError("invalid name size")
// ErrEmailSize indicates that email size exceeds the max.
ErrEmailSize = errors.NewRequestError("invalid email size")
// ErrInvalidRole indicates that an invalid role.
ErrInvalidRole = errors.NewRequestError("invalid client role")
// ErrLimitSize indicates that an invalid limit.
ErrLimitSize = errors.NewRequestError("invalid limit size")
// ErrLevel indicates that an invalid level.
ErrLevel = errors.NewRequestError("invalid level")
// ErrOffsetSize indicates an invalid offset.
ErrOffsetSize = errors.NewRequestError("invalid offset size")
// ErrInvalidOrder indicates an invalid list order.
ErrInvalidOrder = errors.NewRequestError("invalid list order provided")
// ErrInvalidDirection indicates an invalid list direction.
ErrInvalidDirection = errors.NewRequestError("invalid list direction provided")
// ErrInvalidMemberKind indicates an invalid member kind.
ErrInvalidMemberKind = errors.NewRequestError("invalid member kind")
// ErrEmptyList indicates that entity data is empty.
ErrEmptyList = errors.NewRequestError("empty list provided")
// ErrMissingRoleName indicates that role name is empty.
ErrMissingRoleName = errors.NewRequestError("empty role name")
// ErrMissingRoleID indicates that role id is empty.
ErrMissingRoleID = errors.NewRequestError("empty role id")
// ErrMissingRoleOperations indicates that role operations are empty.
ErrMissingRoleOperations = errors.NewRequestError("empty role operations")
// ErrMissingRoleMembers indicates that role members are empty.
ErrMissingRoleMembers = errors.NewRequestError("empty role members")
// ErrMalformedPolicy indicates that policies are malformed.
ErrMalformedPolicy = errors.NewRequestError("malformed policy")
// ErrMissingPolicySub indicates that policies are subject.
ErrMissingPolicySub = errors.NewRequestError("malformed policy subject")
// ErrMissingPolicyObj indicates missing policies object.
ErrMissingPolicyObj = errors.NewRequestError("malformed policy object")
// ErrMalformedPolicyAct indicates missing policies action.
ErrMalformedPolicyAct = errors.NewRequestError("malformed policy action")
// ErrMissingPolicyEntityType indicates missing policies entity type.
ErrMissingPolicyEntityType = errors.NewRequestError("missing policy entity type")
// ErrMalformedPolicyPer indicates missing policies relation.
ErrMalformedPolicyPer = errors.NewRequestError("malformed policy permission")
// ErrMissingCertData indicates missing cert data (ttl).
ErrMissingCertData = errors.NewRequestError("missing certificate data")
// ErrInvalidCertData indicates invalid cert data (ttl).
ErrInvalidCertData = errors.NewRequestError("invalid certificate data")
// ErrInvalidTopic indicates an invalid subscription topic.
ErrInvalidTopic = errors.NewRequestError("invalid Subscription topic")
// ErrInvalidContact indicates an invalid subscription contract.
ErrInvalidContact = errors.NewRequestError("invalid Subscription contact")
// ErrMissingEmail indicates missing email.
ErrMissingEmail = errors.NewRequestError("missing email")
// ErrInvalidEmail indicates missing email.
ErrInvalidEmail = errors.NewRequestError("invalid email")
// ErrMissingHost indicates missing host.
ErrMissingHost = errors.NewRequestError("missing host")
// ErrMissingPass indicates missing password.
ErrMissingPass = errors.NewRequestError("missing password")
// ErrMissingConfPass indicates missing conf password.
ErrMissingConfPass = errors.NewRequestError("missing conf password")
// ErrInvalidResetPass indicates an invalid reset password.
ErrInvalidResetPass = errors.NewRequestError("invalid reset password")
// ErrInvalidComparator indicates an invalid comparator.
ErrInvalidComparator = errors.NewRequestError("invalid comparator")
// ErrMissingMemberIDs indicates missing member ids.
ErrMissingMemberIDs = errors.NewRequestError("missing member ids")
// ErrMissingMemberType indicates missing group member type.
ErrMissingMemberType = errors.NewRequestError("missing group member type")
// ErrMissingMemberKind indicates missing group member kind.
ErrMissingMemberKind = errors.NewRequestError("missing group member kind")
// ErrMissingRelation indicates missing relation.
ErrMissingRelation = errors.NewRequestError("missing relation")
// ErrInvalidRelation indicates an invalid relation.
ErrInvalidRelation = errors.NewRequestError("invalid relation")
// ErrInvalidAPIKey indicates an invalid API key type.
ErrInvalidAPIKey = errors.NewRequestError("invalid api key type")
// ErrInvitationState indicates an invalid invitation state.
ErrInvitationState = errors.NewRequestError("invalid invitation state")
// ErrMissingIdentity indicates missing entity Identity.
ErrMissingIdentity = errors.NewRequestError("missing entity identity")
// ErrMissingSecret indicates missing secret.
ErrMissingSecret = errors.NewRequestError("missing secret")
// ErrPasswordFormat indicates weak password.
ErrPasswordFormat = errors.NewRequestError("password does not meet the requirements")
// ErrMissingName indicates missing identity name.
ErrMissingName = errors.NewRequestError("missing identity name")
// ErrMissingRoute indicates missing route.
ErrMissingRoute = errors.NewRequestError("missing route")
// ErrInvalidLevel indicates an invalid group level.
ErrInvalidLevel = errors.NewRequestError("invalid group level (should be between 0 and 5)")
// ErrNotFoundParam indicates that the parameter was not found in the query.
ErrNotFoundParam = errors.NewRequestError("parameter not found in the query")
// ErrInvalidQueryParams indicates invalid query parameters.
ErrInvalidQueryParams = errors.NewRequestError("invalid query parameters")
// ErrInvalidVisibilityType indicates invalid visibility type.
ErrInvalidVisibilityType = errors.NewRequestError("invalid visibility type")
// ErrUnsupportedContentType indicates unacceptable or lack of Content-Type.
ErrUnsupportedContentType = errors.NewMediaTypeError("unsupported content type")
// ErrRollbackTx indicates failed to rollback transaction.
ErrRollbackTx = errors.NewRequestError("failed to rollback transaction")
// ErrInvalidAggregation indicates invalid aggregation value.
ErrInvalidAggregation = errors.NewRequestError("invalid aggregation value")
// ErrInvalidInterval indicates invalid interval value.
ErrInvalidInterval = errors.NewRequestError("invalid interval value")
// ErrMissingFrom indicates missing from value.
ErrMissingFrom = errors.NewRequestError("missing from time value")
// ErrMissingTo indicates missing to value.
ErrMissingTo = errors.NewRequestError("missing to time value")
// ErrEmptyMessage indicates empty message.
ErrEmptyMessage = errors.NewRequestError("empty message")
// ErrMissingEntityType indicates missing entity type.
ErrMissingEntityType = errors.NewRequestError("missing entity type")
// ErrInvalidEntityType indicates invalid entity type.
ErrInvalidEntityType = errors.NewRequestError("invalid entity type")
// ErrInvalidTimeFormat indicates invalid time format i.e not unix time.
ErrInvalidTimeFormat = errors.NewRequestError("invalid time format use unix time")
// ErrEmptySearchQuery indicates search query should not be empty.
ErrEmptySearchQuery = errors.NewRequestError("search query must not be empty")
// ErrLenSearchQuery indicates search query length.
ErrLenSearchQuery = errors.NewRequestError("search query must be at least 3 characters")
// ErrMissingDomainID indicates missing domainID.
ErrMissingDomainID = errors.NewRequestError("missing domainID")
// ErrMissingUsername indicates missing user name.
ErrMissingUsername = errors.NewRequestError("missing username")
// ErrInvalidUsername indicates invalid user name.
ErrInvalidUsername = errors.NewRequestError("invalid username")
// ErrMissingFirstName indicates missing first name.
ErrMissingFirstName = errors.NewRequestError("missing first name")
// ErrMissingLastName indicates missing last name.
ErrMissingLastName = errors.NewRequestError("missing last name")
// ErrInvalidProfilePictureURL indicates that the profile picture url is invalid.
ErrInvalidProfilePictureURL = errors.NewRequestError("invalid profile picture url")
ErrMultipleEntitiesFilter = errors.NewRequestError("multiple entities are provided in filter are not supported")
// ErrMissingDescription indicates missing description.
ErrMissingDescription = errors.NewRequestError("missing description")
// ErrUnsupportedTokenType indicates that this type of token is not supported.
ErrUnsupportedTokenType = errors.NewRequestError("unsupported content token type")
// ErrMissingUserID indicates missing user ID.
ErrMissingUserID = errors.NewRequestError("missing user id")
// ErrMissingPATID indicates missing pat ID.
ErrMissingPATID = errors.NewRequestError("missing pat id")
// ErrInvalidNameFormat indicates invalid name format.
ErrInvalidNameFormat = errors.NewRequestError("invalid name format")
// ErrInvalidRouteFormat indicates invalid route format.
ErrInvalidRouteFormat = errors.NewRequestError("invalid route format")
// ErrMissingUsernameEmail indicates missing user name / email.
ErrMissingUsernameEmail = errors.NewRequestError("missing username / email")
// ErrInvalidVerification indicates invalid email verification.
ErrInvalidVerification = errors.NewRequestError("invalid verification")
// ErrEmailNotVerified indicates invalid email not verified.
ErrEmailNotVerified = errors.NewRequestError("email not verified")
// ErrMalformedRequest indicates malformed request body.
ErrMalformedRequestBody = errors.NewRequestError("request body is not a valid JSON, expecting a valid JSON")
)
-42
View File
@@ -1,42 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package util
import (
"net/http"
"strings"
)
const (
// BearerPrefix represents the token prefix for Bearer authentication scheme.
BearerPrefix = "Bearer "
// ClientPrefix represents the key prefix for Client authentication scheme.
ClientPrefix = "Client "
// BasicAuthPrefix represents the prefix for Basic authentication scheme.
BasicAuthPrefix = "Basic "
)
// ExtractBearerToken returns value of the bearer token. If there is no bearer token - an empty value is returned.
func ExtractBearerToken(r *http.Request) string {
token := r.Header.Get("Authorization")
if !strings.HasPrefix(token, BearerPrefix) {
return ""
}
return strings.TrimPrefix(token, BearerPrefix)
}
// ExtractClientSecret returns value of the client secret. If it's not present - an empty value is returned.
func ExtractClientSecret(r *http.Request) string {
token := r.Header.Get("Authorization")
if !strings.HasPrefix(token, ClientPrefix) {
return ""
}
return strings.TrimPrefix(token, ClientPrefix)
}
+5
View File
@@ -0,0 +1,5 @@
# Magistrala OpenAPI Specification
This folder contains an OpenAPI specifications for Magistrala API.
View specification in Swagger UI at [api.mainflux.io](https://api.mainflux.io)
+887
View File
@@ -0,0 +1,887 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.3
info:
title: Magistrala Auth Service
description: |
This is the Auth Server based on the OpenAPI 3.0 specification. It is the HTTP API for managing platform users. You can now help us improve the API whether it's by making changes to the definition itself or to the code.
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:8180
- url: https://localhost:8180
tags:
- name: Auth
description: Everything about your Authentication and Authorization.
externalDocs:
description: Find out more about auth
url: https://docs.magistrala.abstractmachines.fr/
- name: Keys
description: Everything about your Keys.
externalDocs:
description: Find out more about keys
url: https://docs.magistrala.abstractmachines.fr/
paths:
/domains:
post:
tags:
- Domains
summary: Adds new domain
description: |
Adds new domain.
requestBody:
$ref: "#/components/requestBodies/DomainCreateReq"
responses:
"201":
$ref: "#/components/responses/DomainCreateRes"
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"409":
description: Failed due to using an existing alias.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
summary: Retrieves list of domains.
description: |
Retrieves list of domains that the user have access.
parameters:
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/Status"
- $ref: "#/components/parameters/DomainName"
- $ref: "#/components/parameters/Permission"
tags:
- Domains
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/DomainsPageRes"
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}:
get:
summary: Retrieves domain information
description: |
Retrieves a specific domain that is identified by the domain ID.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/DomainRes"
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
patch:
summary: Updates name, metadata, tags and alias of the domain.
description: |
Updates name, metadata, tags and alias of the domain.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/DomainUpdateReq"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/DomainRes"
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Unauthorized access to domain id.
"404":
description: Failed due to non existing domain.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
delete:
summary: Delete domain for a domain with the given id.
description: |
Delete domain removes a domain with the given id from repo
and removes all the things, channels, assigned users, policies related to this domain.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"204":
description: Domain deleted.
"401":
description: Missing or invalid access token provided.
"403":
description: Unauthorized access to domain id.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/permissions:
get:
summary: Retrieves user permissions on domain.
description: |
Retrieves user permissions on domain that is identified by the domain ID.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/DomainPermissionRes"
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/enable:
post:
summary: Enables a domain
description: |
Enables a specific domain that is identified by the domain ID.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"200":
description: Successfully enabled domain.
"400":
description: Failed due to malformed domain's ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Unauthorized access the domain ID.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/disable:
post:
summary: Disable a domain
description: |
Disable a specific domain that is identified by the domain ID.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"200":
description: Successfully disabled domain.
"400":
description: Failed due to malformed domain's ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Unauthorized access the domain ID.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/freeze:
post:
summary: Freeze a domain
description: |
Freeze a specific domain that is identified by the domain ID.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
security:
- bearerAuth: []
responses:
"200":
description: Successfully freezed domain.
"400":
description: Failed due to malformed domain's ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Unauthorized access the domain ID.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/users/assign:
post:
summary: Assign users to domain
description: |
Assign users to domain that is identified by the domain ID.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/AssignUserReq"
security:
- bearerAuth: []
responses:
"200":
description: Users successfully assigned to domain.
"400":
description: Failed due to malformed domain's ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Unauthorized access the domain ID.
"404":
description: A non-existent entity request.
"409":
description: Conflict of data.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/domains/{domainID}/users/unassign:
post:
summary: Unassign users from domain
description: |
Unassign users from domain that is identified by the domain ID.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/UnassignUsersReq"
security:
- bearerAuth: []
responses:
"200":
description: Users successfully unassigned from domain.
"400":
description: Failed due to malformed domain's ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Unauthorized access the domain ID.
"404":
description: A non-existent entity request.
"409":
description: Conflict of data.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/keys:
post:
tags:
- Keys
summary: Issue API key
description: |
Generates a new API key. Thew new API key will
be uniquely identified by its ID.
requestBody:
$ref: "#/components/requestBodies/KeyRequest"
responses:
"201":
description: Issued new key.
"400":
description: Failed due to malformed JSON.
"409":
description: Failed due to using already existing ID.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/keys/{keyID}:
get:
summary: Gets API key details.
description: |
Gets API key details for the given key.
tags:
- Keys
parameters:
- $ref: "#/components/parameters/ApiKeyId"
responses:
"200":
$ref: "#/components/responses/KeyRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
delete:
summary: Revoke API key
description: |
Revoke API key identified by the given ID.
tags:
- Keys
parameters:
- $ref: "#/components/parameters/ApiKeyId"
responses:
"204":
description: Key revoked.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
/policies:
post:
summary: Creates new policies.
description: |
Creates new policies. Only admin can use this endpoint. Therefore, you need an authentication token for the admin.
Also, only policies defined on the system are allowed to add. For more details, please see the docs for Authorization.
tags:
- Auth
requestBody:
$ref: "#/components/requestBodies/PoliciesReq"
responses:
"201":
description: Policies created.
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Unauthorized access token provided.
"409":
description: Failed due to using an existing email address.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/policies/delete:
post:
summary: Deletes policies.
description: |
Deletes policies. Only admin can use this endpoint. Therefore, you need an authentication token for the admin.
Also, only policies defined on the system are allowed to delete. For more details, please see the docs for Authorization.
tags:
- Auth
requestBody:
$ref: "#/components/requestBodies/PoliciesReq"
responses:
"204":
description: Policies deleted.
"400":
description: Failed due to malformed JSON.
"409":
description: Failed due to using an existing email address.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/users/{memberID}/domains:
get:
tags:
- Domains
summary: List users in a group
description: |
Retrieves a list of users in a domain. Due to performance concerns, data
is retrieved in subsets. The API must ensure that the entire
dataset is consumed either by making subsequent requests, or by
increasing the subset size of the initial request.
parameters:
- $ref: "users.yml#/components/parameters/MemberID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/Status"
security:
- bearerAuth: []
responses:
"200":
$ref: "users.yml#/components/responses/UserPageRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: |
Missing or invalid access token provided.
This endpoint is available only for administrators.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
DomainReqObj:
type: object
properties:
name:
type: string
example: domainName
description: Domain name.
tags:
type: array
minItems: 0
items:
type: string
example: ["tag1", "tag2"]
description: domain tags.
metadata:
type: object
example: { "domain": "example.com" }
description: Arbitrary, object-encoded domain's data.
alias:
type: string
example: domain alias
description: Domain alias.
required:
- name
- alias
Domain:
type: object
properties:
id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Domain unique identifier.
name:
type: string
example: domainName
description: Domain name.
tags:
type: array
minItems: 0
items:
type: string
example: ["tag1", "tag2"]
description: domain tags.
metadata:
type: object
example: { "domain": "example.com" }
description: Arbitrary, object-encoded domain's data.
alias:
type: string
example: domain alias
description: Domain alias.
status:
type: string
description: Domain Status
format: string
example: enabled
created_by:
type: string
format: uuid
example: "0d837f56-3f8a-4e2a-9359-6347d0fc9f06 "
description: User ID of the user who created the domain.
created_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the domain was created.
updated_by:
type: string
format: uuid
example: "80f66b77-ed74-4e74-9f88-6cce9a0a3049"
description: User ID of the user who last updated the domain.
updated_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the domain was last updated.
xml:
name: domain
DomainsPage:
type: object
properties:
domains:
type: array
minItems: 0
uniqueItems: true
items:
$ref: "#/components/schemas/Domain"
total:
type: integer
example: 1
description: Total number of items.
offset:
type: integer
description: Number of items to skip during retrieval.
limit:
type: integer
example: 10
description: Maximum number of items to return in one page.
required:
- domain
- total
- offset
DomainUpdate:
type: object
properties:
name:
type: string
example: domainName
description: Domain name.
tags:
type: array
minItems: 0
items:
type: string
example: ["tag1", "tag2"]
description: domain tags.
metadata:
type: object
example: { "domain": "example.com" }
description: Arbitrary, object-encoded thing's data.
alias:
type: string
example: domain alias
description: Domain alias.
Permissions:
type: object
properties:
permissions:
type: array
minItems: 0
items:
type: string
description: Permissions
UserDomainRelationReq:
type: object
properties:
users_ids:
type: array
minItems: 1
items:
type: string
description: Users IDs
example:
[
"5dc1ce4b-7cc9-4f12-98a6-9d74cc4980bb",
"c01ed106-e52d-4aa4-bed3-39f360177cfa",
]
relation:
type: string
enum: ["administrator", "editor","viewer","member"]
example: "administrator"
description: Policy relations.
required:
- users_ids
- relation
Key:
type: object
properties:
id:
type: string
format: uuid
example: "c5747f2f-2a7c-4fe1-b41a-51a5ae290945"
description: API key unique identifier
issuer_id:
type: string
format: uuid
example: "9118de62-c680-46b7-ad0a-21748a52833a"
description: In ID of the entity that issued the token.
type:
type: integer
example: 0
description: API key type. Keys of different type are processed differently.
subject:
type: string
format: string
example: "test@example.com"
description: User's email or service identifier of API key subject.
issued_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the key is generated.
expires_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the Key expires. If this field is missing,
that means that Key is valid indefinitely.
PoliciesReqSchema:
type: object
properties:
object:
type: string
description: |
Specifies an object field for the field.
Object indicates application objects such as ThingID.
subjects:
type: array
minItems: 1
uniqueItems: true
items:
type: string
policies:
type: array
minItems: 1
uniqueItems: true
items:
type: string
parameters:
DomainID:
name: domainID
description: Unique domain identifier.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
Status:
name: status
description: Domain status.
in: query
schema:
type: string
default: enabled
required: false
example: enabled
DomainName:
name: name
description: Domain's name.
in: query
schema:
type: string
required: false
example: "domainName"
Permission:
name: permission
description: permission.
in: query
schema:
type: string
required: false
example: "edit"
ApiKeyId:
name: keyID
description: API Key ID.
in: path
schema:
type: string
format: uuid
required: true
Limit:
name: limit
description: Size of the subset to retrieve.
in: query
schema:
type: integer
default: 10
maximum: 100
minimum: 1
required: false
Offset:
name: offset
description: Number of items to skip during retrieval.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
Metadata:
name: metadata
description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
in: query
required: false
schema:
type: object
additionalProperties: {}
Type:
name: type
description: The type of the API Key.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
Subject:
name: subject
description: The subject of an API Key
in: query
schema:
type: string
required: false
requestBodies:
DomainCreateReq:
description: JSON-formatted document describing the new domain to be registered
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DomainReqObj"
DomainUpdateReq:
description: JSON-formated document describing the name, alias, tags, and metadata of the domain to be updated
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/DomainUpdate"
AssignUserReq:
description: JSON-formated document describing the policy related to assigning users to a domain
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UserDomainRelationReq"
UnassignUsersReq:
description: JSON-formated document describing the policy related to unassigning users to a domain
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UserDomainRelationReq"
KeyRequest:
description: JSON-formatted document describing key request.
required: true
content:
application/json:
schema:
type: object
properties:
type:
type: integer
example: 0
description: API key type. Keys of different type are processed differently.
duration:
type: number
format: integer
example: 23456
description: Number of seconds issued token is valid for.
PoliciesReq:
description: JSON-formatted document describing adding policies request.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/PoliciesReqSchema"
responses:
ServiceError:
description: Unexpected server-side error occurred.
DomainCreateRes:
description: Create new domain.
headers:
Location:
schema:
type: string
format: url
description: Registered domain relative URL in the format `/domains/<domainID_id>`
content:
application/json:
schema:
$ref: "#/components/schemas/Domain"
DomainRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Domain"
DomainPermissionRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Permissions"
DomainsPageRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/DomainsPage"
KeyRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Key"
HealthRes:
description: Service Health Check.
content:
application/json:
schema:
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
+597
View File
@@ -0,0 +1,597 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: Magistrala Bootstrap service
description: |
HTTP API for managing platform things configuration.
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:9013
- url: https://localhost:9013
tags:
- name: configs
description: Everything about your Configs
externalDocs:
description: Find out more about Configs
url: https://docs.magistrala.abstractmachines.fr/
paths:
/things/configs:
post:
summary: Adds new config
description: |
Adds new config to the list of config owned by user identified using
the provided access token.
tags:
- configs
requestBody:
$ref: "#/components/requestBodies/ConfigCreateReq"
responses:
'201':
$ref: "#/components/responses/ConfigCreateRes"
'400':
description: Failed due to malformed JSON.
'401':
description: Missing or invalid access token provided.
'415':
description: Missing or invalid content type.
'500':
$ref: "#/components/responses/ServiceError"
get:
summary: Retrieves managed configs
description: |
Retrieves a list of managed configs. Due to performance concerns, data
is retrieved in subsets. The API configs must ensure that the entire
dataset is consumed either by making subsequent requests, or by
increasing the subset size of the initial request.
tags:
- configs
parameters:
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/State"
- $ref: "#/components/parameters/Name"
responses:
'200':
$ref: "#/components/responses/ConfigListRes"
'400':
description: Failed due to malformed query parameters.
'401':
description: Missing or invalid access token provided.
'500':
$ref: "#/components/responses/ServiceError"
/things/configs/{configId}:
get:
summary: Retrieves config info (with channels).
tags:
- configs
parameters:
- $ref: "#/components/parameters/ConfigId"
responses:
'200':
$ref: "#/components/responses/ConfigRes"
'401':
description: Missing or invalid access token provided.
'404':
description: Config does not exist.
'500':
$ref: "#/components/responses/ServiceError"
put:
summary: Updates config info
description: |
Update is performed by replacing the current resource data with values
provided in a request payload. Note that the owner, ID, external ID,
external key, Magistrala Thing ID and key cannot be changed.
tags:
- configs
parameters:
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigUpdateReq"
responses:
'200':
description: Config updated.
'400':
description: Failed due to malformed JSON.
'401':
description: Missing or invalid access token provided.
'404':
description: Config does not exist.
'415':
description: Missing or invalid content type.
'500':
$ref: "#/components/responses/ServiceError"
delete:
summary: Removes a Config
description: |
Removes a Config. In case of successful removal the service will ensure
that the removed config is disconnected from all of the Magistrala channels.
tags:
- configs
parameters:
- $ref: "#/components/parameters/ConfigId"
responses:
'204':
description: Config removed.
'400':
description: Failed due to malformed config ID.
'401':
description: Missing or invalid access token provided.
'500':
$ref: "#/components/responses/ServiceError"
/things/configs/certs/{configId}:
patch:
summary: Updates certs
description: |
Update is performed by replacing the current certificate data with values
provided in a request payload.
tags:
- configs
parameters:
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigCertUpdateReq"
responses:
'200':
description: Config updated.
$ref: "#/components/responses/ConfigUpdateCertsRes"
'400':
description: Failed due to malformed JSON.
'401':
description: Missing or invalid access token provided.
'404':
description: Config does not exist.
'415':
description: Missing or invalid content type.
'500':
$ref: "#/components/responses/ServiceError"
/things/configs/connections/{configId}:
put:
summary: Updates channels the thing is connected to
description: |
Update connections performs update of the channel list corresponding
Thing is connected to.
tags:
- configs
parameters:
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigConnUpdateReq"
responses:
'200':
description: Config updated.
'400':
description: Failed due to malformed JSON.
'401':
description: Missing or invalid access token provided.
'404':
description: Config does not exist.
'415':
description: Missing or invalid content type.
'500':
$ref: "#/components/responses/ServiceError"
/things/bootstrap/{externalId}:
get:
summary: Retrieves configuration.
description: |
Retrieves a configuration with given external ID and external key.
tags:
- configs
security:
- bootstrapAuth: []
parameters:
- $ref: "#/components/parameters/ExternalId"
responses:
'200':
$ref: "#/components/responses/BootstrapConfigRes"
'400':
description: Failed due to malformed JSON.
'401':
description: Missing or invalid external key provided.
'404':
description: Failed to retrieve corresponding config.
'500':
$ref: "#/components/responses/ServiceError"
/things/bootstrap/secure/{externalId}:
get:
summary: Retrieves configuration.
description: |
Retrieves a configuration with given external ID and encrypted external key.
tags:
- configs
security:
- bootstrapEncAuth: []
parameters:
- $ref: "#/components/parameters/ExternalId"
responses:
'200':
$ref: "#/components/responses/BootstrapConfigRes"
'404':
description: |
Failed to retrieve corresponding config.
'500':
$ref: "#/components/responses/ServiceError"
/things/state/{configId}:
put:
summary: Updates Config state.
description: |
Updating state represents enabling/disabling Config, i.e. connecting
and disconnecting corresponding Magistrala Thing to the list of Channels.
tags:
- configs
parameters:
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: '#/components/requestBodies/ConfigStateUpdateReq'
responses:
'204':
description: Config removed.
'400':
description: Failed due to malformed config's ID.
'401':
description: Missing or invalid access token provided.
'500':
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
responses:
'200':
$ref: "#/components/responses/HealthRes"
'500':
$ref: "#/components/responses/ServiceError"
components:
schemas:
State:
type: integer
enum: [0, 1]
Config:
type: object
properties:
thing_id:
type: string
format: uuid
description: Corresponding Magistrala Thing ID.
magistrala_key:
type: string
format: uuid
description: Corresponding Magistrala Thing key.
channels:
type: array
minItems: 0
items:
type: object
properties:
id:
type: string
format: uuid
description: Channel unique identifier.
name:
type: string
description: Name of the Channel.
metadata:
type: object
description: Custom metadata related to the Channel.
external_id:
type: string
description: External ID (MAC address or some unique identifier).
external_key:
type: string
description: External key.
content:
type: string
description: Free-form custom configuration.
state:
$ref: "#/components/schemas/State"
client_cert:
type: string
description: Client certificate.
ca_cert:
type: string
description: Issuing CA certificate.
required:
- external_id
- external_key
ConfigList:
type: object
properties:
total:
type: integer
description: Total number of results.
minimum: 0
offset:
type: integer
description: Number of items to skip during retrieval.
minimum: 0
default: 0
limit:
type: integer
description: Size of the subset to retrieve.
maximum: 100
default: 10
configs:
type: array
minItems: 0
uniqueItems: true
items:
$ref: "#/components/schemas/Config"
required:
- configs
BootstrapConfig:
type: object
properties:
thing_id:
type: string
format: uuid
description: Corresponding Magistrala Thing ID.
thing_key:
type: string
format: uuid
description: Corresponding Magistrala Thing key.
channels:
type: array
minItems: 0
items:
type: string
content:
type: string
description: Free-form custom configuration.
client_cert:
type: string
description: Client certificate.
client_key:
type: string
description: Key for the client_cert.
ca_cert:
type: string
description: Issuing CA certificate.
required:
- thing_id
- thing_key
- channels
- content
ConfigUpdateCerts:
type: object
properties:
thing_id:
type: string
format: uuid
description: Corresponding Magistrala Thing ID.
client_cert:
type: string
description: Client certificate.
client_key:
type: string
description: Key for the client_cert.
ca_cert:
type: string
description: Issuing CA certificate.
required:
- thing_id
- thing_key
- channels
- content
parameters:
ConfigId:
name: configId
description: Unique Config identifier. It's the ID of the corresponding Thing.
in: path
schema:
type: string
format: uuid
required: true
ExternalId:
name: externalId
description: Unique Config identifier provided by external entity.
in: path
schema:
type: string
required: true
Limit:
name: limit
description: Size of the subset to retrieve.
in: query
schema:
type: integer
default: 10
maximum: 100
minimum: 1
required: false
Offset:
name: offset
description: Number of items to skip during retrieval.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
State:
name: state
description: A state of items
in: query
schema:
$ref: "#/components/schemas/State"
required: false
Name:
name: name
description: Name of the config. Search by name is partial-match and case-insensitive.
in: query
schema:
type: string
required: false
requestBodies:
ConfigCreateReq:
description: JSON-formatted document describing the new config.
required: true
content:
application/json:
schema:
type: object
properties:
external_id:
type: string
description: External ID (MAC address or some unique identifier).
external_key:
type: string
description: External key.
thing_id:
type: string
description: ID of the corresponding Magistrala Thing.
channels:
type: array
minItems: 0
items:
type: string
content:
type: string
name:
type: string
client_cert:
type: string
description: Thing Certificate.
client_key:
type: string
description: Thing Private Key.
ca_cert:
type: string
required:
- external_id
- external_key
ConfigUpdateReq:
description: JSON-formatted document describing the updated thing.
content:
application/json:
schema:
type: object
properties:
content:
type: string
name:
type: string
required:
- content
- name
ConfigCertUpdateReq:
description: JSON-formatted document describing the updated thing.
content:
application/json:
schema:
type: object
properties:
client_cert:
type: string
client_key:
type: string
ca_cert:
type: string
ConfigConnUpdateReq:
description: Array if IDs the thing is be connected to.
content:
application/json:
schema:
type: object
properties:
channels:
type: array
minItems: 0
items:
type: string
ConfigStateUpdateReq:
description: Update the state of the Config.
content:
application/json:
schema:
type: object
properties:
state:
$ref: "#/components/schemas/State"
responses:
ConfigCreateRes:
description: Config registered.
headers:
Location:
content:
text/plain:
schema:
type: string
description: Created configuration's relative URL (i.e. /things/configs/{configId}).
ConfigListRes:
description: Data retrieved. Configs from this list don't contain channels.
content:
application/json:
schema:
$ref: "#/components/schemas/ConfigList"
ConfigRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Config"
BootstrapConfigRes:
description: |
Data retrieved. If secure, a response is encrypted using
the secret key, so the response is in the binary form.
content:
application/json:
schema:
$ref: "#/components/schemas/BootstrapConfig"
ServiceError:
description: Unexpected server-side error occurred.
HealthRes:
description: Service Health Check.
content:
application/json:
schema:
$ref: "./schemas/HealthInfo.yml"
ConfigUpdateCertsRes:
description: Data retrieved. Config certs updated.
content:
application/json:
schema:
$ref: "#/components/schemas/ConfigUpdateCerts"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
bootstrapAuth:
type: http
scheme: bearer
bearerFormat: string
description: |
* Things access: "Authorization: Thing <external_key>"
bootstrapEncAuth:
type: http
scheme: bearer
bearerFormat: aes-sha256-uuid
description: |
* Things access: "Authorization: Thing <external_enc_key>"
Hex-encoded configuration external key encrypted using
the AES algorithm and SHA256 sum of the external key
itself as an encryption key.
security:
- bearerAuth: []
+274
View File
@@ -0,0 +1,274 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: Magistrala Certs service
description: |
HTTP API for Certs service
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:9019
- url: https://localhost:9019
tags:
- name: certs
description: Everything about your Certs
externalDocs:
description: Find out more about certs
url: https://docs.magistrala.abstractmachines.fr/
paths:
/certs:
post:
summary: Creates a certificate for thing
description: Creates a certificate for thing
tags:
- certs
requestBody:
$ref: "#/components/requestBodies/CertReq"
responses:
'201':
description: Created
'400':
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
'500':
description: Unexpected server-side error ocurred.
/certs/{certID}:
get:
summary: Retrieves a certificate
description: |
Retrieves a certificate for a given cert ID.
tags:
- certs
parameters:
- $ref: "#/components/parameters/CertID"
responses:
'200':
$ref: "#/components/responses/CertRes"
'400':
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
'404':
description: |
Failed to retrieve corresponding certificate.
'500':
$ref: "#/components/responses/ServiceError"
delete:
summary: Revokes a certificate
description: |
Revokes a certificate for a given cert ID.
tags:
- certs
parameters:
- $ref: "#/components/parameters/CertID"
responses:
'200':
$ref: "#/components/responses/RevokeRes"
"401":
description: Missing or invalid access token provided.
'404':
description: |
Failed to revoke corresponding certificate.
'500':
$ref: "#/components/responses/ServiceError"
/serials/{thingID}:
get:
summary: Retrieves certificates' serial IDs
description: |
Retrieves a list of certificates' serial IDs for a given thing ID.
tags:
- certs
parameters:
- $ref: "#/components/parameters/ThingID"
responses:
'200':
$ref: "#/components/responses/SerialsPageRes"
'400':
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
'404':
description: |
Failed to retrieve corresponding certificates.
'500':
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
responses:
'200':
$ref: "#/components/responses/HealthRes"
'500':
$ref: "#/components/responses/ServiceError"
components:
parameters:
ThingID:
name: thingID
description: Thing ID
in: path
schema:
type: string
format: uuid
required: true
CertID:
name: certID
description: Serial of certificate
in: path
schema:
type: string
format: uuid
required: true
schemas:
Cert:
type: object
properties:
thing_id:
type: string
format: uuid
description: Corresponding Magistrala Thing ID.
client_cert:
type: string
description: Client Certificate.
client_key:
type: string
description: Key for the client_cert.
issuing_ca:
type: string
description: CA Certificate that is used to issue client certs, usually intermediate.
serial:
type: string
description: Certificate serial
expire:
type: string
description: Certificate expiry date
Serial:
type: object
properties:
serial:
type: string
description: Certificate serial
CertsPage:
type: object
properties:
certs:
type: array
minItems: 0
uniqueItems: true
items:
$ref: "#/components/schemas/Cert"
total:
type: integer
description: Total number of items.
offset:
type: integer
description: Number of items to skip during retrieval.
limit:
type: integer
description: Maximum number of items to return in one page.
SerialsPage:
type: object
properties:
serials:
type: array
description: Certificate serials IDs.
minItems: 0
uniqueItems: true
items:
type: string
total:
type: integer
description: Total number of items.
offset:
type: integer
description: Number of items to skip during retrieval.
limit:
type: integer
description: Maximum number of items to return in one page.
Revoke:
type: object
properties:
revocation_time:
type: string
description: Certificate revocation time
requestBodies:
CertReq:
description: |
Issues a certificate that is required for mTLS. To create a certificate for a thing
provide a thing id, data identifying particular thing will be embedded into the Certificate.
x509 and ECC certificates are supported when using when Vault is used as PKI.
content:
application/json:
schema:
type: object
required:
- thing_id
- ttl
properties:
thing_id:
type: string
format: uuid
ttl:
type: string
example: "10h"
responses:
ServiceError:
description: Unexpected server-side error occurred.
CertRes:
description: Certificate data.
content:
application/json:
schema:
$ref: "#/components/schemas/Cert"
CertsPageRes:
description: Certificates page.
content:
application/json:
schema:
$ref: "#/components/schemas/CertsPage"
SerialsPageRes:
description: Serials page.
content:
application/json:
schema:
$ref: "#/components/schemas/SerialsPage"
RevokeRes:
description: Certificate revoked.
content:
application/json:
schema:
$ref: "#/components/schemas/Revoke"
HealthRes:
description: Service Health Check.
content:
application/json:
schema:
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
@@ -9,29 +9,28 @@ info:
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@absmach.eu
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.18.5
url: https://github.com/absmach/magistrala/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:9014
- url: https://localhost:9014
- url: http://localhost:9015
- url: https://localhost:9015
tags:
- name: notifiers
description: Everything about your Notifiers
externalDocs:
description: Find out more about notifiers
url: https://magistrala.absmach.eu/docs/
url: https://docs.magistrala.abstractmachines.fr/
paths:
/subscriptions:
post:
operationId: createSubscription
summary: Create subscription
description: Creates a new subscription give a topic and contact.
tags:
@@ -43,20 +42,13 @@ paths:
$ref: "#/components/responses/Create"
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"409":
description: Failed due to using an existing topic and contact.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listSubscriptions
summary: List subscriptions
description: List subscriptions given list parameters.
tags:
@@ -73,17 +65,10 @@ paths:
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/subscriptions/{id}:
get:
operationId: viewSubscription
summary: Get subscription with the provided id
description: Retrieves a subscription with the provided id.
tags:
@@ -93,20 +78,11 @@ paths:
responses:
"200":
$ref: "#/components/responses/View"
"400":
description: Failed due to malformed ID.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: removeSubscription
summary: Delete subscription with the provided id
description: Removes a subscription with the provided id.
tags:
@@ -118,12 +94,6 @@ paths:
description: Subscription removed
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/health:
@@ -131,11 +101,10 @@ paths:
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
"200":
'200':
$ref: "#/components/responses/HealthRes"
"500":
'500':
$ref: "#/components/responses/ServiceError"
components:
@@ -155,7 +124,7 @@ components:
description: An id of the owner who created subscription.
topic:
type: string
example: topic/subtopic
example: topic.subtopic
description: Topic to which the user subscribes.
contact:
type: string
@@ -166,12 +135,12 @@ components:
properties:
topic:
type: string
example: topic/subtopic
example: topic.subtopic
description: Topic to which the user subscribes.
contact:
type: string
example: user@example.com
description: The contact of the user to which the notification will be sent.
description: The contact of the user to which the notification will be sent.
Page:
type: object
properties:
@@ -260,11 +229,6 @@ components:
application/json:
schema:
$ref: "#/components/schemas/Subscription"
links:
delete:
operationId: removeSubscription
parameters:
id: $response.body#/id
Page:
description: Data retrieved.
content:
@@ -276,9 +240,9 @@ components:
HealthRes:
description: Service Health Check.
content:
application/health+json:
application/json:
schema:
$ref: "./schemas/health_info.yaml"
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
@@ -9,11 +9,11 @@ info:
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@absmach.eu
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.18.0
url: https://github.com/absmach/magistrala/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:8008
@@ -24,10 +24,10 @@ tags:
description: Everything about your Messages
externalDocs:
description: Find out more about messages
url: https://magistrala.absmach.eu/docs/
url: https://docs.magistrala.abstractmachines.fr/
paths:
/m/{domainPrefix}/c/{channelPrefix}:
/channels/{id}/messages:
post:
summary: Sends message to the communication channel
description: |
@@ -36,8 +36,7 @@ paths:
tags:
- messages
parameters:
- $ref: "#/components/parameters/domainPrefix"
- $ref: "#/components/parameters/channelPrefix"
- $ref: "#/components/parameters/ID"
requestBody:
$ref: "#/components/requestBodies/MessageReq"
responses:
@@ -47,24 +46,21 @@ paths:
description: Message discarded due to its malformed content.
"401":
description: Missing or invalid access token provided.
"403":
description: Access denied to the requested resource.
"404":
description: Message discarded due to invalid channel id.
"415":
description: Message discarded due to invalid or missing content type.
"500":
'500':
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
"200":
'200':
$ref: "#/components/responses/HealthRes"
"500":
'500':
$ref: "#/components/responses/ServiceError"
components:
@@ -132,21 +128,13 @@ components:
$ref: "#/components/schemas/SenMLRecord"
parameters:
domainPrefix:
name: domainPrefix
description: ID or route of the domain associated with the channel and client.
ID:
name: id
description: Unique channel identifier.
in: path
schema:
type: string
example: mydomain
required: true
channelPrefix:
name: channelPrefix
description: ID or route of the channel connected to the client.
in: path
schema:
type: string
example: mychannel
format: uuid
required: true
requestBodies:
@@ -166,13 +154,13 @@ components:
responses:
ServiceError:
description: Unexpected server-side error occurred.
HealthRes:
description: Service Health Check.
content:
application/health+json:
application/json:
schema:
$ref: "./schemas/health_info.yaml"
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
@@ -180,13 +168,13 @@ components:
scheme: bearer
bearerFormat: uuid
description: |
* Client access: "Authorization: Client <client_key>"
* Thing access: "Authorization: Thing <thing_key>"
basicAuth:
type: http
scheme: basic
description: |
* Clients access: "Authorization: Basic <base64-encoded_credentials>"
* Things access: "Authorization: Basic <base64-encoded_credentials>"
security:
- bearerAuth: []
+486
View File
@@ -0,0 +1,486 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.3
info:
title: Magistrala Invitations Service
description: |
This is the Invitations Server based on the OpenAPI 3.0 specification. It is the HTTP API for managing platform invitations. You can now help us improve the API whether it's by making changes to the definition itself or to the code.
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:9020
- url: https://localhost:9020
tags:
- name: Invitations
description: Everything about your Invitations
externalDocs:
description: Find out more about Invitations
url: https://docs.magistrala.abstractmachines.fr/
paths:
/invitations:
post:
tags:
- Invitations
summary: Send invitation
description: |
Send invitation to user to join domain.
requestBody:
$ref: "#/components/requestBodies/SendInvitationReq"
security:
- bearerAuth: []
responses:
"201":
description: Invitation sent.
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
get:
tags:
- Invitations
summary: List invitations
description: |
Retrieves a list of invitations. Due to performance concerns, data
is retrieved in subsets. The API must ensure that the entire
dataset is consumed either by making subsequent requests, or by
increasing the subset size of the initial request.
parameters:
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/UserID"
- $ref: "#/components/parameters/InvitedBy"
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/Relation"
- $ref: "#/components/parameters/State"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/InvitationPageRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: |
Missing or invalid access token provided.
This endpoint is available only for administrators.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/invitations/accept:
post:
summary: Accept invitation
description: |
Current logged in user accepts invitation to join domain.
tags:
- Invitations
security:
- bearerAuth: []
requestBody:
$ref: "#/components/requestBodies/AcceptInvitationReq"
responses:
"200":
description: Invitation accepted.
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
/invitations/{user_id}/{domain_id}:
get:
summary: Retrieves a specific invitation
description: |
Retrieves a specific invitation that is identifier by the user ID and domain ID.
tags:
- Invitations
parameters:
- $ref: "#/components/parameters/user_id"
- $ref: "#/components/parameters/domain_id"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/InvitationRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
summary: Deletes a specific invitation
description: |
Deletes a specific invitation that is identifier by the user ID and domain ID.
tags:
- Invitations
parameters:
- $ref: "#/components/parameters/user_id"
- $ref: "#/components/parameters/domain_id"
security:
- bearerAuth: []
responses:
"204":
description: Invitation deleted.
"400":
description: Failed due to malformed JSON.
"404":
description: Failed due to non existing user.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
SendInvitationReqObj:
type: object
properties:
user_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: User unique identifier.
domain_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Domain unique identifier.
relation:
type: string
enum:
- administrator
- editor
- viewer
- member
- domain
- parent_group
- role_group
- group
- platform
example: editor
description: Relation between user and domain.
resend:
type: boolean
example: true
description: Resend invitation.
required:
- user_id
- domain_id
- relation
Invitation:
type: object
properties:
invited_by:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: User unique identifier.
user_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: User unique identifier.
domain_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Domain unique identifier.
relation:
type: string
enum:
- administrator
- editor
- viewer
- member
- domain
- parent_group
- role_group
- group
- platform
example: editor
description: Relation between user and domain.
created_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the group was created.
updated_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the group was created.
confirmed_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the group was created.
xml:
name: invitation
InvitationPage:
type: object
properties:
invitations:
type: array
minItems: 0
uniqueItems: true
items:
$ref: "#/components/schemas/Invitation"
total:
type: integer
example: 1
description: Total number of items.
offset:
type: integer
description: Number of items to skip during retrieval.
limit:
type: integer
example: 10
description: Maximum number of items to return in one page.
required:
- invitations
- total
- offset
Error:
type: object
properties:
error:
type: string
description: Error message
example: { "error": "malformed entity specification" }
HealthRes:
type: object
properties:
status:
type: string
description: Service status.
enum:
- pass
version:
type: string
description: Service version.
example: 0.14.0
commit:
type: string
description: Service commit hash.
example: 7d6f4dc4f7f0c1fa3dc24eddfb18bb5073ff4f62
description:
type: string
description: Service description.
example: <service_name> service
build_time:
type: string
description: Service build time.
example: 1970-01-01_00:00:00
parameters:
Offset:
name: offset
description: Number of items to skip during retrieval.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
example: "0"
Limit:
name: limit
description: Size of the subset to retrieve.
in: query
schema:
type: integer
default: 10
maximum: 10
minimum: 1
required: false
example: "10"
UserID:
name: user_id
description: Unique user identifier.
in: query
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
user_id:
name: user_id
description: Unique user identifier.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
DomainID:
name: domain_id
description: Unique identifier for a domain.
in: query
schema:
type: string
format: uuid
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
domain_id:
name: domain_id
description: Unique identifier for a domain.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
InvitedBy:
name: invited_by
description: Unique identifier for a user that invited the user.
in: query
schema:
type: string
format: uuid
required: false
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
Relation:
name: relation
description: Relation between user and domain.
in: query
schema:
type: string
enum:
- administrator
- editor
- viewer
- member
- domain
- parent_group
- role_group
- group
- platform
required: false
example: editor
State:
name: state
description: Invitation state.
in: query
schema:
type: string
enum:
- pending
- accepted
- all
required: false
example: accepted
requestBodies:
SendInvitationReq:
description: JSON-formatted document describing request for sending invitation
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/SendInvitationReqObj"
AcceptInvitationReq:
description: JSON-formatted document describing request for accepting invitation
required: true
content:
application/json:
schema:
type: object
properties:
domain_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: Domain unique identifier.
required:
- domain_id
responses:
InvitationRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Invitation"
InvitationPageRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/InvitationPage"
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "#/components/schemas/HealthRes"
ServiceError:
description: Unexpected server-side error occurred.
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* User access: "Authorization: Bearer <user_access_token>"
security:
- bearerAuth: []
+116
View File
@@ -0,0 +1,116 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: Magistrala Provision service
description: |
HTTP API for Provision service
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:9016
- url: https://localhost:9016
tags:
- name: provision
description: Everything about your Provision
externalDocs:
description: Find out more about provision
url: https://docs.magistrala.abstractmachines.fr/
paths:
/mapping:
post:
summary: Adds new device to proxy
description: Adds new device to proxy
tags:
- provision
requestBody:
$ref: "#/components/requestBodies/ProvisionReq"
responses:
'201':
description: Created
'400':
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
'500':
$ref: "#/components/responses/ServiceError"
get:
summary: Gets current mapping.
description: Gets current mapping. This can be used in UI
so that when bootstrap config is created from UI matches
configuration created with provision service.
tags:
- provision
responses:
'200':
$ref: "#/components/responses/ProvisionRes"
"401":
description: Missing or invalid access token provided.
'500':
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
responses:
'200':
$ref: "#/components/responses/HealthRes"
'500':
$ref: "#/components/responses/ServiceError"
components:
requestBodies:
ProvisionReq:
description: MAC address of device or other identifier
content:
application/json:
schema:
type: object
required:
- external_id
- external_key
properties:
external_id:
type: string
external_key:
type: string
name:
type: string
responses:
ServiceError:
description: Unexpected server-side error occurred.
ProvisionRes:
description: Current mapping JSON representation.
content:
application/json:
schema:
type: object
HealthRes:
description: Service Health Check.
content:
application/json:
schema:
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
@@ -9,33 +9,34 @@ info:
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@absmach.eu
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.18.5
url: https://github.com/absmach/magistrala/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:9003
- url: https://localhost:9003
- url: http://localhost:9005
- url: https://localhost:9005
- url: http://localhost:9007
- url: https://localhost:9007
- url: http://localhost:9009
- url: https://localhost:9009
- url: http://localhost:9011
- url: https://localhost:9011
tags:
- name: readers
description: Everything about your Readers
externalDocs:
description: Find out more about readers
url: https://magistrala.absmach.eu/docs/
url: https://docs.magistrala.abstractmachines.fr/
paths:
/{domainID}/channels/{chanId}/messages:
/channels/{chanId}/messages:
get:
operationId: getMessages
summary: Retrieves messages sent to single channel
description: |
Retrieves a list of messages sent to specific channel. Due to
@@ -45,7 +46,6 @@ paths:
tags:
- readers
parameters:
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/ChanId"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
@@ -57,30 +57,24 @@ paths:
- $ref: "#/components/parameters/DataValue"
- $ref: "#/components/parameters/From"
- $ref: "#/components/parameters/To"
- $ref: "#/components/parameters/Aggregation"
- $ref: "#/components/parameters/Interval"
responses:
"200":
'200':
$ref: "#/components/responses/MessagesPageRes"
"400":
'400':
description: Failed due to malformed query parameters.
"401":
'401':
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"500":
'500':
$ref: "#/components/responses/ServiceError"
/health:
get:
operationId: health
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
"200":
'200':
$ref: "#/components/responses/HealthRes"
"500":
'500':
$ref: "#/components/responses/ServiceError"
components:
@@ -142,14 +136,6 @@ components:
description: Time of updating measurement.
parameters:
DomainID:
name: domainID
description: Unique domain identifier.
in: path
schema:
type: string
format: uuid
required: true
ChanId:
name: chanId
description: Unique channel identifier.
@@ -240,7 +226,6 @@ components:
in: query
schema:
type: number
example: 1709218556069
required: false
To:
name: to
@@ -248,34 +233,6 @@ components:
in: query
schema:
type: number
example: 1709218757503
required: false
Aggregation:
name: aggregation
description: Aggregation function.
in: query
schema:
type: string
enum:
- MAX
- AVG
- MIN
- SUM
- COUNT
- max
- min
- sum
- avg
- count
example: MAX
required: false
Interval:
name: interval
description: Aggregation interval.
in: query
schema:
type: string
example: 10s
required: false
responses:
@@ -290,9 +247,9 @@ components:
HealthRes:
description: Service Health Check.
content:
application/health+json:
application/json:
schema:
$ref: "./schemas/health_info.yaml"
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
@@ -11,11 +11,11 @@ properties:
version:
type: string
description: Service version.
example: v0.18.0
example: 0.0.1
commit:
type: string
description: Service commit hash.
example: 73362210dd2e04e389eaddb802cab3fe03976593
example: 7d6f4dc4f7f0c1fa3dc24eddfb18bb5073ff4f62
description:
type: string
description: Service description.
@@ -23,8 +23,4 @@ properties:
build_time:
type: string
description: Service build time.
example: 2024-02-01_12:18:15
instance_id:
type: string
description: Service instance ID.
example: 8edbf8af-7db7-4218-bb4f-a8a929ff5266
example: 1970-01-01_00:00:00
File diff suppressed because it is too large Load Diff
+402
View File
@@ -0,0 +1,402 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: Magistrala twins service
description: |
HTTP API for managing digital twins and their states.
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@mainflux.com
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/master/LICENSE
version: 0.14.0
servers:
- url: http://localhost:9018
- url: https://localhost:9018
tags:
- name: twins
description: Everything about your Twins
externalDocs:
description: Find out more about twins
url: https://docs.magistrala.abstractmachines.fr/
paths:
/twins:
post:
summary: Adds new twin
description: |
Adds new twin to the list of twins owned by user identified using
the provided access token.
tags:
- twins
requestBody:
$ref: "#/components/requestBodies/TwinReq"
responses:
'201':
$ref: "#/components/responses/TwinCreateRes"
'400':
description: Failed due to malformed JSON.
'401':
description: Missing or invalid access token provided.
'415':
description: Missing or invalid content type.
'500':
$ref: '#/components/responses/ServiceError'
get:
summary: Retrieves twins
description: |
Retrieves a list of twins. Due to performance concerns, data
is retrieved in subsets.
tags:
- twins
parameters:
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Name'
- $ref: '#/components/parameters/Metadata'
responses:
'200':
$ref: '#/components/responses/TwinsPageRes'
'400':
description: Failed due to malformed query parameters.
'401':
description: Missing or invalid access token provided.
'500':
$ref: '#/components/responses/ServiceError'
/twins/{twinID}:
get:
summary: Retrieves twin info
tags:
- twins
parameters:
- $ref: '#/components/parameters/TwinID'
responses:
'200':
$ref: '#/components/responses/TwinRes'
'400':
description: Failed due to malformed twin's ID.
'401':
description: Missing or invalid access token provided.
'404':
description: Twin does not exist.
'500':
$ref: '#/components/responses/ServiceError'
put:
summary: Updates twin info
description: |
Update is performed by replacing the current resource data with values
provided in a request payload. Note that the twin's ID cannot be changed.
tags:
- twins
parameters:
- $ref: '#/components/parameters/TwinID'
requestBody:
$ref: '#/components/requestBodies/TwinReq'
responses:
'200':
description: Twin updated.
'400':
description: Failed due to malformed twin's ID or malformed JSON.
'401':
description: Missing or invalid access token provided.
'404':
description: Twin does not exist.
'415':
description: Missing or invalid content type.
'500':
$ref: '#/components/responses/ServiceError'
delete:
summary: Removes a twin
description: Removes a twin.
tags:
- twins
parameters:
- $ref: '#/components/parameters/TwinID'
responses:
'204':
description: Twin removed.
'400':
description: Failed due to malformed twin's ID.
'401':
description: Missing or invalid access token provided
'404':
description: Twin does not exist.
'500':
$ref: '#/components/responses/ServiceError'
/states/{twinID}:
get:
summary: Retrieves states of twin with id twinID
description: |
Retrieves a list of states. Due to performance concerns, data
is retrieved in subsets.
tags:
- states
parameters:
- $ref: '#/components/parameters/TwinID'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Offset'
responses:
'200':
$ref: '#/components/responses/StatesPageRes'
'400':
description: Failed due to malformed query parameters.
'401':
description: Missing or invalid access token provided.
'404':
description: Twin does not exist.
'500':
$ref: '#/components/responses/ServiceError'
/health:
get:
summary: Retrieves service health check info.
tags:
- health
responses:
'200':
$ref: "#/components/responses/HealthRes"
'500':
$ref: "#/components/responses/ServiceError"
components:
parameters:
Limit:
name: limit
description: Size of the subset to retrieve.
in: query
schema:
type: integer
default: 10
maximum: 100
minimum: 1
required: false
Offset:
name: offset
description: Number of items to skip during retrieval.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
Name:
name: name
description: Twin name
in: query
schema:
type: string
required: false
Metadata:
name: metadata
description: |
Metadata filter. Filtering is performed matching the parameter with
metadata on top level. Parameter is json.
in: query
schema:
type: string
minimum: 0
required: false
TwinID:
name: twinID
description: Unique twin identifier.
in: path
schema:
type: string
format: uuid
minimum: 1
required: true
schemas:
Attribute:
type: object
properties:
name:
type: string
description: Name of the attribute.
channel:
type: string
description: Magistrala channel used by attribute.
subtopic:
type: string
description: Subtopic used by attribute.
persist_state:
type: boolean
description: Trigger state creation based on the attribute.
Definition:
type: object
properties:
delta:
type: number
description: Minimal time delay before new state creation.
attributes:
type: array
minItems: 0
uniqueItems: true
items:
$ref: '#/components/schemas/Attribute'
TwinReqObj:
type: object
properties:
name:
type: string
description: Free-form twin name.
metadata:
type: object
description: Arbitrary, object-encoded twin's data.
definition:
$ref: '#/components/schemas/Definition'
TwinResObj:
type: object
properties:
owner:
type: string
description: Email address of Magistrala user that owns twin.
id:
type: string
format: uuid
description: Unique twin identifier generated by the service.
name:
type: string
description: Free-form twin name.
revision:
type: number
description: Oridnal revision number of twin.
created:
type: string
format: date
description: Twin creation date and time.
updated:
type: string
format: date
description: Twin update date and time.
definitions:
type: array
minItems: 0
uniqueItems: true
items:
$ref: '#/components/schemas/Definition'
metadata:
type: object
description: Arbitrary, object-encoded twin's data.
TwinsPage:
type: object
properties:
twins:
type: array
minItems: 0
uniqueItems: true
items:
$ref: '#/components/schemas/TwinResObj'
total:
type: integer
description: Total number of items.
offset:
type: integer
description: Number of items to skip during retrieval.
limit:
type: integer
description: Maximum number of items to return in one page.
required:
- twins
State:
type: object
properties:
twin_id:
type: string
format: uuid
description: ID of twin state belongs to.
id:
type: number
description: State position in a time row of states.
created:
type: string
format: date
description: State creation date.
payload:
type: object
description: Object-encoded states's payload.
StatesPage:
type: object
properties:
twins:
type: array
minItems: 0
uniqueItems: true
items:
$ref: '#/components/schemas/State'
total:
type: integer
description: Total number of items.
offset:
type: integer
description: Number of items to skip during retrieval.
limit:
type: integer
description: Maximum number of items to return in one page.
required:
- twins
requestBodies:
TwinReq:
description: JSON-formatted document describing the twin to create or update.
content:
application/json:
schema:
$ref: '#/components/schemas/TwinReqObj'
required: true
responses:
TwinCreateRes:
description: Created twin's relative URL (i.e. /twins/{twinID}).
headers:
Location:
content:
text/plain:
schema:
type: string
TwinRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: '#/components/schemas/TwinResObj'
TwinsPageRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: '#/components/schemas/TwinsPage'
StatesPageRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: '#/components/schemas/StatesPage'
ServiceError:
description: Unexpected server-side error occurred.
HealthRes:
description: Service Health Check.
content:
application/json:
schema:
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
File diff suppressed because it is too large Load Diff
-5
View File
@@ -1,5 +0,0 @@
# Magistrala OpenAPI Specification
This folder contains an OpenAPI specifications for Magistrala API.
View specification in Swagger UI at [docs.api.magistrala.absmach.eu](https://docs.api.magistrala.absmach.eu)
-508
View File
@@ -1,508 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: Magistrala Alarms API
description: |
HTTP API for managing alarms service.
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@absmach.eu
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.18.5
servers:
- url: http://localhost:8050
- url: https://localhost:8050
tags:
- name: alarms
description: Everything about your Alarms
externalDocs:
description: Find out more about alarms
url: https://magistrala.absmach.eu/docs/
paths:
/{domainID}/alarms:
get:
operationId: listAlarms
summary: List Alarms
description: |
Retrieves a list of alarms with optional filtering
tags:
- alarms
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/Order'
- $ref: '#/components/parameters/Dir'
- $ref: '#/components/parameters/ChannelID'
- $ref: '#/components/parameters/ClientID'
- $ref: '#/components/parameters/Subtopic'
- $ref: '#/components/parameters/RuleID'
- $ref: '#/components/parameters/Status'
- $ref: '#/components/parameters/AssigneeID'
- $ref: '#/components/parameters/Severity'
- $ref: '#/components/parameters/UpdatedBy'
- $ref: '#/components/parameters/AssignedBy'
- $ref: '#/components/parameters/AcknowledgedBy'
- $ref: '#/components/parameters/ResolvedBy'
- $ref: '#/components/parameters/CreatedFrom'
- $ref: '#/components/parameters/CreatedTo'
security:
- bearerAuth: []
responses:
'200':
$ref: '#/components/responses/AlarmsPageRes'
'400':
description: Failed due to malformed query parameters
'401':
description: Missing or invalid access token
'422':
description: Database can't process request
'500':
$ref: '#/components/responses/ServiceError'
/{domainID}/alarms/{alarmID}:
get:
operationId: viewAlarm
summary: View Alarm
description: Retrieves an alarm by ID
tags:
- alarms
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/AlarmID'
security:
- bearerAuth: []
responses:
'200':
$ref: '#/components/responses/AlarmRes'
'400':
description: Missing or invalid alarm ID
'401':
description: Missing or invalid access token
'403':
description: Failed to perform authorization over the entity
'404':
description: Alarm does not exist
'422':
description: Database can't process request
'500':
$ref: '#/components/responses/ServiceError'
put:
operationId: updateAlarm
summary: Update Alarm
description: Updates an existing alarm
tags:
- alarms
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/AlarmID'
security:
- bearerAuth: []
requestBody:
$ref: '#/components/requestBodies/AlarmUpdateReq'
responses:
'200':
$ref: '#/components/responses/AlarmRes'
'400':
description: Failed due to malformed JSON
'401':
description: Missing or invalid access token
'403':
description: Failed to perform authorization over the entity
'404':
description: Alarm does not exist
'415':
description: Missing or invalid content type
'422':
description: Database can't process request
'500':
$ref: '#/components/responses/ServiceError'
delete:
operationId: deleteAlarm
summary: Delete Alarm
description: Deletes an alarm
tags:
- alarms
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/AlarmID'
security:
- bearerAuth: []
responses:
'204':
description: Alarm deleted successfully
'400':
description: Failed due to malformed alarm ID
'401':
description: Missing or invalid access token
'403':
description: Failed to perform authorization over the entity
'404':
description: Alarm does not exist
'422':
description: Database can't process request
'500':
$ref: '#/components/responses/ServiceError'
/health:
get:
summary: Retrieves service health check info
tags:
- health
security: []
responses:
'200':
$ref: '#/components/responses/HealthRes'
'500':
$ref: '#/components/responses/ServiceError'
components:
schemas:
Alarm:
type: object
properties:
id:
type: string
description: Unique alarm identifier
readOnly: true
rule_id:
type: string
description: Rule ID that triggered this alarm
domain_id:
type: string
description: Domain ID this alarm belongs to
channel_id:
type: string
description: Channel ID where the alarm was triggered
client_id:
type: string
description: Client ID that triggered the alarm
subtopic:
type: string
description: Subtopic associated with the alarm
status:
type: string
description: Alarm status
enum: [active, cleared]
measurement:
type: string
description: Measurement that triggered the alarm
value:
type: string
description: Value that triggered the alarm
unit:
type: string
description: Unit of measurement
threshold:
type: string
description: Threshold value that was exceeded
cause:
type: string
description: Cause or description of the alarm
severity:
type: integer
description: Severity level (0-100)
minimum: 0
maximum: 100
assignee_id:
type: string
description: ID of the user assigned to this alarm
created_at:
type: string
format: date-time
description: Creation timestamp
readOnly: true
updated_at:
type: string
format: date-time
description: Last update timestamp
readOnly: true
updated_by:
type: string
description: User who last updated the alarm
readOnly: true
assigned_at:
type: string
format: date-time
description: When the alarm was assigned
readOnly: true
assigned_by:
type: string
description: User who assigned the alarm
readOnly: true
acknowledged_at:
type: string
format: date-time
description: When the alarm was acknowledged
readOnly: true
acknowledged_by:
type: string
description: User who acknowledged the alarm
readOnly: true
resolved_at:
type: string
format: date-time
description: When the alarm was resolved
readOnly: true
resolved_by:
type: string
description: User who resolved the alarm
readOnly: true
metadata:
type: object
description: Custom metadata
additionalProperties: true
AlarmsPage:
type: object
properties:
offset:
type: integer
description: Number of items to skip during retrieval
minimum: 0
default: 0
limit:
type: integer
description: Size of the subset to retrieve
minimum: 1
maximum: 1000
default: 10
total:
type: integer
description: Total number of results
minimum: 0
alarms:
type: array
minItems: 0
items:
$ref: '#/components/schemas/Alarm'
required:
- alarms
- total
- offset
- limit
parameters:
DomainID:
name: domainID
description: Domain ID
in: path
required: true
schema:
type: string
AlarmID:
name: alarmID
description: Alarm ID
in: path
required: true
schema:
type: string
Offset:
name: offset
description: Number of items to skip
in: query
required: false
schema:
type: integer
default: 0
minimum: 0
Limit:
name: limit
description: Size of the subset to retrieve
in: query
required: false
schema:
type: integer
default: 10
minimum: 1
maximum: 1000
Order:
name: order
description: Order by field
in: query
required: false
schema:
type: string
enum: [created_at, updated_at]
default: created_at
Dir:
name: dir
description: Sort direction
in: query
required: false
schema:
type: string
enum: [asc, desc]
default: desc
ChannelID:
name: channel_id
description: Filter by channel ID
in: query
required: false
schema:
type: string
ClientID:
name: client_id
description: Filter by client ID
in: query
required: false
schema:
type: string
Subtopic:
name: subtopic
description: Filter by subtopic
in: query
required: false
schema:
type: string
RuleID:
name: rule_id
description: Filter by rule ID
in: query
required: false
schema:
type: string
Status:
name: status
description: Filter by alarm status
in: query
required: false
schema:
type: string
enum: [active, cleared, all]
default: all
AssigneeID:
name: assignee_id
description: Filter by assignee ID
in: query
required: false
schema:
type: string
Severity:
name: severity
description: Filter by severity level
in: query
required: false
schema:
type: integer
minimum: 0
maximum: 100
UpdatedBy:
name: updated_by
description: Filter by user who updated
in: query
required: false
schema:
type: string
AssignedBy:
name: assigned_by
description: Filter by user who assigned
in: query
required: false
schema:
type: string
AcknowledgedBy:
name: acknowledged_by
description: Filter by user who acknowledged
in: query
required: false
schema:
type: string
ResolvedBy:
name: resolved_by
description: Filter by user who resolved
in: query
required: false
schema:
type: string
CreatedFrom:
name: created_from
description: Filter alarms created after this time (RFC3339 format)
in: query
required: false
schema:
type: string
format: date-time
CreatedTo:
name: created_to
description: Filter alarms created before this time (RFC3339 format)
in: query
required: false
schema:
type: string
format: date-time
requestBodies:
AlarmUpdateReq:
description: JSON-formatted document describing the alarm update
required: true
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: Alarm status
enum: [active, cleared]
assignee_id:
type: string
description: ID of the user assigned to this alarm
severity:
type: integer
description: Severity level (0-100)
minimum: 0
maximum: 100
metadata:
type: object
description: Custom metadata
additionalProperties: true
responses:
AlarmRes:
description: Alarm data retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/Alarm'
links:
update:
operationId: updateAlarm
parameters:
alarmID: $response.body#/id
domainID: $response.body#/domain_id
delete:
operationId: deleteAlarm
parameters:
alarmID: $response.body#/id
domainID: $response.body#/domain_id
AlarmsPageRes:
description: Alarms page retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/AlarmsPage'
ServiceError:
description: Unexpected server-side error occurred
HealthRes:
description: Service Health Check
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yaml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
-851
View File
@@ -1,851 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.3
info:
title: Magistrala Auth Service
description: |
This is the Auth Server based on the OpenAPI 3.0 specification. It is the HTTP API for managing platform users. You can now help us improve the API whether it's by making changes to the definition itself or to the code.
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@absmach.eu
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.18.0
servers:
- url: http://localhost:9001
- url: https://localhost:9001
tags:
- name: Keys
description: Everything about your Keys.
externalDocs:
description: Find out more about keys
url: https://magistrala.absmach.eu/docs/
- name: PATs
description: Everything about your Personal Access Tokens.
externalDocs:
description: Find out more about Personal Access Tokens
url: https://magistrala.absmach.eu/docs/
- name: Health
description: Service health check endpoint.
externalDocs:
description: Find out more about health check
url: https://magistrala.absmach.eu/docs/
paths:
/keys:
post:
operationId: issueKey
tags:
- Keys
summary: Issue API key
description: |
Generates a new API key. Thew new API key will
be uniquely identified by its ID.
requestBody:
$ref: "#/components/requestBodies/KeyRequest"
responses:
"201":
description: Issued new key.
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"409":
description: Failed due to using already existing ID.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/keys/{keyID}:
get:
operationId: getKey
summary: Gets API key details.
description: |
Gets API key details for the given key.
tags:
- Keys
parameters:
- $ref: "#/components/parameters/ApiKeyId"
responses:
"200":
$ref: "#/components/responses/KeyRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"422":
description: Service can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: revokeKey
summary: Revoke API key
description: |
Revoke API key identified by the given ID.
tags:
- Keys
parameters:
- $ref: "#/components/parameters/ApiKeyId"
responses:
"204":
description: Key revoked.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"422":
description: Service can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/pats:
post:
operationId: createPAT
tags:
- PATs
summary: Create a new Personal Access Token
description: |
Creates a new Personal Access Token (PAT) for the authenticated user.
requestBody:
$ref: "#/components/requestBodies/CreatePATRequest"
responses:
"201":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listPATs
tags:
- PATs
summary: List all Personal Access Tokens
description: |
Lists all Personal Access Tokens (PATs) for the authenticated user.
parameters:
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
responses:
"200":
$ref: "#/components/responses/PATsPageRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: clearAllPATs
tags:
- PATs
summary: Remove all Personal Access Tokens
description: |
Removes all Personal Access Tokens (PATs) for the authenticated user.
responses:
"200":
description: All PATs removed successfully.
"401":
description: Missing or invalid access token provided.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}:
get:
operationId: retrievePAT
tags:
- PATs
summary: Retrieve a Personal Access Token
description: |
Retrieves details of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
responses:
"200":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: deletePAT
tags:
- PATs
summary: Delete a Personal Access Token
description: |
Deletes a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
responses:
"204":
description: PAT deleted successfully.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/name:
patch:
operationId: updatePATName
tags:
- PATs
summary: Update Personal Access Token name
description: |
Updates the name of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/UpdatePATNameRequest"
responses:
"202":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/description:
patch:
operationId: updatePATDescription
tags:
- PATs
summary: Update Personal Access Token description
description: |
Updates the description of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/UpdatePATDescriptionRequest"
responses:
"202":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/secret/reset:
patch:
operationId: resetPATSecret
tags:
- PATs
summary: Reset Personal Access Token secret
description: |
Resets the secret of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/ResetPATSecretRequest"
responses:
"200":
$ref: "#/components/responses/PATRes"
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/secret/revoke:
patch:
operationId: revokePATSecret
tags:
- PATs
summary: Revoke Personal Access Token secret
description: |
Revokes the secret of a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
responses:
"204":
description: PAT secret revoked successfully.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/scope:
get:
operationId: listScopes
tags:
- PATs
summary: List scopes for a Personal Access Token
description: |
Lists all scopes for a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
responses:
"200":
$ref: "#/components/responses/ScopesPageRes"
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: clearAllScopes
tags:
- PATs
summary: Remove all scopes from a Personal Access Token
description: |
Removes all scopes from a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
responses:
"200":
description: All scopes removed successfully.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/scope/add:
patch:
operationId: addScope
tags:
- PATs
summary: Add scope to a Personal Access Token
description: |
Adds a scope to a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/AddScopeRequest"
responses:
"200":
description: Scope added successfully.
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"422":
description: Database cannot process the request.
"500":
$ref: "#/components/responses/ServiceError"
/pats/{patID}/scope/remove:
patch:
operationId: removeScope
tags:
- PATs
summary: Remove scope from a Personal Access Token
description: |
Removes a scope from a specific Personal Access Token (PAT).
parameters:
- $ref: "#/components/parameters/PatID"
requestBody:
$ref: "#/components/requestBodies/RemoveScopeRequest"
responses:
"200":
description: Scope removed successfully.
"400":
description: Failed due to malformed JSON or validation errors.
"401":
description: Missing or invalid access token provided.
"404":
description: PAT not found.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- Health
security: []
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
PAT:
type: object
properties:
id:
type: string
format: uuid
example: "c5747f2f-2a7c-4fe1-b41a-51a5ae290945"
description: Personal Access Token unique identifier
user_id:
type: string
format: uuid
example: "9118de62-c680-46b7-ad0a-21748a52833a"
description: User ID of the PAT owner
name:
type: string
example: "My PAT"
description: Name of the Personal Access Token
description:
type: string
example: "Token for automation"
description: Description of the Personal Access Token
secret:
type: string
example: "pat_1234567890abcdef"
description: Secret value of the Personal Access Token
issued_at:
type: string
format: date-time
example: "2019-11-26T13:31:52Z"
description: Time when the PAT was issued
expires_at:
type: string
format: date-time
example: "2020-11-26T13:31:52Z"
description: Time when the PAT expires
updated_at:
type: string
format: date-time
example: "2019-11-26T13:31:52Z"
description: Time when the PAT was last updated
last_used_at:
type: string
format: date-time
example: "2019-11-26T13:31:52Z"
description: Time when the PAT was last used
revoked:
type: boolean
example: false
description: Whether the PAT is revoked
revoked_at:
type: string
format: date-time
example: "2019-11-26T13:31:52Z"
description: Time when the PAT was revoked
PATsPage:
type: object
properties:
total:
type: integer
example: 10
description: Total number of PATs
offset:
type: integer
example: 0
description: Number of items to skip during retrieval
limit:
type: integer
example: 10
description: Size of the subset to retrieve
pats:
type: array
items:
$ref: "#/components/schemas/PAT"
description: List of Personal Access Tokens
Scope:
type: object
properties:
optional_domain_id:
type: string
format: uuid
example: "bb7edb32-2eac-4aad-aebe-ed96fe073879"
description: Optional domain ID for the scope
entity_type:
type: string
enum:
[groups, channels, clients, domains, users, dashboards, messages]
example: "groups"
description: Type of entity the scope applies to
entity_id:
type: string
example: "*"
description: ID of the entity the scope applies to. '*' means all entities of the specified type.
operation:
type: string
enum:
[
create,
read,
list,
update,
delete,
share,
unshare,
publish,
subscribe,
]
example: "read"
description: Operation allowed by this scope
ScopesPage:
type: object
properties:
total:
type: integer
example: 10
description: Total number of scopes
offset:
type: integer
example: 0
description: Number of items to skip during retrieval
limit:
type: integer
example: 10
description: Size of the subset to retrieve
scopes:
type: array
items:
$ref: "#/components/schemas/Scope"
description: List of scopes
Key:
type: object
properties:
id:
type: string
format: uuid
example: "c5747f2f-2a7c-4fe1-b41a-51a5ae290945"
description: API key unique identifier
issuer_id:
type: string
format: uuid
example: "9118de62-c680-46b7-ad0a-21748a52833a"
description: In ID of the entity that issued the token.
type:
type: integer
example: 0
description: API key type. Keys of different type are processed differently.
subject:
type: string
format: string
example: "test@example.com"
description: User's email or service identifier of API key subject.
issued_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the key is generated.
expires_at:
type: string
format: date-time
example: "2019-11-26 13:31:52"
description: Time when the Key expires. If this field is missing,
that means that Key is valid indefinitely.
parameters:
PatID:
name: patID
description: Personal Access Token ID.
in: path
schema:
type: string
format: uuid
required: true
DomainID:
name: domainID
description: Unique domain identifier.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
Status:
name: status
description: Domain status.
in: query
schema:
type: string
default: enabled
required: false
example: enabled
DomainName:
name: name
description: Domain's name.
in: query
schema:
type: string
required: false
example: "domainName"
Permission:
name: permission
description: permission.
in: query
schema:
type: string
required: false
example: "edit"
ApiKeyId:
name: keyID
description: API Key ID.
in: path
schema:
type: string
format: uuid
required: true
Limit:
name: limit
description: Size of the subset to retrieve.
in: query
schema:
type: integer
default: 10
maximum: 100
minimum: 1
required: false
Offset:
name: offset
description: Number of items to skip during retrieval.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
Metadata:
name: metadata
description: Metadata filter. Filtering is performed matching the parameter with metadata on top level. Parameter is json.
in: query
required: false
schema:
type: object
additionalProperties: {}
Type:
name: type
description: The type of the API Key.
in: query
schema:
type: integer
default: 0
minimum: 0
required: false
Subject:
name: subject
description: The subject of an API Key
in: query
schema:
type: string
required: false
requestBodies:
CreatePATRequest:
description: JSON-formatted document describing PAT creation request.
required: true
content:
application/json:
schema:
type: object
required:
- name
- duration
properties:
name:
type: string
minLength: 1
example: "My PAT"
description: Name of the Personal Access Token
description:
type: string
example: "Token for automation"
description: Description of the Personal Access Token
duration:
type: string
pattern: "^[0-9]+(ns|us|µs|ms|s|m|h|d|w|y)$"
example: "30d"
description: Duration for which the PAT is valid. Format is a duration string (e.g. "30d", "24h", "1y").
UpdatePATNameRequest:
description: JSON-formatted document describing PAT name update request.
required: true
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
example: "New PAT Name"
description: New name for the Personal Access Token
UpdatePATDescriptionRequest:
description: JSON-formatted document describing PAT description update request.
required: true
content:
application/json:
schema:
type: object
required:
- description
properties:
description:
type: string
example: "New PAT Description"
description: New description for the Personal Access Token
ResetPATSecretRequest:
description: JSON-formatted document describing PAT secret reset request.
required: true
content:
application/json:
schema:
type: object
required:
- duration
properties:
duration:
type: string
pattern: "^[0-9]+(ns|us|µs|ms|s|m|h|d|w|y)$"
example: "30d"
description: Duration for which the new PAT secret is valid. Format is a duration string (e.g. "30d", "24h", "1y").
AddScopeRequest:
description: JSON-formatted document describing add scope request.
required: true
content:
application/json:
schema:
type: object
required:
- scopes
properties:
scopes:
type: array
items:
$ref: "#/components/schemas/Scope"
description: List of scopes to add
RemoveScopeRequest:
description: JSON-formatted document describing remove scope request.
required: true
content:
application/json:
schema:
type: object
required:
- scopes_id
properties:
scopes_id:
type: array
items:
type: string
format: uuid
description: List of scope IDs to remove
KeyRequest:
description: JSON-formatted document describing key request.
required: true
content:
application/json:
schema:
type: object
properties:
type:
type: integer
example: 0
description: API key type. Keys of different type are processed differently.
duration:
type: number
format: integer
example: 23456
description: Number of seconds issued token is valid for.
responses:
PATRes:
description: Personal Access Token data.
content:
application/json:
schema:
$ref: "#/components/schemas/PAT"
PATsPageRes:
description: Page of Personal Access Tokens.
content:
application/json:
schema:
$ref: "#/components/schemas/PATsPage"
ScopesPageRes:
description: Page of scopes.
content:
application/json:
schema:
$ref: "#/components/schemas/ScopesPage"
ServiceError:
description: Unexpected server-side error occurred.
KeyRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/Key"
links:
revoke:
operationId: revokeKey
parameters:
keyID: $response.body#/id
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/health_info.yaml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
File diff suppressed because it is too large Load Diff
-722
View File
@@ -1,722 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.3
info:
title: Certs Service API
description: |
Certificate management service for issuing, renewing, revoking, and managing X.509 certificates.
This service provides PKI functionality including certificate lifecycle management, OCSP responder,
and CRL generation.
version: 1.0.0
contact:
name: Abstract Machines
license:
name: Apache-2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
- url: http://localhost:9019
description: Development server
tags:
- name: certificates
description: Certificate lifecycle management operations
- name: pki
description: PKI infrastructure operations (OCSP, CRL, CA)
- name: health
description: Service health and monitoring
security:
- BearerAuth: []
paths:
/{domainID}/certs/issue/{entityID}:
post:
tags:
- certificates
summary: Issue a new certificate
description: Issues a new X.509 certificate for the specified entity with custom subject options
operationId: issueCert
security:
- BearerAuth: []
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/EntityID'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/IssueCertRequest'
responses:
'201':
description: Certificate successfully issued
content:
application/json:
schema:
$ref: '#/components/schemas/CertificateResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/{domainID}/certs/{id}/renew:
patch:
tags:
- certificates
summary: Renew a certificate
description: Renews an existing certificate with extended TTL and new serial number
operationId: renewCert
security:
- BearerAuth: []
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/CertID'
responses:
'200':
description: Certificate successfully renewed
content:
application/json:
schema:
$ref: '#/components/schemas/RenewCertResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/{domainID}/certs/{id}/revoke:
patch:
tags:
- certificates
summary: Revoke a certificate
description: Revokes a certificate by its serial number
operationId: revokeCert
security:
- BearerAuth: []
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/CertID'
responses:
'204':
description: Certificate successfully revoked
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalServerError'
/{domainID}/certs/{entityID}/delete:
delete:
tags:
- certificates
summary: Delete certificates for an entity
description: Deletes all certificates associated with the specified entity
operationId: deleteCert
security:
- BearerAuth: []
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/EntityID'
responses:
'204':
description: Certificates successfully deleted
'401':
$ref: '#/components/responses/Unauthorized'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'500':
$ref: '#/components/responses/InternalServerError'
/{domainID}/certs:
get:
tags:
- certificates
summary: List certificates
description: Retrieves a paginated list of certificates with optional filtering by entity ID
operationId: listCerts
security:
- BearerAuth: []
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/EntityIDFilter'
responses:
'200':
description: Certificates successfully retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/CertificateListResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/{domainID}/certs/{id}:
get:
tags:
- certificates
summary: View certificate details
description: Retrieves detailed information about a specific certificate by serial number
operationId: viewCert
security:
- BearerAuth: []
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/CertID'
responses:
'200':
description: Certificate details successfully retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/ViewCertResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/{domainID}/certs/csrs/{entityID}:
post:
tags:
- certificates
summary: Issue certificate from CSR
description: Issues a certificate from a Certificate Signing Request (CSR)
operationId: issueFromCSR
security:
- BearerAuth: []
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/EntityID'
- $ref: '#/components/parameters/TTL'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/IssueFromCSRRequest'
responses:
'200':
description: Certificate successfully issued from CSR
content:
application/json:
schema:
$ref: '#/components/schemas/IssueFromCSRResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/certs/csrs/{entityID}:
post:
tags:
- certificates
summary: Issue certificate from CSR (Internal)
description: Issues a certificate from a CSR using internal agent authentication
operationId: issueFromCSRInternal
security:
- AgentAuth: []
parameters:
- $ref: '#/components/parameters/EntityID'
- $ref: '#/components/parameters/TTL'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/IssueFromCSRRequest'
responses:
'200':
description: Certificate successfully issued from CSR
content:
application/json:
schema:
$ref: '#/components/schemas/IssueFromCSRResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/certs/ocsp:
post:
tags:
- pki
summary: OCSP responder
description: |
Online Certificate Status Protocol (OCSP) responder endpoint.
Accepts both binary OCSP requests and JSON format requests.
operationId: ocsp
security: []
parameters:
- name: force_status
in: query
description: Force a specific OCSP status for testing
required: false
schema:
type: string
requestBody:
required: true
content:
application/ocsp-request:
schema:
type: string
format: binary
description: DER-encoded OCSP request
application/json:
schema:
$ref: '#/components/schemas/OCSPRequest'
responses:
'200':
description: OCSP response
content:
application/ocsp-response:
schema:
type: string
format: binary
description: DER-encoded OCSP response
'400':
$ref: '#/components/responses/BadRequest'
'500':
$ref: '#/components/responses/InternalServerError'
/certs/crl:
get:
tags:
- pki
summary: Generate Certificate Revocation List
description: Generates and returns the current Certificate Revocation List (CRL)
operationId: generateCRL
security: []
responses:
'200':
description: CRL successfully generated
content:
application/json:
schema:
$ref: '#/components/schemas/CRLResponse'
'500':
$ref: '#/components/responses/InternalServerError'
/certs/view-ca:
get:
tags:
- pki
summary: View CA certificate
description: Retrieves the CA certificate chain (root and intermediate certificates)
operationId: viewCA
security: []
responses:
'200':
description: CA certificate successfully retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/ViewCertResponse'
'500':
$ref: '#/components/responses/InternalServerError'
/certs/download-ca:
get:
tags:
- pki
summary: Download CA certificate
description: Downloads the CA certificate as a ZIP file
operationId: downloadCA
security: []
responses:
'200':
description: CA certificate ZIP file
content:
application/zip:
schema:
type: string
format: binary
'500':
$ref: '#/components/responses/InternalServerError'
/health:
get:
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
'200':
$ref: '#/components/responses/HealthRes'
'500':
$ref: '#/components/responses/InternalServerError'
/metrics:
get:
tags:
- health
summary: Prometheus metrics
description: Returns Prometheus metrics for monitoring
operationId: metrics
security: []
responses:
'200':
description: Metrics successfully retrieved
content:
text/plain:
schema:
type: string
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: User authentication token
AgentAuth:
type: http
scheme: bearer
description: Agent authentication token for internal operations
parameters:
DomainID:
name: domainID
in: path
required: true
description: Domain identifier
schema:
type: string
EntityID:
name: entityID
in: path
required: true
description: Entity identifier for the certificate
schema:
type: string
CertID:
name: id
in: path
required: true
description: Certificate serial number
schema:
type: string
Offset:
name: offset
in: query
description: Number of items to skip
schema:
type: integer
minimum: 0
default: 0
Limit:
name: limit
in: query
description: Maximum number of items to return
schema:
type: integer
minimum: 1
maximum: 100
default: 10
EntityIDFilter:
name: entity_id
in: query
description: Filter certificates by entity ID
schema:
type: string
TTL:
name: ttl
in: query
description: Time to live for the certificate (e.g., "8760h", "365d")
schema:
type: string
schemas:
IssueCertRequest:
type: object
required:
- options
properties:
ttl:
type: string
description: Time to live for the certificate (e.g., "8760h" for 1 year)
example: "8760h"
ip_addresses:
type: array
items:
type: string
description: IP addresses to include in the certificate
example: ["192.168.1.1", "10.0.0.1"]
options:
$ref: '#/components/schemas/SubjectOptions'
SubjectOptions:
type: object
required:
- common_name
properties:
common_name:
type: string
description: Common Name (CN) for the certificate subject
example: "example.com"
organization:
type: array
items:
type: string
description: Organization (O)
example: ["Abstract Machines"]
organizational_unit:
type: array
items:
type: string
description: Organizational Unit (OU)
example: ["Engineering"]
country:
type: array
items:
type: string
description: Country (C)
example: ["US"]
province:
type: array
items:
type: string
description: Province or State (ST)
example: ["California"]
locality:
type: array
items:
type: string
description: Locality or City (L)
example: ["San Francisco"]
street_address:
type: array
items:
type: string
description: Street Address
example: ["123 Main St"]
postal_code:
type: array
items:
type: string
description: Postal Code
example: ["94105"]
dns_names:
type: array
items:
type: string
description: DNS names for Subject Alternative Names
example: ["example.com", "www.example.com"]
ip_addresses:
type: array
items:
type: string
description: IP addresses for Subject Alternative Names
example: ["192.168.1.1"]
CertificateResponse:
type: object
properties:
serial_number:
type: string
description: Unique serial number of the certificate
example: "4a:3f:5e:2c:1b:8d:9e:7f"
certificate:
type: string
description: PEM-encoded certificate
example: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
key:
type: string
description: PEM-encoded private key
example: "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
revoked:
type: boolean
description: Whether the certificate is revoked
example: false
expiry_time:
type: string
format: date-time
description: Certificate expiration time
example: "2026-11-05T12:00:00Z"
entity_id:
type: string
description: Entity identifier associated with the certificate
example: "entity-123"
RenewCertResponse:
type: object
properties:
certificate:
$ref: '#/components/schemas/ViewCertResponse'
ViewCertResponse:
type: object
properties:
serial_number:
type: string
description: Certificate serial number
example: "4a:3f:5e:2c:1b:8d:9e:7f"
certificate:
type: string
description: PEM-encoded certificate
example: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
key:
type: string
description: PEM-encoded private key
example: "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"
revoked:
type: boolean
description: Revocation status
example: false
expiry_time:
type: string
format: date-time
description: Expiration timestamp
example: "2026-11-05T12:00:00Z"
entity_id:
type: string
description: Associated entity identifier
example: "entity-123"
CertificateListResponse:
type: object
properties:
total:
type: integer
format: uint64
description: Total number of certificates
example: 100
offset:
type: integer
format: uint64
description: Current offset
example: 0
limit:
type: integer
format: uint64
description: Current limit
example: 10
certificates:
type: array
items:
$ref: '#/components/schemas/ViewCertResponse'
IssueFromCSRRequest:
type: object
required:
- csr
properties:
csr:
type: string
format: byte
description: PEM-encoded Certificate Signing Request
example: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K..."
IssueFromCSRResponse:
type: object
properties:
serial_number:
type: string
description: Serial number of the issued certificate
example: "4a:3f:5e:2c:1b:8d:9e:7f"
certificate:
type: string
description: PEM-encoded certificate
example: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
revoked:
type: boolean
description: Revocation status
example: false
expiry_time:
type: string
format: date-time
description: Expiration timestamp
example: "2026-11-05T12:00:00Z"
entity_id:
type: string
description: Associated entity identifier
example: "entity-123"
OCSPRequest:
type: object
properties:
serial_number:
type: string
description: Certificate serial number to check
example: "4a:3f:5e:2c:1b:8d:9e:7f"
certificate:
type: string
description: PEM-encoded certificate to check
example: "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
status:
type: string
description: Force a specific status (for testing)
enum: [good, revoked, unknown]
CRLResponse:
type: object
properties:
crl:
type: string
format: byte
description: DER-encoded Certificate Revocation List
Error:
type: object
properties:
error:
type: string
description: Error message
example: "invalid request"
responses:
BadRequest:
description: Bad request - invalid parameters or malformed request
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
Unauthorized:
description: Unauthorized - invalid or missing authentication token
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
NotFound:
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
UnprocessableEntity:
description: Unprocessable entity - request cannot be processed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
InternalServerError:
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: './schemas/health_info.yaml'
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More