Compare commits

...

387 Commits

Author SHA1 Message Date
dusan e35ac13390 NOISSUE - Archive
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-04-06 23:37:04 +02:00
dusan 94255e2393 Add warning
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-04-06 12:11:19 +02:00
dusan 02b13d8e0c Rename to magistrala-old to be replaced with magistrala
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-04-06 11:32:57 +02:00
Steve Munene 1f91de480e NOISSUE - Fix alarms metadata (#444)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-18 13:30:06 +01:00
dusan eb29b4e298 NOISSUE - Update SMQ version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-18 10:26:47 +01:00
dusan 5841d3f7e4 NOISSUE - Update SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-17 19:57:15 +01:00
dusan f44b910546 NOISSUE - Update SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-17 18:11:14 +01:00
dusan 52896241c5 NOISSUE - Update dependencies
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-17 18:10:29 +01:00
dependabot[bot] 1b36c6e1b6 NOISSUE - Bump the gh-dependency group in /.github/workflows with 3 updates (#443)
Bumps the gh-dependency group in /.github/workflows with 3 updates: [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action), [docker/login-action](https://github.com/docker/login-action) and [dorny/paths-filter](https://github.com/dorny/paths-filter).


Updates `docker/setup-buildx-action` from 3 to 4
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)

Updates `docker/login-action` from 3 to 4
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

Updates `dorny/paths-filter` from 3 to 4
- [Release notes](https://github.com/dorny/paths-filter/releases)
- [Changelog](https://github.com/dorny/paths-filter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/dorny/paths-filter/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-dependency
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-dependency
- dependency-name: dorny/paths-filter
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-17 17:19:02 +01:00
Steve Munene d5d5e8bf7e NOISSUE - Add build tag constraint for middlewares (#442)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-17 14:49:52 +01:00
Steve Munene b2967fb2e5 NOISSUE - Fix SDK test (#441)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-16 16:37:19 +01:00
Steve Munene 7fb5dd7b55 NOISSUE - Refactor listing for rules and reports (#433)
* add access control to rules engine

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update authorization method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove domain from method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix userid parameter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update checksuperadmin method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert changes

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-16 14:39:49 +01:00
Steve Munene 2ef8437d8b MG-370 - Add fine grained access control to alarms (#404)
* add access control to rules engine

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add access control to reports

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add access control to alarms

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused variables

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update authorization method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove roles

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update alarm permissions

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update alarm permissions

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert endpoint changes

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix make fetch

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove rule prefix

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove trailing line

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused constants

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* re consumer

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update listing

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix rule roles interface

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* refactor listing commands

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fetch supermq

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address coments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update script

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fetch supermq

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix time layout

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix role name

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove white spaces

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update check usperadmin method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update go mod file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add missing env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-13 14:29:32 +01:00
dusan 6dbcfcae58 NOISSUE - Update SuperMQ version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-12 11:37:31 +01:00
Ian Ngethe Muchiri ab8d335767 NOISSUE - Update UI docker compose (#439)
Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2026-03-11 16:22:06 +01:00
dusan 99cea4abe8 NOISSUE - Update Compose to use the latest UI
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-11 15:58:59 +01:00
dusan 04379dc7a9 NOISSUE - Fix SDK bugs
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-11 12:48:15 +01:00
dependabot[bot] 0800b260d5 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#434)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.66.0 to 0.67.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.66.0...zpages/v0.67.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-version: 0.67.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-11 10:59:45 +01:00
dusan 67feea693e NOISSUE - Fix Reports test status code bug
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-11 10:57:56 +01:00
dusan db1676cb0f NOISSUE - Update Mockery version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-11 09:54:10 +01:00
Steve Munene 4b57387110 NOISSUE - Remove Panic method from go scripts (#437)
* add regex

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-10 20:46:46 +01:00
Dušan Borovčanin e3373e1b49 NOISSUE - Fix SeaweedFS init (#436)
* Fix SeaweedFS init

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Use 20s wait period

Signed-off-by: dusan <borovcanindusan1@gmail.com>

---------

Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-10 16:29:59 +01:00
dependabot[bot] 453c880efc NOISSUE - Bump go.opentelemetry.io/otel/trace from 1.41.0 to 1.42.0 (#429)
Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.41.0 to 1.42.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.41.0...v1.42.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/trace
  dependency-version: 1.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 08:55:11 +01:00
dependabot[bot] dc2b063b6e NOISSUE - Bump go.opentelemetry.io/otel from 1.41.0 to 1.42.0 (#431)
Bumps [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) from 1.41.0 to 1.42.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.41.0...v1.42.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel
  dependency-version: 1.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 08:54:48 +01:00
dependabot[bot] 65ee66dc32 NOISSUE - Bump github.com/slack-go/slack from 0.18.0 to 0.19.0 (#428)
Bumps [github.com/slack-go/slack](https://github.com/slack-go/slack) from 0.18.0 to 0.19.0.
- [Release notes](https://github.com/slack-go/slack/releases)
- [Changelog](https://github.com/slack-go/slack/blob/master/CHANGELOG.md)
- [Commits](https://github.com/slack-go/slack/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: github.com/slack-go/slack
  dependency-version: 0.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 08:48:14 +01:00
dependabot[bot] df9fe93a98 NOISSUE - Bump golang.org/x/sync from 0.19.0 to 0.20.0 (#430)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.19.0 to 0.20.0.
- [Commits](https://github.com/golang/sync/compare/v0.19.0...v0.20.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.20.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 08:47:57 +01:00
dependabot[bot] 84fba105c9 NOISSUE - Bump google.golang.org/grpc from 1.79.1 to 1.79.2 (#432)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.79.1 to 1.79.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.79.1...v1.79.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.79.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-10 08:47:42 +01:00
Arvindh f75f08db4a NOISSUE - Fix alarms schema (#425)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2026-03-05 17:04:00 +01:00
Steve Munene be1dc130d6 NOISSUE - Add alarm relation to rules (#424)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-05 15:21:34 +01:00
Steve Munene 178a62c08f MG-370 - Add fine grained access control to reports (#403)
* add access control to rules engine

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix build

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix report database

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix variable naming

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix entity type

Signed-off-by: Arvindh <arvindh91@gmail.com>

* update authorize method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix generate report

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert env changes

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update generate permission

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert go mod file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert go mod file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Arvindh <arvindh91@gmail.com>
2026-03-05 13:59:22 +01:00
Steve Munene 362a4fc76d MG-370 - Add fine grained access control to rules engine (#402)
* update go mod file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix rules endpoint tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix yaml file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix build

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove roles from alarms

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* change approach for schema combaine

Signed-off-by: Arvindh <arvindh91@gmail.com>

* change approach for schema combaine

Signed-off-by: Arvindh <arvindh91@gmail.com>

* fix permissions for rules

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix authorization file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Arvindh <arvindh91@gmail.com>
2026-03-05 11:42:51 +01:00
Ian Ngethe Muchiri 8e75edc9f5 NOISSUE - Add alarms, reports and rules sdk (#423)
* add alarms, reports and rules sdk

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* fix tests

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* fix linter

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2026-03-05 10:54:14 +01:00
Steve Munene a031426715 NOISSUE - Update metadata UI type to string (#422)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-03 16:01:48 +01:00
dusan 962b473a5f Update SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-03-03 15:35:30 +01:00
Steve Munene de6f3921a4 MG-406 - Fix panic issues in rules engine go script (#407)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-03 15:34:27 +01:00
Steve Munene 0a45a96fac NOISSUE - Update Rules metadata migrations (#421)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-03 15:33:58 +01:00
dependabot[bot] c2afb88e79 NOISSUE - Bump github.com/nats-io/nats.go from 1.48.0 to 1.49.0 (#420)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.48.0 to 1.49.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.48.0...v1.49.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.49.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 13:07:29 +01:00
Steve Munene 9a3a07cd2e NOISSUE - Update Authorization method (#418)
* fix authorization

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fetch supermq

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fetch supermq

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-03-02 12:55:07 +01:00
dependabot[bot] 28e809b9d8 NOISSUE - Bump golang in /docker in the docker-dependency group (#419)
Bumps the docker-dependency group in /docker with 1 update: golang.


Updates `golang` from 1.26rc2-alpine3.22 to 1.26-alpine3.22

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.26-alpine3.22
  dependency-type: direct:production
  dependency-group: docker-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-02 11:08:51 +01:00
Felix Gateru eb14615cf5 MG-344 - Update Provision Service (#386)
* feat: update provison service

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: remove duplicate env variables

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* ci: make fetch_supermq

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* docs(README.md): update README

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2026-02-28 17:55:22 +01:00
dusan d652652b79 NOISSUE - Update SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-02-27 21:33:18 +01:00
dependabot[bot] a2087a1f1f NOISSUE - Bump google.golang.org/grpc from 1.78.0 to 1.79.1 (#405)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.78.0 to 1.79.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.78.0...v1.79.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.79.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 10:33:17 +01:00
dependabot[bot] f195ced6a0 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.17.3 to 9.18.0 (#410)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.17.3 to 9.18.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.17.3...v9.18.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 10:07:10 +01:00
dependabot[bot] a33d1cfe4f NOISSUE - Bump github.com/authzed/authzed-go from 1.7.0 to 1.8.0 (#413)
Bumps [github.com/authzed/authzed-go](https://github.com/authzed/authzed-go) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/authzed/authzed-go/releases)
- [Commits](https://github.com/authzed/authzed-go/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/authzed/authzed-go
  dependency-version: 1.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 10:01:31 +01:00
dependabot[bot] 40cbb66638 NOISSUE - Bump github.com/slack-go/slack from 0.17.3 to 0.18.0 (#411)
Bumps [github.com/slack-go/slack](https://github.com/slack-go/slack) from 0.17.3 to 0.18.0.
- [Release notes](https://github.com/slack-go/slack/releases)
- [Changelog](https://github.com/slack-go/slack/blob/master/CHANGELOG.md)
- [Commits](https://github.com/slack-go/slack/compare/v0.17.3...v0.18.0)

---
updated-dependencies:
- dependency-name: github.com/slack-go/slack
  dependency-version: 0.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 10:00:26 +01:00
dependabot[bot] 08b5ac52cf NOISSUE - Bump github.com/caarlos0/env/v11 from 11.3.1 to 11.4.0 (#412)
Bumps [github.com/caarlos0/env/v11](https://github.com/caarlos0/env) from 11.3.1 to 11.4.0.
- [Release notes](https://github.com/caarlos0/env/releases)
- [Commits](https://github.com/caarlos0/env/compare/v11.3.1...v11.4.0)

---
updated-dependencies:
- dependency-name: github.com/caarlos0/env/v11
  dependency-version: 11.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 10:00:03 +01:00
Felix Gateru 0c1ccf1f04 MG-408 - Fix client authentication in readers (#409)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2026-02-25 09:59:43 +01:00
Felix Gateru f28a3e8390 MG-401 - Fix authorization error in Magistrala services (#400)
* chore: update SMQ version

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: run make fetch_supermq

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* tests: fix provison tests

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* ci(build.yaml): get go version from go mod

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2026-02-11 11:17:13 +01:00
Felix Gateru 3685d231cf NOISSUE - Fix API docs page (#399)
* fix: fix api docs page

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: run make fetch_supermq

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2026-02-09 16:21:58 +01:00
Steve Munene f3c5d603a0 MG-379 - Refactor makefile (#385)
* refactor command

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update makefile and readme file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update commands

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* Add changes for apple silicon

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Co-authored-by: dorcaslitunya <anonolitunya@gmail.com>
2026-01-29 09:50:38 +01:00
dependabot[bot] 5050caa3d3 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.17.2 to 9.17.3 (#391)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.17.2 to 9.17.3.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/v9.17.3/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.17.2...v9.17.3)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.17.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-29 09:45:44 +01:00
dependabot[bot] 4ed31c2c66 NOISSUE - Bump github.com/absmach/certs from 0.18.4 to 0.18.5 (#392)
Bumps [github.com/absmach/certs](https://github.com/absmach/certs) from 0.18.4 to 0.18.5.
- [Release notes](https://github.com/absmach/certs/releases)
- [Commits](https://github.com/absmach/certs/compare/v0.18.4...v0.18.5)

---
updated-dependencies:
- dependency-name: github.com/absmach/certs
  dependency-version: 0.18.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-29 09:45:23 +01:00
dusan bba6c57532 NOISSUE - Update SMQ version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-01-23 17:37:28 +01:00
Felix Gateru 2c37cfc53c MG-389 - Return all values on alarm update (#390)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2026-01-23 10:08:43 +01:00
Felix Gateru f3ce37a80d NOISSUE - Update SMQ & Postgres version (#388)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2026-01-22 16:40:44 +01:00
Nataly Musilah 8203666e58 NOISSUE - Update READMEs (#380)
* fix web url

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* add new readmes

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* add other services

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix docker link

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix reports examples

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* revert go.sum change

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

---------

Signed-off-by: Musilah <nataleigh.nk@gmail.com>
2026-01-22 14:16:52 +01:00
dependabot[bot] e320051ec0 NOISSUE - Bump golang in /docker in the docker-dependency group (#381)
Bumps the docker-dependency group in /docker with 1 update: golang.


Updates `golang` from 1.25.5-alpine3.22 to 1.26rc2-alpine3.22

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.26rc2-alpine3.22
  dependency-type: direct:production
  dependency-group: docker-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 14:14:26 +01:00
dependabot[bot] ec055cb4b4 NOISSUE - Bump github.com/go-chi/chi/v5 from 5.2.3 to 5.2.4 (#382)
Bumps [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) from 5.2.3 to 5.2.4.
- [Release notes](https://github.com/go-chi/chi/releases)
- [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-chi/chi/compare/v5.2.3...v5.2.4)

---
updated-dependencies:
- dependency-name: github.com/go-chi/chi/v5
  dependency-version: 5.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 14:13:36 +01:00
dependabot[bot] bcae0de50e NOISSUE - Bump github.com/absmach/certs from 0.18.3 to 0.18.4 (#384)
Bumps [github.com/absmach/certs](https://github.com/absmach/certs) from 0.18.3 to 0.18.4.
- [Release notes](https://github.com/absmach/certs/releases)
- [Commits](https://github.com/absmach/certs/compare/v0.18.3...v0.18.4)

---
updated-dependencies:
- dependency-name: github.com/absmach/certs
  dependency-version: 0.18.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-22 14:13:18 +01:00
dusan ba344290ed Update SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2026-01-22 14:03:52 +01:00
Steve Munene c7bc9b7cf9 NOISSUE - Fetch SuperMQ (#387)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-01-21 15:59:46 +01:00
Steve Munene b02b3411db NOISSUE - Fetch certs (#383)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2026-01-19 13:54:31 +01:00
Felix Gateru 5a769e1981 MG-327 - Allow superadmin to access channel messages (#377)
* refactor: allow superadmin to read channel messages

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* dep: update SMQ version

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2026-01-15 17:53:41 +01:00
Arvindh 91bdb274b2 NOISSUE - Add ui-backend-db health check (#376)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2026-01-14 14:56:07 +01:00
dependabot[bot] 982636a87a NOISSUE - Bump gonum.org/v1/gonum from 0.16.0 to 0.17.0 (#375)
Bumps [gonum.org/v1/gonum](https://github.com/gonum/gonum) from 0.16.0 to 0.17.0.
- [Release notes](https://github.com/gonum/gonum/releases)
- [Commits](https://github.com/gonum/gonum/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: gonum.org/v1/gonum
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-12 08:54:20 +01:00
dusan 68ef843564 NOISSUE - Update Nginx ports config
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-31 18:28:08 +01:00
dusan a6cd64ed6a NOISSUE - Update Dockerfile Go version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-31 17:38:51 +01:00
Arvindh 67180a55f7 NOISSUE - Update Errors (#374)
* update MG errors

Signed-off-by: Arvindh <arvindh91@gmail.com>

* update MG errors

Signed-off-by: Arvindh <arvindh91@gmail.com>

* sync with supermq main

Signed-off-by: Arvindh <arvindh91@gmail.com>

* update MG errors

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-12-31 16:57:06 +01:00
dusan c9b3107ad9 NOISSUE - Update SMQ version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-31 11:04:52 +01:00
dependabot[bot] da289e58b5 NOISSUE - Bump google.golang.org/grpc from 1.77.0 to 1.78.0 (#372)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.77.0 to 1.78.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.77.0...v1.78.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.78.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 12:11:36 +01:00
dependabot[bot] 94458dde3e NOISSUE - Bump github.com/jackc/pgx/v5 from 5.7.6 to 5.8.0 (#373)
* NOISSUE - Housekeeping

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Add DeepWiki link

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Update GH Actions for API docs

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Update SMQ

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Bump github.com/spf13/cobra from 1.10.1 to 1.10.2 (#362)

Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.10.1 to 1.10.2.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.10.1...v1.10.2)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-version: 1.10.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NOISSUE - Bump github.com/redis/go-redis/v9 from 9.17.1 to 9.17.2 (#361)

Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.17.1 to 9.17.2.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/v9.17.2/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.17.1...v9.17.2)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.17.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NOISSUE - Update SMQ

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Bump golang.org/x/sync from 0.18.0 to 0.19.0 (#365)

Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.18.0 to 0.19.0.
- [Commits](https://github.com/golang/sync/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Update SMQ version

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Bump go.opentelemetry.io/otel/trace from 1.38.0 to 1.39.0 (#364)

Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.38.0 to 1.39.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.38.0...v1.39.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/trace
  dependency-version: 1.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NOISSUE - Bump google.golang.org/protobuf from 1.36.10 to 1.36.11 (#363)

Bumps google.golang.org/protobuf from 1.36.10 to 1.36.11.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-version: 1.36.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#366)

Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.63.0 to 0.64.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.63.0...zpages/v0.64.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-version: 0.64.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NOISSUE - Bump github.com/absmach/certs from 0.18.2 to 0.18.3 (#359)

Bumps [github.com/absmach/certs](https://github.com/absmach/certs) from 0.18.2 to 0.18.3.
- [Release notes](https://github.com/absmach/certs/releases)
- [Commits](https://github.com/absmach/certs/compare/v0.18.2...v0.18.3)

---
updated-dependencies:
- dependency-name: github.com/absmach/certs
  dependency-version: 0.18.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NOISSUE - Bump github.com/nats-io/nats.go from 1.47.0 to 1.48.0 (#368)

Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.47.0 to 1.48.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.47.0...v1.48.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NOISSUE - Update SMQ version

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Refactor `alarms`, `reports` and `rule engines` middlewares (#369)

* refactor middleware

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update go mod file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix rules tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert common code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update supermq version

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* NOISSUE - Sync with SMQ

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Update MG and SMQ versions

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Update MG and SMQ versions

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Revert "NOISSUE - Update MG and SMQ versions"

This reverts commit 7faca6b73d6ac27ae4d28ee45f4860bbb7340ef4.

* Revert SMQ version tag

Use latest for development.

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Bump github.com/jackc/pgx/v5 from 5.7.6 to 5.8.0

Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.7.6 to 5.8.0.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.7.6...v5.8.0)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-version: 5.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

---------

Signed-off-by: dusan <borovcanindusan1@gmail.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Co-authored-by: dusan <borovcanindusan1@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Steve Munene <stevenyaga2014@gmail.com>
2025-12-29 11:38:54 +01:00
dusan 8dc4d72b98 NOISSUE - Improve running different versions
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dusan 4dbdea585d Revert SMQ version tag
Use latest for development.

Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dusan e75536418a Revert "NOISSUE - Update MG and SMQ versions"
This reverts commit 7faca6b73d6ac27ae4d28ee45f4860bbb7340ef4.
2025-12-29 11:23:43 +01:00
dusan e64140ce75 NOISSUE - Update MG and SMQ versions
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dusan 12a5919a73 NOISSUE - Update MG and SMQ versions
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dusan 845cf4c75e NOISSUE - Sync with SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
Steve Munene 99e2c7aec4 NOISSUE - Refactor alarms, reports and rule engines middlewares (#369)
* refactor middleware

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update go mod file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix rules tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert common code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update supermq version

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-12-29 11:23:43 +01:00
dusan e4cef0fdc2 NOISSUE - Update SMQ version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dependabot[bot] cadb035405 NOISSUE - Bump github.com/nats-io/nats.go from 1.47.0 to 1.48.0 (#368)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.47.0 to 1.48.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.47.0...v1.48.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 11:23:43 +01:00
dependabot[bot] f38b6c072a NOISSUE - Bump github.com/absmach/certs from 0.18.2 to 0.18.3 (#359)
Bumps [github.com/absmach/certs](https://github.com/absmach/certs) from 0.18.2 to 0.18.3.
- [Release notes](https://github.com/absmach/certs/releases)
- [Commits](https://github.com/absmach/certs/compare/v0.18.2...v0.18.3)

---
updated-dependencies:
- dependency-name: github.com/absmach/certs
  dependency-version: 0.18.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 11:23:43 +01:00
dependabot[bot] af93588588 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#366)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.63.0 to 0.64.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.63.0...zpages/v0.64.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-version: 0.64.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 11:23:43 +01:00
dependabot[bot] a1a0e459d9 NOISSUE - Bump google.golang.org/protobuf from 1.36.10 to 1.36.11 (#363)
Bumps google.golang.org/protobuf from 1.36.10 to 1.36.11.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-version: 1.36.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 11:23:43 +01:00
dependabot[bot] a5f6afcb14 NOISSUE - Bump go.opentelemetry.io/otel/trace from 1.38.0 to 1.39.0 (#364)
Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.38.0 to 1.39.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.38.0...v1.39.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/trace
  dependency-version: 1.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 11:23:43 +01:00
dusan 8348633e06 Update SMQ version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dependabot[bot] 31a96ac7a1 NOISSUE - Bump golang.org/x/sync from 0.18.0 to 0.19.0 (#365)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.18.0 to 0.19.0.
- [Commits](https://github.com/golang/sync/compare/v0.18.0...v0.19.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 11:23:43 +01:00
dusan a7f6d33cf0 NOISSUE - Update SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dependabot[bot] 1342760593 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.17.1 to 9.17.2 (#361)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.17.1 to 9.17.2.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/v9.17.2/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.17.1...v9.17.2)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.17.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 11:23:43 +01:00
dependabot[bot] 4f99fffcee NOISSUE - Bump github.com/spf13/cobra from 1.10.1 to 1.10.2 (#362)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.10.1 to 1.10.2.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.10.1...v1.10.2)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-version: 1.10.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-29 11:23:43 +01:00
dusan 833701cf66 NOISSUE - Update SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dusan 35f99e6e6c NOISSUE - Update GH Actions for API docs
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dusan 867ae73a2a NOISSUE - Add DeepWiki link
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:43 +01:00
dusan 5e504aa104 NOISSUE - Housekeeping
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-12-29 11:23:36 +01:00
dusan 8e8e02f0cb NOISSUE - Update SMQ version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-11-28 18:36:50 +01:00
dependabot[bot] a257e8049e NOISSUE - Bump github.com/rubenv/sql-migrate from 1.8.0 to 1.8.1 (#354)
Bumps [github.com/rubenv/sql-migrate](https://github.com/rubenv/sql-migrate) from 1.8.0 to 1.8.1.
- [Commits](https://github.com/rubenv/sql-migrate/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/rubenv/sql-migrate
  dependency-version: 1.8.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-26 19:26:42 +01:00
dependabot[bot] 1c2050bc20 NOISSUE - Bump actions/checkout in /.github/workflows in the gh-dependency group (#353)
Bumps the gh-dependency group in /.github/workflows with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 5 to 6
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-26 17:42:26 +01:00
dependabot[bot] c6ade6603e NOISSUE - Bump google.golang.org/grpc from 1.76.0 to 1.77.0 (#355)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.76.0 to 1.77.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.76.0...v1.77.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.77.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-26 17:42:00 +01:00
dependabot[bot] 5149cf9ba0 NOISSUE - Bump github.com/authzed/authzed-go from 1.6.0 to 1.7.0 (#356)
Bumps [github.com/authzed/authzed-go](https://github.com/authzed/authzed-go) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/authzed/authzed-go/releases)
- [Commits](https://github.com/authzed/authzed-go/compare/v1.6.0...v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/authzed/authzed-go
  dependency-version: 1.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-26 17:41:40 +01:00
dependabot[bot] bd953651b4 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.16.0 to 9.17.0 (#357)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.16.0 to 9.17.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.16.0...v9.17.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-26 17:41:10 +01:00
dependabot[bot] f11625071f NOISSUE - Bump golangci/golangci-lint-action (#351)
Bumps the gh-dependency group in /.github/workflows with 1 update: [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action).


Updates `golangci/golangci-lint-action` from 8 to 9
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v8...v9)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-19 10:44:36 +01:00
dusan 98397efd9d Festch SuperMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-11-19 10:13:16 +01:00
Steve Munene 257db27769 MG-132 - Improve RE tests (#346)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add coverage for api tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add coverage for api tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add tests for handler

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add tests for start schedular

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix race condition

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix addrule test

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix list rule method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* use sorting for the slice

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fetch supermq

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-11-10 18:03:10 +01:00
dependabot[bot] a26d84b12d NOISSUE - Bump github.com/gofrs/uuid/v5 from 5.3.2 to 5.4.0 (#345)
Bumps [github.com/gofrs/uuid/v5](https://github.com/gofrs/uuid) from 5.3.2 to 5.4.0.
- [Release notes](https://github.com/gofrs/uuid/releases)
- [Commits](https://github.com/gofrs/uuid/compare/v5.3.2...v5.4.0)

---
updated-dependencies:
- dependency-name: github.com/gofrs/uuid/v5
  dependency-version: 5.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-10 13:54:01 +01:00
dependabot[bot] a769de809e NOISSUE - Bump github.com/vadv/gopher-lua-libs from 0.7.0 to 0.8.0 (#348)
Bumps [github.com/vadv/gopher-lua-libs](https://github.com/vadv/gopher-lua-libs) from 0.7.0 to 0.8.0.
- [Release notes](https://github.com/vadv/gopher-lua-libs/releases)
- [Changelog](https://github.com/vadv/gopher-lua-libs/blob/master/.goreleaser.yml)
- [Commits](https://github.com/vadv/gopher-lua-libs/compare/v0.7.0...v0.8.0)

---
updated-dependencies:
- dependency-name: github.com/vadv/gopher-lua-libs
  dependency-version: 0.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-10 13:53:14 +01:00
dependabot[bot] 06a42526dd NOISSUE - Bump golang.org/x/sync from 0.17.0 to 0.18.0 (#349)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.17.0 to 0.18.0.
- [Commits](https://github.com/golang/sync/compare/v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-10 13:52:03 +01:00
dusan de74711554 NOISSUE - Simplify object storage setup
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-11-05 12:25:37 +01:00
dependabot[bot] 678c61498b NOISSUE - Bump golang in /docker in the docker-dependency group (#343)
Bumps the docker-dependency group in /docker with 1 update: golang.


Updates `golang` from 1.25.1-alpine to 1.25.3-alpine

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.3-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docker-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-03 09:53:21 +01:00
Dušan Borovčanin 7bc02a2816 NOISSUE - Update SMQ and Certs dependencies (#342)
* NOISSUE - Update Certs dependencies

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* NOISSUE - Update Certs dependencies

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Fix linter errors

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Fix testing errors

Signed-off-by: dusan <borovcanindusan1@gmail.com>

---------

Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-11-03 09:52:17 +01:00
Sammy Kerata Oina 2720ad0497 NOISSUE - Update callhome dependency version (#341)
Signed-off-by: Sammy Oina <sammyoina@gmail.com>
2025-10-31 13:30:46 +01:00
Steve Munene 517588b675 NOISSUE - Update API docs (#340)
* update rules api docs

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update api docs

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix url

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-31 13:09:42 +01:00
dusan 7ee8c26864 NOISSUE - Fix API docs
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-30 18:28:29 +01:00
dependabot[bot] 6015c548fe NOISSUE - Bump github.com/redis/go-redis/v9 from 9.14.1 to 9.16.0 (#338)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.14.1 to 9.16.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.14.1...v9.16.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-29 11:20:23 +01:00
Dušan Borovčanin f5171a2c03 NOISSUE - Use S3 storage for images (#337)
* NOISSUE - Add object storage for UI images

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Simplify local object storage

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* WIP - Seaweed

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Add dynamic domain

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Update compose

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Update bucket init

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Update bucket init

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Update mod

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Fix compose format

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Fix UI backend env

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Fix env for backend URL

Signed-off-by: dusan <borovcanindusan1@gmail.com>

---------

Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-29 10:07:36 +01:00
Nataly Musilah 7e4f26ecf5 NOISSUE - Add SenML ordering (#339)
Signed-off-by: Musilah <nataleigh.nk@gmail.com>
2025-10-29 09:21:16 +01:00
dusan 7236666e1d NOISSUE - Sync SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-27 13:52:46 +01:00
Dušan Borovčanin 7bdf4c681e NOISSUE - Update dependencies (#336)
* NOISSUE - Update dependencies

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Update go.mod

Signed-off-by: dusan <borovcanindusan1@gmail.com>

---------

Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-20 20:45:24 +02:00
dependabot[bot] d4b7ed2a1e NOISSUE - Bump github.com/nats-io/nats.go from 1.46.1 to 1.47.0 (#335)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.46.1 to 1.47.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.46.1...v1.47.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.47.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-20 12:46:23 +02:00
dependabot[bot] 02c99ac7e4 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.14.0 to 9.14.1 (#334)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.14.0 to 9.14.1.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/v9.14.1/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.14.0...v9.14.1)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.14.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-20 11:45:15 +02:00
dusan 164a64bc25 NOISSUE - Fetch Supermq
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-15 21:53:12 +02:00
dependabot[bot] b4108d14a9 NOISSUE - Bump google.golang.org/grpc from 1.75.1 to 1.76.0 (#331)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.75.1 to 1.76.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.75.1...v1.76.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.76.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-13 13:38:49 +02:00
Steve Munene 5a6e0343dc NOISSUE - Fix Report time range display (#330)
* fx to and from

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* change to UTC

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix template pagination and address comment

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix pagination

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-09 16:28:15 +02:00
Steve Munene 8d4ead8e86 NOISSUE - Add timezone support for reports (#329)
* add timezone support

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update supermq

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add reports title for context

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-08 18:27:02 +02:00
Steve Munene ce5cb76dd4 NOISSUE - Remove reports trailing empty page (#328)
* remove empty page

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-07 17:24:09 +02:00
dependabot[bot] b9f401cb73 NOISSUE - Bump peter-evans/repository-dispatch (#323)
Bumps the gh-dependency group in /.github/workflows with 1 update: [peter-evans/repository-dispatch](https://github.com/peter-evans/repository-dispatch).


Updates `peter-evans/repository-dispatch` from 3 to 4
- [Release notes](https://github.com/peter-evans/repository-dispatch/releases)
- [Commits](https://github.com/peter-evans/repository-dispatch/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peter-evans/repository-dispatch
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-06 11:12:44 +02:00
dependabot[bot] 264e0c1a25 NOISSUE - Bump github.com/authzed/authzed-go from 1.5.0 to 1.6.0 (#324)
Bumps [github.com/authzed/authzed-go](https://github.com/authzed/authzed-go) from 1.5.0 to 1.6.0.
- [Release notes](https://github.com/authzed/authzed-go/releases)
- [Commits](https://github.com/authzed/authzed-go/compare/v1.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/authzed/authzed-go
  dependency-version: 1.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-06 11:12:24 +02:00
dependabot[bot] 7fa86fe9b1 NOISSUE - Bump github.com/nats-io/nats.go from 1.46.0 to 1.46.1 (#325)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.46.0 to 1.46.1.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.46.0...v1.46.1)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.46.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-06 11:10:39 +02:00
dependabot[bot] a5f847b064 NOISSUE - Bump google.golang.org/protobuf from 1.36.9 to 1.36.10 (#326)
Bumps google.golang.org/protobuf from 1.36.9 to 1.36.10.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-version: 1.36.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-06 11:05:30 +02:00
dusan 776c77cfcf Fix docs link
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-02 16:09:28 +02:00
dusan 7b52fc2a60 Fix docs link
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-02 15:59:11 +02:00
dusan 282bcc50e8 Fix website link
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-10-02 14:54:31 +02:00
Steve Munene 3702e99f17 NOISSUE - Update Magistrala certs (#322)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-10-01 17:38:48 +02:00
dusan 9078a67566 NOISSUE - Update mod file
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-09-28 12:42:29 +02:00
Ian Ngethe Muchiri 7ef90440f2 MG-853 - Add Slack output integration (#315)
* add slack integration

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* allow support for multiple message options

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* add message to slack struct

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* update template name

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* group postgres and slack

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-09-26 11:24:31 +02:00
dependabot[bot] a4abb61239 NOISSUE - Bump github.com/nats-io/nats.go from 1.45.0 to 1.46.0 (#319)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.45.0 to 1.46.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.45.0...v1.46.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-25 16:48:15 +02:00
Nataly Musilah 196e323f46 update readmessages via grpc (#316)
Signed-off-by: musilah <nataleigh.nk@gmail.com>
2025-09-19 16:05:07 +02:00
dependabot[bot] 16be00c50c NOISSUE - Bump github.com/eclipse/paho.mqtt.golang from 1.5.0 to 1.5.1 (#313)
Bumps [github.com/eclipse/paho.mqtt.golang](https://github.com/eclipse/paho.mqtt.golang) from 1.5.0 to 1.5.1.
- [Release notes](https://github.com/eclipse/paho.mqtt.golang/releases)
- [Commits](https://github.com/eclipse/paho.mqtt.golang/compare/v1.5.0...v1.5.1)

---
updated-dependencies:
- dependency-name: github.com/eclipse/paho.mqtt.golang
  dependency-version: 1.5.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-17 14:39:34 +02:00
Arvindh f44903b63b NOISSUE - Add user verification env to Rules Engine (#312)
* add user verification env to RE

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add user verification env to Alarms, Reports

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-09-16 10:51:35 +02:00
dependabot[bot] 1433ad6fe4 NOISSUE - Bump google.golang.org/grpc from 1.75.0 to 1.75.1 (#310)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.75.0 to 1.75.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.75.0...v1.75.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.75.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-12 13:38:09 +02:00
dependabot[bot] 699cd052bc NOISSUE - Bump github.com/redis/go-redis/v9 from 9.13.0 to 9.14.0 (#311)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.13.0 to 9.14.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.13.0...v9.14.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-12 13:37:53 +02:00
Nataly Musilah a22685f168 NOISSUE - Add Messages page ordering (#306)
* add messaging ordering

Signed-off-by: musilah <nataleigh.nk@gmail.com>

* fix lint

Signed-off-by: musilah <nataleigh.nk@gmail.com>

* use orderByTime

Signed-off-by: musilah <nataleigh.nk@gmail.com>

* fix endpoint tests

Signed-off-by: musilah <nataleigh.nk@gmail.com>

* return ui build

Signed-off-by: musilah <nataleigh.nk@gmail.com>

* use switch cases

Signed-off-by: musilah <nataleigh.nk@gmail.com>

---------

Signed-off-by: musilah <nataleigh.nk@gmail.com>
2025-09-12 12:17:34 +02:00
Steve Munene 9a621f4a88 MG-308 - Fix reports default template (#308)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-09-12 12:17:00 +02:00
dependabot[bot] f57f8f5a8a NOISSUE - Bump google.golang.org/protobuf from 1.36.8 to 1.36.9 (#303)
Bumps google.golang.org/protobuf from 1.36.8 to 1.36.9.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-version: 1.36.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 13:43:41 +02:00
dependabot[bot] 424d5a6d22 NOISSUE - Bump github.com/spf13/viper from 1.20.1 to 1.21.0 (#304)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.20.1 to 1.21.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.20.1...v1.21.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-version: 1.21.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 13:43:26 +02:00
dependabot[bot] 4428fdc31b NOISSUE - Bump github.com/jackc/pgx/v5 from 5.7.5 to 5.7.6 (#305)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.7.5 to 5.7.6.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.7.5...v5.7.6)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-version: 5.7.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-09 13:42:57 +02:00
dependabot[bot] de9637f71a NOISSUE - Bump golang.org/x/sync from 0.16.0 to 0.17.0 (#302)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.16.0 to 0.17.0.
- [Commits](https://github.com/golang/sync/compare/v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.17.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-08 13:14:17 +02:00
dependabot[bot] 4aa7f71224 NOISSUE - Bump actions/setup-go in /.github/workflows in the gh-dependency group (#295)
Bumps the gh-dependency group in /.github/workflows with 1 update: [actions/setup-go](https://github.com/actions/setup-go).


Updates `actions/setup-go` from 5 to 6
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-07 10:48:22 +02:00
dependabot[bot] 963eeaa87e NOISSUE - Bump golang in /docker in the docker-dependency group (#300)
Bumps the docker-dependency group in /docker with 1 update: golang.


Updates `golang` from 1.25.0-alpine to 1.25.1-alpine

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.1-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docker-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-07 10:47:26 +02:00
dependabot[bot] b08b457039 NOISSUE - Bump github.com/prometheus/client_golang from 1.23.0 to 1.23.2 (#299)
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.23.0 to 1.23.2.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.23.0...v1.23.2)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.23.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-07 10:46:07 +02:00
dependabot[bot] d718eb0151 NOISSUE - Bump github.com/absmach/callhome from 0.14.0 to 0.18.0 (#296)
Bumps [github.com/absmach/callhome](https://github.com/absmach/callhome) from 0.14.0 to 0.18.0.
- [Release notes](https://github.com/absmach/callhome/releases)
- [Commits](https://github.com/absmach/callhome/compare/v0.14.0...v0.18.0)

---
updated-dependencies:
- dependency-name: github.com/absmach/callhome
  dependency-version: 0.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-06 22:30:28 +02:00
Dušan Borovčanin be7ee7a877 NOISSUE - Fix bugs caused by SMQ update (#301)
* Fix SMQ-caused issues

Signed-off-by: dusan <borovcanindusan1@gmail.com>

* Fix tests

Signed-off-by: dusan <borovcanindusan1@gmail.com>

---------

Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-09-06 21:58:41 +02:00
dependabot[bot] 2b97993c30 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.12.1 to 9.13.0 (#298)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.12.1 to 9.13.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.12.1...v9.13.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-06 18:16:24 +02:00
dusan 42af2b4cdf NOISSUE - Update SMQ
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-09-06 18:15:54 +02:00
dependabot[bot] a7bd60ea51 NOISSUE - Bump github.com/absmach/supermq from 0.18.0 to 0.18.1 (#297)
Bumps [github.com/absmach/supermq](https://github.com/absmach/supermq) from 0.18.0 to 0.18.1.
- [Release notes](https://github.com/absmach/supermq/releases)
- [Commits](https://github.com/absmach/supermq/compare/v0.18.0...v0.18.1)

---
updated-dependencies:
- dependency-name: github.com/absmach/supermq
  dependency-version: 0.18.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-06 18:12:24 +02:00
dependabot[bot] b4fc9ea54c NOISSUE - Bump github.com/go-chi/chi/v5 from 5.2.2 to 5.2.3 (#288)
Bumps [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/go-chi/chi/releases)
- [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-chi/chi/compare/v5.2.2...v5.2.3)

---
updated-dependencies:
- dependency-name: github.com/go-chi/chi/v5
  dependency-version: 5.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-01 15:38:46 +02:00
dependabot[bot] 671d8ddd1d NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#286)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.62.0 to 0.63.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.62.0...zpages/v0.63.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-version: 0.63.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-01 15:23:41 +02:00
dependabot[bot] aac49e5a5d NOISSUE - Bump github.com/gookit/color from 1.5.4 to 1.6.0 (#290)
Bumps [github.com/gookit/color](https://github.com/gookit/color) from 1.5.4 to 1.6.0.
- [Release notes](https://github.com/gookit/color/releases)
- [Commits](https://github.com/gookit/color/compare/v1.5.4...v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/gookit/color
  dependency-version: 1.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-01 15:23:19 +02:00
Dušan Borovčanin 60e256c267 NOISSUE - Replace interface{} with any (#285)
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-26 13:26:32 +02:00
dependabot[bot] 21494525fe NOISSUE - Bump actions/checkout in /.github/workflows in the gh-dependency group (#279)
Bumps the gh-dependency group in /.github/workflows with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 4 to 5
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 09:55:32 +02:00
dependabot[bot] 49fe83fa01 NOISSUE - Bump github.com/nats-io/nats.go from 1.44.0 to 1.45.0 (#280)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.44.0 to 1.45.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.44.0...v1.45.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.45.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 09:51:19 +02:00
dependabot[bot] 46dfd26285 NOISSUE - Bump github.com/stretchr/testify from 1.10.0 to 1.11.0 (#283)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.10.0 to 1.11.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.10.0...v1.11.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 09:50:33 +02:00
dependabot[bot] d2f11592a9 NOISSUE - Bump google.golang.org/protobuf from 1.36.7 to 1.36.8 (#282)
Bumps google.golang.org/protobuf from 1.36.7 to 1.36.8.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-version: 1.36.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 09:49:44 +02:00
dusan 8a1967f98a NOISSUE - Remove duplicate mocks target
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-26 09:46:52 +02:00
dusan 0ab6889000 NOISSUE - Update Go version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-26 09:45:11 +02:00
dependabot[bot] 6abf94ce4a NOISSUE - Bump golang in /docker in the docker-dependency group (#278)
Bumps the docker-dependency group in /docker with 1 update: golang.


Updates `golang` from 1.24.5-alpine to 1.25.0-alpine

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.25.0-alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: docker-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 09:18:28 +02:00
dependabot[bot] 879c5e4c4c NOISSUE - Bump google.golang.org/grpc from 1.74.2 to 1.75.0 (#281)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.74.2 to 1.75.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.74.2...v1.75.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.75.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 09:18:11 +02:00
dependabot[bot] 31ae32bd16 NOISSUE - Bump github.com/authzed/authzed-go from 1.4.1 to 1.5.0 (#284)
Bumps [github.com/authzed/authzed-go](https://github.com/authzed/authzed-go) from 1.4.1 to 1.5.0.
- [Release notes](https://github.com/authzed/authzed-go/releases)
- [Commits](https://github.com/authzed/authzed-go/compare/v1.4.1...v1.5.0)

---
updated-dependencies:
- dependency-name: github.com/authzed/authzed-go
  dependency-version: 1.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-26 09:17:54 +02:00
Arvindh ffc7a1ff78 NOISSUE - Add callout in Rule Engine Service (#277)
* add callout to re

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add callout to re

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add callout to re

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add rule events

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add rule events

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add rule events

Signed-off-by: Arvindh <arvindh91@gmail.com>

* remove lints

Signed-off-by: Arvindh <arvindh91@gmail.com>

* remove lints

Signed-off-by: Arvindh <arvindh91@gmail.com>

* remove decoders

Signed-off-by: Arvindh <arvindh91@gmail.com>

* remove lints

Signed-off-by: Arvindh <arvindh91@gmail.com>

* remove lints

Signed-off-by: Arvindh <arvindh91@gmail.com>

* replace interface{} with any

Signed-off-by: Arvindh <arvindh91@gmail.com>

* optimization of event

Signed-off-by: Arvindh <arvindh91@gmail.com>

* remove lints

Signed-off-by: Arvindh <arvindh91@gmail.com>

* align code

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-08-26 09:17:27 +02:00
dusan 3413564148 NOISSUE - Update SMQ version
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-21 23:16:53 +02:00
dusan 4f1d96cc21 NOISSUE - Update login action
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-20 10:13:35 +02:00
dependabot[bot] 61225a98aa NOISSUE - Bump google.golang.org/protobuf from 1.36.6 to 1.36.7 (#271)
Bumps google.golang.org/protobuf from 1.36.6 to 1.36.7.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-version: 1.36.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 22:58:04 +02:00
dependabot[bot] c3a5cf3e4f NOISSUE - Bump github.com/redis/go-redis/v9 from 9.12.0 to 9.12.1 (#275)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.12.0 to 9.12.1.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/RELEASE-NOTES.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.12.0...v9.12.1)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-19 22:55:57 +02:00
Nataly Musilah e7633ffafd NOISSUE - Update alarms and reports sorting (#272)
* update alarms and reports

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix linter

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix structs

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix defDir

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* remove name from alarms

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* use switch clases

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* chore: update SMQ dep

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* use if statements for 3 cases

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* chore: bump SMQ version

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* use api keys

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* use COALESCE for updatedAt

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix lint

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

---------

Signed-off-by: Musilah <nataleigh.nk@gmail.com>
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
Co-authored-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-19 22:34:55 +02:00
dusan 83b5d0b9eb NOISSUE - Update dependencies
Signed-off-by: dusan <borovcanindusan1@gmail.com>
2025-08-06 18:50:51 +02:00
Steve Munene 8b4766d740 NOISSUE - Add reports template tests (#264)
* fix template tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add endpoint tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-08-06 10:18:36 +02:00
Nataly Musilah f4e3cfab6d NOISSUE - Add rules ordering by order and name (#265)
Signed-off-by: Musilah <nataleigh.nk@gmail.com>
2025-08-06 09:49:10 +02:00
Steve Munene 067bdc3631 NOISSUE - Refactor reports template validation (#260)
* fix validation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* NOISSUE - Bump github.com/nats-io/nats.go from 1.43.0 to 1.44.0 (#262)

Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.43.0 to 1.44.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.43.0...v1.44.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* NOISSUE -  Update to using OpenBao in certs service (#259)

* chore: update smq dep

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: remove am-certs and replace with open-bao

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: remove vault references

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* NOISSUE - Bump github.com/prometheus/client_golang from 1.22.0 to 1.23.0 (#263)

Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.22.0 to 1.23.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/v1.23.0/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.22.0...v1.23.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove walk node method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-04 14:56:46 +02:00
Felix Gateru c07922e0be NOISSUE - Update e2e tests (#261)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-04 11:14:17 +02:00
dependabot[bot] b194e845ec NOISSUE - Bump github.com/prometheus/client_golang from 1.22.0 to 1.23.0 (#263)
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.22.0 to 1.23.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/v1.23.0/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.22.0...v1.23.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.23.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 10:04:51 +02:00
Felix Gateru 4007f86fb9 NOISSUE - Update to using OpenBao in certs service (#259)
* chore: update smq dep

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: remove am-certs and replace with open-bao

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: remove vault references

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-08-01 09:51:08 +02:00
dependabot[bot] 5312a317e3 NOISSUE - Bump github.com/nats-io/nats.go from 1.43.0 to 1.44.0 (#262)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.43.0 to 1.44.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.43.0...v1.44.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 09:49:00 +02:00
Ian Ngethe Muchiri 389205ec5b NOISSUE -Fix return value for update tags in RE (#258)
Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-07-25 16:06:07 +02:00
Dusan Borovcanin 4ce270c9dc NOISSUE - Update SMQ
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-24 14:20:50 +02:00
dependabot[bot] a2b09e9d2d NOISSUE - Bump google.golang.org/grpc from 1.73.0 to 1.74.2 (#257)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.73.0 to 1.74.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.73.0...v1.74.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.74.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-24 10:07:03 +02:00
Dusan Borovcanin 3cd9774a91 NOISSUE - Fix typo
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-18 11:48:27 +02:00
Felix Gateru f7dad77613 NOISSUE - Move codecov yaml file (#252)
* refactor: move codecov.yaml file

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: remove config yaml referece

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: add auto generated api files to ignore

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-18 10:55:41 +02:00
Dusan Borovcanin 62c6a34725 NOISSUE - Update dependencies
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-15 12:21:58 +02:00
Dusan Borovcanin 989c883249 NOISSUE - Sync with SMQ
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-15 11:01:43 +02:00
Steve Munene 748a3dcb49 NOISSUE - Update mockery files (#251)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-07-14 10:35:47 +02:00
Steve Munene b4eb6fd1aa NOISSUE - Update reports to use chromedp (#249)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* switch to gotenberg

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix top bar

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update changes

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update query

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address commants

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-07-14 10:33:22 +02:00
Dusan Borovcanin ef6417a15d NOISSUE - Update Go version
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-11 10:51:41 +02:00
dependabot[bot] 6d514a4709 NOISSUE - Bump golang in /docker in the docker-dependency group (#247)
Bumps the docker-dependency group in /docker with 1 update: golang.


Updates `golang` from 1.24.4-alpine to 1.24.5-alpine

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.24.5-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docker-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-11 10:50:06 +02:00
dependabot[bot] fbd52d0ee0 NOISSUE - Bump golang.org/x/sync from 0.15.0 to 0.16.0 (#248)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.15.0 to 0.16.0.
- [Commits](https://github.com/golang/sync/compare/v0.15.0...v0.16.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-11 10:49:41 +02:00
Dusan Borovcanin 77c2483f0d NOISSUE - Update SMQ
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-10 16:02:35 +02:00
Steve Munene 2e0432bdb5 MG-134 - Add support for Report templates (#180)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add remove report from nats handler

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* move runinfo to pkg

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update report handler

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update reports handler

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update handler in reports

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update go.mod and go.sum

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update package to chromedp

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* change update reorts to use chromium

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update report template

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add endpoint and repo methods

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add template validation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove repeated code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix template formatting

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update report template

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix mocks and tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove debug logs

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix api docs

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove pointers

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix template path

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix template path

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing validation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix logic

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert ui variable changes

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* rename method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update to browserless service

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix go mod file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-07-09 18:44:59 +02:00
Arvindh 148e2fbb7f NOISSUE - Remove Vault scripts and compose (#246)
* remove vault from MG

Signed-off-by: Arvindh <arvindh91@gmail.com>

* rename env in readme

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-07-08 14:18:32 +02:00
Arvindh 5568589182 NOISSUE - Add MG UI configuration in env (#244)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-07-07 17:49:10 +02:00
dependabot[bot] 2029ded7b1 NOISSUE - Bump github.com/absmach/supermq (#243)
Bumps [github.com/absmach/supermq](https://github.com/absmach/supermq) from 0.16.1-0.20250616095552-e98b6576f103 to 0.17.0-rc.1.
- [Release notes](https://github.com/absmach/supermq/releases)
- [Commits](https://github.com/absmach/supermq/commits/v0.17.0-rc.1)

---
updated-dependencies:
- dependency-name: github.com/absmach/supermq
  dependency-version: 0.17.0-rc.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-07 14:15:02 +02:00
Dusan Borovcanin 25617f69dc NOISSUE - Update CI actions
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-01 14:41:05 +02:00
Dusan Borovcanin 013d73a4bb NOISSUE - Update CI actions
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-07-01 14:14:40 +02:00
Felix Gateru 0c97f61680 NOISSUE - Remove irrelevant test case (#236)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-07-01 12:09:13 +02:00
dependabot[bot] fa161a0a46 NOISSUE - Bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0 (#235)
* Bump github.com/go-viper/mapstructure/v2 from 2.2.1 to 2.3.0

Bumps [github.com/go-viper/mapstructure/v2](https://github.com/go-viper/mapstructure) from 2.2.1 to 2.3.0.
- [Release notes](https://github.com/go-viper/mapstructure/releases)
- [Changelog](https://github.com/go-viper/mapstructure/blob/main/CHANGELOG.md)
- [Commits](https://github.com/go-viper/mapstructure/compare/v2.2.1...v2.3.0)

---
updated-dependencies:
- dependency-name: github.com/go-viper/mapstructure/v2
  dependency-version: 2.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* NOISSUE - Fix CI lint

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-30 20:06:42 +02:00
Dusan Borovcanin 53046db47e NOISSUE - Fix Rule update
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-30 19:55:45 +02:00
Dušan Borovčanin bf5e18acb4 NOISSUE - Fix RE schedule (#234)
* NOISSUE - Fix RE schedule

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add domain to the scheduled message

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove debug log

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-30 13:28:37 +02:00
dependabot[bot] f569c8a4fe NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#229)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.61.0 to 0.62.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.61.0...zpages/v0.62.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-version: 0.62.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 10:35:43 +02:00
dependabot[bot] e08e8f2316 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.10.0 to 9.11.0 (#230)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.10.0 to 9.11.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.10.0...v9.11.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 10:29:04 +02:00
dependabot[bot] 54cd2846da NOISSUE - Bump go.opentelemetry.io/otel/trace from 1.36.0 to 1.37.0 (#231)
Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.36.0 to 1.37.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.36.0...v1.37.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/trace
  dependency-version: 1.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 10:26:30 +02:00
dependabot[bot] 06671670b0 NOISSUE - Bump github.com/authzed/authzed-go from 1.4.0 to 1.4.1 (#232)
Bumps [github.com/authzed/authzed-go](https://github.com/authzed/authzed-go) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/authzed/authzed-go/releases)
- [Commits](https://github.com/authzed/authzed-go/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: github.com/authzed/authzed-go
  dependency-version: 1.4.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-30 10:18:40 +02:00
Dusan Borovcanin d5fa6e45a0 NOISSUE - Fix comment typo
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-27 12:33:43 +02:00
Dusan Borovcanin 0414e91268 NOISSUE - Fix Golang RE integration
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-27 11:53:31 +02:00
Dušan Borovčanin bfe6ec09c3 NOISSUE - Remove AES and use library instead (#226)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-26 23:35:40 +02:00
Ian Ngethe Muchiri 0d48e4ecdd MG-820 - RE outputs handling (#213)
* Fix: Update send alarm output handling

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Update send email output

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Update remote posgres output handling

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Update keys for result and message to constants

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Remove unused param

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Remove test for query by output channel

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Separate outputs

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Revert docker compose changes

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Update mocks

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Update license header

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Update output type

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Update handling outputs

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Update test outputs

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: rename publisher to channel

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: update imports

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Update unmarshal outputs

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* NOISSUE - Fix JSON marshalling and unmarshalling (#1)

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix: Update outputs

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: update the templating

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: update how we marshal alarms

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
Co-authored-by: Dušan Borovčanin <borovcanindusan1@gmail.com>
2025-06-26 17:35:46 +02:00
Steve Munene 88d2ef3257 MG-225 - Fix schedule validation (#222)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add utc for reports

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fic wrapper

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove auth error

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-24 14:45:21 +02:00
wambui-pixel 2c9c594100 MG-219 - Update UI variables (#221)
Signed-off-by: wambuipixel <kiokowambui015@gmail.com>
2025-06-23 16:29:18 +02:00
Steve Munene 8f45405efb MG-133 - Prevent Rule scheduling in past (#211)
* add validation during unmarshalling

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* move validation to individual requests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert error

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert error

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-23 13:15:32 +02:00
dependabot[bot] cc18373844 NOISSUE - Bump github.com/go-chi/chi/v5 from 5.2.1 to 5.2.2 (#220)
Bumps [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) from 5.2.1 to 5.2.2.
- [Release notes](https://github.com/go-chi/chi/releases)
- [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-chi/chi/compare/v5.2.1...v5.2.2)

---
updated-dependencies:
- dependency-name: github.com/go-chi/chi/v5
  dependency-version: 5.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-23 13:05:54 +02:00
Dušan Borovčanin 612823b4d2 MG-217 - Update the RE update tag repo logic
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-20 17:06:10 +02:00
Steve Munene 184a9161d6 MG-154 - Add Tags in Rule Engine listing and support filter by tags (#212)
* add tags to repo layer

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update service layer

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update api layer

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix postgres methods

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix logic

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-20 16:28:24 +02:00
Felix Gateru d66e5ce329 NOISSUE - Add cache for channel and domain routes (#215)
* feat: add channels redis

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: update smq dep

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-06-20 14:49:14 +02:00
Dusan Borovcanin 35c84741d5 NOISSUE - Fix certs compose
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-18 18:41:35 +02:00
JeffMboya fbb030c22e NOISSUE - Update workflow (#206)
Update SMQ

Signed-off-by: JeffMboya <jangina.mboya@gmail.com>
2025-06-18 13:01:39 +02:00
Steve Munene ca95368d3d NOISSUE - Fix reports FileFormat json tag (#207)
* fix json tags

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update supermq

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-18 08:15:23 +02:00
JeffMboya c7aa2b88e8 MG-178 - Add repo dispatch to trigger stage deployment (#179)
* Add repo dispatch

Signed-off-by: JeffMboya <jangina.mboya@gmail.com>

* Update repo dispatch

Signed-off-by: JeffMboya <jangina.mboya@gmail.com>

* Update repo dispatch

Signed-off-by: JeffMboya <jangina.mboya@gmail.com>

---------

Signed-off-by: JeffMboya <jangina.mboya@gmail.com>
2025-06-17 10:01:06 +02:00
Steve Munene c2a03e6128 MG-167 - Terminate Alarms message which failed to handle (#191)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update postgres writer

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix readers tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix senML naming

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove logger from service

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* terminate message when alarm fails to decode

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert changes

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove message from logging

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove empty line

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* wrap error

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-16 16:20:01 +02:00
Steve Munene 5566c0970d NOISSUE - Fix mockery (#205)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-16 15:45:04 +02:00
Dušan Borovčanin 9a62ee6068 NOISSUE - Add Golang support to RE (#161)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-16 12:31:26 +02:00
Arvindh a2db0717b3 NOISSUE - Add message error type to handle Writer errors (#200)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update postgres writer

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix readers tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix senML naming

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove logger from service

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update messaging to NACK

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove error wrapping

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove message in logging

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* writer add msg error

Signed-off-by: Arvindh <arvindh91@gmail.com>

* revert the postgres writer changes

Signed-off-by: Arvindh <arvindh91@gmail.com>

* dependency: update supermq version

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-16 12:22:31 +02:00
Steve Munene dcd5ff914d MG-136 - Move reports to a separate service (#152)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add remove report from nats handler

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add license header

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update docker compose

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* move runinfo to pkg

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update report handler

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update reports handler

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update handler in reports

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update repo method from time to due

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix validation methods

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update reports port to 9017

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update nginx to support reports

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix reports location in nginx

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-06-16 12:10:50 +02:00
Felix Gateru e57db52b34 NOISSUE - Fix certs config file path (#199)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-06-12 15:58:59 +03:00
Dusan Borovcanin 075ff2ff6c NOISSUE - Send anonymous telemtry by default
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-12 13:12:38 +03:00
dependabot[bot] a6a3bb1c30 NOISSUE - Bump golang in /docker in the docker-dependency group (#192)
Bumps the docker-dependency group in /docker with 1 update: golang.


Updates `golang` from 1.24.3-alpine to 1.24.4-alpine

---
updated-dependencies:
- dependency-name: golang
  dependency-version: 1.24.4-alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: docker-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 11:34:54 +02:00
dependabot[bot] 9db6fc5e90 NOISSUE - Bump github.com/nats-io/nats.go from 1.42.0 to 1.43.0 (#195)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.42.0 to 1.43.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.42.0...v1.43.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.43.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-09 11:34:23 +02:00
Dusan Borovcanin 6fa0b1378a NOISSUE - Update SMQ and Go versions
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-09 11:25:54 +02:00
Dusan Borovcanin c35bc42210 NOISSUE - Fix typos
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-06 14:05:18 +02:00
Dusan Borovcanin 33289561c0 NOISSUE - Fix RE nil error
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-06 12:07:37 +02:00
Dusan Borovcanin e29691c8e3 NOISSUE - Update Lua libs dependency
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-06 10:19:21 +02:00
Dusan Borovcanin 69f8039749 NOISSUE - Update Go version
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-05 14:27:16 +02:00
Ian Ngethe Muchiri 8551f24893 NOISSUE - Update UI env variables (#189)
* Fix: Update UI env variables

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Add comment for EULA link

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Update support env variables

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: fix typo

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* Fix: Remove agreement

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-06-05 14:25:26 +02:00
Arvindh a8b61fe5bd NOISSUE - Change topic format in RE (#183)
* Change topic in RE for change internal msg fmt

Signed-off-by: Arvindh <arvindh91@gmail.com>

* update re message topic

Signed-off-by: Arvindh <arvindh91@gmail.com>

* sync with supermq main

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-06-05 12:52:01 +02:00
Dusan Borovcanin b51ce5f1d2 NOISSUE - Add support for bitwise ops in Lua scripts
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-04 18:09:47 +02:00
Dusan Borovcanin 73f9ab5bf8 NOISSUE - Add HTTP client to RE Lua scripts
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-03 11:54:36 +02:00
Dušan Borovčanin 38f233c611 MG-181 - Add wildcard support to RE (#185)
* Add wildcard

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix RE tests

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add comments for wildcards

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix match check

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-06-03 10:57:10 +02:00
dependabot[bot] b1182642f2 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.8.0 to 9.9.0 (#184)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.8.0 to 9.9.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.8.0...v9.9.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-02 11:59:14 +02:00
Dusan Borovcanin 2f78320f59 NOISSUE - Improve RE logging
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-30 14:47:25 +02:00
b1ackd0t 861c82cfdc NOISSUE - Add Tests For AES Module on Rules Engine (#182)
* refactor(re): aes error handling and adding unit tests

Added unit tests for lua bindings

* fix(re): improve error handling

return 2 values in case of error and 1 value for valid data

* style: add license information
2025-05-29 17:12:11 +02:00
Dušan Borovčanin 5b5fa78032 NOISSUE - Fix RE logging (#176)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-27 14:31:26 +02:00
Dusan Borovcanin beb6dea596 NOISSUE - Update SMQ and mocks
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-26 14:41:21 +02:00
Kisaka the Jones 2e6128e912 NOISSUE - Add AES support to RE (#143)
* AES RE support Lua script

* AES RE support Lua script

* AES support on RE

* AES Support on RE

* AES code change

* Modified AES script

* Modified AES script

* AES Go script

* AES Go script

* Update: String use to Byte use

* Update: AES Lua binding and Go script

* Update: AES Lua binding reviewed changes and Go script

* Reviewed Update: Lint Checking with code

* Reviewed Update: Lint Checking with code

* Reviewed Update: Lint Checking with code

* Reviewed Update: Lint Checking with code

* Reviewed Update: Lint Checking with code

* Reviewed Update: Lint Checking with code

* Reviewed Update: Lint Checking with code

* Reviewed Update: Lint Checking with code

* Reviewed Update: Lint Checking with code

* Reviewed Update: Lint Checking with code

* Fix remarks

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add IV size check

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add IV size check

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add IV size check

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix variable names

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Use common decode params

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
Co-authored-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-26 13:35:38 +02:00
dependabot[bot] 090e10910e NOISSUE - Bump google.golang.org/grpc from 1.72.1 to 1.72.2 (#175)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.72.1 to 1.72.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.1...v1.72.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 12:22:45 +02:00
dependabot[bot] 52846a267c NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#172)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.60.0 to 0.61.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.60.0...zpages/v0.61.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-version: 0.61.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-26 11:42:48 +02:00
Dusan Borovcanin 51989d2af2 NOISSUE - Update SMQ
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-26 11:11:17 +02:00
Arvindh effbb7091d NOISSUE - Update docker compose and env file (#171)
* Update docker compose and env

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add MG_AUTH_URL

Signed-off-by: Arvindh <arvindh91@gmail.com>

* update smq copy script

Signed-off-by: Arvindh <arvindh91@gmail.com>

* sync with supermq main

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-05-23 15:05:17 +02:00
Dusan Borovcanin e810530cd7 NOISSUE - Remove trailing spaces from .env
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-22 16:49:24 +02:00
Steve Munene b5b992f208 NOISSUE - Update SMQ env variables (#170)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-05-22 16:37:14 +02:00
Felix Gateru 68e58fc499 NOISSUE - Fix volume path (#164)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-05-20 18:44:46 +02:00
dependabot[bot] 7fe3ced954 NOISSUE - Bump google.golang.org/grpc from 1.72.0 to 1.72.1 (#159)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.72.0 to 1.72.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.72.0...v1.72.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 16:52:29 +02:00
dependabot[bot] bcaadca1fd NOISSUE - Bump github.com/jackc/pgx/v5 from 5.7.4 to 5.7.5 (#160)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.7.4 to 5.7.5.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.7.4...v5.7.5)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-version: 5.7.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-19 16:51:51 +02:00
Arvindh e10a7646cd NOISSUE - Add Measurement to Creation of alarm (#158)
* fix alarm logic

Signed-off-by: Arvindh <arvindh91@gmail.com>

* rename created_till to created_to

Signed-off-by: Arvindh <arvindh91@gmail.com>

* move alarm logic to sql

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-05-19 13:49:28 +02:00
Dusan Borovcanin 5d7d4b842d NOISSUE - Remove reports from the Nats handler
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-14 14:58:21 +02:00
Arvindh c9a51947a3 NOISSUE - Update Timescale DB and queries (#147)
* updated timescaledb and queries

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add pgx connection pool

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add pgx config

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add pgx config

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add pgx config

Signed-off-by: Arvindh <arvindh91@gmail.com>

* fix message sdk and sql migration

Signed-off-by: Arvindh <arvindh91@gmail.com>

* updated pgx pool set config

Signed-off-by: Arvindh <arvindh91@gmail.com>

* clean up values

Signed-off-by: Arvindh <arvindh91@gmail.com>

* clean up values

Signed-off-by: Arvindh <arvindh91@gmail.com>

* change pgclient in test

Signed-off-by: Arvindh <arvindh91@gmail.com>

* remove comments

Signed-off-by: Arvindh <arvindh91@gmail.com>

* fix test

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-05-14 10:40:53 +02:00
Dusan Borovcanin 47ed0aa112 NOISSUE - Improve alarms and reports handling
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-13 10:24:54 +02:00
Steve Munene 8882066435 NOISSUE - Remove field in footer (#150)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-05-12 17:05:48 +02:00
Arvindh 53ef51326a NOISSUE - Override supermq-base-net with magistrala-base-net (#148)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-05-12 12:02:37 +02:00
dependabot[bot] fe0d547091 NOISSUE - Bump golang.org/x/sync from 0.13.0 to 0.14.0 (#149)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.13.0 to 0.14.0.
- [Commits](https://github.com/golang/sync/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-12 12:02:16 +02:00
Arvindh 6c4ed66d62 NOISSUE - Add filter by name in rule listing (#142)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-05-09 15:23:58 +02:00
Dusan Borovcanin f5e7602aa2 NOISSUE - Remove unused encode functions
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-08 11:48:25 +02:00
dependabot[bot] f94d40d2b2 NOISSUE - Bump github.com/nats-io/nats.go from 1.41.2 to 1.42.0 (#138)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.41.2 to 1.42.0.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.41.2...v1.42.0)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-07 09:48:46 +02:00
Steve Munene f44c38dbc9 NOISSUE - Add custom title for reports (#140)
* add custom title

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-05-05 16:13:57 +02:00
Arvindh b0652d1170 NOISSUE - Add option to have mutiple clientIDs in request (#141)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-05-05 16:05:52 +02:00
dependabot[bot] b35b4c7cf0 NOISSUE - Bump golangci/golangci-lint-action from 7 to 8 in /.github/workflows in the gh-dependency group (#139)
* Bump golangci/golangci-lint-action

Bumps the gh-dependency group in /.github/workflows with 1 update: [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action).


Updates `golangci/golangci-lint-action` from 7 to 8
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/v7...v8)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: gh-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update version

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update SMQ

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-05 13:51:17 +02:00
dependabot[bot] b2b0f073ac NOISSUE - Bump github.com/redis/go-redis/v9 from 9.7.3 to 9.8.0 (#137)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.7.3 to 9.8.0.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.7.3...v9.8.0)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-version: 9.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-02 00:31:53 +02:00
Dusan Borovcanin cc877286dd NOISSUE - Fetch latest SMQ
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-05-02 00:10:41 +02:00
Dušan Borovčanin 831674b036 NOISSUE - Fix scheduler (#131)
* Rename and reorganize files

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix scheduler

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix scheduler and use UTC

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update scheduler calculation

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Rules loop

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix tests

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix linter errors

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix due

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove faling tests

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-29 13:30:24 +02:00
Steve Munene c170b51f7b NOISSUE - Fix Device ID column (#130)
* fix client row

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix subtopic width

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* move name to the top row

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-04-29 09:15:19 +02:00
Steve Munene a2b108785c NOISSUE - Fix text alignment in PDF (#129)
* fix text alignment in PDF

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* adjust column sizes

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert env variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-04-28 18:29:49 +02:00
Arvindh e924103df6 NOISSUE - Fix client id optional in reports (#128)
* fix client id optional

Signed-off-by: Arvindh <arvindh91@gmail.com>

* add timescale reader client env

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-04-28 17:15:37 +02:00
Steve Munene 28d4548dd9 NOISSUE - Remove mandatory requirement for client id in report (#127)
* remove mandory requirement for client id

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter because of vault

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix pdf and csv column

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-04-28 15:02:12 +02:00
Dusan Borovcanin 2de8e6ccda NOISSUE - Add decodeF32 function
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-28 13:04:20 +02:00
Steve Munene 02da121280 MG-94 - Add backend support for reports (#107)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix missing variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix api and add report config to rule engine

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix repo command

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix download request

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix download api

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix add report config

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused parameters

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add limit field to config

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add test and address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add logger

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove logger

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* uncomment code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add status check

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* resolve conflicts

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* rebase code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix startdate when zero

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add time expression parser and logics

Signed-off-by: Arvindh <arvindh91@gmail.com>

* fix postgres methods

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix pdf and csv generation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add description for reports

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove aggregation field

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove logs

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix go mod file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix endpoint and postgres methods

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update report config update methods

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix service test

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unnecessary check

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove endpoints

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix generate PDF and CSV

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused code

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert UI variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add empty line

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix go mod file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update download api

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* revert UI variable

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix download endpoint

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update generateREport method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* refactor generate api

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix csv column

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix csv generator

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove logs

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* updated reports logic and api

Signed-off-by: Arvindh <arvindh91@gmail.com>

* fix time conversion

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
Signed-off-by: Arvindh <arvindh91@gmail.com>
Co-authored-by: Arvindh <arvindh91@gmail.com>
2025-04-28 09:09:22 +02:00
Dušan Borovčanin 4dd0de64fb NOISSUE - Revert success logger (#126)
* Fix info logs in RE

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Lua handling

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Docker dir

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add info and warning

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix logging

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-25 18:20:20 +02:00
Dusan Borovcanin 88fdaeb8c0 Update SMQ dependency
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-25 14:17:01 +02:00
Dušan Borovčanin 4e9480266e NOISSUE - Add script outputs (#121)
* Update RE to use pure Go instead of Lua bindings

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix RE DB

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix nil error case

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix adding query

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix constraints on kind and logic type

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update RE to use multiple outputs

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update PG writer output

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix protocol error in MQTT forwareder

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix rules error handings

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add false value check

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix topic filtering

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix consumers

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix publisher

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix mocks

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix tests

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-24 23:27:08 +02:00
dependabot[bot] 2a65b6b655 NOISSUE - Bump github.com/nats-io/nats.go from 1.41.1 to 1.41.2 (#122)
Bumps [github.com/nats-io/nats.go](https://github.com/nats-io/nats.go) from 1.41.1 to 1.41.2.
- [Release notes](https://github.com/nats-io/nats.go/releases)
- [Commits](https://github.com/nats-io/nats.go/compare/v1.41.1...v1.41.2)

---
updated-dependencies:
- dependency-name: github.com/nats-io/nats.go
  dependency-version: 1.41.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 20:53:33 +02:00
dependabot[bot] d92974551a NOISSUE - Bump google.golang.org/grpc from 1.71.1 to 1.72.0 (#125)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.71.1 to 1.72.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.1...v1.72.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.72.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 20:51:21 +02:00
dependabot[bot] 2b88909363 NOISSUE - Bump github.com/rubenv/sql-migrate from 1.7.1 to 1.8.0 (#123)
Bumps [github.com/rubenv/sql-migrate](https://github.com/rubenv/sql-migrate) from 1.7.1 to 1.8.0.
- [Commits](https://github.com/rubenv/sql-migrate/compare/v1.7.1...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/rubenv/sql-migrate
  dependency-version: 1.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 20:48:13 +02:00
dependabot[bot] 61b8e6244a NOISSUE - Bump github.com/authzed/authzed-go (#124)
Bumps [github.com/authzed/authzed-go](https://github.com/authzed/authzed-go) from 1.3.1-0.20250320210445-0cde0d8c71e2 to 1.4.0.
- [Release notes](https://github.com/authzed/authzed-go/releases)
- [Commits](https://github.com/authzed/authzed-go/commits/v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/authzed/authzed-go
  dependency-version: 1.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-21 20:44:18 +02:00
Ian Ngethe Muchiri 513586c982 MG-664 - Refactor update rule (#120)
* update update rule

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* refactor repository sql queries

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* revert docker compose change

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* remove unnecessary test

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-04-17 16:37:30 +02:00
Dusan Borovcanin 73e338966f NOISSUE - Fix input topic filter on RE
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-17 09:46:38 +02:00
Ian Ngethe Muchiri 35552c2651 NOISSUE - Add alarms function to send alarm message to NATS (#114)
* add send alarm function

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* move to alarm page

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* add status column

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* update alarms function

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* update send alarm

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* fix tests

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* fix alarms prefix

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-04-16 16:22:42 +02:00
Arvindh aef424c5da NOISSUE - Add broker options (#119)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-04-16 14:21:57 +02:00
Arvindh 17fa535502 NOISSUE - Fix create alarms test and add alarms to GitHub actions (#118)
* fix: Create alarms test

Signed-off-by: Arvindh <arvindh91@gmail.com>

* update: github actions for test

Signed-off-by: Arvindh <arvindh91@gmail.com>

---------

Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-04-16 13:11:41 +02:00
b1ackd0t ddce4f4a46 NOISSUE - Fix Duplicate Streams (#117)
* fix(re): duplicate streams

Fixes nats: API error: code=400 err_code=10058 description=stream name already in use
Align the codebase to use one config for alarms for both alarms service and rules engine
Move writers config to utilize build tags

* fix(brokers): change package names for brokers

move re brokers package to consumers
For RE broker, provide a publisher interface
Move alarms broker from consumer package

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): renaming rePubSub to msgSub

---------

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-04-16 12:36:12 +02:00
Dusan Borovcanin 8c3b3229a8 NOISSUE - Add case for a single SenML value
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-16 00:21:14 +02:00
Dušan Borovčanin 08d727bf6e NOISSUE - Update RE message handling (#116)
* Refactor RE

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Use Publisher only where possible

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Simplify message payload

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Lua code and message preprocessing

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix JSON parsing

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update SMQ dependency

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove case that is never going to happen

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove SenML part

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Reorder functions

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Updarte RE setup AND Timescale writer

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Use NATS instead of brokers

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix pubsub

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix RE publishers

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update JS config description

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix configs and remove unused code

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix linter remarks

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-15 20:12:27 +02:00
b1ackd0t b3e2f41194 NOISSUE - Add Alarms (#106)
* WIP: alarms service

* fix(alarms): remove rule entity since it is not stored here

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* test(alarms): add tests cases for invalid alarms

* feat(alarms): add authorization

* feat(alarms): add docker deployment files

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix: update go mod file

* feat(alarms): support filtering by resolved_by, updated_by and severity

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* style: fix linter errors

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): provide correct otel naming for create alarm

Fixes https://github.com/absmach/magistrala/pull/106#discussion_r2030151971

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): group routes appropriately

Resolves https://github.com/absmach/magistrala/pull/106#discussion_r2030160891

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): extract alarm id from url path rather than query params

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): add all status to help in decoding

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* style(alarms): maintain consistent import as naming for supermq api package

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* refactor(alarms): update supermq dependecy to the latest

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): Add domains gRPC service config to alarms service

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* test(alarms): all CRUD operations from the service

Return empty results instead of nil

This standardizes error responses across alarm endpoints to return empty
result structs rather than nil. Also renames entityReq to alarmReq and
adds HTTP status codes for created/deleted alarms.

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* test(alarms): fix failing tests due to introduction of context on sdk

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): remove channel id

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): standardize error handling across CRUD operations

Updated error responses to use specific repository errors for consistency

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* feat(alarms): add assignment fields to Alarm model and database

Introduced AssignedAt and AssignedBy fields to the Alarm struct and updated the database schema accordingly. Enhanced the UpdateAlarm function to handle these new fields, ensuring proper assignment tracking in the alarms system.

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* feat(alarms): enhance Alarm model with measurement attributes

Updated the Alarm struct to include Measurement, Value, Unit, and Cause fields. Modified the validation logic to ensure these fields are present. Adjusted logging and tracing middleware to reflect the new attributes. Updated database schema and related functions to accommodate these changes, ensuring comprehensive alarm data management.

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* feat(alarms): consume events from pubsub for creation of alarms

Removed session dependencies from CreateAlarm method and enhanced alarm validation to ensure all required fields are present

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* style(alarms): add newline at the end of docker compose

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): Add assignee id and metadata fields when consuming messages

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* feat(alarms): add acknowledged field

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* feat(alarms): Add threshold value for the specific measurement

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* feat(alarms): Add channel, thing, and subtopic fields to Alarm model

This change adds required fields for tracking alarm sources and reorganizes
alarm-related fields for better grouping. Alarms now track the channel,
thing, and subtopic that triggered them, along with domain and rule info.

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* test(alarms): add service layer tests

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): consume created at from message rather than creating it

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* feat(alarms): ready alarm as a gob encoded object

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): read alarms from alarms queue and remove transformer

g

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* feat(alarms): update version of supermq

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* feat(alarms): add gob transformer

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): rename thing id to client id

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): create alarms stream

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): check on logic to create new alarm

create new alarm if severity, status, subtopic changes
enhance logging with additional details for alarms management

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* remove conusmer and use pubsub

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>

* fix(alarms): use build tags for rabbitmq and nats

* fix(alarms): add health and metrics endpoint

* fix(magistrala): use supermq as build flags to see version and commit

* fix(alarms): use js config

* fix(alarms): remove validation when updating an alarm

fix authorization too

---------

Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-04-15 19:32:09 +02:00
dependabot[bot] 629838a571 NOISSUE - Bump github.com/prometheus/client_golang from 1.21.1 to 1.22.0 (#115)
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.21.1 to 1.22.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.21.1...v1.22.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-version: 1.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 10:09:47 +02:00
Ian Ngethe Muchiri edf835b73a MG-659 - Add message storage to Rules Engine (#112)
* add save senml function

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* add multiple pubsubs

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* remove ununsed constant

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* add domain id to message

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* use full words for prefixes

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* update prefixes

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-04-11 16:25:41 +02:00
Dusan Borovcanin faaf42941d Sync with SMQ
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-11 15:31:55 +02:00
Dusan Borovcanin ffad1181cf NOISSUE - Update SMQ version
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-11 12:44:57 +02:00
Dusan Borovcanin 24e99b1af5 NOISSUE - Update SMQ and message params
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-11 11:29:36 +02:00
Dusan Borovcanin 642f326355 NOISSUE - Update SMQ version
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-11 10:03:32 +02:00
Dušan Borovčanin 4b5474ce28 NOISSUE - Fix RE message handling (#113)
* NOISSUE - Fix RE message handing

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* NOISSUE - Fix docker compose

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add supprot for Lua message list

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix Lua indexing

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update SMQ

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix transformer key

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix typo and add int value

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add JSON traverse

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update SMQ

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add supprot for nested objects

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix JSON traversal

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-10 23:07:42 +02:00
Dusan Borovcanin 99a3505003 NOISSUE - Update SMQ dependencies
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-10 12:24:23 +02:00
Dusan Borovcanin 0e04e90803 NOISSUE - Sync with SMQ
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-10 11:27:52 +02:00
Nataly Musilah 478c9907db NOISSUE - Add Readers GRPC Endpoints (#87)
* add ui prefix

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* add grpc backend

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* revert email utility and ui

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* update env variables and docker-composes

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* update env variables

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* add middleware folder

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix linter

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* ui commented

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* resolve comments and conflicts

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* resolve comments pt2

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* remove token from request

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* resolve comments

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* revert makefile and docker changes

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* force open grpc conn

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix linter

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* refactor components

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix tests

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* fix query issue

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* update protoc

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* rename variables

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* remove unused envs

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* use senml and json types for the messages struct

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* remove repetitive message fields

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* update protoc version

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

* return ui to docker

Signed-off-by: Musilah <nataleigh.nk@gmail.com>

---------

Signed-off-by: Musilah <nataleigh.nk@gmail.com>
2025-04-09 11:34:14 +02:00
Dusan Borovcanin 58aca168c8 NOISSUE - Fix pub subtopic in RE
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-08 23:50:02 +02:00
Dusan Borovcanin 352cc663f4 NOISSUE - Fix nil PubSub
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-08 23:15:28 +02:00
dependabot[bot] 9bb59e255d NOISSUE - Bump golang.org/x/sync from 0.12.0 to 0.13.0 (#109)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.12.0 to 0.13.0.
- [Commits](https://github.com/golang/sync/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-version: 0.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 12:10:43 +02:00
dependabot[bot] eff586ae1f NOISSUE - Bump github.com/ory/dockertest/v3 from 3.11.0 to 3.12.0 (#108)
Bumps [github.com/ory/dockertest/v3](https://github.com/ory/dockertest) from 3.11.0 to 3.12.0.
- [Release notes](https://github.com/ory/dockertest/releases)
- [Commits](https://github.com/ory/dockertest/compare/v3.11.0...v3.12.0)

---
updated-dependencies:
- dependency-name: github.com/ory/dockertest/v3
  dependency-version: 3.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 12:02:00 +02:00
dependabot[bot] 2d790d703e NOISSUE - Bump google.golang.org/grpc from 1.71.0 to 1.71.1 (#110)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.71.0 to 1.71.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.71.0...v1.71.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.71.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-07 11:59:41 +02:00
Dusan Borovcanin b862d02a4e NOISSUE - Fix Makefile user repo sed expression
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-04 19:38:58 +02:00
Ian Ngethe Muchiri 4f74efe305 NOISSUE - Create preload function (#105)
* add preload

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* run go mod tidy

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-04-04 12:33:58 +02:00
Ian Ngethe Muchiri 3a892108e1 MG-597- Add writers integrations (#104)
* add gopher-lua-libs library

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* update postgres writer

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-04-04 10:41:49 +02:00
Ian Ngethe Muchiri d1e855ccd4 NOISSUE - Update Rules Engine (#88)
* update rules lua processing

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* remove logs

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* add emailer functionality

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* check error

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* remove files

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* fix tests

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* format template

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-04-02 18:09:11 +02:00
Dusan Borovcanin dd1df566c7 NOISSUE - Simplify generated mocks check
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 19:10:33 +02:00
Dusan Borovcanin 0b19ac9f65 NOISSUE - Fix license header check
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 13:39:41 +02:00
Dusan Borovcanin 1d3515e667 NOISSUE - Update Actions Go version
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 13:32:59 +02:00
Dušan Borovčanin 3fd1e3c503 NOISSUE - Update Mockery version in Makefile (#103)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 13:24:26 +02:00
dependabot[bot] cc57b91117 NOISSUE - Bump github.com/jackc/pgx/v5 from 5.7.3 to 5.7.4 (#97)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.7.3 to 5.7.4.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.7.3...v5.7.4)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 13:21:16 +02:00
Dušan Borovčanin b34a6cb457 NOISSUE - Simplify Mockery config (#101)
* Fix Mockery config

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Simplify Mockery config

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 12:13:52 +02:00
dependabot[bot] 097490ad34 NOISSUE - Bump github.com/gofrs/uuid/v5 from 5.3.1 to 5.3.2 (#98)
Bumps [github.com/gofrs/uuid/v5](https://github.com/gofrs/uuid) from 5.3.1 to 5.3.2.
- [Release notes](https://github.com/gofrs/uuid/releases)
- [Commits](https://github.com/gofrs/uuid/compare/v5.3.1...v5.3.2)

---
updated-dependencies:
- dependency-name: github.com/gofrs/uuid/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 12:06:39 +02:00
dependabot[bot] 5df14dffa5 NOISSUE - Bump github.com/spf13/viper from 1.20.0 to 1.20.1 (#99)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.20.0 to 1.20.1.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.20.0...v1.20.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 11:29:43 +02:00
Dušan Borovčanin d6477a484f NOISSUE - Update YAML files (#100)
* Rename yml to yaml extensions

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Docker project name

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update SMQ YAML files

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Mockery

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Mockery version

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove mocks before running Mockery

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update check order

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix tests

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-04-01 10:41:26 +02:00
Dušan Borovčanin 8f9a496ed6 NOISSUE - Fix SMQ script and dependencies (#96)
* Update Makefile

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update SMQ dependencies

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix Makefile

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update CI linter

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Codecov version

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Mockery version

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-03-28 19:38:37 +01:00
dependabot[bot] 952764c4e9 NOISSUE - Bump github.com/redis/go-redis/v9 from 9.7.1 to 9.7.3 (#90)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.7.1 to 9.7.3.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.7.1...v9.7.3)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-28 19:37:10 +01:00
dependabot[bot] b65536c8b1 NOISSUE - Bump gonum.org/v1/gonum from 0.15.1 to 0.16.0 (#91)
Bumps [gonum.org/v1/gonum](https://github.com/gonum/gonum) from 0.15.1 to 0.16.0.
- [Release notes](https://github.com/gonum/gonum/releases)
- [Commits](https://github.com/gonum/gonum/compare/v0.15.1...v0.16.0)

---
updated-dependencies:
- dependency-name: gonum.org/v1/gonum
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 15:03:52 +01:00
dependabot[bot] 6f86340e5c Bump github.com/jackc/pgx/v5 from 5.7.2 to 5.7.3 (#92)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.7.2 to 5.7.3.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.7.2...v5.7.3)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-25 13:55:18 +01:00
Dušan Borovčanin ff69d3d4ff NOISSUE - Fix SMQ fetch script (#93)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-03-25 13:55:04 +01:00
Ian Ngethe Muchiri 67996efe06 NOISSUE - Fix Readers (#89)
* fix readers

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* fix ci

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* fix docker compose

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-03-21 16:10:56 +01:00
Felix Gateru 0bc6c26ecc NOISSUE - Update postgres reader and writer env variables (#75)
* chore: update postgres reader and writer env variables

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: remove redundant env variable

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* ci: fix ci

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-03-19 16:05:43 +01:00
Felix Gateru be6d8deef7 MG-67 - Update Magistrala Compose with SuperMQ Compose (#76)
* chore: update compose with supermq override

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: remove duplicate env variables

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* ci(check-license.yaml): ignore rabbitmq files

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: add supermq docker file

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* feat: add update option to make file

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor(supermq-docker-compose.override.yml): fix errors in files

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: add amend commit to fetch and update commands

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: add supermq dependency update script

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: update SuperMQ dependency files

* fix: remove reverted changes to Makefile

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor(supermq.sh): remove git staging and commit from script

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: remove redundant docker config files

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: remove redundant files, update compose p[roject directory

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: update project dir path

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: update nginv env file variable, remove redundant nginx config files

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore: include journal and certs to mg compose

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: update script to use sparse checkout and move docker files into ./docker/supermq-docker

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: update docker compose file

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* feat(Makefile): add fetch_supermq to run recipe

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor(supermq.sh): clean up

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* chore(go.mod): remove toolchain definition

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* ci(build.yml): add check for supermq dependency

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* ci: move check to ci

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-03-19 12:37:51 +01:00
b1ackd0t 1b772d3bbe NOISSUE - Fix e2e script (#85)
Signed-off-by: Rodney Osodo <socials@rodneyosodo.com>
2025-03-18 13:58:51 +01:00
dependabot[bot] a1fe43b0a7 NOISSUE - Bump github.com/spf13/viper from 1.19.0 to 1.20.0 (#86)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.19.0 to 1.20.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.19.0...v1.20.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 13:57:58 +01:00
dependabot[bot] 77b1ea63f7 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#81)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.59.0 to 0.60.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.59.0...zpages/v0.60.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 12:20:39 +01:00
dependabot[bot] 614a879faa NOISSUE - Bump golang.org/x/sync from 0.11.0 to 0.12.0 (#82)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.11.0 to 0.12.0.
- [Commits](https://github.com/golang/sync/compare/v0.11.0...v0.12.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 12:00:20 +01:00
dependabot[bot] 660e73c8e4 NOISSUE - Bump google.golang.org/grpc from 1.70.0 to 1.71.0 (#80)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.70.0 to 1.71.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.70.0...v1.71.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 11:57:08 +01:00
dependabot[bot] 8599fa6e12 NOISSUE - Bump github.com/prometheus/client_golang from 1.21.0 to 1.21.1 (#83)
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.21.0 to 1.21.1.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.21.0...v1.21.1)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 11:54:58 +01:00
dependabot[bot] 31b539dd8d NOISSUE - Bump go.opentelemetry.io/otel/trace from 1.34.0 to 1.35.0 (#84)
Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.34.0 to 1.35.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.34.0...v1.35.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/trace
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-17 11:50:43 +01:00
Steve Munene 7a3341b07c MG-37 - Add Rules Engine tests (#74)
* add service and endpoint tests

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update github workflows

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove unused field

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* remove logs

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update github workflows

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix time format

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update to plural

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-03-17 11:46:44 +01:00
Steve Munene 753f44ce53 NOISSUE - Fix SDK (#68)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-03-13 17:20:27 +01:00
nnpvaan 9393dcfa9a MG-72 - Fix NamedQueryContext not returning sql.ErrNoRows (#73) 2025-03-11 16:20:13 +01:00
Steve Munene 1a1d54aa25 fix env variables for pats (#78)
Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-03-05 14:32:55 +01:00
Ian Ngethe Muchiri 9b18f5580a NOISSUE - Fix env variable naming (#77)
Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-03-03 16:29:25 +01:00
dependabot[bot] 8b8cb8d5bc NOISSUE - Bump github.com/prometheus/client_golang from 1.20.5 to 1.21.0 (#70)
Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.20.5 to 1.21.0.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](https://github.com/prometheus/client_golang/compare/v1.20.5...v1.21.0)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 11:29:55 +01:00
dependabot[bot] 6cdd95e44c Bump github.com/redis/go-redis/v9 from 9.7.0 to 9.7.1 (#69)
Bumps [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) from 9.7.0 to 9.7.1.
- [Release notes](https://github.com/redis/go-redis/releases)
- [Changelog](https://github.com/redis/go-redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/redis/go-redis/compare/v9.7.0...v9.7.1)

---
updated-dependencies:
- dependency-name: github.com/redis/go-redis/v9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-26 13:48:02 +01:00
dependabot[bot] 9c15ba61e2 NOISSUE - Bump github.com/spf13/cobra from 1.8.1 to 1.9.1 (#64)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.1 to 1.9.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.8.1...v1.9.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 09:18:02 +01:00
dependabot[bot] adc1f5e5ba NOISSUE - Bump github.com/gofrs/uuid/v5 from 5.3.0 to 5.3.1 (#65)
Bumps [github.com/gofrs/uuid/v5](https://github.com/gofrs/uuid) from 5.3.0 to 5.3.1.
- [Release notes](https://github.com/gofrs/uuid/releases)
- [Commits](https://github.com/gofrs/uuid/compare/v5.3.0...v5.3.1)

---
updated-dependencies:
- dependency-name: github.com/gofrs/uuid/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 09:14:37 +01:00
dependabot[bot] 78d380a680 NOISSUE - Bump golang in /docker in the docker-dependency group (#63)
Bumps the docker-dependency group in /docker with 1 update: golang.


Updates `golang` from 1.23-alpine to 1.24-alpine

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  dependency-group: docker-dependency
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-17 09:08:58 +01:00
Drasko DRASKOVIC e2e701f3e7 Update README.md 2025-02-14 16:31:41 +01:00
Dusan Borovcanin 40fbf6a080 NOISSUE - Fix Nginx config
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-02-14 10:41:30 +01:00
Dušan Borovčanin 20bc79ad8b NOISSUE - Move invitations to Domain (#62)
* Move invitations to Domain

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update README run command

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove invitations from UI

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-02-13 17:42:35 +01:00
Dušan Borovčanin 9636f356fe NOISSUE - Add UI to the compose (#56)
* NOISSUE - Bump github.com/authzed/authzed-go from 1.2.1 to 1.3.0 (#55)

Bumps [github.com/authzed/authzed-go](https://github.com/authzed/authzed-go) from 1.2.1 to 1.3.0.
- [Release notes](https://github.com/authzed/authzed-go/releases)
- [Commits](https://github.com/authzed/authzed-go/compare/v1.2.1...v1.3.0)

---
updated-dependencies:
- dependency-name: github.com/authzed/authzed-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add RE to default compose

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix remarks

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update compose and move Journal to it

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 10:30:14 +01:00
Steve Munene 4540148166 NOISSUE - Refactor time parsing for scheduler (#57)
* use unix time for the scheduler

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* refactor time field

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* use constants

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* change time format

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add logging

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix linter error

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix linter error

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update decodeUpdateRuleRequest

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix wording

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix wording

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add missing words

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-02-10 16:59:20 +01:00
dependabot[bot] 9d083c5e98 NOISSUE - Bump golang.org/x/sync from 0.10.0 to 0.11.0 (#60)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.10.0 to 0.11.0.
- [Commits](https://github.com/golang/sync/compare/v0.10.0...v0.11.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 14:23:17 +01:00
dependabot[bot] 7189c70576 NOISSUE - Bump github.com/go-chi/chi/v5 from 5.2.0 to 5.2.1 (#59)
Bumps [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) from 5.2.0 to 5.2.1.
- [Release notes](https://github.com/go-chi/chi/releases)
- [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-chi/chi/compare/v5.2.0...v5.2.1)

---
updated-dependencies:
- dependency-name: github.com/go-chi/chi/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-10 14:22:27 +01:00
dependabot[bot] b3def5b8df NOISSUE - Bump github.com/authzed/authzed-go from 1.2.1 to 1.3.0 (#55)
Bumps [github.com/authzed/authzed-go](https://github.com/authzed/authzed-go) from 1.2.1 to 1.3.0.
- [Release notes](https://github.com/authzed/authzed-go/releases)
- [Commits](https://github.com/authzed/authzed-go/compare/v1.2.1...v1.3.0)

---
updated-dependencies:
- dependency-name: github.com/authzed/authzed-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-07 11:37:31 +01:00
Dusan Borovcanin ddc43c482f Remove unused builds from CI
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2025-01-28 09:50:23 +01:00
Steve Munene 80f725ee1b MG-34 - Add API docs to rules engine (#47)
* add rules engine

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update header license

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update the api docs

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-01-28 09:32:33 +01:00
dependabot[bot] 033cf80a57 Bump google.golang.org/grpc from 1.69.4 to 1.70.0 (#54)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.69.4 to 1.70.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.69.4...v1.70.0)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-28 09:32:06 +01:00
Steve Munene 01d954cb63 MG-38 - Add Rules Engine README (#51)
* add readme for rules engine

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add api examples

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add how the scheduler works

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-01-27 11:58:17 +01:00
Steve Munene 1b6b7f558c MG-36 - Global ticker for scheduled rules (#42)
* initial implementation

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update main.go file

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* update Reccuring Type method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add marshalling and unmrshalling for times

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix postgres storage

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* add tests for schedular

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix failing linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* fix linter

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* refactor should run

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* refactor how rule are ran

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* address comments

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

* rename method

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>

---------

Signed-off-by: nyagamunene <stevenyaga2014@gmail.com>
2025-01-24 15:01:36 +01:00
Felix Gateru 1f57031ea7 NOISSUE - Remove unnecessary mock files and add sdk tests to CI (#53)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-24 14:43:21 +01:00
Ian Ngethe Muchiri b853f9e1ea NOISSUE - Add domain ID to Reader URL (#52)
Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-01-24 13:46:31 +01:00
Ian Ngethe Muchiri 89eaa8e09f NOISSUE - Fix readers env Prefix(#46)
* update timescale

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* remove omitempty to mess resp

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* remove domain_id

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* update tests

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-01-24 10:56:54 +01:00
Arvindh 82d0a10d47 NOISSUE - Remove UI from compose (#50)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-01-23 16:31:04 +01:00
dependabot[bot] 6e1efa5183 NOISSUE - Bump go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp (#44)
Bumps [go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp](https://github.com/open-telemetry/opentelemetry-go-contrib) from 0.58.0 to 0.59.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go-contrib/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go-contrib/compare/zpages/v0.58.0...zpages/v0.59.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-21 17:04:43 +01:00
dependabot[bot] 7b389bbaee NOISSUE - Bump go.opentelemetry.io/otel/trace from 1.33.0 to 1.34.0 (#45)
Bumps [go.opentelemetry.io/otel/trace](https://github.com/open-telemetry/opentelemetry-go) from 1.33.0 to 1.34.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.33.0...v1.34.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/trace
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-21 17:00:09 +01:00
Arvindh 62f77e3d42 NOISSUE - Update Nginx conf (#49)
Signed-off-by: Arvindh <arvindh91@gmail.com>
2025-01-21 16:59:48 +01:00
Felix Gateru 0bcb846e86 NOISSUE - Add Magistrala CLI (#40)
Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-14 14:08:19 +01:00
Ian Ngethe Muchiri 96158cdc8e NOISSUE - Limit listing based on domain (#41)
* add domain_id as a page metadata

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* add missing created_by

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-01-14 10:57:14 +01:00
Ian Ngethe Muchiri 17e59d2beb NOISSUE - Add Metadata to Rule struct (#39)
* add metadata

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* update sql formatting

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* add created by

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* format sql

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* format sql query

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-01-13 14:16:11 +01:00
Felix Gateru cd528e75d3 NOISSUE - Add Readers and Consumers SDK (#33)
* refactor: aligh bootstrap with new supermq architecture

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: rename env variables

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* style: add empty line to config files and bootstrap docker compose file

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: add supermq sdk to magistrala sdk

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: extend supermq sdk in magistrala sdk

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* reafctor: update responses

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* feat: add readers and consumers sdk

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* ci(messages.go): fix filename

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* feat: add readers sdk

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: remove notifier interface

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: remove notifier interface

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-13 10:31:45 +01:00
Felix Gateru ec71a5edfd MG-28 - Align Bootstrap with SuperMQ (#31)
* refactor: aligh bootstrap with new supermq architecture

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* feat: add sdk and update api docs

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: rename env variables

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* style: add empty line to config files and bootstrap docker compose file

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: add supermq sdk to magistrala sdk

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* refactor: extend supermq sdk in magistrala sdk

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* reafctor: update responses

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

* ci: update api docs dir in swagger-ui deployment

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>

---------

Signed-off-by: Felix Gateru <felix.gateru@gmail.com>
2025-01-10 14:56:17 +01:00
Ian Ngethe Muchiri 3f0bb258c7 NOISSUE - Update Rules Service (#32)
* update re service

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* add status update for rules

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

* revert docker compose changes

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>

---------

Signed-off-by: ianmuchyri <ianmuchiri8@gmail.com>
2025-01-09 09:56:45 +01:00
Dušan Borovčanin 3ee7b13538 NOISSUE - Move SMPP notifier to Magistrala core (#26)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2024-12-31 18:59:23 +01:00
Drasko DRASKOVIC 14282fb021 Update README.md (#25) 2024-12-31 18:29:55 +01:00
Dušan Borovčanin a34df79e9b NOISSUE - Use Magistrala packages instead of SMQ (#24)
* Use Magistrala packages where needed

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Move SMQ scripts to MG

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2024-12-31 18:00:47 +01:00
dependabot[bot] b32e6b22d5 NOISSUE - Bump github.com/go-chi/chi from 1.5.5 to 4.1.2+incompatible (#19)
Bumps [github.com/go-chi/chi](https://github.com/go-chi/chi) from 1.5.5 to 4.1.2+incompatible.
- [Release notes](https://github.com/go-chi/chi/releases)
- [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-chi/chi/compare/v1.5.5...v4.1.2)

---
updated-dependencies:
- dependency-name: github.com/go-chi/chi
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-31 12:16:05 +01:00
Dušan Borovčanin 3bbb25bd64 NOISSUE - Remove SuperMQ duplicates (#23)
* Update docker-compose to use SuperMQ

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove duplicate services

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update Bootstrap

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update other services to use SMQ

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Switch config prefix to SMQ

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove leftovers

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove duplicate interface definitions

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove unused actions

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove unused API docs

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Resolve linter comments

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix provision

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2024-12-31 11:04:17 +01:00
Dušan Borovčanin 57c3ecb175 MG-13 - Magistrala Rules engine (#16)
* Add initial Rules Engine model

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* WIP - Add API layer

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Add async consumer

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Use Named queries and single topics

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Update rules listing

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Enable consumers with no transformer

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Move RE to addons

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Fix HTTP server host

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove unused code

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

* Remove cache for the time being

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>

---------

Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2024-12-27 20:00:50 +01:00
Dušan Borovčanin af072b0b37 MG-7 - Return an error in case of missing token type (#17)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2024-12-25 23:44:30 +01:00
dependabot[bot] 3e70b71142 NOISSUE - Bump go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp (#8)
Bumps [go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp](https://github.com/open-telemetry/opentelemetry-go) from 1.32.0 to 1.33.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.32.0...v1.33.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-25 23:00:12 +01:00
dependabot[bot] df292bd9f6 NOISSUE - Bump golang.org/x/crypto from 0.29.0 to 0.31.0 (#10)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.29.0 to 0.31.0.
- [Commits](https://github.com/golang/crypto/compare/v0.29.0...v0.31.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-25 22:55:25 +01:00
dependabot[bot] 1fcc4d2d55 Bump golang.org/x/sync from 0.9.0 to 0.10.0 (#6)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.9.0 to 0.10.0.
- [Commits](https://github.com/golang/sync/compare/v0.9.0...v0.10.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 15:30:49 +01:00
dependabot[bot] 1d82ee71cd Bump github.com/authzed/authzed-go from 1.1.1 to 1.2.0 (#3)
Bumps [github.com/authzed/authzed-go](https://github.com/authzed/authzed-go) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/authzed/authzed-go/releases)
- [Commits](https://github.com/authzed/authzed-go/compare/v1.1.1...v1.2.0)

---
updated-dependencies:
- dependency-name: github.com/authzed/authzed-go
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 15:15:06 +01:00
dependabot[bot] 844a50ae1d Bump google.golang.org/grpc from 1.68.0 to 1.69.2 (#15)
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.68.0 to 1.69.2.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.68.0...v1.69.2)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-23 15:12:15 +01:00
Dušan Borovčanin 74fffed91e NOISSUE - Use GitHub registry instead of Docker Hub (#2)
Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
2024-12-03 15:02:54 +01:00
dependabot[bot] e4004d043f NOISSUE - Bump github.com/absmach/senml from 1.0.5 to 1.0.6 (#1)
Bumps [github.com/absmach/senml](https://github.com/absmach/senml) from 1.0.5 to 1.0.6.
- [Release notes](https://github.com/absmach/senml/releases)
- [Commits](https://github.com/absmach/senml/compare/v1.0.5...v1.0.6)

---
updated-dependencies:
- dependency-name: github.com/absmach/senml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-03 14:58:40 +01:00
981 changed files with 73917 additions and 132518 deletions
@@ -1,10 +1,9 @@
# 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:
- "api/grpc/*"
- "tools/*"
- "coap/*"
- "**/mocks*"
- "*/middleware/*"
+181
View File
@@ -0,0 +1,181 @@
<!--
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>
-244
View File
@@ -1,244 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Property Based Tests
on:
pull_request:
branches:
- main
paths:
- ".github/workflows/api-tests.yml"
- "api/**"
- "auth/api/http/**"
- "bootstrap/api**"
- "certs/api/**"
- "consumers/notifiers/api/**"
- "http/api/**"
- "invitations/api/**"
- "journal/api/**"
- "provision/api/**"
- "readers/api/**"
- "things/api/**"
- "users/api/**"
env:
TOKENS_URL: http://localhost:9002/users/tokens/issue
DOMAINS_URL: http://localhost:8189/domains
USER_IDENTITY: admin@example.com
USER_SECRET: 12345678
DOMAIN_NAME: demo-test
USERS_URL: http://localhost:9002
THINGS_URL: http://localhost:9000
HTTP_ADAPTER_URL: http://localhost:8008
INVITATIONS_URL: http://localhost:9020
AUTH_URL: http://localhost:8189
BOOTSTRAP_URL: http://localhost:9013
CERTS_URL: http://localhost:9019
PROVISION_URL: http://localhost:9016
POSTGRES_READER_URL: http://localhost:9009
TIMESCALE_READER_URL: http://localhost:9011
JOURNAL_URL: http://localhost:9021
jobs:
api-test:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.22.x
cache-dependency-path: "go.sum"
- name: Build images
run: make all -j $(nproc) && make dockers_dev -j $(nproc)
- name: Start containers
run: make run up args="-d" && make run_addons up args="-d"
- name: Set access token
run: |
export USER_TOKEN=$(curl -sSX POST $TOKENS_URL -H "Content-Type: application/json" -d "{\"identity\": \"$USER_IDENTITY\",\"secret\": \"$USER_SECRET\"}" | jq -r .access_token)
export DOMAIN_ID=$(curl -sSX POST $DOMAINS_URL -H "Content-Type: application/json" -H "Authorization: Bearer $USER_TOKEN" -d "{\"name\":\"$DOMAIN_NAME\",\"alias\":\"$DOMAIN_NAME\"}" | jq -r .id)
export USER_TOKEN=$(curl -sSX POST $TOKENS_URL -H "Content-Type: application/json" -d "{\"identity\": \"$USER_IDENTITY\",\"secret\": \"$USER_SECRET\",\"domain_id\": \"$DOMAIN_ID\"}" | jq -r .access_token)
echo "USER_TOKEN=$USER_TOKEN" >> $GITHUB_ENV
export THING_SECRET=$(magistrala-cli provision test | /usr/bin/grep -Eo '"secret": "[^"]+"' | awk 'NR % 2 == 0' | sed 's/"secret": "\(.*\)"/\1/')
echo "THING_SECRET=$THING_SECRET" >> $GITHUB_ENV
- name: Check for changes in specific paths
uses: dorny/paths-filter@v3
id: changes
with:
filters: |
journal:
- ".github/workflows/api-tests.yml"
- "api/openapi/journal.yml"
- "journal/api/**"
auth:
- ".github/workflows/api-tests.yml"
- "api/openapi/auth.yml"
- "auth/api/http/**"
bootstrap:
- ".github/workflows/api-tests.yml"
- "api/openapi/bootstrap.yml"
- "bootstrap/api/**"
certs:
- ".github/workflows/api-tests.yml"
- "api/openapi/certs.yml"
- "certs/api/**"
http:
- ".github/workflows/api-tests.yml"
- "api/openapi/http.yml"
- "http/api/**"
invitations:
- ".github/workflows/api-tests.yml"
- "api/openapi/invitations.yml"
- "invitations/api/**"
provision:
- ".github/workflows/api-tests.yml"
- "api/openapi/provision.yml"
- "provision/api/**"
readers:
- ".github/workflows/api-tests.yml"
- "api/openapi/readers.yml"
- "readers/api/**"
things:
- ".github/workflows/api-tests.yml"
- "api/openapi/things.yml"
- "things/api/**"
users:
- ".github/workflows/api-tests.yml"
- "api/openapi/users.yml"
- "users/api/**"
- name: Run Users API tests
if: steps.changes.outputs.users == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/users.yml
base-url: ${{ env.USERS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Run Things API tests
if: steps.changes.outputs.things == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/things.yml
base-url: ${{ env.THINGS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Run HTTP Adapter API tests
if: steps.changes.outputs.http == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/http.yml
base-url: ${{ env.HTTP_ADAPTER_URL }}
checks: all
report: false
args: '--header "Authorization: Thing ${{ env.THING_SECRET }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Run Invitations API tests
if: steps.changes.outputs.invitations == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/invitations.yml
base-url: ${{ env.INVITATIONS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Run Auth API tests
if: steps.changes.outputs.auth == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/auth.yml
base-url: ${{ env.AUTH_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Run Journal API tests
if: steps.changes.outputs.journal == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/journal.yml
base-url: ${{ env.JOURNAL_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Run Bootstrap API tests
if: steps.changes.outputs.bootstrap == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/bootstrap.yml
base-url: ${{ env.BOOTSTRAP_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Run Certs API tests
if: steps.changes.outputs.certs == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/certs.yml
base-url: ${{ env.CERTS_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Run Provision API tests
if: steps.changes.outputs.provision == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/provision.yml
base-url: ${{ env.PROVISION_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Seed Messages
if: steps.changes.outputs.readers == 'true'
run: |
make cli
./build/cli provision test
- name: Run Postgres Reader API tests
if: steps.changes.outputs.readers == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/readers.yml
base-url: ${{ env.POSTGRES_READER_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Run Timescale Reader API tests
if: steps.changes.outputs.readers == 'true'
uses: schemathesis/action@v1
with:
schema: api/openapi/readers.yml
base-url: ${{ env.TIMESCALE_READER_URL }}
checks: all
report: false
args: '--header "Authorization: Bearer ${{ env.USER_TOKEN }}" --contrib-openapi-formats-uuid --hypothesis-suppress-health-check=filter_too_much --stateful=links'
- name: Stop containers
if: always()
run: make run down args="-v" && make run_addons down args="-v"
@@ -2,7 +2,6 @@
# SPDX-License-Identifier: Apache-2.0
name: Continuous Delivery
on:
push:
branches:
@@ -12,21 +11,33 @@ jobs:
build-and-push:
name: Build and Push
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Fetch tags for the build
run: |
git fetch --prune --unshallow --tags
- name: Get Go version from go.mod
id: go-version
run: echo "version=$(grep '^go ' go.mod | awk '{print $2}')" >> $GITHUB_OUTPUT
- name: Install Go
uses: actions/setup-go@v5
uses: actions/setup-go@v6
with:
go-version: 1.22.x
go-version: ${{ steps.go-version.outputs.version }}
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: Run tests
run: |
make test
@@ -36,27 +47,26 @@ jobs:
with:
token: ${{ secrets.CODECOV }}
files: ./coverage/*.out
codecov_yml_path: tools/codecov.yml
verbose: true
- name: Set up Docker Build
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Login to DockerHub
uses: docker/login-action@v3
uses: docker/login-action@v4
with:
registry: docker.io
registry: ghcr.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Compile check for rabbitmq
run: |
MG_MESSAGE_BROKER_TYPE=rabbitmq make mqtt
- name: Compile check for redis
run: |
MG_ES_TYPE=redis make mqtt
- name: Build and push Dockers
run: |
make latest -j $(nproc)
- name: Trigger Helm Chart Deployment
if: success() && github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: peter-evans/repository-dispatch@v4
with:
token: ${{ secrets.REPO_DISPATCH_TOKEN }}
repository: absmach/amdm
event-type: deploy-latest-mg-images
-217
View File
@@ -1,217 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: Check the consistency of generated files
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
check-generated-files:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Go
uses: actions/setup-go@v5
with:
go-version: 1.22.x
cache-dependency-path: "go.sum"
- 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@v3
id: changes
with:
base: main
filters: |
proto:
- ".github/workflows/check-generated-files.yml"
- "auth.proto"
- "auth/*.pb.go"
- "pkg/messaging/message.proto"
- "pkg/messaging/*.pb.go"
mocks:
- ".github/workflows/check-generated-files.yml"
- "pkg/sdk/go/sdk.go"
- "users/postgres/clients.go"
- "users/clients.go"
- "pkg/clients/clients.go"
- "pkg/messaging/pubsub.go"
- "things/postgres/clients.go"
- "things/things.go"
- "pkg/authz.go"
- "pkg/authn.go"
- "auth/domains.go"
- "auth/keys.go"
- "auth/service.go"
- "pkg/events/events.go"
- "provision/service.go"
- "pkg/groups/groups.go"
- "bootstrap/service.go"
- "bootstrap/configs.go"
- "invitations/invitations.go"
- "users/emailer.go"
- "users/hasher.go"
- "mqtt/events/streams.go"
- "readers/messages.go"
- "lora/routemap.go"
- "consumers/notifiers/notifier.go"
- "consumers/notifiers/service.go"
- "consumers/notifiers/subscriptions.go"
- "certs/certs.go"
- "certs/pki/vault.go"
- "certs/service.go"
- "journal/journal.go"
- "magistrala/auth_grpc.pb.go"
- name: Set up protoc
if: steps.changes.outputs.proto == 'true'
run: |
PROTOC_VERSION=27.1
PROTOC_GEN_VERSION=v1.34.2
PROTOC_GRPC_VERSION=v1.4.0
# Export the variables so they are available in future steps
echo "PROTOC_VERSION=$PROTOC_VERSION" >> $GITHUB_ENV
echo "PROTOC_GEN_VERSION=$PROTOC_GEN_VERSION" >> $GITHUB_ENV
echo "PROTOC_GRPC_VERSION=$PROTOC_GRPC_VERSION" >> $GITHUB_ENV
# Download and install protoc
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
sudo mv protoc3/bin/* /usr/local/bin/
sudo mv protoc3/include/* /usr/local/include/
rm -rf $PROTOC_ZIP protoc3
# Install protoc-gen-go and protoc-gen-go-grpc
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
# Add protoc to the PATH
export PATH=$PATH:/usr/local/bin/protoc
- 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_VERSION and protoc-gen-go-grpc version $PROTOC_GRPC_VERSION and commit the changes."
exit 1
fi
done
- name: Check Mocks are up to Date
if: steps.changes.outputs.mocks == 'true'
run: |
MOCKERY_VERSION=v2.43.2
go install github.com/vektra/mockery/v2@$MOCKERY_VERSION
mv ./pkg/sdk/mocks/sdk.go ./pkg/sdk/mocks/sdk.go.tmp
mv ./users/mocks/repository.go ./users/mocks/repository.go.tmp
mv ./users/mocks/service.go ./users/mocks/service.go.tmp
mv ./pkg/messaging/mocks/pubsub.go ./pkg/messaging/mocks/pubsub.go.tmp
mv ./things/mocks/repository.go ./things/mocks/repository.go.tmp
mv ./things/mocks/service.go ./things/mocks/service.go.tmp
mv ./things/mocks/cache.go ./things/mocks/cache.go.tmp
mv ./auth/mocks/authz.go ./auth/mocks/authz.go.tmp
mv ./auth/mocks/domains.go ./auth/mocks/domains.go.tmp
mv ./auth/mocks/keys.go ./auth/mocks/keys.go.tmp
mv ./auth/mocks/service.go ./auth/mocks/service.go.tmp
mv ./auth/mocks/token_client.go ./auth/mocks/token_client.go.tmp
mv ./pkg/events/mocks/publisher.go ./pkg/events/mocks/publisher.go.tmp
mv ./pkg/events/mocks/subscriber.go ./pkg/events/mocks/subscriber.go.tmp
mv ./provision/mocks/service.go ./provision/mocks/service.go.tmp
mv ./pkg/groups/mocks/repository.go ./pkg/groups/mocks/repository.go.tmp
mv ./pkg/groups/mocks/service.go ./pkg/groups/mocks/service.go.tmp
mv ./bootstrap/mocks/service.go ./bootstrap/mocks/service.go.tmp
mv ./bootstrap/mocks/configs.go ./bootstrap/mocks/configs.go.tmp
mv ./invitations/mocks/service.go ./invitations/mocks/service.go.tmp
mv ./invitations/mocks/repository.go ./invitations/mocks/repository.go.tmp
mv ./users/mocks/emailer.go ./users/mocks/emailer.go.tmp
mv ./users/mocks/hasher.go ./users/mocks/hasher.go.tmp
mv ./mqtt/mocks/events.go ./mqtt/mocks/events.go.tmp
mv ./readers/mocks/messages.go ./readers/mocks/messages.go.tmp
mv ./consumers/notifiers/mocks/notifier.go ./consumers/notifiers/mocks/notifier.go.tmp
mv ./consumers/notifiers/mocks/service.go ./consumers/notifiers/mocks/service.go.tmp
mv ./consumers/notifiers/mocks/repository.go ./consumers/notifiers/mocks/repository.go.tmp
mv ./certs/mocks/pki.go ./certs/mocks/pki.go.tmp
mv ./certs/mocks/service.go ./certs/mocks/service.go.tmp
mv ./journal/mocks/repository.go ./journal/mocks/repository.go.tmp
mv ./journal/mocks/service.go ./journal/mocks/service.go.tmp
mv ./auth/mocks/domains_client.go ./auth/mocks/domains_client.go.tmp
mv ./things/mocks/things_client.go ./things/mocks/things_client.go.tmp
mv ./pkg/authz/mocks/authz.go ./pkg/authz/mocks/authz.go.tmp
mv ./pkg/authn/mocks/authn.go ./pkg/authn/mocks/authn.go.tmp
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
}
check_mock_changes ./pkg/sdk/mocks/sdk.go "SDK ./pkg/sdk/mocks/sdk.go"
check_mock_changes ./users/mocks/repository.go "Users Repository ./users/mocks/repository.go"
check_mock_changes ./users/mocks/service.go "Users Service ./users/mocks/service.go"
check_mock_changes ./pkg/messaging/mocks/pubsub.go "PubSub ./pkg/messaging/mocks/pubsub.go"
check_mock_changes ./things/mocks/repository.go "Things Repository ./things/mocks/repository.go"
check_mock_changes ./things/mocks/service.go "Things Service ./things/mocks/service.go"
check_mock_changes ./things/mocks/cache.go "Things Cache ./things/mocks/cache.go"
check_mock_changes ./auth/mocks/authz.go "Auth Authz ./auth/mocks/authz.go"
check_mock_changes ./auth/mocks/domains.go "Auth Domains ./auth/mocks/domains.go"
check_mock_changes ./auth/mocks/keys.go "Auth Keys ./auth/mocks/keys.go"
check_mock_changes ./auth/mocks/service.go "Auth Service ./auth/mocks/service.go"
check_mock_changes ./pkg/authn/mocks/authn.go "Authn Service Client .pkg/authn/mocks/authn.go"
check_mock_changes ./pkg/authz/mocks/authz.go "Authz Service Client .pkg/authz/mocks/authz.go"
check_mock_changes ./pkg/events/mocks/publisher.go "ES Publisher ./pkg/events/mocks/publisher.go"
check_mock_changes ./pkg/events/mocks/subscriber.go "EE Subscriber ./pkg/events/mocks/subscriber.go"
check_mock_changes ./provision/mocks/service.go "Provision Service ./provision/mocks/service.go"
check_mock_changes ./pkg/groups/mocks/repository.go "Groups Repository ./pkg/groups/mocks/repository.go"
check_mock_changes ./pkg/groups/mocks/service.go "Groups Service ./pkg/groups/mocks/service.go"
check_mock_changes ./bootstrap/mocks/service.go "Bootstrap Service ./bootstrap/mocks/service.go"
check_mock_changes ./bootstrap/mocks/configs.go "Bootstrap Repository ./bootstrap/mocks/configs.go"
check_mock_changes ./invitations/mocks/service.go "Invitations Service ./invitations/mocks/service.go"
check_mock_changes ./invitations/mocks/repository.go "Invitations Repository ./invitations/mocks/repository.go"
check_mock_changes ./users/mocks/emailer.go "Users Emailer ./users/mocks/emailer.go"
check_mock_changes ./users/mocks/hasher.go "Users Hasher ./users/mocks/hasher.go"
check_mock_changes ./mqtt/mocks/events.go "MQTT Events Store ./mqtt/mocks/events.go"
check_mock_changes ./readers/mocks/messages.go "Message Readers ./readers/mocks/messages.go"
check_mock_changes ./consumers/notifiers/mocks/notifier.go "Notifiers Notifier ./consumers/notifiers/mocks/notifier.go"
check_mock_changes ./consumers/notifiers/mocks/service.go "Notifiers Service ./consumers/notifiers/mocks/service.go"
check_mock_changes ./consumers/notifiers/mocks/repository.go "Notifiers Repository ./consumers/notifiers/mocks/repository.go"
check_mock_changes ./certs/mocks/pki.go "PKI ./certs/mocks/pki.go"
check_mock_changes ./certs/mocks/service.go "Certs Service ./certs/mocks/service.go"
check_mock_changes ./journal/mocks/repository.go "Journal Repository ./journal/mocks/repository.go"
check_mock_changes ./journal/mocks/service.go "Journal Service ./journal/mocks/service.go"
check_mock_changes ./auth/mocks/domains_client.go "Domains Service Client ./auth/mocks/domains_client.go"
check_mock_changes ./auth/mocks/token_client.go "Token Service Client ./auth/mocks/token_client.go"
check_mock_changes ./things/mocks/things_client.go "Things Service Client things/mocks/things_client.go"
+3 -3
View File
@@ -16,14 +16,14 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Check License Header
run: |
CHECK=""
for file in $(grep -rl --exclude-dir={.git,build,**vernemq**} \
for file in $(grep -rl --exclude-dir={.git,build,**vernemq**,coverage} \
--exclude=\*.{crt,key,pem,zed,hcl,md,json,csv,mod,sum,tmpl,args} \
--exclude={CODEOWNERS,LICENSE,MAINTAINERS} \
--exclude={CODEOWNERS,LICENSE,MAINTAINERS,enabled_plugins,rabbitmq.conf} \
.); do
if ! head -n 5 "$file" | grep -q "Copyright (c) Abstract Machines"; then
+24 -10
View File
@@ -8,24 +8,38 @@ on:
branches:
- main
permissions:
contents: write
jobs:
swagger-ui:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Swagger UI action
id: swagger-ui-action
uses: blokovi/swagger-ui-action@main
with:
dir: "./api/openapi"
pattern: "*.yml"
debug: "true"
- 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.abstractmachines.fr
publish_dir: ./swagger-ui
cname: docs.api.magistrala.absmach.eu
+203
View File
@@ -0,0 +1,203 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: CI Pipeline
on:
pull_request:
branches:
- main
jobs:
lint-and-build: # Linting and building are combined to save time for setting up Go
name: Lint and Build
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v6
- name: Get Go version from go.mod
id: go-version
run: echo "version=$(grep '^go ' go.mod | awk '{print $2}')" >> $GITHUB_OUTPUT
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: ${{ steps.go-version.outputs.version }}
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: Fetch SuperMQ
run: |
make fetch_supermq
if [[ -n $(git status --porcelain docker/supermq-docker) ]]; then
echo "SuperMQ docker file is not up to date. Please update it"
git diff docker/supermq-docker
exit 1
else
exit 0
fi
- name: Build all Binaries
run: |
make all -j $(nproc)
- name: Run linters
uses: golangci/golangci-lint-action@v9
with:
version: latest
args: --config ./tools/config/.golangci.yaml
run-tests:
name: Run tests
runs-on: ubuntu-latest
needs: lint-and-build
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Get Go version from go.mod
id: go-version
run: echo "version=$(grep '^go ' go.mod | awk '{print $2}')" >> $GITHUB_OUTPUT
- name: Setup Go
uses: actions/setup-go@v6
with:
go-version: ${{ steps.go-version.outputs.version }}
cache-dependency-path: "go.sum"
- name: Check for changes in specific paths
uses: dorny/paths-filter@v4
id: changes
with:
base: main
filters: |
workflow:
- ".github/workflows/tests.yaml"
bootstrap:
- "bootstrap/**"
- "cmd/bootstrap/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/sdk/**"
- "pkg/events/**"
cli:
- "cli/**"
- "cmd/cli/**"
- "pkg/sdk/**"
consumers:
- "consumers/**"
- "cmd/postgres-writer/**"
- "cmd/timescale-writer/**"
- "cmd/smpp-notifier/**"
- "cmd/smtp-notifier/**"
internal:
- "internal/**"
pkg-events:
- "pkg/events/**"
- "pkg/messaging/**"
pkg-sdk:
- "pkg/sdk/**"
- "bootstrap/api/**"
- "consumers/notifiers/api/**"
provision:
- "provision/**"
- "cmd/provision/**"
- "logger/**"
- "pkg/sdk/**"
readers:
- "readers/**"
- "cmd/postgres-reader/**"
- "cmd/timescale-reader/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "things/**"
- "auth/**"
re:
- "re/**"
- "cmd/re/**"
- "re/api/**"
alarms:
- "alarms/**"
- "cmd/alarms/**"
- name: Create coverage directory
run: |
mkdir coverage
- name: Run bootstrap tests
if: steps.changes.outputs.bootstrap == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/bootstrap.out ./bootstrap/...
- name: Run cli tests
if: steps.changes.outputs.cli == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/cli.out ./cli/...
- name: Run consumers tests
if: steps.changes.outputs.consumers == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/consumers.out ./consumers/...
- name: Run internal tests
if: steps.changes.outputs.internal == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/internal.out ./internal/...
- name: Run pkg sdk tests
if: steps.changes.outputs.pkg-sdk == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-sdk.out ./pkg/sdk/...
- name: Run provision tests
if: steps.changes.outputs.provision == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/provision.out ./provision/...
- name: Run readers tests
if: steps.changes.outputs.readers == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/readers.out ./readers/...
- name: Run rule engine tests
if: steps.changes.outputs.re == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/re.out ./re/...
- name: Run reports tests
if: steps.changes.outputs.reports == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/reports.out ./reports/...
- name: Run alarms tests
if: steps.changes.outputs.alarms == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/alarms.out ./alarms/...
- name: Upload coverage
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV }}
files: ./coverage/*.out
verbose: true
-390
View File
@@ -1,390 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
name: CI Pipeline
on:
pull_request:
branches:
- main
jobs:
lint-and-build: # Linting and building are combined to save time for setting up Go
name: Lint and Build
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.22.x
cache-dependency-path: "go.sum"
- name: Install protolint
run: |
go install github.com/yoheimuta/protolint/cmd/protolint@latest
- name: Lint Protobuf Files
run: |
protolint .
- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: v1.60.3
args: --config ./tools/config/golangci.yml
- name: Build all Binaries
run: |
make all -j $(nproc)
- name: Compile check for rabbitmq
run: |
MG_MESSAGE_BROKER_TYPE=rabbitmq make mqtt
- name: Compile check for redis
run: |
MG_ES_TYPE=redis make mqtt
run-tests:
name: Run tests
runs-on: ubuntu-latest
needs: lint-and-build
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.22.x
cache-dependency-path: "go.sum"
- name: Check for changes in specific paths
uses: dorny/paths-filter@v3
id: changes
with:
base: main
filters: |
workflow:
- ".github/workflows/tests.yml"
auth:
- "auth/**"
- "cmd/auth/**"
- "auth.proto"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "pkg/ulid/**"
- "pkg/uuid/**"
bootstrap:
- "bootstrap/**"
- "cmd/bootstrap/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/sdk/**"
- "pkg/events/**"
certs:
- "certs/**"
- "cmd/certs/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/sdk/**"
cli:
- "cli/**"
- "cmd/cli/**"
- "pkg/sdk/**"
coap:
- "coap/**"
- "cmd/coap/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "things/**"
- "pkg/messaging/**"
consumers:
- "consumers/**"
- "cmd/postgres-writer/**"
- "cmd/timescale-writer/**"
- "cmd/smpp-notifier/**"
- "cmd/smtp-notifier/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/ulid/**"
- "pkg/uuid/**"
- "pkg/messaging/**"
journal:
- "journal/**"
- "cmd/journal/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/events/**"
http:
- "http/**"
- "cmd/http/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "things/**"
- "pkg/messaging/**"
- "logger/**"
internal:
- "internal/**"
invitations:
- "invitations/**"
- "cmd/invitations/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/sdk/**"
logger:
- "logger/**"
mqtt:
- "mqtt/**"
- "cmd/mqtt/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "things/**"
- "pkg/messaging/**"
- "logger/**"
- "pkg/events/**"
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/**"
- "auth/**"
- "bootstrap/**"
- "certs/**"
- "consumers/**"
- "http/**"
- "internal/*"
- "internal/api/**"
- "internal/apiutil/**"
- "internal/groups/**"
- "invitations/**"
- "provision/**"
- "readers/**"
- "things/**"
- "users/**"
pkg-transformers:
- "pkg/transformers/**"
pkg-ulid:
- "pkg/ulid/**"
pkg-uuid:
- "pkg/uuid/**"
provision:
- "provision/**"
- "cmd/provision/**"
- "logger/**"
- "pkg/sdk/**"
readers:
- "readers/**"
- "cmd/postgres-reader/**"
- "cmd/timescale-reader/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "things/**"
- "auth/**"
things:
- "things/**"
- "cmd/things/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/ulid/**"
- "pkg/uuid/**"
- "pkg/events/**"
users:
- "users/**"
- "cmd/users/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "auth/**"
- "pkg/ulid/**"
- "pkg/uuid/**"
- "pkg/events/**"
ws:
- "ws/**"
- "cmd/ws/**"
- "auth.pb.go"
- "auth_grpc.pb.go"
- "things/**"
- "pkg/messaging/**"
- name: Create coverage directory
run: |
mkdir coverage
- name: Run Journal tests
if: steps.changes.outputs.journal == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/journal.out ./journal/...
- name: Run auth tests
if: steps.changes.outputs.auth == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/auth.out ./auth/...
- name: Run bootstrap tests
if: steps.changes.outputs.bootstrap == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/bootstrap.out ./bootstrap/...
- name: Run certs tests
if: steps.changes.outputs.certs == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/certs.out ./certs/...
- name: Run cli tests
if: steps.changes.outputs.cli == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/cli.out ./cli/...
- name: Run CoAP tests
if: steps.changes.outputs.coap == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/coap.out ./coap/...
- name: Run consumers tests
if: steps.changes.outputs.consumers == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/consumers.out ./consumers/...
- name: Run HTTP tests
if: steps.changes.outputs.http == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/http.out ./http/...
- name: Run internal tests
if: steps.changes.outputs.internal == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/internal.out ./internal/...
- name: Run invitations tests
if: steps.changes.outputs.invitations == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/invitations.out ./invitations/...
- name: Run logger tests
if: steps.changes.outputs.logger == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/logger.out ./logger/...
- name: Run MQTT tests
if: steps.changes.outputs.mqtt == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/mqtt.out ./mqtt/...
- name: Run pkg errors tests
if: steps.changes.outputs.pkg-errors == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-errors.out ./pkg/errors/...
- name: Run pkg events tests
if: steps.changes.outputs.pkg-events == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-events.out ./pkg/events/...
- name: Run pkg grpcclient tests
if: steps.changes.outputs.pkg-grpcclient == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-grpcclient.out ./pkg/grpcclient/...
- name: Run pkg messaging tests
if: steps.changes.outputs.pkg-messaging == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-messaging.out ./pkg/messaging/...
- name: Run pkg sdk tests
if: steps.changes.outputs.pkg-sdk == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-sdk.out ./pkg/sdk/...
- name: Run pkg transformers tests
if: steps.changes.outputs.pkg-transformers == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-transformers.out ./pkg/transformers/...
- name: Run pkg ulid tests
if: steps.changes.outputs.pkg-ulid == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-ulid.out ./pkg/ulid/...
- name: Run pkg uuid tests
if: steps.changes.outputs.pkg-uuid == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/pkg-uuid.out ./pkg/uuid/...
- name: Run provision tests
if: steps.changes.outputs.provision == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/provision.out ./provision/...
- name: Run readers tests
if: steps.changes.outputs.readers == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/readers.out ./readers/...
- name: Run things tests
if: steps.changes.outputs.things == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/things.out ./things/...
- name: Run users tests
if: steps.changes.outputs.users == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/users.out ./users/...
- name: Run WebSocket tests
if: steps.changes.outputs.ws == 'true' || steps.changes.outputs.workflow == 'true'
run: |
go test --race -v -count=1 -coverprofile=coverage/ws.out ./ws/...
- name: Upload coverage
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV }}
files: ./coverage/*.out
codecov_yml_path: tools/codecov.yml
verbose: true
+2 -2
View File
@@ -16,5 +16,5 @@ coverage
# Schemathesis
.hypothesis
# Ignore Vault data directory as it contains runtime-generated data
docker/addons/vault/data/
# Docker volume mounted data
docker/data/*
+2 -2
View File
@@ -7,7 +7,7 @@
[[drasko]]
Name = "Drasko Draskovic"
Email = "draasko.draskovic@abstractmachines.fr"
Email = "draasko.draskovic@absmach.eu"
GitHub = "drasko"
# However, this role serves only in dead-lock events, or in a special and very rare cases
@@ -26,5 +26,5 @@
[[dusan]]
Name = "Dusan Borovcanin"
Email = "dusan.borovcanin@abstractmachines.fr"
Email = "dusan.borovcanin@absmach.eu"
GitHub = "dborovcanin"
+109 -34
View File
@@ -1,46 +1,72 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
MG_DOCKER_IMAGE_NAME_PREFIX ?= magistrala
MG_DOCKER_IMAGE_NAME_PREFIX ?= ghcr.io/absmach/magistrala
BUILD_DIR = build
SERVICES = auth users things http coap ws postgres-writer postgres-reader timescale-writer \
timescale-reader cli bootstrap mqtt provision certs invitations journal
TEST_API_SERVICES = journal auth bootstrap certs http invitations notifiers provision readers things users
TEST_API = $(addprefix test_api_,$(TEST_API_SERVICES))
SERVICES = bootstrap provision re postgres-writer postgres-reader timescale-writer timescale-reader cli alarms reports
DOCKERS = $(addprefix docker_,$(SERVICES))
DOCKERS_DEV = $(addprefix docker_dev_,$(SERVICES))
CGO_ENABLED ?= 0
GOARCH ?= amd64
# Auto-detect architecture: use arm64 for Apple Silicon, default to amd64 otherwise
UNAME_M := $(shell uname -m)
ifeq ($(UNAME_M),arm64)
GOARCH ?= arm64
else ifeq ($(UNAME_M),aarch64)
GOARCH ?= arm64
else
GOARCH ?= amd64
endif
# Detect OS for sed compatibility: macOS (BSD sed) vs Linux (GNU sed)
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
SED_INPLACE := sed -i ''
else
SED_INPLACE := sed -i
endif
# For Apple Silicon: use amd64 platform for pre-built images (emulation via Rosetta)
# This is needed because upstream stable images may not have ARM64 builds
ifeq ($(UNAME_M),arm64)
DOCKER_PLATFORM := --platform linux/amd64
else
DOCKER_PLATFORM :=
endif
VERSION ?= $(shell git describe --abbrev=0 --tags 2>/dev/null || echo 'unknown')
COMMIT ?= $(shell git rev-parse HEAD)
TIME ?= $(shell date +%F_%T)
USER_REPO ?= $(shell git remote get-url origin | sed -e 's/.*\/\([^/]*\)\/\([^/]*\).*/\1_\2/' )
USER_REPO ?= $(shell git remote get-url origin | sed -E 's@.*/([^/]+)/([^/.]+)(\.git)?@\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)) | tr -c -s '[:alnum:][=-=]' '_' | tr '[:upper:]' '[:lower:]')
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
DEFAULT_DOCKER_COMPOSE_COMMAND := up
GRPC_MTLS_CERT_FILES_EXISTS = 0
MOCKERY_VERSION=v2.43.2
MOCKERY = $(GOBIN)/mockery
MOCKERY_VERSION=3.7.0
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)/||')
ifneq ($(MG_MESSAGE_BROKER_TYPE),)
MG_MESSAGE_BROKER_TYPE := $(MG_MESSAGE_BROKER_TYPE)
else
MG_MESSAGE_BROKER_TYPE=nats
MG_MESSAGE_BROKER_TYPE=msg_nats
endif
ifneq ($(MG_ES_TYPE),)
MG_ES_TYPE := $(MG_ES_TYPE)
else
MG_ES_TYPE=nats
MG_ES_TYPE=es_nats
endif
define compile_service
CGO_ENABLED=$(CGO_ENABLED) GOOS=$(GOOS) GOARCH=$(GOARCH) GOARM=$(GOARM) \
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)'" \
go build -tags $(MG_MESSAGE_BROKER_TYPE) -tags $(MG_ES_TYPE) -ldflags "-s -w \
-X 'github.com/absmach/supermq.BuildTime=$(TIME)' \
-X 'github.com/absmach/supermq.Version=$(VERSION)' \
-X 'github.com/absmach/supermq.Commit=$(COMMIT)'" \
-o ${BUILD_DIR}/$(1) cmd/$(1)/main.go
endef
@@ -69,9 +95,34 @@ define make_docker_dev
-f docker/Dockerfile.dev ./build
endef
ADDON_SERVICES = bootstrap journal provision certs timescale-reader timescale-writer postgres-reader postgres-writer
define run_with_arch_detection
@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 ghcr.io/absmach/magistrala/$$svc ghcr.io/absmach/magistrala/$$svc:latest; \
done; \
sed -i.bak 's/^MG_RELEASE_TAG=.*/MG_RELEASE_TAG=latest/' docker/.env && rm -f docker/.env.bak; \
MG_ADDONS_CERTS_PATH_PREFIX="../." docker compose -f docker/docker-compose.yaml \
-f docker/addons/timescale-reader/docker-compose.yaml \
-f docker/addons/timescale-writer/docker-compose.yaml \
--env-file docker/.env -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; \
MG_ADDONS_CERTS_PATH_PREFIX="../." docker compose -f docker/docker-compose.yaml \
-f docker/addons/timescale-reader/docker-compose.yaml \
-f docker/addons/timescale-writer/docker-compose.yaml \
--env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args); \
fi
endef
EXTERNAL_SERVICES = vault prometheus
ADDON_SERVICES = bootstrap provision certs timescale-reader timescale-writer postgres-reader postgres-writer
EXTERNAL_SERVICES = prometheus
ifneq ($(filter run%,$(firstword $(MAKECMDGOALS))),)
temp_args := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))
@@ -95,14 +146,14 @@ FILTERED_SERVICES = $(filter-out $(RUN_ADDON_ARGS), $(SERVICES))
all: $(SERVICES)
.PHONY: all $(SERVICES) dockers dockers_dev latest release run run_addons grpc_mtls_certs check_mtls check_certs test_api mocks
.PHONY: all $(SERVICES) dockers dockers_dev latest release run_latest run_stable run_addons grpc_mtls_certs check_mtls check_certs test_api mocks
clean:
rm -rf ${BUILD_DIR}
cleandocker:
# Stops containers and removes containers, networks, volumes, and images created by up
docker compose -f docker/docker-compose.yml -p $(DOCKER_PROJECT) down --rmi all -v --remove-orphans
docker compose -f docker/docker-compose.yaml -p $(DOCKER_PROJECT) down --rmi all -v --remove-orphans
ifdef pv
# Remove unused volumes
@@ -114,11 +165,16 @@ install:
cp $$file $(GOBIN)/magistrala-`basename $$file`; \
done
mocks:
@which mockery > /dev/null || go install github.com/vektra/mockery/v2@$(MOCKERY_VERSION)
@unset MOCKERY_VERSION && go generate ./...
mockery --config ./tools/config/mockery.yaml
$(MOCKERY):
@mkdir -p $(GOBIN)
@mkdir -p mockery
@echo ">> downloading mockery $(MOCKERY_VERSION)..."
@curl -sL https://github.com/vektra/mockery/releases/download/v$(MOCKERY_VERSION)/mockery_$(MOCKERY_VERSION)_Linux_x86_64.tar.gz | tar -xz -C mockery
@mv mockery/mockery $(GOBIN)
@rm -r mockery
mocks: $(MOCKERY)
@$(MOCKERY) --config ./tools/config/.mockery.yaml
DIRS = consumers readers postgres internal
test: mocks
@@ -145,7 +201,7 @@ define test_api_service
fi
@if [ "$(svc)" = "http" ]; then \
st run api/openapi/$(svc).yml \
st run api/openapi/$(svc).yaml \
--checks all \
--base-url $(2) \
--header "Authorization: Thing $(THING_SECRET)" \
@@ -153,7 +209,7 @@ define test_api_service
--hypothesis-suppress-health-check=filter_too_much \
--stateful=links; \
else \
st run api/openapi/$(svc).yml \
st run api/openapi/$(svc).yaml \
--checks all \
--base-url $(2) \
--header "Authorization: Bearer $(USER_TOKEN)" \
@@ -178,8 +234,8 @@ $(TEST_API):
$(call test_api_service,$(@),$(TEST_API_URL))
proto:
protoc -I. --go_out=. --go_opt=paths=source_relative pkg/messaging/*.proto
protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./*.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)
$(FILTERED_SERVICES):
$(call compile_service,$(@))
@@ -222,21 +278,21 @@ grpc_mtls_certs:
check_tls:
ifeq ($(GRPC_TLS),true)
@unset GRPC_MTLS
@bash -c 'unset GRPC_MTLS'
@echo "gRPC TLS is enabled"
GRPC_MTLS=
else
@unset GRPC_TLS
@bash -c 'unset GRPC_TLS'
GRPC_TLS=
endif
check_mtls:
ifeq ($(GRPC_MTLS),true)
@unset GRPC_TLS
@bash -c 'unset GRPC_TLS'
@echo "gRPC MTLS is enabled"
GRPC_TLS=
else
@unset GRPC_MTLS
@bash -c 'unset GRPC_MTLS'
GRPC_MTLS=
endif
@@ -249,11 +305,30 @@ endif
endif
endif
run: check_certs
docker compose -f docker/docker-compose.yml --env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
fetch_supermq:
@./scripts/supermq.sh
run_latest: check_certs
DOCKER_DEFAULT_PLATFORM=$(if $(DOCKER_PLATFORM),linux/amd64,) MG_ADDONS_CERTS_PATH_PREFIX="../." docker compose -f docker/docker-compose.yaml \
-f docker/addons/timescale-reader/docker-compose.yaml \
-f docker/addons/timescale-writer/docker-compose.yaml \
--env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
run_stable: check_certs
@version=$$(git describe --abbrev=0 --tags 2>/dev/null) || { echo "Error: No git tags found. Please create a release tag first (e.g., git tag v0.1.0) or use 'make run_latest' instead."; exit 1; }; \
echo "Using stable version: $$version"; \
git checkout $$version; \
$(SED_INPLACE) "s/^SMQ_RELEASE_TAG=.*/SMQ_RELEASE_TAG=$$version/" docker/supermq-docker/.env; \
$(SED_INPLACE) "s/^MG_RELEASE_TAG=.*/MG_RELEASE_TAG=$$version/" docker/.env; \
DOCKER_DEFAULT_PLATFORM=$(if $(DOCKER_PLATFORM),linux/amd64,) docker compose -f docker/docker-compose.yaml --env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args); \
DOCKER_DEFAULT_PLATFORM=$(if $(DOCKER_PLATFORM),linux/amd64,) MG_ADDONS_CERTS_PATH_PREFIX="../." docker compose -f docker/docker-compose.yaml \
-f docker/addons/timescale-reader/docker-compose.yaml \
-f docker/addons/timescale-writer/docker-compose.yaml \
--env-file docker/.env -p $(DOCKER_PROJECT) $(DOCKER_COMPOSE_COMMAND) $(args)
run_addons: check_certs
$(foreach SVC,$(RUN_ADDON_ARGS),$(if $(filter $(SVC),$(ADDON_SERVICES) $(EXTERNAL_SERVICES)),,$(error Invalid Service $(SVC))))
@for SVC in $(RUN_ADDON_ARGS); do \
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) & \
DOCKER_DEFAULT_PLATFORM=$(if $(DOCKER_PLATFORM),linux/amd64,) MG_ADDONS_CERTS_PATH_PREFIX="../." docker compose -f docker/addons/$$SVC/docker-compose.yaml -p $(DOCKER_PROJECT) --env-file ./docker/.env $(DOCKER_COMPOSE_COMMAND) $(args) & \
done
+100 -134
View File
@@ -1,191 +1,157 @@
# Magistrala
> [!WARNING]
> This repository is obsolete. All of its content has been merged to [www.github.com/absmach/magistrala](https://www.github.com/absmach/magistrala).
> Please use that repository for all active development.
<div align="center">
# SuperMQ
### Planetary event-driven infrastructure
**Made with ❤️ by [Abstract Machines](https://absmach.eu/)**
[![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 the consistency of generated files](https://github.com/absmach/magistrala/actions/workflows/check-generated-files.yml/badge.svg?branch=main)](https://github.com/absmach/magistrala/actions/workflows/check-generated-files.yml)
[![Continuous Delivery](https://github.com/absmach/magistrala/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/absmach/magistrala/actions/workflows/build.yml)
[![go report card][grc-badge]][grc-url]
[![coverage][cov-badge]][cov-url]
[![license][license]](LICENSE)
[![chat][gitter-badge]][gitter]
[![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)
### [Guide](https://magistrala.absmach.eu/docs/) | [Contributing](CONTRIBUTING.md) | [Website](https://absmach.eu/) | [Chat](https://matrix.to/#/#supermq:matrix.org)
![banner][banner]
</div>
Magistrala is modern, scalable, secure, open-source, and patent-free IoT cloud platform written in Go.
## Introduction 📖
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.
SuperMQ is a distributed, highly scalable, and secure open-source cloud platform for messaging and event-driven architecture (EDA). It is a planetarily distributed, highly scalable, and secure platform that serves as a robust foundation for building advanced real-time and reactive systems.
For more details, check out the [official documentation][docs].
For extra bits and services see [our contrib repository][contrib].
## Why SuperMQ Stands Out 🚀
## Features
SuperMQ bridges the gap between various network protocols (HTTP, MQTT, WebSocket, CoAP, and more) to provide a seamless messaging experience. Whether you're working on IoT solutions, real-time data pipelines, or event-driven systems, MagisSuperMQtrala has you covered. 🌐✨
- Multi-protocol connectivity and bridging (HTTP, MQTT, WebSocket and CoAP; see [contrib repository][contrib] for LoRa and OPC UA)
- Device management and provisioning (Zero Touch provisioning)
- Mutual TLS Authentication (mTLS) using X.509 Certificates
- Fine-grained access control (policies, ABAC/RBAC)
- Message persistence (Timescale and PostgresSQL - see [contrib repository][contrib] for Cassandra, InfluxDB, and MongoDB support)
- Platform logging and instrumentation support (Prometheus and OpenTelemetry)
- Event sourcing
- Container-based deployment using [Docker][docker] and [Kubernetes][kubernetes]
- 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
## Key Features 🌟
## Prerequisites
- **Multi-Protocol Connectivity**: HTTP, MQTT, WebSocket, CoAP, and more! 🌉
- **Secure by Design**: Mutual TLS (mTLS) with X.509 Certificates, JWT support, and multi-protocol authorization. 🔒
- **Fine-Grained Access Control**: Support for ABAC and RBAC policies. 📜
- **Multi-Tenant**: Manage multiple domains seamlessly. 🏢
- **Multi-User**: Unlimited organizational hierarchies for user management. 👥
- **Application Management**: Group and share messaging clients for streamlined operations. 📱
- **Ease of Use**: Simple and powerful communication channel management, grouping, and sharing. ✨
- **Personal Access Tokens (PATs)**: Scoped and revocable tokens for enhanced security. 🔑
- **Observability**: Integrated logging and instrumentation with Prometheus and OpenTelemetry. 📈
- **Event Sourcing**: Build robust and scalable architectures. ⚡
- **Edge and IoT Ready**: Supports MQTT and CoAP protocols for seamless IoT gateway and sensor communication and management. 🌍
- **Developer-Friendly**: SDKs, CLI tools, and comprehensive documentation to get you started. 👩‍💻👨‍💻
- **Production-Ready**: Container-based deployment using Docker and Kubernetes. 🐳☸️
The following are needed to run Magistrala:
## Installation 🛠️
- [Docker](https://docs.docker.com/install/) (version 26.0.0)
Developing Magistrala will also require:
- [Go](https://golang.org/doc/install) (version 1.21)
- [Protobuf](https://github.com/protocolbuffers/protobuf#protocol-compiler-installation) (version 25.1)
## Install
Once the prerequisites are installed, execute the following commands from the project's root:
There are multiple ways to run SuperMQ.
First, clone the repository and position to it:
```bash
docker compose -f docker/docker-compose.yml --env-file docker/.env -p git_github_com_absmach_magistrala_git_ up
git clone https://github.com/absmach/supermq.git
cd supermq
```
This will bring up the Magistrala docker services and interconnect them. This command can also be executed using the project's included Makefile:
To run the latest stable (tagged) version, use:
```bash
make run
# Run with latest stable tagged version
make run_stable
```
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
To run the latest version, use:
```bash
git checkout tags/<release_number> -b <release_number>
# e.g. `git checkout tags/0.13.0 -b 0.13.0`
# Run with latest development version (from main branch)
make run_latest
```
Check that `.env` file contains:
The `make run_stable` command will:
- Checkout the repository to the latest git tag
- Update the version in the environment configuration
- Start the services with the stable release
**Note:** After running `make run_stable`, you'll be on a detached HEAD state. To return to your working branch:
```bash
MG_RELEASE_TAG=<release_number>
git checkout main
```
> `docker-compose` should be used for development and testing deployments. For production we suggest using [Kubernetes](https://docs.magistrala.abstractmachines.fr/kubernetes).
### Running on Apple Silicon (M1/M2/M3) Macs
## Usage
When running SuperMQ on Apple Silicon Macs, the Makefile will automatically detect your ARM64 architecture and build Docker images locally.
The quickest way to start using Magistrala is via the CLI. The latest version can be downloaded from the [official releases page][releases].
**If using Docker Desktop:**
It can also be built and used from the project's root directory:
1. **Enable Apple Virtualization Framework**: In Docker Desktop, go to:
- Settings → General → Enable "Use the new Virtualization framework"
2. **Enable Rosetta for x86_64 Emulation**: In Docker Desktop, go to:
- Settings → General → Enable "Use Rosetta for x86_64/amd64 emulation on Apple Silicon"
After enabling these options, restart Docker Desktop, then run `make run_stable` or `make run_latest` as usual.
To manually run SuperMQ, clone the repository and start all core services:
```bash
docker compose -f docker/docker-compose.yaml --env-file docker/.env up
```
### Usage 📤📥
**Using the CLI :**
```bash
make cli
./build/cli version
./build/supermq-cli status
```
Additional details on using the CLI can be found in the [CLI documentation](https://docs.magistrala.abstractmachines.fr/cli).
This command retrieves the status of the SuperMQ server and outputs it to the console.
## Documentation
**Using HTTP with Curl :**
Official documentation is hosted at [Magistrala official docs page][docs]. Documentation is auto-generated, checkout the instructions on [official docs repository](https://github.com/absmach/magistrala-docs):
```bash
curl -X GET http://localhost:8080/status
```
If you spot an error or a need for corrections, please let us know - or even better: send us a PR.
This request fetches the server status over HTTP and provides a JSON response.
## Authors
See our [CLI documentation](https://magistrala.absmach.eu/docs/dev-guide/cli/introduction-to-cli/) for more details.
Main architect and BDFL of Magistrala project is [@drasko][drasko].
## Documentation 📚
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.
The official documentation is hosted at [SuperMQ docs page](https://magistrala.absmach.eu/docs/).
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.
Documentation is auto-generated, check out the instructions in the [docs repository](https://github.com/absmach/magistrala-website).
If you spot an error or a need for corrections, please let us know - or even better: send us a PR! 💌
Maintainers are listed in [MAINTAINERS](MAINTAINERS) file.
## Community and Contributing 🤝
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!
Thank you for your interest in SuperMQ 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.
Also, explore our [contrib][contrib] repository for extra services such as Cassandra, InfluxDB, MongoDB readers and writers, LoRa, OPC UA support, Digital Twins, and more. If you have a contribution that is not a good fit for the core monorepo (it's specific to your use case, it's an additional feature or a new service, it's optional or an add-on), this is a great place to submit the pull request.
Join our community:
### We're Hiring
- [Matrix Room](https://matrix.to/#/#supermq\:matrix.org)
You like Magistrala and you would like to make it your day job? We're always looking for talented engineers interested in open-source, IoT and distributed systems. If you recognize yourself, reach out to [@drasko][drasko] - he will contact you back.
## Professional Support 💼
> The best way to grab our attention is, of course, by sending PRs :sunglasses:.
Need help deploying SuperMQ or integrating it into your system? Reach out to **[Abstract Machines](https://absmach.eu/)** for professional support and guidance.
## Community
## License 📜
- [Google group][forum]
- [Gitter][gitter]
- [Twitter][twitter]
SuperMQ is open-source software licensed under the [Apache License 2.0](LICENSE). Contributions are welcome!
## License
## Acknowledgments 🙌
[Apache-2.0](LICENSE)
Special thanks to the amazing contributors who make SuperMQ possible. Check out the [MAINTAINERS](MAINTAINERS) file to see the team behind the magic.
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fabsmach%2Fmagistrala.svg?type=large&issueType=license)](https://app.fossa.com/projects/git%2Bgithub.com%2Fabsmach%2Fmagistrala?ref=badge_large&issueType=license)
## 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/absmach/magistrala-docs/blob/main/docs/img/gopherBanner.jpg
[docs]: https://docs.magistrala.abstractmachines.fr
[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/absmach
[agent]: https://github.com/absmach/agent
[export]: https://github.com/absmach/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.magistrala.abstractmachines.fr/
[contrib]: https://www.github.com/absmach/mg-contrib
Ready to build the future of messaging and event-driven systems? Let's get started! 🚀
+197
View File
@@ -0,0 +1,197 @@
# 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 | "" |
| `SMQ_MESSAGE_BROKER_URL` | Message broker URL for alarm ingestion | `nats://nats:4222` |
| `SMQ_JAEGER_URL` | Jaeger collector endpoint | `http://jaeger:4318/v1/traces` |
| `SMQ_JAEGER_TRACE_RATIO` | Trace sampling ratio | `1.0` |
| `SMQ_AUTH_GRPC_URL` | Auth gRPC endpoint | `auth:7001` |
| `SMQ_AUTH_GRPC_TIMEOUT` | Auth gRPC timeout | `300s` |
| `SMQ_AUTH_GRPC_CLIENT_CERT` | Auth gRPC client cert path | `${GRPC_MTLS:+./ssl/certs/auth-grpc-client.crt}` |
| `SMQ_AUTH_GRPC_CLIENT_KEY` | Auth gRPC client key path | `${GRPC_MTLS:+./ssl/certs/auth-grpc-client.key}` |
| `SMQ_AUTH_GRPC_SERVER_CA_CERTS` | Auth gRPC server CA path | `${GRPC_MTLS:+./ssl/certs/ca.crt}` |
| `SMQ_DOMAINS_GRPC_URL` | Domains gRPC endpoint | `domains:7003` |
| `SMQ_DOMAINS_GRPC_TIMEOUT` | Domains gRPC timeout | `300s` |
| `SMQ_DOMAINS_GRPC_CLIENT_CERT` | Domains gRPC client cert path | `${GRPC_MTLS:+./ssl/certs/domains-grpc-client.crt}` |
| `SMQ_DOMAINS_GRPC_CLIENT_KEY` | Domains gRPC client key path | `${GRPC_MTLS:+./ssl/certs/domains-grpc-client.key}` |
| `SMQ_DOMAINS_GRPC_SERVER_CA_CERTS` | Domains gRPC server CA path | `${GRPC_MTLS:+./ssl/certs/ca.crt}` |
| `SMQ_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 via gRPC auth and domains services.
## 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 \
SMQ_MESSAGE_BROKER_URL=nats://localhost:4222 \
SMQ_AUTH_GRPC_URL=localhost:7001 \
SMQ_AUTH_GRPC_TIMEOUT=300s \
SMQ_DOMAINS_GRPC_URL=localhost:7003 \
SMQ_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
@@ -0,0 +1,123 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package alarms
import (
"context"
"errors"
"time"
"github.com/absmach/supermq/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"`
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) 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)
ListUserAlarms(ctx context.Context, userID string, pm PageMetadata) (AlarmsPage, error)
DeleteAlarm(ctx context.Context, id string) error
}
+173
View File
@@ -0,0 +1,173 @@
// 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/supermq/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
@@ -0,0 +1,104 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
import (
"context"
"github.com/absmach/magistrala/alarms"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/pkg/authn"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/go-kit/kit/endpoint"
)
func 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
@@ -0,0 +1,59 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
import (
"errors"
"github.com/absmach/magistrala/alarms"
api "github.com/absmach/supermq/api/http"
apiutil "github.com/absmach/supermq/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
@@ -0,0 +1,70 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
import (
"fmt"
"net/http"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/supermq"
)
var (
_ supermq.Response = (*alarmRes)(nil)
_ supermq.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
@@ -0,0 +1,209 @@
// 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/alarms"
"github.com/absmach/supermq"
api "github.com/absmach/supermq/api/http"
apiutil "github.com/absmach/supermq/api/http/util"
smqauthn "github.com/absmach/supermq/pkg/authn"
"github.com/absmach/supermq/pkg/errors"
"github.com/go-chi/chi/v5"
kithttp "github.com/go-kit/kit/transport/http"
"github.com/prometheus/client_golang/prometheus/promhttp"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
func MakeHandler(svc alarms.Service, logger *slog.Logger, idp supermq.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", supermq.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
@@ -0,0 +1,53 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
//go:build !rabbitmq
// +build !rabbitmq
package brokers
import (
"context"
"log/slog"
"time"
"github.com/absmach/supermq/pkg/messaging"
broker "github.com/absmach/supermq/pkg/messaging/nats"
"github.com/nats-io/nats.go/jetstream"
)
const (
AllTopic = "alarms.>"
prefix = "alarms"
)
var cfg = jetstream.StreamConfig{
Name: "alarms",
Description: "SuperMQ 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
}
+40
View File
@@ -0,0 +1,40 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
//go:build rabbitmq
// +build rabbitmq
package brokers
import (
"context"
"log/slog"
"github.com/absmach/supermq/pkg/messaging"
broker "github.com/absmach/supermq/pkg/messaging/rabbitmq"
)
const (
AllTopic = "alarms.#"
exchangeName = "alarms"
prefix = "alarms"
)
func NewPubSub(_ context.Context, url string, logger *slog.Logger) (messaging.PubSub, error) {
pb, err := broker.NewPubSub(url, logger, broker.Prefix(prefix), broker.Exchange(exchangeName))
if err != nil {
return nil, err
}
return pb, nil
}
func NewPublisher(_ context.Context, url string) (messaging.Publisher, error) {
pb, err := broker.NewPublisher(url, broker.Prefix(prefix), broker.Exchange(exchangeName))
if err != nil {
return nil, err
}
return pb, nil
}
+56
View File
@@ -0,0 +1,56 @@
// 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/supermq/pkg/errors"
"github.com/absmach/supermq/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.GetPublisher()
alarm.Subtopic = msg.GetSubtopic()
alarm.CreatedAt = time.Unix(0, int64(msg.GetCreated()))
if err := alarm.Validate(); err != nil {
return err
}
return h.svc.CreateAlarm(context.Background(), alarm)
}
func (h handler) Cancel() error {
return nil
}
+6
View File
@@ -0,0 +1,6 @@
// 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
+172
View File
@@ -0,0 +1,172 @@
// 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/supermq/auth"
"github.com/absmach/supermq/pkg/authn"
smqauthz "github.com/absmach/supermq/pkg/authz"
"github.com/absmach/supermq/pkg/errors"
svcerr "github.com/absmach/supermq/pkg/errors/service"
"github.com/absmach/supermq/pkg/permissions"
"github.com/absmach/supermq/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
entitiesOps permissions.EntitiesOperations[permissions.Operation]
}
var _ alarms.Service = (*authorizationMiddleware)(nil)
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 (am *authorizationMiddleware) CreateAlarm(ctx context.Context, 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) {
if len(alarm.Metadata) > 0 {
if err := am.authorize(ctx, operations.OpUpdateAlarm, session, policies.DomainType, session.DomainID); err != nil {
return alarms.Alarm{}, errors.Wrap(errDomainUpdateAlarms, err)
}
}
if alarm.AssigneeID != "" {
if err := am.authorize(ctx, operations.OpAssignAlarm, session, policies.DomainType, session.DomainID); err != nil {
return alarms.Alarm{}, errors.Wrap(errDomainUpdateAlarms, err)
}
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.authorize(ctx, operations.OpAcknowledgeAlarm, session, policies.DomainType, session.DomainID); err != nil {
return alarms.Alarm{}, errors.Wrap(errDomainUpdateAlarms, err)
}
}
if alarm.ResolvedBy != "" {
if err := am.authorize(ctx, operations.OpResolveAlarm, session, policies.DomainType, session.DomainID); 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 {
if err := am.authorize(ctx, operations.OpDeleteAlarm, session, policies.DomainType, session.DomainID); 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):
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) {
if err := am.authorize(ctx, operations.OpViewAlarm, session, policies.DomainType, session.DomainID); err != nil {
return alarms.Alarm{}, errors.Wrap(errDomainViewAlarms, err)
}
return am.svc.ViewAlarm(ctx, session, id)
}
func (am *authorizationMiddleware) authorize(ctx context.Context, op permissions.Operation, session authn.Session, objType, obj string) error {
perm, err := am.entitiesOps.GetPermission(operations.EntityType, op)
if err != nil {
return err
}
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: session.DomainID,
EntityType: operations.EntityType,
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 err := am.authz.Authorize(ctx, smqauthz.PolicyReq{
SubjectType: policies.UserType,
Subject: session.UserID,
Permission: policies.AdminPermission,
ObjectType: policies.PlatformType,
Object: policies.SuperMQObject,
}, nil); err != nil {
return err
}
return nil
}
@@ -1,6 +1,6 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package middleware provides middleware for the journal service.
// Package middleware provides middleware for the alarms service.
// This is logging, metrics, and tracing middleware.
package middleware
+155
View File
@@ -0,0 +1,155 @@
// 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/supermq/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) (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 alarm.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
@@ -0,0 +1,74 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package middleware
import (
"context"
"time"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/supermq/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) 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
@@ -0,0 +1,84 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package middleware
import (
"context"
"github.com/absmach/magistrala/alarms"
"github.com/absmach/supermq/pkg/authn"
smqTracing "github.com/absmach/supermq/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) 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)
}
+442
View File
@@ -0,0 +1,442 @@
// 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
}
// ListUserAlarms provides a mock function for the type Repository
func (_mock *Repository) ListUserAlarms(ctx context.Context, userID string, pm alarms.PageMetadata) (alarms.AlarmsPage, error) {
ret := _mock.Called(ctx, userID, pm)
if len(ret) == 0 {
panic("no return value specified for ListUserAlarms")
}
var r0 alarms.AlarmsPage
var r1 error
if returnFunc, ok := ret.Get(0).(func(context.Context, string, alarms.PageMetadata) (alarms.AlarmsPage, error)); ok {
return returnFunc(ctx, userID, pm)
}
if returnFunc, ok := ret.Get(0).(func(context.Context, string, alarms.PageMetadata) alarms.AlarmsPage); ok {
r0 = returnFunc(ctx, userID, pm)
} else {
r0 = ret.Get(0).(alarms.AlarmsPage)
}
if returnFunc, ok := ret.Get(1).(func(context.Context, string, alarms.PageMetadata) error); ok {
r1 = returnFunc(ctx, userID, pm)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Repository_ListUserAlarms_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListUserAlarms'
type Repository_ListUserAlarms_Call struct {
*mock.Call
}
// ListUserAlarms is a helper method to define mock.On call
// - ctx context.Context
// - userID string
// - pm alarms.PageMetadata
func (_e *Repository_Expecter) ListUserAlarms(ctx interface{}, userID interface{}, pm interface{}) *Repository_ListUserAlarms_Call {
return &Repository_ListUserAlarms_Call{Call: _e.mock.On("ListUserAlarms", ctx, userID, pm)}
}
func (_c *Repository_ListUserAlarms_Call) Run(run func(ctx context.Context, userID string, pm alarms.PageMetadata)) *Repository_ListUserAlarms_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 alarms.PageMetadata
if args[2] != nil {
arg2 = args[2].(alarms.PageMetadata)
}
run(
arg0,
arg1,
arg2,
)
})
return _c
}
func (_c *Repository_ListUserAlarms_Call) Return(alarmsPage alarms.AlarmsPage, err error) *Repository_ListUserAlarms_Call {
_c.Call.Return(alarmsPage, err)
return _c
}
func (_c *Repository_ListUserAlarms_Call) RunAndReturn(run func(ctx context.Context, userID string, pm alarms.PageMetadata) (alarms.AlarmsPage, error)) *Repository_ListUserAlarms_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
}
+380
View File
@@ -0,0 +1,380 @@
// 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/supermq/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) error {
ret := _mock.Called(ctx, alarm)
if len(ret) == 0 {
panic("no return value specified for CreateAlarm")
}
var r0 error
if returnFunc, ok := ret.Get(0).(func(context.Context, alarms.Alarm) error); ok {
r0 = returnFunc(ctx, alarm)
} else {
r0 = ret.Error(0)
}
return r0
}
// 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(err error) *Service_CreateAlarm_Call {
_c.Call.Return(err)
return _c
}
func (_c *Service_CreateAlarm_Call) RunAndReturn(run func(ctx context.Context, 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
@@ -0,0 +1,52 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package operations
import "github.com/absmach/supermq/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: "assign",
PermissionRequired: true,
},
OpAcknowledgeAlarm: {
Name: "acknowledge",
PermissionRequired: true,
},
OpResolveAlarm: {
Name: "resolve",
PermissionRequired: true,
},
OpUpdateAlarm: {
Name: "update",
PermissionRequired: true,
},
}
}
+518
View File
@@ -0,0 +1,518 @@
// 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/supermq/api/http"
"github.com/absmach/supermq/pkg/errors"
repoerr "github.com/absmach/supermq/pkg/errors/repository"
"github.com/absmach/supermq/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) ListUserAlarms(ctx context.Context, userID string, pm alarms.PageMetadata) (alarms.AlarmsPage, error) {
query, err := pageQuery(pm)
if err != nil {
return alarms.AlarmsPage{}, errors.Wrap(repoerr.ErrViewEntity, err)
}
pm.UserID = userID
comQuery := fmt.Sprintf(`SELECT DISTINCT %s
FROM alarms
INNER JOIN rules_roles rr ON rr.entity_id = alarms.rule_id
INNER JOIN rules_role_members rrm ON rrm.role_id = rr.id AND rrm.member_id = :user_id
%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) {
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 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")
}
var emq string
if len(query) > 0 {
emq = fmt.Sprintf("WHERE %s", strings.Join(query, " AND "))
}
return emq, nil
}
+659
View File
@@ -0,0 +1,659 @@
// 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/supermq/pkg/errors"
repoerr "github.com/absmach/supermq/pkg/errors/repository"
"github.com/absmach/supermq/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 TestListUserAlarms(t *testing.T) {
t.Cleanup(func() {
_, err := db.Exec("DELETE FROM alarms")
require.Nil(t, err, fmt.Sprintf("clean alarms unexpected error: %s", err))
_, err = db.Exec("DELETE FROM rules")
require.Nil(t, err, fmt.Sprintf("clean rules unexpected error: %s", err))
})
repo := postgres.NewAlarmsRepo(db)
domainID := generateUUID(t)
userID := generateUUID(t)
otherUserID := generateUUID(t)
adminUserID := generateUUID(t)
// Create 10 rules and 10 alarms referencing them.
// Assign userID to the first 6 rules via role membership.
var ruleIDs []string
var createdAlarms []alarms.Alarm
for i := range 10 {
ruleID := generateUUID(t)
_, err := db.Exec(`INSERT INTO rules (id, name, domain_id, status, logic_type, logic_value) VALUES ($1, $2, $3, 0, 0, '')`,
ruleID, fmt.Sprintf("rule-%d", i), domainID)
require.Nil(t, err, fmt.Sprintf("insert rule unexpected error: %s", err))
ruleIDs = append(ruleIDs, ruleID)
alarm := alarms.Alarm{
ID: generateUUID(t),
RuleID: ruleID,
DomainID: domainID,
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().Add(time.Duration(i) * time.Minute),
}
alarm, err = repo.CreateAlarm(context.Background(), alarm)
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
createdAlarms = append(createdAlarms, alarm)
}
// Assign userID to the first 6 rules via rules_roles + rules_role_members.
userRoleIDs := make([]string, 6)
for i := range 6 {
roleID := generateUUID(t)
userRoleIDs[i] = roleID
_, err := db.Exec(`INSERT INTO rules_roles (id, name, entity_id) VALUES ($1, $2, $3)`, roleID, "admin", ruleIDs[i])
require.Nil(t, err, fmt.Sprintf("insert rules_roles unexpected error: %s", err))
_, err = db.Exec(`INSERT INTO rules_role_members (role_id, member_id, entity_id) VALUES ($1, $2, $3)`, roleID, userID, ruleIDs[i])
require.Nil(t, err, fmt.Sprintf("insert rules_role_members unexpected error: %s", err))
}
for i := range 10 {
var roleID string
if i < 6 {
roleID = userRoleIDs[i]
} else {
roleID = generateUUID(t)
_, err := db.Exec(`INSERT INTO rules_roles (id, name, entity_id) VALUES ($1, $2, $3)`, roleID, "admin", ruleIDs[i])
require.Nil(t, err, fmt.Sprintf("insert rules_roles unexpected error: %s", err))
}
_, err := db.Exec(`INSERT INTO rules_role_members (role_id, member_id, entity_id) VALUES ($1, $2, $3)`, roleID, adminUserID, ruleIDs[i])
require.Nil(t, err, fmt.Sprintf("insert rules_role_members unexpected error: %s", err))
}
_ = createdAlarms
cases := []struct {
desc string
userID string
pm alarms.PageMetadata
count int
err error
}{
{
desc: "list user alarms returns only accessible alarms",
userID: userID,
pm: alarms.PageMetadata{
Offset: 0,
Limit: 100,
},
count: 6,
err: nil,
},
{
desc: "list user alarms with limit",
userID: userID,
pm: alarms.PageMetadata{
Offset: 0,
Limit: 3,
},
count: 3,
err: nil,
},
{
desc: "list user alarms with offset",
userID: userID,
pm: alarms.PageMetadata{
Offset: 4,
Limit: 100,
},
count: 2,
err: nil,
},
{
desc: "list user alarms with domain filter",
userID: userID,
pm: alarms.PageMetadata{
DomainID: domainID,
Offset: 0,
Limit: 100,
},
count: 6,
err: nil,
},
{
desc: "list user alarms with non-existing domain returns 0",
userID: userID,
pm: alarms.PageMetadata{
DomainID: generateUUID(t),
Offset: 0,
Limit: 100,
},
count: 0,
err: nil,
},
{
desc: "list alarms for user with no role assignments returns 0",
userID: otherUserID,
pm: alarms.PageMetadata{
Offset: 0,
Limit: 100,
},
count: 0,
err: nil,
},
{
desc: "list alarms for admin user with role on all rules returns all alarms",
userID: adminUserID,
pm: alarms.PageMetadata{
Offset: 0,
Limit: 100,
},
count: 10,
err: nil,
},
{
desc: "list user alarms ordered by created_at ascending",
userID: userID,
pm: alarms.PageMetadata{
Offset: 0,
Limit: 100,
Order: "created_at",
Dir: "asc",
},
count: 6,
err: nil,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
page, err := repo.ListUserAlarms(context.Background(), tc.userID, 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
}
require.Nil(t, err, fmt.Sprintf("unexpected error: %s", err))
assert.Equal(t, tc.count, len(page.Alarms), fmt.Sprintf("%s: expected %d alarms, got %d", tc.desc, tc.count, len(page.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
}
+65
View File
@@ -0,0 +1,65 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package postgres
import (
rpostgres "github.com/absmach/magistrala/re/postgres"
"github.com/absmach/supermq/pkg/errors"
repoerr "github.com/absmach/supermq/pkg/errors/repository"
_ "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`,
},
},
},
}
rulesMigration, err := rpostgres.Migration()
if err != nil {
return &migrate.MemoryMigrationSource{}, errors.Wrap(repoerr.ErrRoleMigration, err)
}
alarmsMigration.Migrations = append(alarmsMigration.Migrations, rulesMigration.Migrations...)
return alarmsMigration, nil
}
@@ -11,8 +11,8 @@ import (
"testing"
"time"
ipostgres "github.com/absmach/magistrala/invitations/postgres"
"github.com/absmach/magistrala/pkg/postgres"
apostgres "github.com/absmach/magistrala/alarms/postgres"
"github.com/absmach/supermq/pkg/postgres"
"github.com/jmoiron/sqlx"
dockertest "github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
@@ -75,13 +75,14 @@ func TestMain(m *testing.M) {
SSLRootCert: "",
}
if db, err = postgres.Setup(dbConfig, *ipostgres.Migration()); err != nil {
migration, err := apostgres.Migration()
if err != nil {
log.Fatalf("Could not get migration: %s", err)
}
if db, err = postgres.Setup(dbConfig, *migration); err != nil {
log.Fatalf("Could not setup test DB connection: %s", err)
}
if db, err = postgres.Connect(dbConfig); err != nil {
log.Fatalf("Could not setup test DB connection: %s", err)
}
database = postgres.NewDatabase(db, dbConfig, tracer)
code := m.Run()
+70
View File
@@ -0,0 +1,70 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package alarms
import (
"context"
"time"
"github.com/absmach/supermq"
"github.com/absmach/supermq/pkg/authn"
repoerr "github.com/absmach/supermq/pkg/errors/repository"
)
type service struct {
idp supermq.IDProvider
repo Repository
}
var _ Service = (*service)(nil)
func NewService(idp supermq.IDProvider, repo Repository) Service {
return &service{
idp: idp,
repo: repo,
}
}
func (s *service) CreateAlarm(ctx context.Context, alarm Alarm) error {
id, err := s.idp.ID()
if err != nil {
return err
}
alarm.ID = id
if alarm.CreatedAt.IsZero() {
alarm.CreatedAt = time.Now()
}
if err := alarm.Validate(); err != nil {
return err
}
if _, err = s.repo.CreateAlarm(ctx, alarm); err != nil && err != repoerr.ErrNotFound {
return err
}
return 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) {
if session.SuperAdmin {
return s.repo.ListAllAlarms(ctx, pm)
}
return s.repo.ListUserAlarms(ctx, session.UserID, 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
@@ -0,0 +1,254 @@
// 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/supermq/pkg/authn"
"github.com/absmach/supermq/pkg/errors"
repoerr "github.com/absmach/supermq/pkg/errors/repository"
"github.com/absmach/supermq/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("ListUserAlarms", context.Background(), s.UserID, 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
@@ -0,0 +1,70 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package alarms
import (
"encoding/json"
"strings"
svcerr "github.com/absmach/supermq/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
}
-16
View File
@@ -1,16 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package magistrala
// Response contains HTTP response specific methods.
type Response interface {
// Code returns HTTP response code.
Code() int
// Headers returns map of HTTP headers with their values.
Headers() map[string]string
// Empty indicates if HTTP response has content.
Empty() bool
}
+75
View File
@@ -0,0 +1,75 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package api
import (
"context"
"encoding/json"
"net/http"
"github.com/absmach/magistrala/bootstrap"
api "github.com/absmach/supermq/api/http"
apiutil "github.com/absmach/supermq/api/http/util"
"github.com/absmach/supermq/pkg/errors"
)
// EncodeError encodes an error response.
func EncodeError(ctx context.Context, err error, w http.ResponseWriter) {
var wrapper error
if errors.Contains(err, apiutil.ErrValidation) {
wrapper, err = errors.Unwrap(err)
}
w.Header().Set("Content-Type", api.ContentType)
status, nerr := toStatus(err)
if nerr != nil {
err = unwrap(err)
w.WriteHeader(status)
encodeErrorMessage(err, wrapper, w)
return
}
if wrapper != nil {
err = errors.Wrap(wrapper, err)
}
api.EncodeError(ctx, err, w)
}
func toStatus(err error) (int, error) {
switch {
case errors.Contains(err, bootstrap.ErrExternalKey),
errors.Contains(err, bootstrap.ErrExternalKeySecure):
return http.StatusForbidden, err
case errors.Contains(err, bootstrap.ErrBootstrapState),
errors.Contains(err, bootstrap.ErrAddBootstrap):
return http.StatusBadRequest, err
case errors.Contains(err, bootstrap.ErrBootstrap):
return http.StatusNotFound, err
default:
return 0, nil
}
}
func encodeErrorMessage(err, wrapper error, w http.ResponseWriter) {
if wrapper != nil {
err = errors.Wrap(wrapper, err)
}
if errorVal, ok := err.(errors.Error); ok {
if err := json.NewEncoder(w).Encode(errorVal); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
}
}
func unwrap(err error) error {
wrapper, err := errors.Unwrap(err)
if wrapper != nil {
return wrapper
}
return err
}
+873
View File
@@ -0,0 +1,873 @@
// 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.10
// protoc v6.33.0
// 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_MAX Aggregation = 1
Aggregation_MIN Aggregation = 2
Aggregation_SUM Aggregation = 3
Aggregation_COUNT Aggregation = 4
Aggregation_AVG Aggregation = 5
)
// Enum value maps for Aggregation.
var (
Aggregation_name = map[int32]string{
0: "AGGREGATION_UNSPECIFIED",
1: "MAX",
2: "MIN",
3: "SUM",
4: "COUNT",
5: "AVG",
}
Aggregation_value = map[string]int32{
"AGGREGATION_UNSPECIFIED": 0,
"MAX": 1,
"MIN": 2,
"SUM": 3,
"COUNT": 4,
"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"`
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 ""
}
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\"\x8c\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\"\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*Y\n" +
"\vAggregation\x12\x1b\n" +
"\x17AGGREGATION_UNSPECIFIED\x10\x00\x12\a\n" +
"\x03MAX\x10\x01\x12\a\n" +
"\x03MIN\x10\x02\x12\a\n" +
"\x03SUM\x10\x03\x12\t\n" +
"\x05COUNT\x10\x04\x12\a\n" +
"\x03AVG\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
@@ -0,0 +1,130 @@
// 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.5.1
// - 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.Errorf(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 pancis, 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",
}
-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.abstractmachines.fr](https://docs.api.magistrala.abstractmachines.fr)
-833
View File
@@ -1,833 +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@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.14.0
servers:
- url: http://localhost:8189
- url: https://localhost:8189
tags:
- name: Keys
description: Everything about your Keys.
externalDocs:
description: Find out more about keys
url: https://docs.magistrala.abstractmachines.fr/
- name: Domains
description: Everything about your Domains.
externalDocs:
description: Find out more about domains
url: https://docs.magistrala.abstractmachines.fr/
- name: Health
description: Service health check endpoint.
externalDocs:
description: Find out more about health check
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"
"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"
/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"
"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"
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"
/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"
"400":
description: Malformed entity specification.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed authorization over the domain.
"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 user from domain
description: |
Unassign user from domain that is identified by the domain ID.
tags:
- Domains
parameters:
- $ref: "#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/UnassignUsersReq"
security:
- bearerAuth: []
responses:
"204":
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:
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.
"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.
"500":
$ref: "#/components/responses/ServiceError"
/users/{userID}/domains:
get:
tags:
- Domains
summary: Lists domains associated with a user.
description: |
Retrieves a list of domains associated with a user. 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/UserID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/Metadata"
- $ref: "#/components/parameters/Status"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/DomainsPageRes"
"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
security: []
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:
- domains
- 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
AssignUserDomainRelationReq:
type: object
properties:
user_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", "contributor", "member", "guest"]
example: "administrator"
description: Policy relations.
required:
- user_ids
- relation
UnassignUserDomainRelationReq:
type: object
properties:
user_id:
type: string
format: uuid
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
description: User unique identifier.
required:
- user_id
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:
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/AssignUserDomainRelationReq"
UnassignUsersReq:
description: JSON-formated document describing the policy related to unassigning user from a domain
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/UnassignUserDomainRelationReq"
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:
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"
links:
revoke:
operationId: revokeKey
parameters:
keyID: $response.body#/id
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
-313
View File
@@ -1,313 +0,0 @@
# 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@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/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:
/{domainID}/certs:
post:
operationId: createCert
summary: Creates a certificate for thing
description: Creates a certificate for thing
tags:
- certs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/CertReq"
responses:
"201":
description: Created
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/certs/{certID}:
get:
operationId: getCert
summary: Retrieves a certificate
description: |
Retrieves a certificate for a given cert ID.
tags:
- certs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $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.
"403":
description: Failed to perform authorization over the entity.
"404":
description: |
Failed to retrieve corresponding certificate.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: revokeCert
summary: Revokes a certificate
description: |
Revokes a certificate for a given cert ID.
tags:
- certs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/CertID"
responses:
"200":
$ref: "#/components/responses/RevokeRes"
"400":
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: |
Failed to revoke corresponding certificate.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/serials/{thingID}:
get:
operationId: getSerials
summary: Retrieves certificates' serial IDs
description: |
Retrieves a list of certificates' serial IDs for a given thing ID.
tags:
- certs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $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.
"403":
description: Failed to perform authorization over the entity.
"404":
description: |
Failed to retrieve corresponding certificates.
"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:
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"
links:
serial:
operationId: getSerials
parameters:
thingID: $response.body#/thing_id
delete:
operationId: revokeCert
parameters:
certID: $response.body#/serial
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/health+json:
schema:
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
description: |
* Users access: "Authorization: Bearer <user_token>"
security:
- bearerAuth: []
-182
View File
@@ -1,182 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: Magistrala http adapter
description: |
HTTP API for sending messages through communication channels.
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.14.0
servers:
- url: http://localhost:8008
- url: https://localhost:8008
tags:
- name: messages
description: Everything about your Messages
externalDocs:
description: Find out more about messages
url: https://docs.magistrala.abstractmachines.fr/
paths:
/channels/{id}/messages:
post:
summary: Sends message to the communication channel
description: |
Sends message to the communication channel. Messages can be sent as
JSON formatted SenML or as blob.
tags:
- messages
parameters:
- $ref: "#/components/parameters/ID"
requestBody:
$ref: "#/components/requestBodies/MessageReq"
responses:
"202":
description: Message is accepted for processing.
"400":
description: Message discarded due to its malformed content.
"401":
description: Missing or invalid access token provided.
"404":
description: Message discarded due to invalid channel id.
"415":
description: Message discarded due to invalid or missing 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:
SenMLRecord:
type: object
properties:
bn:
type: string
description: Base Name
bt:
type: number
format: double
description: Base Time
bu:
type: number
format: double
description: Base Unit
bv:
type: number
format: double
description: Base Value
bs:
type: number
format: double
description: Base Sum
bver:
type: number
format: double
description: Version
n:
type: string
description: Name
u:
type: string
description: Unit
v:
type: number
format: double
description: Value
vs:
type: string
description: String Value
vb:
type: boolean
description: Boolean Value
vd:
type: string
description: Data Value
s:
type: number
format: double
description: Value Sum
t:
type: number
format: double
description: Time
ut:
type: number
format: double
description: Update Time
SenMLArray:
type: array
items:
$ref: "#/components/schemas/SenMLRecord"
parameters:
ID:
name: id
description: Unique channel identifier.
in: path
schema:
type: string
format: uuid
required: true
requestBodies:
MessageReq:
description: |
Message to be distributed. Since the platform expects messages to be
properly formatted SenML in order to be post-processed, clients are
obliged to specify Content-Type header for each published message.
Note that all messages that aren't SenML will be accepted and published,
but no post-processing will be applied.
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/SenMLArray"
responses:
ServiceError:
description: Unexpected server-side error occurred.
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/HealthInfo.yml"
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: uuid
description: |
* Thing access: "Authorization: Thing <thing_key>"
basicAuth:
type: http
scheme: basic
description: |
* Things access: "Authorization: Basic <base64-encoded_credentials>"
security:
- bearerAuth: []
- basicAuth: []
-537
View File
@@ -1,537 +0,0 @@
# 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@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/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:
operationId: sendInvitation
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.
"403":
description: Failed to perform authorization over the entity.
"404":
description: A non-existent entity request.
"409":
description: Failed due to using an existing identity.
"415":
description: Missing or invalid content type.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: listInvitations
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.
"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"
/invitations/accept:
post:
operationId: acceptInvitation
summary: Accept invitation
description: |
Current logged in user accepts invitation to join domain.
tags:
- Invitations
security:
- bearerAuth: []
requestBody:
$ref: "#/components/requestBodies/AcceptInvitationReq"
responses:
"204":
description: Invitation accepted.
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"500":
$ref: "#/components/responses/ServiceError"
/invitations/reject:
post:
operationId: rejectInvitation
summary: Reject invitation
description: |
Current logged in user rejects invitation to join domain.
tags:
- Invitations
security:
- bearerAuth: []
requestBody:
$ref: "#/components/requestBodies/AcceptInvitationReq"
responses:
"204":
description: Invitation rejected.
"400":
description: Failed due to malformed query parameters.
"401":
description: Missing or invalid access token provided.
"404":
description: A non-existent entity request.
"500":
$ref: "#/components/responses/ServiceError"
/invitations/{user_id}/{domain_id}:
get:
operationId: getInvitation
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.
"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: deleteInvitation
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.
"403":
description: Failed to perform authorization over the entity.
"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
security: []
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
- contributor
- member
- guest
- 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
- contributor
- member
- guest
- 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
- contributor
- member
- guest
- 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"
links:
delete:
operationId: deleteInvitation
parameters:
user_id: $response.body#/user_id
domain_id: $response.body#/domain_id
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: []
-344
View File
@@ -1,344 +0,0 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.3
info:
title: Magistrala Journal Log Service
description: |
This is the Journal Log Server based on the OpenAPI 3.0 specification. It is the HTTP API for viewing journal log history. 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:9021
- url: https://localhost:9021
tags:
- name: journal-log
description: Everything about your Journal Log
externalDocs:
description: Find out more about Journal Log
url: http://docs.mainflux.io/
paths:
/journal/user/{userID}:
get:
tags:
- journal-log
summary: List user journal log
description: |
Retrieves a list of journal. 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/user_id"
- $ref: "#/components/parameters/offset"
- $ref: "#/components/parameters/limit"
- $ref: "#/components/parameters/operation"
- $ref: "#/components/parameters/with_attributes"
- $ref: "#/components/parameters/with_metadata"
- $ref: "#/components/parameters/from"
- $ref: "#/components/parameters/to"
- $ref: "#/components/parameters/dir"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/JournalsPageRes"
"400":
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"
/{domainID}/journal/{entityType}/{id}:
get:
tags:
- journal-log
summary: List entity journal log
description: |
Retrieves a list of journal. 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/domain_id"
- $ref: "#/components/parameters/entity_type"
- $ref: "#/components/parameters/id"
- $ref: "#/components/parameters/offset"
- $ref: "#/components/parameters/limit"
- $ref: "#/components/parameters/operation"
- $ref: "#/components/parameters/with_attributes"
- $ref: "#/components/parameters/with_metadata"
- $ref: "#/components/parameters/from"
- $ref: "#/components/parameters/to"
- $ref: "#/components/parameters/dir"
security:
- bearerAuth: []
responses:
"200":
$ref: "#/components/responses/JournalsPageRes"
"400":
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"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
schemas:
Journal:
type: object
properties:
operation:
type: string
example: user.create
description: Journal operation.
occurred_at:
type: string
format: date-time
example: "2024-01-11T12:05:07.449053Z"
description: Time when the journal occurred.
attributes:
type: object
description: Journal attributes.
example:
{
"created_at": "2024-06-12T11:34:32.991591Z",
"id": "29d425c8-542b-4614-8a4d-a5951945d720",
"identity": "Gawne-Havlicek@email.com",
"name": "Newgard-Frisina",
"status": "enabled",
"updated_at": "2024-06-12T11:34:33.116795Z",
"updated_by": "ad228f20-4741-47c5-bef7-d871b541c019",
}
metadata:
type: object
description: Journal payload.
example: { "Update": "Calvo-Felkins" }
xml:
name: journal
JournalPage:
type: object
properties:
journals:
type: array
minItems: 0
uniqueItems: true
items:
$ref: "#/components/schemas/Journal"
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:
- journals
- total
- offset
Error:
type: object
properties:
error:
type: string
description: Error message
example: { "error": "malformed entity specification" }
parameters:
domain_id:
name: domainID
description: Unique identifier for a domain.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
entity_type:
name: entityType
description: Type of entity, e.g. user, group, thing, etc.entityType
in: path
schema:
type: string
enum:
- group
- thing
- channel
required: true
example: group
user_id:
name: userID
description: Unique identifier for a user.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
id:
name: id
description: Unique identifier for an entity, e.g. group, channel or thing. Used together with entity_type.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
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"
operation:
name: operation
description: Journal operation.
in: query
schema:
type: string
required: false
example: user.create
with_attributes:
name: with_attributes
description: Include journal attributes.
in: query
schema:
type: boolean
required: false
example: true
with_metadata:
name: with_metadata
description: Include journal metadata.
in: query
schema:
type: boolean
required: false
example: true
from:
name: from
description: Start date in unix time.
in: query
schema:
type: string
format: int64
required: false
example: 1966777289
to:
name: to
description: End date in unix time.
in: query
schema:
type: string
format: int64
required: false
example: 1966777289
dir:
name: dir
description: Sort direction.
in: query
schema:
type: string
enum:
- asc
- desc
required: false
example: desc
responses:
JournalsPageRes:
description: Data retrieved.
content:
application/json:
schema:
$ref: "#/components/schemas/JournalPage"
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/HealthInfo.yml"
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: []
-129
View File
@@ -1,129 +0,0 @@
# 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@abstracmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/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:
/{domainID}/mapping:
post:
summary: Adds new device to proxy
description: Adds new device to proxy
tags:
- provision
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/ProvisionReq"
responses:
"201":
description: Created
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
summary: Gets current mapping.
description: Gets current mapping. This can be used in UI
so that when bootstrap config is created from UI matches
configuration created with provision service.
tags:
- provision
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
responses:
"200":
$ref: "#/components/responses/ProvisionRes"
"401":
description: Missing or invalid access token provided.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
tags:
- health
security: []
responses:
"200":
$ref: "#/components/responses/HealthRes"
"500":
$ref: "#/components/responses/ServiceError"
components:
requestBodies:
ProvisionReq:
description: MAC address of device or other identifier
content:
application/json:
schema:
type: object
required:
- external_id
- external_key
properties:
external_id:
type: string
external_key:
type: string
name:
type: string
responses:
ServiceError:
description: Unexpected server-side error occurred.
ProvisionRes:
description: Current mapping JSON representation.
content:
application/json:
schema:
type: object
HealthRes:
description: Service Health Check.
content:
application/health+json:
schema:
$ref: "./schemas/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
-431
View File
@@ -1,431 +0,0 @@
# 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@abstractmachines.fr
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/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:
operationId: createTwin
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.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
get:
operationId: getTwins
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.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/twins/{twinID}:
get:
operationId: getTwin
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.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
put:
operationId: updateTwin
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.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: removeTwin
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.
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/states/{twinID}:
get:
operationId: getStates
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.
"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:
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
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
items:
$ref: "#/components/schemas/Definition"
metadata:
type: object
description: Arbitrary, object-encoded twin's data.
TwinsPage:
type: object
properties:
twins:
type: array
minItems: 0
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:
states:
type: array
minItems: 0
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:
- states
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"
links:
update:
operationId: updateTwin
parameters:
twinID: $response.body#/id
delete:
operationId: removeTwin
parameters:
twinID: $response.body#/id
states:
operationId: getStates
parameters:
twinID: $response.body#/id
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/health+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
@@ -2,14 +2,14 @@
# SPDX-License-Identifier: Apache-2.0
asyncapi: '2.6.0'
id: 'https://github.com/absmach/magistrala/blob/main/api/asyncapi/mqtt.yml'
id: 'https://github.com/absmach/magistrala/blob/main/api/asyncapi/mqtt.yaml'
info:
title: Magistrala MQTT Adapter
version: '1.0.0'
contact:
name: Magistrala Team
url: 'https://github.com/absmach/magistrala'
email: info@abstractmachines.fr
email: info@absmach.eu
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.
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0
asyncapi: 2.6.0
id: 'https://github.com/absmach/magistrala/blob/main/api/asyncapi/websocket.yml'
id: 'https://github.com/absmach/magistrala/blob/main/api/asyncapi/websocket.yaml'
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.
@@ -10,7 +10,7 @@ info:
contact:
name: Magistrala Team
url: 'https://github.com/absmach/magistrala'
email: info@abstractmachines.fr
email: info@absmach.eu
license:
name: Apache 2.0
url: 'https://github.com/absmach/magistrala/blob/main/LICENSE'
+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 [docs.api.magistrala.absmach.eu](https://docs.api.magistrala.absmach.eu)
+508
View File
@@ -0,0 +1,508 @@
# 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://docs.magistrala.absmach.eu
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>"
@@ -5,15 +5,15 @@ openapi: 3.0.1
info:
title: Magistrala Bootstrap service
description: |
HTTP API for managing platform things configuration.
HTTP API for managing platform clients configuration.
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@abstractmachines.fr
email: info@absmach.eu
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.14.0
version: 0.18.5
servers:
- url: http://localhost:9013
@@ -24,10 +24,10 @@ tags:
description: Everything about your Configs
externalDocs:
description: Find out more about Configs
url: https://docs.magistrala.abstractmachines.fr/
url: https://docs.magistrala.absmach.eu
paths:
/{domainID}/things/configs:
/{domainID}/clients/configs:
post:
operationId: createConfig
summary: Adds new config
@@ -37,7 +37,7 @@ paths:
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
requestBody:
$ref: "#/components/requestBodies/ConfigCreateReq"
responses:
@@ -60,7 +60,7 @@ paths:
"500":
$ref: "#/components/responses/ServiceError"
"503":
description: Failed to receive response from the things service.
description: Failed to receive response from the clients service.
get:
operationId: getConfigs
summary: Retrieves managed configs
@@ -72,7 +72,7 @@ paths:
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/Limit"
- $ref: "#/components/parameters/Offset"
- $ref: "#/components/parameters/State"
@@ -88,14 +88,15 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/things/configs/{configId}:
/{domainID}/clients/configs/{configID}:
get:
operationId: getConfig
summary: Retrieves config info (with channels).
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
responses:
"200":
@@ -118,11 +119,11 @@ paths:
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.
external key, SuperMQ Client ID and key cannot be changed.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigUpdateReq"
@@ -148,11 +149,11 @@ paths:
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.
that the removed config is disconnected from all of the SuperMQ channels.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
responses:
"204":
@@ -167,7 +168,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/things/configs/certs/{configId}:
/{domainID}/clients/configs/certs/{configID}:
patch:
operationId: updateConfigCerts
summary: Updates certs
@@ -177,7 +179,7 @@ paths:
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigCertUpdateReq"
@@ -199,17 +201,18 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/things/configs/connections/{configId}:
/{domainID}/clients/configs/connections/{configID}:
put:
operationId: updateConfigConnections
summary: Updates channels the thing is connected to
summary: Updates channels the client is connected to
description: |
Update connections performs update of the channel list corresponding
Thing is connected to.
Client is connected to.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigConnUpdateReq"
@@ -230,7 +233,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/things/bootstrap/{externalId}:
/clients/bootstrap/{externalId}:
get:
operationId: getBootstrapConfig
summary: Retrieves configuration.
@@ -255,7 +259,8 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/things/bootstrap/secure/{externalId}:
/clients/bootstrap/secure/{externalId}:
get:
operationId: getSecureBootstrapConfig
summary: Retrieves configuration.
@@ -281,17 +286,18 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/things/state/{configId}:
/{domainID}/clients/state/{configID}:
put:
operationId: updateConfigState
summary: Updates Config state.
description: |
Updating state represents enabling/disabling Config, i.e. connecting
and disconnecting corresponding Magistrala Thing to the list of Channels.
and disconnecting corresponding SuperMQ Client to the list of Channels.
tags:
- configs
parameters:
- $ref: "auth.yml#/components/parameters/DomainID"
- $ref: "#/components/parameters/DomainID"
- $ref: "#/components/parameters/ConfigId"
requestBody:
$ref: "#/components/requestBodies/ConfigStateUpdateReq"
@@ -310,6 +316,7 @@ paths:
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/health:
get:
summary: Retrieves service health check info.
@@ -330,14 +337,14 @@ components:
Config:
type: object
properties:
thing_id:
client_id:
type: string
format: uuid
description: Corresponding Magistrala Thing ID.
magistrala_key:
description: Corresponding SuperMQ Client ID.
magistrala_secret:
type: string
format: uuid
description: Corresponding Magistrala Thing key.
description: Corresponding SuperMQ Client key.
channels:
type: array
minItems: 0
@@ -402,14 +409,14 @@ components:
BootstrapConfig:
type: object
properties:
thing_id:
client_id:
type: string
format: uuid
description: Corresponding Magistrala Thing ID.
thing_key:
description: Corresponding SuperMQ Client ID.
client_key:
type: string
format: uuid
description: Corresponding Magistrala Thing key.
description: Corresponding SuperMQ Client key.
channels:
type: array
minItems: 0
@@ -421,24 +428,18 @@ components:
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
- client_id
- client_key
- channels
- content
ConfigUpdateCerts:
type: object
properties:
thing_id:
client_id:
type: string
format: uuid
description: Corresponding Magistrala Thing ID.
description: Corresponding SuperMQ Client ID.
client_cert:
type: string
description: Client certificate.
@@ -449,15 +450,15 @@ components:
type: string
description: Issuing CA certificate.
required:
- thing_id
- thing_key
- client_id
- client_key
- channels
- content
parameters:
ConfigId:
name: configId
description: Unique Config identifier. It's the ID of the corresponding Thing.
name: configID
description: Unique Config identifier. It's the ID of the corresponding Client.
in: path
schema:
type: string
@@ -503,6 +504,15 @@ components:
schema:
type: string
required: false
DomainID:
name: domainID
description: Unique domain identifier.
in: path
schema:
type: string
format: uuid
required: true
example: bb7edb32-2eac-4aad-aebe-ed96fe073879
requestBodies:
ConfigCreateReq:
@@ -519,10 +529,10 @@ components:
external_key:
type: string
description: External key.
thing_id:
client_id:
type: string
format: uuid
description: ID of the corresponding Magistrala Thing.
description: ID of the corresponding SuperMQ Client.
channels:
type: array
minItems: 0
@@ -535,17 +545,17 @@ components:
type: string
client_cert:
type: string
description: Thing Certificate.
description: Client Certificate.
client_key:
type: string
description: Thing Private Key.
description: Client Private Key.
ca_cert:
type: string
required:
- external_id
- external_key
ConfigUpdateReq:
description: JSON-formatted document describing the updated thing.
description: JSON-formatted document describing the updated client.
content:
application/json:
schema:
@@ -559,7 +569,7 @@ components:
- content
- name
ConfigCertUpdateReq:
description: JSON-formatted document describing the updated thing.
description: JSON-formatted document describing the updated client.
content:
application/json:
schema:
@@ -572,7 +582,7 @@ components:
ca_cert:
type: string
ConfigConnUpdateReq:
description: Array if IDs the thing is be connected to.
description: Array if IDs the client is be connected to.
content:
application/json:
schema:
@@ -603,7 +613,7 @@ components:
text/plain:
schema:
type: string
description: Created configuration's relative URL (i.e. /things/configs/{configId}).
description: Created configuration's relative URL (i.e. /clients/configs/{configID}).
ConfigListRes:
description: Data retrieved. Configs from this list don't contain channels.
content:
@@ -620,23 +630,23 @@ components:
update:
operationId: updateConfig
parameters:
configId: $response.body#/id
configID: $response.body#/id
updateCerts:
operationId: updateConfigCerts
parameters:
configId: $response.body#/id
configID: $response.body#/id
updateConnections:
operationId: updateConfigConnections
parameters:
configId: $response.body#/id
configID: $response.body#/id
updateState:
operationId: updateConfigState
parameters:
configId: $response.body#/id
configID: $response.body#/id
delete:
operationId: removeConfig
parameters:
configId: $response.body#/id
configID: $response.body#/id
BootstrapConfigRes:
description: |
Data retrieved. If secure, a response is encrypted using
@@ -652,7 +662,7 @@ components:
content:
application/health+json:
schema:
$ref: "./schemas/HealthInfo.yml"
$ref: "./schemas/health_info.yaml"
ConfigUpdateCertsRes:
description: Data retrieved. Config certs updated.
content:
@@ -673,14 +683,14 @@ components:
scheme: bearer
bearerFormat: string
description: |
* Things access: "Authorization: Thing <external_key>"
* Clients access: "Authorization: Client <external_key>"
bootstrapEncAuth:
type: http
scheme: bearer
bearerFormat: aes-sha256-uuid
description: |
* Things access: "Authorization: Thing <external_enc_key>"
* Clients access: "Authorization: Client <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.
@@ -9,11 +9,11 @@ info:
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@abstractmachines.fr
email: info@absmach.eu
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.14.0
version: 0.18.5
servers:
- url: http://localhost:9014
@@ -26,7 +26,7 @@ tags:
description: Everything about your Notifiers
externalDocs:
description: Find out more about notifiers
url: https://docs.magistrala.abstractmachines.fr/
url: https://docs.magistrala.absmach.eu
paths:
/subscriptions:
@@ -44,7 +44,7 @@ paths:
"400":
description: Failed due to malformed JSON.
"401":
description: Missing or invalid access token provided.
description: Missing or invalid access token provided.
"403":
description: Failed to perform authorization over the entity.
"409":
@@ -278,7 +278,7 @@ components:
content:
application/health+json:
schema:
$ref: "./schemas/HealthInfo.yml"
$ref: "./schemas/health_info.yaml"
securitySchemes:
bearerAuth:
@@ -9,19 +9,17 @@ info:
Some useful links:
- [The Magistrala repository](https://github.com/absmach/magistrala)
contact:
email: info@abstractmachines.fr
email: info@absmach.eu
license:
name: Apache 2.0
url: https://github.com/absmach/magistrala/blob/main/LICENSE
version: 0.14.0
version: 0.18.5
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
@@ -32,7 +30,7 @@ tags:
description: Everything about your Readers
externalDocs:
description: Find out more about readers
url: https://docs.magistrala.abstractmachines.fr/
url: https://docs.magistrala.absmach.eu
paths:
/{domainID}/channels/{chanId}/messages:
@@ -292,7 +290,7 @@ components:
content:
application/health+json:
schema:
$ref: "./schemas/HealthInfo.yml"
$ref: "./schemas/health_info.yaml"
securitySchemes:
bearerAuth:
+556
View File
@@ -0,0 +1,556 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: Magistrala Reports Service API
description: |
HTTP API for managing reports service.
version: 0.18.5
servers:
- url: http://localhost:9017
tags:
- name: reports
description: Operations related to report configurations and generation
paths:
/{domainID}/reports:
post:
operationId: generateReport
summary: Generate a report
description: Generates a report based on the provided configuration or an existing config. The action determines the response format.
tags:
- reports
parameters:
- $ref: '#/components/parameters/DomainID'
security:
- bearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateReportRequest'
responses:
'200':
description: Report generated successfully (content varies by action)
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateReportResponse'
application/octet-stream:
schema:
type: string
format: binary
'400':
description: Invalid request parameters
'401':
description: Missing or invalid access token
'500':
$ref: '#/components/responses/ServiceError'
/{domainID}/reports/configs:
post:
operationId: addReportConfig
summary: Create a report configuration
description: Creates a new report configuration.
tags:
- reports
parameters:
- $ref: '#/components/parameters/DomainID'
security:
- bearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/AddReportConfigRequest'
responses:
'201':
description: Report configuration created
headers:
Location:
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/ReportConfig'
'400':
description: Invalid request body
'401':
description: Missing or invalid access token
'500':
$ref: '#/components/responses/ServiceError'
get:
operationId: listReportConfigs
summary: List report configurations
description: Retrieves a paginated list of report configurations.
tags:
- reports
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Limit'
security:
- bearerAuth: []
responses:
'200':
description: List of report configurations
content:
application/json:
schema:
$ref: '#/components/schemas/ListReportsConfigResponse'
'400':
description: Invalid query parameters
'401':
description: Missing or invalid access token
'500':
$ref: '#/components/responses/ServiceError'
/{domainID}/reports/configs/{reportID}:
get:
operationId: viewReportConfig
summary: View a report configuration
description: Retrieves details of a specific report configuration.
tags:
- reports
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/ReportID'
security:
- bearerAuth: []
responses:
'200':
description: Report configuration details
content:
application/json:
schema:
$ref: '#/components/schemas/ReportConfig'
'404':
description: Report configuration not found
'401':
description: Missing or invalid access token
'500':
$ref: '#/components/responses/ServiceError'
patch:
operationId: updateReportConfig
summary: Update a report configuration
description: Updates specified fields of a report configuration.
tags:
- reports
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/ReportID'
security:
- bearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/UpdateReportConfigRequest'
responses:
'200':
description: Report configuration updated
content:
application/json:
schema:
$ref: '#/components/schemas/ReportConfig'
'400':
description: Invalid request body
'401':
description: Missing or invalid access token
'404':
description: Report configuration not found
'500':
$ref: '#/components/responses/ServiceError'
delete:
operationId: deleteReportConfig
summary: Delete a report configuration
description: Permanently deletes a report configuration.
tags:
- reports
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/ReportID'
security:
- bearerAuth: []
responses:
'204':
description: Report configuration deleted
'401':
description: Missing or invalid access token
'404':
description: Report configuration not found
'500':
$ref: '#/components/responses/ServiceError'
/{domainID}/reports/configs/{reportID}/schedule:
patch:
operationId: updateReportSchedule
summary: Update report schedule
description: Updates the schedule of a report configuration.
tags:
- reports
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/ReportID'
security:
- bearerAuth: []
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/Schedule'
responses:
'200':
description: Schedule updated
content:
application/json:
schema:
$ref: '#/components/schemas/ReportConfig'
'400':
description: Invalid schedule
'401':
description: Missing or invalid access token
'404':
description: Report configuration not found
'500':
$ref: '#/components/responses/ServiceError'
/{domainID}/reports/configs/{reportID}/enable:
post:
operationId: enableReportConfig
summary: Enable a report configuration
description: Enables a report configuration to generate scheduled reports.
tags:
- reports
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/ReportID'
security:
- bearerAuth: []
responses:
'200':
description: Report configuration enabled
content:
application/json:
schema:
$ref: '#/components/schemas/ReportConfig'
'401':
description: Missing or invalid access token
'404':
description: Report configuration not found
'500':
$ref: '#/components/responses/ServiceError'
/{domainID}/reports/configs/{reportID}/disable:
post:
operationId: disableReportConfig
summary: Disable a report configuration
description: Disables a report configuration, stopping scheduled reports.
tags:
- reports
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/ReportID'
security:
- bearerAuth: []
responses:
'200':
description: Report configuration disabled
content:
application/json:
schema:
$ref: '#/components/schemas/ReportConfig'
'401':
description: Missing or invalid access token
'404':
description: Report configuration not found
'500':
$ref: '#/components/responses/ServiceError'
/health:
get:
summary: Service health check
tags:
- health
responses:
'200':
$ref: '#/components/responses/HealthRes'
components:
schemas:
ReportConfig:
type: object
properties:
id:
type: string
readOnly: true
name:
type: string
description:
type: string
domain_id:
type: string
readOnly: true
schedule:
$ref: '#/components/schemas/Schedule'
config:
$ref: '#/components/schemas/MetricConfig'
email:
$ref: '#/components/schemas/EmailSetting'
metrics:
type: array
items:
$ref: '#/components/schemas/ReqMetric'
status:
$ref: '#/components/schemas/Status'
created_at:
type: string
format: date-time
readOnly: true
created_by:
type: string
readOnly: true
updated_at:
type: string
format: date-time
readOnly: true
updated_by:
type: string
readOnly: true
required:
- name
- metrics
- config
Schedule:
type: object
properties:
recurring:
type: string
enum: [None, Daily, Weekly, Monthly]
recurring_period:
type: integer
minimum: 1
start_time:
type: string
format: date-time
next_run:
type: string
format: date-time
readOnly: true
MetricConfig:
type: object
properties:
title:
type: string
maxLength: 100
format:
type: string
enum: [pdf, csv, html]
aggregation:
$ref: '#/components/schemas/AggConfig'
AggConfig:
type: object
properties:
window:
type: string
function:
type: string
enum: [sum, average, max, min]
EmailSetting:
type: object
properties:
recipients:
type: array
items:
type: string
format: email
subject:
type: string
body_template:
type: string
required:
- recipients
- subject
ReqMetric:
type: object
properties:
name:
type: string
type:
type: string
enum: [gauge, counter, histogram]
parameters:
type: object
required:
- name
- type
Status:
type: string
enum: [enabled, disabled]
GenerateReportRequest:
type: object
properties:
action:
type: string
enum: [view, download, email]
config_id:
type: string
name:
type: string
description:
type: string
schedule:
$ref: '#/components/schemas/Schedule'
config:
$ref: '#/components/schemas/MetricConfig'
email:
$ref: '#/components/schemas/EmailSetting'
metrics:
type: array
items:
$ref: '#/components/schemas/ReqMetric'
required:
- action
GenerateReportResponse:
type: object
properties:
total:
type: integer
from:
type: string
format: date-time
to:
type: string
format: date-time
aggregation:
$ref: '#/components/schemas/AggConfig'
reports:
type: array
items:
$ref: '#/components/schemas/Report'
Report:
type: object
properties:
timestamp:
type: string
format: date-time
value:
type: number
metric_name:
type: string
AddReportConfigRequest:
type: object
properties:
name:
type: string
description:
type: string
schedule:
$ref: '#/components/schemas/Schedule'
config:
$ref: '#/components/schemas/MetricConfig'
email:
$ref: '#/components/schemas/EmailSetting'
metrics:
type: array
items:
$ref: '#/components/schemas/ReqMetric'
status:
$ref: '#/components/schemas/Status'
required:
- name
- metrics
- config
UpdateReportConfigRequest:
type: object
properties:
name:
type: string
description:
type: string
schedule:
$ref: '#/components/schemas/Schedule'
config:
$ref: '#/components/schemas/MetricConfig'
email:
$ref: '#/components/schemas/EmailSetting'
metrics:
type: array
items:
$ref: '#/components/schemas/ReqMetric'
status:
$ref: '#/components/schemas/Status'
ListReportsConfigResponse:
type: object
properties:
total:
type: integer
offset:
type: integer
limit:
type: integer
report_configs:
type: array
items:
$ref: '#/components/schemas/ReportConfig'
parameters:
DomainID:
name: domainID
in: path
required: true
schema:
type: string
ReportID:
name: reportID
in: path
required: true
schema:
type: string
Offset:
name: offset
in: query
schema:
type: integer
default: 0
minimum: 0
Limit:
name: limit
in: query
schema:
type: integer
default: 10
minimum: 1
maximum: 100
responses:
ServiceError:
description: Unexpected server error
HealthRes:
description: Service health status
content:
application/json:
schema:
type: object
properties:
status:
type: string
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
+586
View File
@@ -0,0 +1,586 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0
openapi: 3.0.1
info:
title: Magistrala Rules Engine API
description: |
HTTP API for managing rules engine 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:9008
- url: http://localhost:9008
tags:
- name: rules engine
description: Everything about your Rules Engine
externalDocs:
description: Find out more about rules engine
url: https://docs.magistrala.absmach.eu
paths:
/{domainID}/rules:
post:
operationId: createRule
summary: Create Rule
description: |
Creates a new rule for message processing
tags:
- rules
parameters:
- $ref: '#/components/parameters/DomainID'
security:
- bearerAuth: []
requestBody:
$ref: '#/components/requestBodies/RuleCreateReq'
responses:
'201':
$ref: '#/components/responses/RuleCreateRes'
'400':
description: Failed due to malformed JSON
'401':
description: Missing or invalid access token
'415':
description: Missing or invalid content type
"500":
$ref: "#/components/responses/ServiceError"
"503":
description: Failed to receive response from the clients service.
get:
operationId: getRules
summary: List Rules
description: |
Retrieves a list of rules with optional filtering
tags:
- rules
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/Offset'
- $ref: '#/components/parameters/Limit'
- $ref: '#/components/parameters/InputChannel'
- $ref: '#/components/parameters/OutputChannel'
- $ref: '#/components/parameters/Status'
security:
- bearerAuth: []
responses:
'200':
$ref: '#/components/responses/RuleListRes'
'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}/rules/{ruleID}:
get:
operationId: getRule
summary: View Rule
description: Retrieves a rule by ID
tags:
- rules
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/RuleID'
security:
- bearerAuth: []
responses:
'200':
$ref: '#/components/responses/RuleRes'
"400":
description: Missing or invalid rule
"403":
description: Failed to perform authorization over the entity
'401':
description: Missing or invalid access token
'404':
description: Rule does not exist
"422":
description: Database can't process request
"500":
$ref: "#/components/responses/ServiceError"
put:
operationId: updateRule
summary: Update Rule
description: Updates an existing rule
tags:
- rules
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/RuleID'
security:
- bearerAuth: []
requestBody:
$ref: '#/components/requestBodies/RuleUpdateReq'
responses:
'200':
$ref: '#/components/responses/RuleRes'
'400':
description: Failed due to malformed JSON
'401':
description: Missing or invalid access token
'404':
description: Rule does not exist
"415":
description: Missing or invalid content type.
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
delete:
operationId: removeRule
summary: Delete Rule
description: Deletes a rule
tags:
- rules
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/RuleID'
security:
- bearerAuth: []
responses:
'204':
description: Rule deleted successfully
"400":
description: Failed due to malformed rule ID
'401':
description: Missing or invalid access token
"403":
description: Failed to perform authorization over the entity
"422":
description: Database can't process request
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/rules/{ruleID}/enable:
put:
operationId: enableRule
summary: Enable Rule
description: Enables a rule for processing
tags:
- rules
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/RuleID'
security:
- bearerAuth: []
responses:
'200':
description: Rule enabled successfully
"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: Rule does not exist
"422":
description: Database can't process request.
"500":
$ref: "#/components/responses/ServiceError"
/{domainID}/rules/{ruleID}/disable:
put:
operationId: disableRule
summary: Disable Rule
description: Disables a rule from processing
tags:
- Rules
parameters:
- $ref: '#/components/parameters/DomainID'
- $ref: '#/components/parameters/RuleID'
security:
- bearerAuth: []
responses:
'200':
description: Rule disabled successfully
"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: Rule 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:
RulesListRes:
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
rules:
type: array
minItems: 0
uniqueItems: true
items:
$ref: '#/components/schemas/Rule'
required:
- rules
Rule:
type: object
properties:
id:
type: string
description: Unique rule identifier
name:
type: string
description: Rule name
domain:
type: string
description: Domain ID this rule belongs to
metadata:
type: object
description: Custom metadata
additionalProperties:
type: string
input_channel:
type: string
description: Input channel for receiving messages
input_topic:
type: string
description: Input topic for receiving messages
logic:
type: object
description: Rule processing logic script
properties:
script:
type: string
description: Script content
output_channel:
type: string
description: Output channel for processed messages
output_topic:
type: string
description: Output topic for processed messages
schedule:
type: object
description: Rule execution schedule
properties:
start_datetime:
type: string
format: date-time
description: When the schedule becomes active
time:
type: string
format: date-time
description: Specific time for the rule to run
recurring:
type: string
description: Schedule recurrence pattern
enum: [None, Daily, Weekly, Monthly]
recurring_period:
type: integer
minimum: 1
description: Controls how many intervals to skip between executions (1 = every interval, 2 = every second interval, etc.)
status:
type: string
description: Rule status
enum: [enabled, disabled]
created_at:
type: string
format: date-time
description: Creation timestamp
readOnly: true
created_by:
type: string
description: User who created the rule
updated_at:
type: string
format: date-time
description: Last update timestamp
readOnly: true
updated_by:
type: string
description: User who last updated the rule
required:
- name
- domain
- input_channel
- input_topic
- logic
- status
parameters:
DomainID:
name: domainID
description: Domain ID
in: path
required: true
schema:
type: string
RuleID:
name: ruleID
description: Rule 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
in: query
required: false
schema:
type: integer
default: 10
minimum: 1
InputChannel:
name: input_channel
description: Filter by input channel
in: query
required: false
schema:
type: string
OutputChannel:
name: output_channel
description: Filter by output channel
in: query
required: false
schema:
type: string
Status:
name: status
description: Filter by rule status
in: query
required: false
schema:
type: string
enum: [enabled, disabled]
default: enabled
requestBodies:
RuleCreateReq:
description: JSON-formatted document describing the new rule
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: Rule name
domain:
type: string
description: Domain ID this rule belongs to
metadata:
type: object
description: Custom metadata
additionalProperties:
type: string
input_channel:
type: string
description: Input channel for receiving messages
input_topic:
type: string
description: Input topic for receiving messages
logic:
type: object
description: Rule processing logic script
properties:
script:
type: string
description: Script content
output_channel:
type: string
description: Output channel for processed messages
output_topic:
type: string
description: Output topic for processed messages
schedule:
type: object
description: Rule execution schedule
properties:
start_datetime:
type: string
format: date-time
description: When the schedule becomes active
time:
type: string
format: date-time
description: Specific time for the rule to run
recurring:
type: string
description: Schedule recurrence pattern
enum: [None, Daily, Weekly, Monthly]
recurring_period:
type: integer
minimum: 1
description: Controls how many intervals to skip between executions
status:
type: string
description: Rule status
enum: [enabled, disabled]
required:
- name
- domain
- input_channel
- input_topic
- logic
- schedule
RuleUpdateReq:
description: JSON-formatted document describing the rule update
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: Rule name
metadata:
type: object
description: Custom metadata
additionalProperties:
type: string
input_channel:
type: string
description: Input channel for receiving messages
input_topic:
type: string
description: Input topic for receiving messages
logic:
type: object
description: Rule processing logic script
properties:
script:
type: string
description: Script content
output_channel:
type: string
description: Output channel for processed messages
output_topic:
type: string
description: Output topic for processed messages
schedule:
type: object
description: Rule execution schedule
properties:
start_datetime:
type: string
format: date-time
description: When the schedule becomes active
time:
type: string
format: date-time
description: Specific time for the rule to run
recurring:
type: string
description: Schedule recurrence pattern
enum: [None, Daily, Weekly, Monthly]
recurring_period:
type: integer
minimum: 1
description: Controls how many intervals to skip between executions
status:
type: string
description: Rule status
enum: [enabled, disabled]
responses:
RuleCreateRes:
description: Rule registered
headers:
Location:
content:
text/plain:
schema:
type: string
description: Created rule's relative URL (i.e. /rules/{ruleID})
RuleListRes:
description: Data retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/RulesListRes'
RuleRes:
description: Data retrieved
content:
application/json:
schema:
$ref: '#/components/schemas/Rule'
links:
update:
operationId: updateRule
parameters:
ruleID: $response.body#/id
enable:
operationId: enableRule
parameters:
ruleID: $response.body#/id
disable:
operationId: disableRule
parameters:
ruleID: $response.body#/id
delete:
operationId: removeRule
parameters:
ruleID: $response.body#/id
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>"
-993
View File
@@ -1,993 +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.34.2
// protoc v5.27.1
// source: auth.proto
package magistrala
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
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)
)
// 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
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
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"`
}
func (x *Token) Reset() {
*x = Token{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[0]
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_auth_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && 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_auth_proto_rawDescGZIP(), []int{0}
}
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 AuthNReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
}
func (x *AuthNReq) Reset() {
*x = AuthNReq{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[1]
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_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && 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_proto_rawDescGZIP(), []int{1}
}
func (x *AuthNReq) GetToken() string {
if x != nil {
return x.Token
}
return ""
}
type AuthNRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // change "id" to "subject", sub in jwt = user + domain id
UserId string `protobuf:"bytes,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"` // user id
DomainId string `protobuf:"bytes,3,opt,name=domain_id,json=domainId,proto3" json:"domain_id,omitempty"` // domain id
}
func (x *AuthNRes) Reset() {
*x = AuthNRes{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[2]
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_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && 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_proto_rawDescGZIP(), []int{2}
}
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) GetDomainId() string {
if x != nil {
return x.DomainId
}
return ""
}
type IssueReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
UserId string `protobuf:"bytes,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
Type uint32 `protobuf:"varint,2,opt,name=type,proto3" json:"type,omitempty"`
}
func (x *IssueReq) Reset() {
*x = IssueReq{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[3]
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_auth_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && 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_auth_proto_rawDescGZIP(), []int{3}
}
func (x *IssueReq) GetUserId() string {
if x != nil {
return x.UserId
}
return ""
}
func (x *IssueReq) GetType() uint32 {
if x != nil {
return x.Type
}
return 0
}
type RefreshReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
}
func (x *RefreshReq) Reset() {
*x = RefreshReq{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[4]
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_auth_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && 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_auth_proto_rawDescGZIP(), []int{4}
}
func (x *RefreshReq) GetRefreshToken() string {
if x != nil {
return x.RefreshToken
}
return ""
}
type AuthZReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Domain string `protobuf:"bytes,1,opt,name=domain,proto3" json:"domain,omitempty"` // Domain
SubjectType string `protobuf:"bytes,2,opt,name=subject_type,json=subjectType,proto3" json:"subject_type,omitempty"` // Thing or User
SubjectKind string `protobuf:"bytes,3,opt,name=subject_kind,json=subjectKind,proto3" json:"subject_kind,omitempty"` // ID or Token
SubjectRelation string `protobuf:"bytes,4,opt,name=subject_relation,json=subjectRelation,proto3" json:"subject_relation,omitempty"` // Subject relation
Subject string `protobuf:"bytes,5,opt,name=subject,proto3" json:"subject,omitempty"` // Subject value (id or token, depending on kind)
Relation string `protobuf:"bytes,6,opt,name=relation,proto3" json:"relation,omitempty"` // Relation to filter
Permission string `protobuf:"bytes,7,opt,name=permission,proto3" json:"permission,omitempty"` // Action
Object string `protobuf:"bytes,8,opt,name=object,proto3" json:"object,omitempty"` // Object ID
ObjectType string `protobuf:"bytes,9,opt,name=object_type,json=objectType,proto3" json:"object_type,omitempty"` // Thing, User, Group
}
func (x *AuthZReq) Reset() {
*x = AuthZReq{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[5]
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_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && 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_proto_rawDescGZIP(), []int{5}
}
func (x *AuthZReq) GetDomain() string {
if x != nil {
return x.Domain
}
return ""
}
func (x *AuthZReq) GetSubjectType() string {
if x != nil {
return x.SubjectType
}
return ""
}
func (x *AuthZReq) GetSubjectKind() string {
if x != nil {
return x.SubjectKind
}
return ""
}
func (x *AuthZReq) GetSubjectRelation() string {
if x != nil {
return x.SubjectRelation
}
return ""
}
func (x *AuthZReq) GetSubject() string {
if x != nil {
return x.Subject
}
return ""
}
func (x *AuthZReq) GetRelation() string {
if x != nil {
return x.Relation
}
return ""
}
func (x *AuthZReq) GetPermission() string {
if x != nil {
return x.Permission
}
return ""
}
func (x *AuthZReq) GetObject() string {
if x != nil {
return x.Object
}
return ""
}
func (x *AuthZReq) GetObjectType() string {
if x != nil {
return x.ObjectType
}
return ""
}
type AuthZRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
}
func (x *AuthZRes) Reset() {
*x = AuthZRes{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[6]
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_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && 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_proto_rawDescGZIP(), []int{6}
}
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 ""
}
type DeleteUserRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Deleted bool `protobuf:"varint,1,opt,name=deleted,proto3" json:"deleted,omitempty"`
}
func (x *DeleteUserRes) Reset() {
*x = DeleteUserRes{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[7]
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_auth_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && 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_auth_proto_rawDescGZIP(), []int{7}
}
func (x *DeleteUserRes) GetDeleted() bool {
if x != nil {
return x.Deleted
}
return false
}
type DeleteUserReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
}
func (x *DeleteUserReq) Reset() {
*x = DeleteUserReq{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[8]
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_auth_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && 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_auth_proto_rawDescGZIP(), []int{8}
}
func (x *DeleteUserReq) GetId() string {
if x != nil {
return x.Id
}
return ""
}
type ThingsAuthzReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
ChannelId string `protobuf:"bytes,1,opt,name=channel_id,json=channelId,proto3" json:"channel_id,omitempty"`
ThingId string `protobuf:"bytes,2,opt,name=thing_id,json=thingId,proto3" json:"thing_id,omitempty"`
ThingKey string `protobuf:"bytes,3,opt,name=thing_key,json=thingKey,proto3" json:"thing_key,omitempty"`
Permission string `protobuf:"bytes,4,opt,name=permission,proto3" json:"permission,omitempty"`
}
func (x *ThingsAuthzReq) Reset() {
*x = ThingsAuthzReq{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ThingsAuthzReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ThingsAuthzReq) ProtoMessage() {}
func (x *ThingsAuthzReq) ProtoReflect() protoreflect.Message {
mi := &file_auth_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ThingsAuthzReq.ProtoReflect.Descriptor instead.
func (*ThingsAuthzReq) Descriptor() ([]byte, []int) {
return file_auth_proto_rawDescGZIP(), []int{9}
}
func (x *ThingsAuthzReq) GetChannelId() string {
if x != nil {
return x.ChannelId
}
return ""
}
func (x *ThingsAuthzReq) GetThingId() string {
if x != nil {
return x.ThingId
}
return ""
}
func (x *ThingsAuthzReq) GetThingKey() string {
if x != nil {
return x.ThingKey
}
return ""
}
func (x *ThingsAuthzReq) GetPermission() string {
if x != nil {
return x.Permission
}
return ""
}
type ThingsAuthzRes struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Authorized bool `protobuf:"varint,1,opt,name=authorized,proto3" json:"authorized,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
}
func (x *ThingsAuthzRes) Reset() {
*x = ThingsAuthzRes{}
if protoimpl.UnsafeEnabled {
mi := &file_auth_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ThingsAuthzRes) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ThingsAuthzRes) ProtoMessage() {}
func (x *ThingsAuthzRes) ProtoReflect() protoreflect.Message {
mi := &file_auth_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ThingsAuthzRes.ProtoReflect.Descriptor instead.
func (*ThingsAuthzRes) Descriptor() ([]byte, []int) {
return file_auth_proto_rawDescGZIP(), []int{10}
}
func (x *ThingsAuthzRes) GetAuthorized() bool {
if x != nil {
return x.Authorized
}
return false
}
func (x *ThingsAuthzRes) GetId() string {
if x != nil {
return x.Id
}
return ""
}
var File_auth_proto protoreflect.FileDescriptor
var file_auth_proto_rawDesc = []byte{
0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x6d, 0x61,
0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x22, 0x87, 0x01, 0x0a, 0x05, 0x54, 0x6f, 0x6b,
0x65, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x6f, 0x6b,
0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73,
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x28, 0x0a, 0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68,
0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c,
0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x88, 0x01, 0x01, 0x12,
0x1f, 0x0a, 0x0b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x54, 0x79, 0x70, 0x65,
0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b,
0x65, 0x6e, 0x22, 0x20, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x4e, 0x52, 0x65, 0x71, 0x12, 0x14,
0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74,
0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x50, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x4e, 0x52, 0x65, 0x73,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6f, 0x6d,
0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x6f,
0x6d, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x22, 0x37, 0x0a, 0x08, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52,
0x65, 0x71, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74,
0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22,
0x31, 0x0a, 0x0a, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x12, 0x23, 0x0a,
0x0d, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x54, 0x6f, 0x6b,
0x65, 0x6e, 0x22, 0xa2, 0x02, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x5a, 0x52, 0x65, 0x71, 0x12,
0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x75, 0x62, 0x6a, 0x65,
0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73,
0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x75,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x52, 0x0b, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x29, 0x0a,
0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65,
0x63, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e,
0x0a, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01,
0x28, 0x09, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16,
0x0a, 0x06, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a,
0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3a, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x5a,
0x52, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69,
0x7a, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x02, 0x69, 0x64, 0x22, 0x29, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65,
0x72, 0x52, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x22, 0x1f,
0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12,
0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22,
0x87, 0x01, 0x0a, 0x0e, 0x54, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x41, 0x75, 0x74, 0x68, 0x7a, 0x52,
0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x49,
0x64, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09,
0x74, 0x68, 0x69, 0x6e, 0x67, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72,
0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70,
0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x40, 0x0a, 0x0e, 0x54, 0x68, 0x69,
0x6e, 0x67, 0x73, 0x41, 0x75, 0x74, 0x68, 0x7a, 0x52, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69,
0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x32, 0x56, 0x0a, 0x0d, 0x54,
0x68, 0x69, 0x6e, 0x67, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x09,
0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x12, 0x1a, 0x2e, 0x6d, 0x61, 0x67, 0x69,
0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e, 0x54, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x41, 0x75, 0x74,
0x68, 0x7a, 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e, 0x6d, 0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61,
0x6c, 0x61, 0x2e, 0x54, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x41, 0x75, 0x74, 0x68, 0x7a, 0x52, 0x65,
0x73, 0x22, 0x00, 0x32, 0x7a, 0x0a, 0x0c, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x12, 0x32, 0x0a, 0x05, 0x49, 0x73, 0x73, 0x75, 0x65, 0x12, 0x14, 0x2e, 0x6d,
0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x52,
0x65, 0x71, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e,
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x00, 0x12, 0x36, 0x0a, 0x07, 0x52, 0x65, 0x66, 0x72, 0x65,
0x73, 0x68, 0x12, 0x16, 0x2e, 0x6d, 0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e,
0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x67,
0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x00, 0x32,
0x86, 0x01, 0x0a, 0x0b, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
0x39, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x2e, 0x6d,
0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x5a, 0x52,
0x65, 0x71, 0x1a, 0x14, 0x2e, 0x6d, 0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e,
0x41, 0x75, 0x74, 0x68, 0x5a, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x3c, 0x0a, 0x0c, 0x41, 0x75,
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x14, 0x2e, 0x6d, 0x61, 0x67,
0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4e, 0x52, 0x65, 0x71,
0x1a, 0x14, 0x2e, 0x6d, 0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e, 0x41, 0x75,
0x74, 0x68, 0x4e, 0x52, 0x65, 0x73, 0x22, 0x00, 0x32, 0x61, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61,
0x69, 0x6e, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x4f, 0x0a, 0x15, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x46, 0x72, 0x6f, 0x6d, 0x44, 0x6f, 0x6d, 0x61,
0x69, 0x6e, 0x73, 0x12, 0x19, 0x2e, 0x6d, 0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61,
0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x19,
0x2e, 0x6d, 0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x2e, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x22, 0x00, 0x42, 0x0e, 0x5a, 0x0c, 0x2e,
0x2f, 0x6d, 0x61, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
}
var (
file_auth_proto_rawDescOnce sync.Once
file_auth_proto_rawDescData = file_auth_proto_rawDesc
)
func file_auth_proto_rawDescGZIP() []byte {
file_auth_proto_rawDescOnce.Do(func() {
file_auth_proto_rawDescData = protoimpl.X.CompressGZIP(file_auth_proto_rawDescData)
})
return file_auth_proto_rawDescData
}
var file_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_auth_proto_goTypes = []any{
(*Token)(nil), // 0: magistrala.Token
(*AuthNReq)(nil), // 1: magistrala.AuthNReq
(*AuthNRes)(nil), // 2: magistrala.AuthNRes
(*IssueReq)(nil), // 3: magistrala.IssueReq
(*RefreshReq)(nil), // 4: magistrala.RefreshReq
(*AuthZReq)(nil), // 5: magistrala.AuthZReq
(*AuthZRes)(nil), // 6: magistrala.AuthZRes
(*DeleteUserRes)(nil), // 7: magistrala.DeleteUserRes
(*DeleteUserReq)(nil), // 8: magistrala.DeleteUserReq
(*ThingsAuthzReq)(nil), // 9: magistrala.ThingsAuthzReq
(*ThingsAuthzRes)(nil), // 10: magistrala.ThingsAuthzRes
}
var file_auth_proto_depIdxs = []int32{
9, // 0: magistrala.ThingsService.Authorize:input_type -> magistrala.ThingsAuthzReq
3, // 1: magistrala.TokenService.Issue:input_type -> magistrala.IssueReq
4, // 2: magistrala.TokenService.Refresh:input_type -> magistrala.RefreshReq
5, // 3: magistrala.AuthService.Authorize:input_type -> magistrala.AuthZReq
1, // 4: magistrala.AuthService.Authenticate:input_type -> magistrala.AuthNReq
8, // 5: magistrala.DomainsService.DeleteUserFromDomains:input_type -> magistrala.DeleteUserReq
10, // 6: magistrala.ThingsService.Authorize:output_type -> magistrala.ThingsAuthzRes
0, // 7: magistrala.TokenService.Issue:output_type -> magistrala.Token
0, // 8: magistrala.TokenService.Refresh:output_type -> magistrala.Token
6, // 9: magistrala.AuthService.Authorize:output_type -> magistrala.AuthZRes
2, // 10: magistrala.AuthService.Authenticate:output_type -> magistrala.AuthNRes
7, // 11: magistrala.DomainsService.DeleteUserFromDomains:output_type -> magistrala.DeleteUserRes
6, // [6:12] is the sub-list for method output_type
0, // [0:6] 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_auth_proto_init() }
func file_auth_proto_init() {
if File_auth_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_auth_proto_msgTypes[0].Exporter = func(v any, i int) any {
switch v := v.(*Token); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[1].Exporter = func(v any, i int) any {
switch v := v.(*AuthNReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[2].Exporter = func(v any, i int) any {
switch v := v.(*AuthNRes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[3].Exporter = func(v any, i int) any {
switch v := v.(*IssueReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[4].Exporter = func(v any, i int) any {
switch v := v.(*RefreshReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[5].Exporter = func(v any, i int) any {
switch v := v.(*AuthZReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[6].Exporter = func(v any, i int) any {
switch v := v.(*AuthZRes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[7].Exporter = func(v any, i int) any {
switch v := v.(*DeleteUserRes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[8].Exporter = func(v any, i int) any {
switch v := v.(*DeleteUserReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[9].Exporter = func(v any, i int) any {
switch v := v.(*ThingsAuthzReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_auth_proto_msgTypes[10].Exporter = func(v any, i int) any {
switch v := v.(*ThingsAuthzRes); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_auth_proto_msgTypes[0].OneofWrappers = []any{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_auth_proto_rawDesc,
NumEnums: 0,
NumMessages: 11,
NumExtensions: 0,
NumServices: 4,
},
GoTypes: file_auth_proto_goTypes,
DependencyIndexes: file_auth_proto_depIdxs,
MessageInfos: file_auth_proto_msgTypes,
}.Build()
File_auth_proto = out.File
file_auth_proto_rawDesc = nil
file_auth_proto_goTypes = nil
file_auth_proto_depIdxs = nil
}
-98
View File
@@ -1,98 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
syntax = "proto3";
package magistrala;
option go_package = "./magistrala";
// ThingsService is a service that provides things authorization functionalities
// for magistrala services.
service ThingsService {
// Authorize checks if the thing is authorized to perform
// the action on the channel.
rpc Authorize(ThingsAuthzReq) returns (ThingsAuthzRes) {}
}
service TokenService {
rpc Issue(IssueReq) returns (Token) {}
rpc Refresh(RefreshReq) returns (Token) {}
}
// AuthService is a service that provides authentication and authorization
// functionalities for magistrala services.
service AuthService {
rpc Authorize(AuthZReq) returns (AuthZRes) {}
rpc Authenticate(AuthNReq) returns (AuthNRes) {}
}
// DomainsService is a service that provides access to domains
// functionalities for magistrala services.
service DomainsService {
rpc DeleteUserFromDomains(DeleteUserReq) returns (DeleteUserRes) {}
}
// 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.
message Token {
string access_token = 1;
optional string refresh_token = 2;
string access_type = 3;
}
message AuthNReq {
string token = 1;
}
message AuthNRes {
string id = 1; // change "id" to "subject", sub in jwt = user + domain id
string user_id = 2; // user id
string domain_id = 3; // domain id
}
message IssueReq {
string user_id = 1;
uint32 type = 2;
}
message RefreshReq {
string refresh_token = 1;
}
message AuthZReq {
string domain = 1; // Domain
string subject_type = 2; // Thing or User
string subject_kind = 3; // ID or Token
string subject_relation = 4; // Subject relation
string subject = 5; // Subject value (id or token, depending on kind)
string relation = 6; // Relation to filter
string permission = 7; // Action
string object = 8; // Object ID
string object_type = 9; // Thing, User, Group
}
message AuthZRes {
bool authorized = 1;
string id = 2;
}
message DeleteUserRes {
bool deleted = 1;
}
message DeleteUserReq {
string id = 1;
}
message ThingsAuthzReq {
string channel_id = 1;
string thing_id = 2;
string thing_key = 3;
string permission = 4;
}
message ThingsAuthzRes {
bool authorized = 1;
string id = 2;
}
-159
View File
@@ -1,159 +0,0 @@
# Auth - Authentication and Authorization service
Auth service provides authentication features as an API for managing authentication keys as well as administering groups of entities - `things` and `users`.
## Authentication
User service is using Auth service gRPC API to obtain login token or password reset token. Authentication key consists of the following fields:
- ID - key ID
- Type - one of the three types described below
- IssuerID - an ID of the Magistrala User who issued the key
- Subject - user ID for which the key is issued
- IssuedAt - the timestamp when the key is issued
- ExpiresAt - the timestamp after which the key is invalid
There are four types of authentication keys:
- Access key - keys issued to the user upon login request
- Refresh key - keys used to generate new access keys
- Recovery key - password recovery key
- API key - keys issued upon the user request
- Invitation key - keys used to invite new users
Authentication keys are represented and distributed by the corresponding [JWT](jwt.io).
User keys are issued when user logs in. Each user request (other than `registration` and `login`) contains user key that is used to authenticate the user.
API keys are similar to the User keys. The main difference is that API keys have configurable expiration time. If no time is set, the key will never expire. For that reason, API keys are _the only key type that can be revoked_. This also means that, despite being used as a JWT, it requires a query to the database to validate the API key. The user with API key can perform all the same actions as the user with login key (can act on behalf of the user for Thing, Channel, or user profile management), _except issuing new API keys_.
Recovery key is the password recovery key. It's short-lived token used for password recovery process.
For in-depth explanation of the aforementioned scenarios, as well as thorough understanding of Magistrala, please check out the [official documentation][doc].
The following actions are supported:
- create (all key types)
- verify (all key types)
- obtain (API keys only)
- revoke (API keys only)
## Domains
Domains are used to group users and things. Each domain has a unique alias that is used to identify the domain. Domains are used to group users and their entities.
Domain consists of the following fields:
- ID - UUID uniquely representing domain
- Name - name of the domain
- Tags - array of tags
- Metadata - Arbitrary, object-encoded domain's data
- Alias - unique alias of the domain
- CreatedAt - timestamp at which the domain is created
- UpdatedAt - timestamp at which the domain is updated
- UpdatedBy - user that updated the domain
- CreatedBy - user that created the domain
- Status - domain status
## Configuration
The service is configured using the environment variables presented in the following table. Note that any unset variables will be replaced with their default values.
| Variable | Description | Default |
| ------------------------------ | ----------------------------------------------------------------------- | ------------------------------- |
| MG_AUTH_LOG_LEVEL | Log level for the Auth service (debug, info, warn, error) | info |
| MG_AUTH_DB_HOST | Database host address | localhost |
| MG_AUTH_DB_PORT | Database host port | 5432 |
| MG_AUTH_DB_USER | Database user | magistrala |
| MG_AUTH_DB_PASSWORD | Database password | magistrala |
| MG_AUTH_DB_NAME | Name of the database used by the service | auth |
| MG_AUTH_DB_SSL_MODE | Database connection SSL mode (disable, require, verify-ca, verify-full) | disable |
| MG_AUTH_DB_SSL_CERT | Path to the PEM encoded certificate file | "" |
| MG_AUTH_DB_SSL_KEY | Path to the PEM encoded key file | "" |
| MG_AUTH_DB_SSL_ROOT_CERT | Path to the PEM encoded root certificate file | "" |
| MG_AUTH_HTTP_HOST | Auth service HTTP host | "" |
| MG_AUTH_HTTP_PORT | Auth service HTTP port | 8189 |
| MG_AUTH_HTTP_SERVER_CERT | Path to the PEM encoded HTTP server certificate file | "" |
| MG_AUTH_HTTP_SERVER_KEY | Path to the PEM encoded HTTP server key file | "" |
| MG_AUTH_GRPC_HOST | Auth service gRPC host | "" |
| MG_AUTH_GRPC_PORT | Auth service gRPC port | 8181 |
| MG_AUTH_GRPC_SERVER_CERT | Path to the PEM encoded gRPC server certificate file | "" |
| MG_AUTH_GRPC_SERVER_KEY | Path to the PEM encoded gRPC server key file | "" |
| MG_AUTH_GRPC_SERVER_CA_CERTS | Path to the PEM encoded gRPC server CA certificate file | "" |
| MG_AUTH_GRPC_CLIENT_CA_CERTS | Path to the PEM encoded gRPC client CA certificate file | "" |
| MG_AUTH_SECRET_KEY | String used for signing tokens | secret |
| MG_AUTH_ACCESS_TOKEN_DURATION | The access token expiration period | 1h |
| MG_AUTH_REFRESH_TOKEN_DURATION | The refresh token expiration period | 24h |
| MG_AUTH_INVITATION_DURATION | The invitation token expiration period | 168h |
| MG_SPICEDB_HOST | SpiceDB host address | localhost |
| MG_SPICEDB_PORT | SpiceDB host port | 50051 |
| MG_SPICEDB_PRE_SHARED_KEY | SpiceDB pre-shared key | 12345678 |
| MG_SPICEDB_SCHEMA_FILE | Path to SpiceDB schema file | ./docker/spicedb/schema.zed |
| MG_JAEGER_URL | Jaeger server URL | <http://jaeger:4318/v1/traces> |
| MG_JAEGER_TRACE_RATIO | Jaeger sampling ratio | 1.0 |
| MG_SEND_TELEMETRY | Send telemetry to magistrala call home server | true |
| MG_AUTH_ADAPTER_INSTANCE_ID | Adapter instance ID | "" |
## Deployment
The service itself is distributed as Docker container. Check the [`auth`](https://github.com/absmach/magistrala/blob/main/docker/docker-compose.yml) service section in docker-compose file to see how service is deployed.
Running this service outside of container requires working instance of the postgres database, SpiceDB, and Jaeger server.
To start the service outside of the container, execute the following shell script:
```bash
# download the latest version of the service
git clone https://github.com/absmach/magistrala
cd magistrala
# compile the service
make auth
# copy binary to bin
make install
# set the environment variables and run the service
MG_AUTH_LOG_LEVEL=info \
MG_AUTH_DB_HOST=localhost \
MG_AUTH_DB_PORT=5432 \
MG_AUTH_DB_USER=magistrala \
MG_AUTH_DB_PASSWORD=magistrala \
MG_AUTH_DB_NAME=auth \
MG_AUTH_DB_SSL_MODE=disable \
MG_AUTH_DB_SSL_CERT="" \
MG_AUTH_DB_SSL_KEY="" \
MG_AUTH_DB_SSL_ROOT_CERT="" \
MG_AUTH_HTTP_HOST=localhost \
MG_AUTH_HTTP_PORT=8189 \
MG_AUTH_HTTP_SERVER_CERT="" \
MG_AUTH_HTTP_SERVER_KEY="" \
MG_AUTH_GRPC_HOST=localhost \
MG_AUTH_GRPC_PORT=8181 \
MG_AUTH_GRPC_SERVER_CERT="" \
MG_AUTH_GRPC_SERVER_KEY="" \
MG_AUTH_GRPC_SERVER_CA_CERTS="" \
MG_AUTH_GRPC_CLIENT_CA_CERTS="" \
MG_AUTH_SECRET_KEY=secret \
MG_AUTH_ACCESS_TOKEN_DURATION=1h \
MG_AUTH_REFRESH_TOKEN_DURATION=24h \
MG_AUTH_INVITATION_DURATION=168h \
MG_SPICEDB_HOST=localhost \
MG_SPICEDB_PORT=50051 \
MG_SPICEDB_PRE_SHARED_KEY=12345678 \
MG_SPICEDB_SCHEMA_FILE=./docker/spicedb/schema.zed \
MG_JAEGER_URL=http://localhost:14268/api/traces \
MG_JAEGER_TRACE_RATIO=1.0 \
MG_SEND_TELEMETRY=true \
MG_AUTH_ADAPTER_INSTANCE_ID="" \
$GOBIN/magistrala-auth
```
Setting `MG_AUTH_HTTP_SERVER_CERT` and `MG_AUTH_HTTP_SERVER_KEY` will enable TLS against the service. The service expects a file in PEM format for both the certificate and the key.
Setting `MG_AUTH_GRPC_SERVER_CERT` and `MG_AUTH_GRPC_SERVER_KEY` will enable TLS against the service. The service expects a file in PEM format for both the certificate and the key. Setting `MG_AUTH_GRPC_SERVER_CA_CERTS` will enable TLS against the service trusting only those CAs that are provided. The service expects a file in PEM format of trusted CAs. Setting `MG_AUTH_GRPC_CLIENT_CA_CERTS` will enable TLS against the service trusting only those CAs that are provided. The service expects a file in PEM format of trusted CAs.
## Usage
For more information about service capabilities and its usage, please check out the [API documentation](https://docs.api.magistrala.abstractmachines.fr/?urls.primaryName=auth.yml).
[doc]: https://docs.magistrala.abstractmachines.fr
-5
View File
@@ -1,5 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package api contains implementation of Auth service HTTP API.
package api
-111
View File
@@ -1,111 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package auth
import (
"context"
"time"
"github.com/absmach/magistrala"
grpcapi "github.com/absmach/magistrala/auth/api/grpc"
"github.com/go-kit/kit/endpoint"
kitgrpc "github.com/go-kit/kit/transport/grpc"
"google.golang.org/grpc"
)
const authSvcName = "magistrala.AuthService"
type authGrpcClient struct {
authenticate endpoint.Endpoint
authorize endpoint.Endpoint
timeout time.Duration
}
var _ magistrala.AuthServiceClient = (*authGrpcClient)(nil)
// NewAuthClient returns new auth gRPC client instance.
func NewAuthClient(conn *grpc.ClientConn, timeout time.Duration) magistrala.AuthServiceClient {
return &authGrpcClient{
authenticate: kitgrpc.NewClient(
conn,
authSvcName,
"Authenticate",
encodeIdentifyRequest,
decodeIdentifyResponse,
magistrala.AuthNRes{},
).Endpoint(),
authorize: kitgrpc.NewClient(
conn,
authSvcName,
"Authorize",
encodeAuthorizeRequest,
decodeAuthorizeResponse,
magistrala.AuthZRes{},
).Endpoint(),
timeout: timeout,
}
}
func (client authGrpcClient) Authenticate(ctx context.Context, token *magistrala.AuthNReq, _ ...grpc.CallOption) (*magistrala.AuthNRes, error) {
ctx, cancel := context.WithTimeout(ctx, client.timeout)
defer cancel()
res, err := client.authenticate(ctx, authenticateReq{token: token.GetToken()})
if err != nil {
return &magistrala.AuthNRes{}, grpcapi.DecodeError(err)
}
ir := res.(authenticateRes)
return &magistrala.AuthNRes{Id: ir.id, UserId: ir.userID, DomainId: ir.domainID}, nil
}
func encodeIdentifyRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(authenticateReq)
return &magistrala.AuthNReq{Token: req.token}, nil
}
func decodeIdentifyResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
res := grpcRes.(*magistrala.AuthNRes)
return authenticateRes{id: res.GetId(), userID: res.GetUserId(), domainID: res.GetDomainId()}, nil
}
func (client authGrpcClient) Authorize(ctx context.Context, req *magistrala.AuthZReq, _ ...grpc.CallOption) (r *magistrala.AuthZRes, err error) {
ctx, cancel := context.WithTimeout(ctx, client.timeout)
defer cancel()
res, err := client.authorize(ctx, authReq{
Domain: req.GetDomain(),
SubjectType: req.GetSubjectType(),
Subject: req.GetSubject(),
SubjectKind: req.GetSubjectKind(),
Relation: req.GetRelation(),
Permission: req.GetPermission(),
ObjectType: req.GetObjectType(),
Object: req.GetObject(),
})
if err != nil {
return &magistrala.AuthZRes{}, grpcapi.DecodeError(err)
}
ar := res.(authorizeRes)
return &magistrala.AuthZRes{Authorized: ar.authorized, Id: ar.id}, nil
}
func decodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
res := grpcRes.(*magistrala.AuthZRes)
return authorizeRes{authorized: res.Authorized, id: res.Id}, nil
}
func encodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(authReq)
return &magistrala.AuthZReq{
Domain: req.Domain,
SubjectType: req.SubjectType,
Subject: req.Subject,
SubjectKind: req.SubjectKind,
Relation: req.Relation,
Permission: req.Permission,
ObjectType: req.ObjectType,
Object: req.Object,
}, nil
}
-5
View File
@@ -1,5 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package auth contains implementation of Auth service gRPC API.
package auth
-52
View File
@@ -1,52 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package auth
import (
"context"
"github.com/absmach/magistrala/auth"
"github.com/absmach/magistrala/pkg/policies"
"github.com/go-kit/kit/endpoint"
)
func authenticateEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(authenticateReq)
if err := req.validate(); err != nil {
return authenticateRes{}, err
}
key, err := svc.Identify(ctx, req.token)
if err != nil {
return authenticateRes{}, err
}
return authenticateRes{id: key.Subject, userID: key.User, domainID: key.Domain}, nil
}
}
func authorizeEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(authReq)
if err := req.validate(); err != nil {
return authorizeRes{}, err
}
err := svc.Authorize(ctx, policies.Policy{
Domain: req.Domain,
SubjectType: req.SubjectType,
SubjectKind: req.SubjectKind,
Subject: req.Subject,
Relation: req.Relation,
Permission: req.Permission,
ObjectType: req.ObjectType,
Object: req.Object,
})
if err != nil {
return authorizeRes{authorized: false}, err
}
return authorizeRes{authorized: true}, nil
}
}
-228
View File
@@ -1,228 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package auth_test
import (
"context"
"fmt"
"net"
"testing"
"time"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/auth"
grpcapi "github.com/absmach/magistrala/auth/api/grpc/auth"
"github.com/absmach/magistrala/internal/testsutil"
"github.com/absmach/magistrala/pkg/apiutil"
"github.com/absmach/magistrala/pkg/errors"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
const (
port = 8081
secret = "secret"
email = "test@example.com"
id = "testID"
thingsType = "things"
usersType = "users"
description = "Description"
groupName = "mgx"
adminpermission = "admin"
authoritiesObj = "authorities"
memberRelation = "member"
loginDuration = 30 * time.Minute
refreshDuration = 24 * time.Hour
invalidDuration = 7 * 24 * time.Hour
validToken = "valid"
inValidToken = "invalid"
validPolicy = "valid"
)
var (
domainID = testsutil.GenerateUUID(&testing.T{})
authAddr = fmt.Sprintf("localhost:%d", port)
)
func startGRPCServer(svc auth.Service, port int) *grpc.Server {
listener, _ := net.Listen("tcp", fmt.Sprintf(":%d", port))
server := grpc.NewServer()
magistrala.RegisterAuthServiceServer(server, grpcapi.NewAuthServer(svc))
go func() {
err := server.Serve(listener)
assert.Nil(&testing.T{}, err, fmt.Sprintf(`"Unexpected error creating auth server %s"`, err))
}()
return server
}
func TestIdentify(t *testing.T) {
conn, err := grpc.NewClient(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
assert.Nil(t, err, fmt.Sprintf("Unexpected error creating client connection %s", err))
grpcClient := grpcapi.NewAuthClient(conn, time.Second)
cases := []struct {
desc string
token string
idt *magistrala.AuthNRes
svcErr error
err error
}{
{
desc: "authenticate user with valid user token",
token: validToken,
idt: &magistrala.AuthNRes{Id: id, UserId: email, DomainId: domainID},
err: nil,
},
{
desc: "authenticate user with invalid user token",
token: "invalid",
idt: &magistrala.AuthNRes{},
svcErr: svcerr.ErrAuthentication,
err: svcerr.ErrAuthentication,
},
{
desc: "authenticate user with empty token",
token: "",
idt: &magistrala.AuthNRes{},
err: apiutil.ErrBearerToken,
},
}
for _, tc := range cases {
svcCall := svc.On("Identify", mock.Anything, mock.Anything, mock.Anything).Return(auth.Key{Subject: id, User: email, Domain: domainID}, tc.svcErr)
idt, err := grpcClient.Authenticate(context.Background(), &magistrala.AuthNReq{Token: tc.token})
if idt != nil {
assert.Equal(t, tc.idt, idt, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.idt, idt))
}
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
}
}
func TestAuthorize(t *testing.T) {
conn, err := grpc.NewClient(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
assert.Nil(t, err, fmt.Sprintf("Unexpected error creating client connection %s", err))
grpcClient := grpcapi.NewAuthClient(conn, time.Second)
cases := []struct {
desc string
token string
authRequest *magistrala.AuthZReq
authResponse *magistrala.AuthZRes
err error
}{
{
desc: "authorize user with authorized token",
token: validToken,
authRequest: &magistrala.AuthZReq{
Subject: id,
SubjectType: usersType,
Object: authoritiesObj,
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
},
authResponse: &magistrala.AuthZRes{Authorized: true},
err: nil,
},
{
desc: "authorize user with unauthorized token",
token: inValidToken,
authRequest: &magistrala.AuthZReq{
Subject: id,
SubjectType: usersType,
Object: authoritiesObj,
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
},
authResponse: &magistrala.AuthZRes{Authorized: false},
err: svcerr.ErrAuthorization,
},
{
desc: "authorize user with empty subject",
token: validToken,
authRequest: &magistrala.AuthZReq{
Subject: "",
SubjectType: usersType,
Object: authoritiesObj,
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
},
authResponse: &magistrala.AuthZRes{Authorized: false},
err: apiutil.ErrMissingPolicySub,
},
{
desc: "authorize user with empty subject type",
token: validToken,
authRequest: &magistrala.AuthZReq{
Subject: id,
SubjectType: "",
Object: authoritiesObj,
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
},
authResponse: &magistrala.AuthZRes{Authorized: false},
err: apiutil.ErrMissingPolicySub,
},
{
desc: "authorize user with empty object",
token: validToken,
authRequest: &magistrala.AuthZReq{
Subject: id,
SubjectType: usersType,
Object: "",
ObjectType: usersType,
Relation: memberRelation,
Permission: adminpermission,
},
authResponse: &magistrala.AuthZRes{Authorized: false},
err: apiutil.ErrMissingPolicyObj,
},
{
desc: "authorize user with empty object type",
token: validToken,
authRequest: &magistrala.AuthZReq{
Subject: id,
SubjectType: usersType,
Object: authoritiesObj,
ObjectType: "",
Relation: memberRelation,
Permission: adminpermission,
},
authResponse: &magistrala.AuthZRes{Authorized: false},
err: apiutil.ErrMissingPolicyObj,
},
{
desc: "authorize user with empty permission",
token: validToken,
authRequest: &magistrala.AuthZReq{
Subject: id,
SubjectType: usersType,
Object: authoritiesObj,
ObjectType: usersType,
Relation: memberRelation,
Permission: "",
},
authResponse: &magistrala.AuthZRes{Authorized: false},
err: apiutil.ErrMalformedPolicyPer,
},
}
for _, tc := range cases {
svccall := svc.On("Authorize", mock.Anything, mock.Anything).Return(tc.err)
ar, err := grpcClient.Authorize(context.Background(), tc.authRequest)
if ar != nil {
assert.Equal(t, tc.authResponse, ar, fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.authResponse, ar))
}
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svccall.Unset()
}
}
-51
View File
@@ -1,51 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package auth
import (
"github.com/absmach/magistrala/pkg/apiutil"
)
type authenticateReq struct {
token string
}
func (req authenticateReq) validate() error {
if req.token == "" {
return apiutil.ErrBearerToken
}
return nil
}
// authReq represents authorization request. It contains:
// 1. subject - an action invoker
// 2. object - an entity over which action will be executed
// 3. action - type of action that will be executed (read/write).
type authReq struct {
Domain string
SubjectType string
SubjectKind string
Subject string
Relation string
Permission string
ObjectType string
Object string
}
func (req authReq) validate() error {
if req.Subject == "" || req.SubjectType == "" {
return apiutil.ErrMissingPolicySub
}
if req.Object == "" || req.ObjectType == "" {
return apiutil.ErrMissingPolicyObj
}
if req.Permission == "" {
return apiutil.ErrMalformedPolicyPer
}
return nil
}
-15
View File
@@ -1,15 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package auth
type authenticateRes struct {
id string
userID string
domainID string
}
type authorizeRes struct {
id string
authorized bool
}
-83
View File
@@ -1,83 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package auth
import (
"context"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/auth"
grpcapi "github.com/absmach/magistrala/auth/api/grpc"
kitgrpc "github.com/go-kit/kit/transport/grpc"
)
var _ magistrala.AuthServiceServer = (*authGrpcServer)(nil)
type authGrpcServer struct {
magistrala.UnimplementedAuthServiceServer
authorize kitgrpc.Handler
authenticate kitgrpc.Handler
}
// NewAuthServer returns new AuthnServiceServer instance.
func NewAuthServer(svc auth.Service) magistrala.AuthServiceServer {
return &authGrpcServer{
authorize: kitgrpc.NewServer(
(authorizeEndpoint(svc)),
decodeAuthorizeRequest,
encodeAuthorizeResponse,
),
authenticate: kitgrpc.NewServer(
(authenticateEndpoint(svc)),
decodeAuthenticateRequest,
encodeAuthenticateResponse,
),
}
}
func (s *authGrpcServer) Authenticate(ctx context.Context, req *magistrala.AuthNReq) (*magistrala.AuthNRes, error) {
_, res, err := s.authenticate.ServeGRPC(ctx, req)
if err != nil {
return nil, grpcapi.EncodeError(err)
}
return res.(*magistrala.AuthNRes), nil
}
func (s *authGrpcServer) Authorize(ctx context.Context, req *magistrala.AuthZReq) (*magistrala.AuthZRes, error) {
_, res, err := s.authorize.ServeGRPC(ctx, req)
if err != nil {
return nil, grpcapi.EncodeError(err)
}
return res.(*magistrala.AuthZRes), nil
}
func decodeAuthenticateRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(*magistrala.AuthNReq)
return authenticateReq{token: req.GetToken()}, nil
}
func encodeAuthenticateResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
res := grpcRes.(authenticateRes)
return &magistrala.AuthNRes{Id: res.id, UserId: res.userID, DomainId: res.domainID}, nil
}
func decodeAuthorizeRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(*magistrala.AuthZReq)
return authReq{
Domain: req.GetDomain(),
SubjectType: req.GetSubjectType(),
SubjectKind: req.GetSubjectKind(),
Subject: req.GetSubject(),
Relation: req.GetRelation(),
Permission: req.GetPermission(),
ObjectType: req.GetObjectType(),
Object: req.GetObject(),
}, nil
}
func encodeAuthorizeResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
res := grpcRes.(authorizeRes)
return &magistrala.AuthZRes{Authorized: res.authorized, Id: res.id}, nil
}
-24
View File
@@ -1,24 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package auth_test
import (
"os"
"testing"
"github.com/absmach/magistrala/auth/mocks"
)
var svc *mocks.Service
func TestMain(m *testing.M) {
svc = new(mocks.Service)
server := startGRPCServer(svc, port)
code := m.Run()
server.GracefulStop()
os.Exit(code)
}
-67
View File
@@ -1,67 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package domains
import (
"context"
"time"
"github.com/absmach/magistrala"
grpcapi "github.com/absmach/magistrala/auth/api/grpc"
"github.com/go-kit/kit/endpoint"
kitgrpc "github.com/go-kit/kit/transport/grpc"
"google.golang.org/grpc"
)
const domainsSvcName = "magistrala.DomainsService"
var _ magistrala.DomainsServiceClient = (*domainsGrpcClient)(nil)
type domainsGrpcClient struct {
deleteUserFromDomains endpoint.Endpoint
timeout time.Duration
}
// NewDomainsClient returns new domains gRPC client instance.
func NewDomainsClient(conn *grpc.ClientConn, timeout time.Duration) magistrala.DomainsServiceClient {
return &domainsGrpcClient{
deleteUserFromDomains: kitgrpc.NewClient(
conn,
domainsSvcName,
"DeleteUserFromDomains",
encodeDeleteUserRequest,
decodeDeleteUserResponse,
magistrala.DeleteUserRes{},
).Endpoint(),
timeout: timeout,
}
}
func (client domainsGrpcClient) DeleteUserFromDomains(ctx context.Context, in *magistrala.DeleteUserReq, opts ...grpc.CallOption) (*magistrala.DeleteUserRes, error) {
ctx, cancel := context.WithTimeout(ctx, client.timeout)
defer cancel()
res, err := client.deleteUserFromDomains(ctx, deleteUserPoliciesReq{
ID: in.GetId(),
})
if err != nil {
return &magistrala.DeleteUserRes{}, grpcapi.DecodeError(err)
}
dpr := res.(deleteUserRes)
return &magistrala.DeleteUserRes{Deleted: dpr.deleted}, nil
}
func decodeDeleteUserResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
res := grpcRes.(*magistrala.DeleteUserRes)
return deleteUserRes{deleted: res.GetDeleted()}, nil
}
func encodeDeleteUserRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(deleteUserPoliciesReq)
return &magistrala.DeleteUserReq{
Id: req.ID,
}, nil
}
-5
View File
@@ -1,5 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package grpc contains implementation of Domains service gRPC API.
package domains
-26
View File
@@ -1,26 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package domains
import (
"context"
"github.com/absmach/magistrala/auth"
"github.com/go-kit/kit/endpoint"
)
func deleteUserFromDomainsEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(deleteUserPoliciesReq)
if err := req.validate(); err != nil {
return deleteUserRes{}, err
}
if err := svc.DeleteUserFromDomains(ctx, req.ID); err != nil {
return deleteUserRes{}, err
}
return deleteUserRes{deleted: true}, nil
}
}
-104
View File
@@ -1,104 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package domains_test
import (
"context"
"fmt"
"net"
"testing"
"time"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/auth"
grpcapi "github.com/absmach/magistrala/auth/api/grpc/domains"
"github.com/absmach/magistrala/pkg/apiutil"
"github.com/absmach/magistrala/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
const (
port = 8081
secret = "secret"
email = "test@example.com"
id = "testID"
thingsType = "things"
usersType = "users"
description = "Description"
groupName = "mgx"
adminpermission = "admin"
authoritiesObj = "authorities"
memberRelation = "member"
loginDuration = 30 * time.Minute
refreshDuration = 24 * time.Hour
invalidDuration = 7 * 24 * time.Hour
validToken = "valid"
inValidToken = "invalid"
validPolicy = "valid"
)
var authAddr = fmt.Sprintf("localhost:%d", port)
func startGRPCServer(svc auth.Service, port int) *grpc.Server {
listener, _ := net.Listen("tcp", fmt.Sprintf(":%d", port))
server := grpc.NewServer()
magistrala.RegisterDomainsServiceServer(server, grpcapi.NewDomainsServer(svc))
go func() {
err := server.Serve(listener)
assert.Nil(&testing.T{}, err, fmt.Sprintf(`"Unexpected error creating auth server %s"`, err))
}()
return server
}
func TestDeleteUserFromDomains(t *testing.T) {
conn, err := grpc.NewClient(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
assert.Nil(t, err, fmt.Sprintf("Unexpected error creating client connection %s", err))
grpcClient := grpcapi.NewDomainsClient(conn, time.Second)
cases := []struct {
desc string
token string
deleteUserReq *magistrala.DeleteUserReq
deleteUserRes *magistrala.DeleteUserRes
err error
}{
{
desc: "delete valid req",
token: validToken,
deleteUserReq: &magistrala.DeleteUserReq{
Id: id,
},
deleteUserRes: &magistrala.DeleteUserRes{Deleted: true},
err: nil,
},
{
desc: "delete invalid req with invalid token",
token: inValidToken,
deleteUserReq: &magistrala.DeleteUserReq{},
deleteUserRes: &magistrala.DeleteUserRes{Deleted: false},
err: apiutil.ErrMissingID,
},
{
desc: "delete invalid req with invalid token",
token: inValidToken,
deleteUserReq: &magistrala.DeleteUserReq{
Id: id,
},
deleteUserRes: &magistrala.DeleteUserRes{Deleted: false},
err: apiutil.ErrMissingPolicyEntityType,
},
}
for _, tc := range cases {
repoCall := svc.On("DeleteUserFromDomains", mock.Anything, tc.deleteUserReq.Id).Return(tc.err)
dpr, err := grpcClient.DeleteUserFromDomains(context.Background(), tc.deleteUserReq)
assert.Equal(t, tc.deleteUserRes.GetDeleted(), dpr.GetDeleted(), fmt.Sprintf("%s: expected %v got %v", tc.desc, tc.deleteUserRes.GetDeleted(), dpr.GetDeleted()))
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
repoCall.Unset()
}
}
-20
View File
@@ -1,20 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package domains
import (
"github.com/absmach/magistrala/pkg/apiutil"
)
type deleteUserPoliciesReq struct {
ID string
}
func (req deleteUserPoliciesReq) validate() error {
if req.ID == "" {
return apiutil.ErrMissingID
}
return nil
}
-8
View File
@@ -1,8 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package domains
type deleteUserRes struct {
deleted bool
}
-50
View File
@@ -1,50 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package domains
import (
"context"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/auth"
grpcapi "github.com/absmach/magistrala/auth/api/grpc"
kitgrpc "github.com/go-kit/kit/transport/grpc"
)
var _ magistrala.DomainsServiceServer = (*domainsGrpcServer)(nil)
type domainsGrpcServer struct {
magistrala.UnimplementedDomainsServiceServer
deleteUserFromDomains kitgrpc.Handler
}
func NewDomainsServer(svc auth.Service) magistrala.DomainsServiceServer {
return &domainsGrpcServer{
deleteUserFromDomains: kitgrpc.NewServer(
(deleteUserFromDomainsEndpoint(svc)),
decodeDeleteUserRequest,
encodeDeleteUserResponse,
),
}
}
func decodeDeleteUserRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(*magistrala.DeleteUserReq)
return deleteUserPoliciesReq{
ID: req.GetId(),
}, nil
}
func encodeDeleteUserResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
res := grpcRes.(deleteUserRes)
return &magistrala.DeleteUserRes{Deleted: res.deleted}, nil
}
func (s *domainsGrpcServer) DeleteUserFromDomains(ctx context.Context, req *magistrala.DeleteUserReq) (*magistrala.DeleteUserRes, error) {
_, res, err := s.deleteUserFromDomains.ServeGRPC(ctx, req)
if err != nil {
return nil, grpcapi.EncodeError(err)
}
return res.(*magistrala.DeleteUserRes), nil
}
-95
View File
@@ -1,95 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package token
import (
"context"
"time"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/auth"
grpcapi "github.com/absmach/magistrala/auth/api/grpc"
"github.com/go-kit/kit/endpoint"
kitgrpc "github.com/go-kit/kit/transport/grpc"
"google.golang.org/grpc"
)
const tokenSvcName = "magistrala.TokenService"
type tokenGrpcClient struct {
issue endpoint.Endpoint
refresh endpoint.Endpoint
timeout time.Duration
}
var _ magistrala.TokenServiceClient = (*tokenGrpcClient)(nil)
// NewAuthClient returns new auth gRPC client instance.
func NewTokenClient(conn *grpc.ClientConn, timeout time.Duration) magistrala.TokenServiceClient {
return &tokenGrpcClient{
issue: kitgrpc.NewClient(
conn,
tokenSvcName,
"Issue",
encodeIssueRequest,
decodeIssueResponse,
magistrala.Token{},
).Endpoint(),
refresh: kitgrpc.NewClient(
conn,
tokenSvcName,
"Refresh",
encodeRefreshRequest,
decodeRefreshResponse,
magistrala.Token{},
).Endpoint(),
timeout: timeout,
}
}
func (client tokenGrpcClient) Issue(ctx context.Context, req *magistrala.IssueReq, _ ...grpc.CallOption) (*magistrala.Token, error) {
ctx, cancel := context.WithTimeout(ctx, client.timeout)
defer cancel()
res, err := client.issue(ctx, issueReq{
userID: req.GetUserId(),
keyType: auth.KeyType(req.GetType()),
})
if err != nil {
return &magistrala.Token{}, grpcapi.DecodeError(err)
}
return res.(*magistrala.Token), nil
}
func encodeIssueRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(issueReq)
return &magistrala.IssueReq{
UserId: req.userID,
Type: uint32(req.keyType),
}, nil
}
func decodeIssueResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
return grpcRes, nil
}
func (client tokenGrpcClient) Refresh(ctx context.Context, req *magistrala.RefreshReq, _ ...grpc.CallOption) (*magistrala.Token, error) {
ctx, cancel := context.WithTimeout(ctx, client.timeout)
defer cancel()
res, err := client.refresh(ctx, refreshReq{refreshToken: req.GetRefreshToken()})
if err != nil {
return &magistrala.Token{}, grpcapi.DecodeError(err)
}
return res.(*magistrala.Token), nil
}
func encodeRefreshRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(refreshReq)
return &magistrala.RefreshReq{RefreshToken: req.refreshToken}, nil
}
func decodeRefreshResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
return grpcRes, nil
}
-5
View File
@@ -1,5 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
// Package grpc contains implementation of Auth service gRPC API.
package token
-56
View File
@@ -1,56 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package token
import (
"context"
"github.com/absmach/magistrala/auth"
"github.com/go-kit/kit/endpoint"
)
func issueEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(issueReq)
if err := req.validate(); err != nil {
return issueRes{}, err
}
key := auth.Key{
Type: req.keyType,
User: req.userID,
}
tkn, err := svc.Issue(ctx, "", key)
if err != nil {
return issueRes{}, err
}
ret := issueRes{
accessToken: tkn.AccessToken,
refreshToken: tkn.RefreshToken,
accessType: tkn.AccessType,
}
return ret, nil
}
}
func refreshEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(refreshReq)
if err := req.validate(); err != nil {
return issueRes{}, err
}
key := auth.Key{Type: auth.RefreshKey}
tkn, err := svc.Issue(ctx, req.refreshToken, key)
if err != nil {
return issueRes{}, err
}
ret := issueRes{
accessToken: tkn.AccessToken,
refreshToken: tkn.RefreshToken,
accessType: tkn.AccessType,
}
return ret, nil
}
}
-171
View File
@@ -1,171 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package token_test
import (
"context"
"fmt"
"net"
"testing"
"time"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/auth"
grpcapi "github.com/absmach/magistrala/auth/api/grpc/token"
"github.com/absmach/magistrala/internal/testsutil"
"github.com/absmach/magistrala/pkg/apiutil"
"github.com/absmach/magistrala/pkg/errors"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
const (
port = 8081
secret = "secret"
email = "test@example.com"
id = "testID"
thingsType = "things"
usersType = "users"
description = "Description"
groupName = "mgx"
adminpermission = "admin"
authoritiesObj = "authorities"
memberRelation = "member"
loginDuration = 30 * time.Minute
refreshDuration = 24 * time.Hour
invalidDuration = 7 * 24 * time.Hour
validToken = "valid"
inValidToken = "invalid"
validPolicy = "valid"
)
var (
validID = testsutil.GenerateUUID(&testing.T{})
authAddr = fmt.Sprintf("localhost:%d", port)
)
func startGRPCServer(svc auth.Service, port int) *grpc.Server {
listener, _ := net.Listen("tcp", fmt.Sprintf(":%d", port))
server := grpc.NewServer()
magistrala.RegisterTokenServiceServer(server, grpcapi.NewTokenServer(svc))
go func() {
err := server.Serve(listener)
assert.Nil(&testing.T{}, err, fmt.Sprintf(`"Unexpected error creating auth server %s"`, err))
}()
return server
}
func TestIssue(t *testing.T) {
conn, err := grpc.NewClient(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
assert.Nil(t, err, fmt.Sprintf("Unexpected error creating client connection %s", err))
grpcClient := grpcapi.NewTokenClient(conn, time.Second)
cases := []struct {
desc string
userId string
kind auth.KeyType
issueResponse auth.Token
err error
}{
{
desc: "issue for user with valid token",
userId: validID,
kind: auth.AccessKey,
issueResponse: auth.Token{
AccessToken: validToken,
RefreshToken: validToken,
},
err: nil,
},
{
desc: "issue recovery key",
userId: validID,
kind: auth.RecoveryKey,
issueResponse: auth.Token{
AccessToken: validToken,
RefreshToken: validToken,
},
err: nil,
},
{
desc: "issue API key unauthenticated",
userId: validID,
kind: auth.APIKey,
issueResponse: auth.Token{},
err: svcerr.ErrAuthentication,
},
{
desc: "issue for invalid key type",
userId: validID,
kind: 32,
issueResponse: auth.Token{},
err: errors.ErrMalformedEntity,
},
{
desc: "issue for user that does notexist",
userId: "",
kind: auth.APIKey,
issueResponse: auth.Token{},
err: svcerr.ErrAuthentication,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("Issue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.issueResponse, tc.err)
_, err := grpcClient.Issue(context.Background(), &magistrala.IssueReq{UserId: tc.userId, Type: uint32(tc.kind)})
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
func TestRefresh(t *testing.T) {
conn, err := grpc.NewClient(authAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
assert.Nil(t, err, fmt.Sprintf("Unexpected error creating client connection %s", err))
grpcClient := grpcapi.NewTokenClient(conn, time.Second)
cases := []struct {
desc string
token string
issueResponse auth.Token
err error
}{
{
desc: "refresh token with valid token",
token: validToken,
issueResponse: auth.Token{
AccessToken: validToken,
RefreshToken: validToken,
},
err: nil,
},
{
desc: "refresh token with invalid token",
token: inValidToken,
issueResponse: auth.Token{},
err: svcerr.ErrAuthentication,
},
{
desc: "refresh token with empty token",
token: "",
issueResponse: auth.Token{},
err: apiutil.ErrMissingSecret,
},
}
for _, tc := range cases {
t.Run(tc.desc, func(t *testing.T) {
svcCall := svc.On("Issue", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.issueResponse, tc.err)
_, err := grpcClient.Refresh(context.Background(), &magistrala.RefreshReq{RefreshToken: tc.token})
assert.True(t, errors.Contains(err, tc.err), fmt.Sprintf("%s: expected %s got %s\n", tc.desc, tc.err, err))
svcCall.Unset()
})
}
}
-37
View File
@@ -1,37 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package token
import (
"github.com/absmach/magistrala/auth"
"github.com/absmach/magistrala/pkg/apiutil"
)
type issueReq struct {
userID string
keyType auth.KeyType
}
func (req issueReq) validate() error {
if req.keyType != auth.AccessKey &&
req.keyType != auth.APIKey &&
req.keyType != auth.RecoveryKey &&
req.keyType != auth.InvitationKey {
return apiutil.ErrInvalidAuthKey
}
return nil
}
type refreshReq struct {
refreshToken string
}
func (req refreshReq) validate() error {
if req.refreshToken == "" {
return apiutil.ErrMissingSecret
}
return nil
}
-10
View File
@@ -1,10 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package token
type issueRes struct {
accessToken string
refreshToken string
accessType string
}
-76
View File
@@ -1,76 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package token
import (
"context"
"github.com/absmach/magistrala"
"github.com/absmach/magistrala/auth"
grpcapi "github.com/absmach/magistrala/auth/api/grpc"
kitgrpc "github.com/go-kit/kit/transport/grpc"
)
var _ magistrala.TokenServiceServer = (*tokenGrpcServer)(nil)
type tokenGrpcServer struct {
magistrala.UnimplementedTokenServiceServer
issue kitgrpc.Handler
refresh kitgrpc.Handler
}
// NewAuthServer returns new AuthnServiceServer instance.
func NewTokenServer(svc auth.Service) magistrala.TokenServiceServer {
return &tokenGrpcServer{
issue: kitgrpc.NewServer(
(issueEndpoint(svc)),
decodeIssueRequest,
encodeIssueResponse,
),
refresh: kitgrpc.NewServer(
(refreshEndpoint(svc)),
decodeRefreshRequest,
encodeIssueResponse,
),
}
}
func (s *tokenGrpcServer) Issue(ctx context.Context, req *magistrala.IssueReq) (*magistrala.Token, error) {
_, res, err := s.issue.ServeGRPC(ctx, req)
if err != nil {
return nil, grpcapi.EncodeError(err)
}
return res.(*magistrala.Token), nil
}
func (s *tokenGrpcServer) Refresh(ctx context.Context, req *magistrala.RefreshReq) (*magistrala.Token, error) {
_, res, err := s.refresh.ServeGRPC(ctx, req)
if err != nil {
return nil, grpcapi.EncodeError(err)
}
return res.(*magistrala.Token), nil
}
func decodeIssueRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(*magistrala.IssueReq)
return issueReq{
userID: req.GetUserId(),
keyType: auth.KeyType(req.GetType()),
}, nil
}
func decodeRefreshRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
req := grpcReq.(*magistrala.RefreshReq)
return refreshReq{refreshToken: req.GetRefreshToken()}, nil
}
func encodeIssueResponse(_ context.Context, grpcRes interface{}) (interface{}, error) {
res := grpcRes.(issueRes)
return &magistrala.Token{
AccessToken: res.accessToken,
RefreshToken: &res.refreshToken,
AccessType: res.accessType,
}, nil
}
-24
View File
@@ -1,24 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package token_test
import (
"os"
"testing"
"github.com/absmach/magistrala/auth/mocks"
)
var svc *mocks.Service
func TestMain(m *testing.M) {
svc = new(mocks.Service)
server := startGRPCServer(svc, port)
code := m.Run()
server.GracefulStop()
os.Exit(code)
}
-72
View File
@@ -1,72 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package grpc
import (
"fmt"
"github.com/absmach/magistrala/auth"
"github.com/absmach/magistrala/pkg/apiutil"
"github.com/absmach/magistrala/pkg/errors"
svcerr "github.com/absmach/magistrala/pkg/errors/service"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func EncodeError(err error) error {
switch {
case errors.Contains(err, nil):
return nil
case errors.Contains(err, errors.ErrMalformedEntity),
errors.Contains(err, svcerr.ErrInvalidPolicy),
err == apiutil.ErrInvalidAuthKey,
err == apiutil.ErrMissingID,
err == apiutil.ErrMissingMemberType,
err == apiutil.ErrMissingPolicySub,
err == apiutil.ErrMissingPolicyObj,
err == apiutil.ErrMalformedPolicyAct:
return status.Error(codes.InvalidArgument, err.Error())
case errors.Contains(err, svcerr.ErrAuthentication),
errors.Contains(err, auth.ErrKeyExpired),
err == apiutil.ErrMissingEmail,
err == apiutil.ErrBearerToken:
return status.Error(codes.Unauthenticated, err.Error())
case errors.Contains(err, svcerr.ErrAuthorization),
errors.Contains(err, svcerr.ErrDomainAuthorization):
return status.Error(codes.PermissionDenied, err.Error())
case errors.Contains(err, svcerr.ErrNotFound):
return status.Error(codes.NotFound, err.Error())
case errors.Contains(err, svcerr.ErrConflict):
return status.Error(codes.AlreadyExists, err.Error())
default:
return status.Error(codes.Internal, err.Error())
}
}
func DecodeError(err error) error {
if st, ok := status.FromError(err); ok {
switch st.Code() {
case codes.NotFound:
return errors.Wrap(svcerr.ErrNotFound, errors.New(st.Message()))
case codes.InvalidArgument:
return errors.Wrap(errors.ErrMalformedEntity, errors.New(st.Message()))
case codes.AlreadyExists:
return errors.Wrap(svcerr.ErrConflict, errors.New(st.Message()))
case codes.Unauthenticated:
return errors.Wrap(svcerr.ErrAuthentication, errors.New(st.Message()))
case codes.OK:
if msg := st.Message(); msg != "" {
return errors.Wrap(errors.ErrUnidentified, errors.New(msg))
}
return nil
case codes.FailedPrecondition:
return errors.Wrap(errors.ErrMalformedEntity, errors.New(st.Message()))
case codes.PermissionDenied:
return errors.Wrap(svcerr.ErrAuthorization, errors.New(st.Message()))
default:
return errors.Wrap(fmt.Errorf("unexpected gRPC status: %s (status code:%v)", st.Code().String(), st.Code()), errors.New(st.Message()))
}
}
return err
}
-3
View File
@@ -1,3 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package http
-201
View File
@@ -1,201 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package domains
import (
"context"
"encoding/json"
"net/http"
"strings"
"github.com/absmach/magistrala/auth"
"github.com/absmach/magistrala/internal/api"
"github.com/absmach/magistrala/pkg/apiutil"
"github.com/absmach/magistrala/pkg/errors"
"github.com/go-chi/chi/v5"
)
func decodeCreateDomainRequest(_ context.Context, r *http.Request) (interface{}, error) {
if !strings.Contains(r.Header.Get("Content-Type"), api.ContentType) {
return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType)
}
req := createDomainReq{
token: apiutil.ExtractBearerToken(r),
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity))
}
return req, nil
}
func decodeRetrieveDomainRequest(_ context.Context, r *http.Request) (interface{}, error) {
req := retrieveDomainRequest{
token: apiutil.ExtractBearerToken(r),
domainID: chi.URLParam(r, "domainID"),
}
return req, nil
}
func decodeRetrieveDomainPermissionsRequest(_ context.Context, r *http.Request) (interface{}, error) {
req := retrieveDomainPermissionsRequest{
token: apiutil.ExtractBearerToken(r),
domainID: chi.URLParam(r, "domainID"),
}
return req, nil
}
func decodeUpdateDomainRequest(_ context.Context, r *http.Request) (interface{}, error) {
if !strings.Contains(r.Header.Get("Content-Type"), api.ContentType) {
return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType)
}
req := updateDomainReq{
token: apiutil.ExtractBearerToken(r),
domainID: chi.URLParam(r, "domainID"),
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity))
}
return req, nil
}
func decodeListDomainRequest(ctx context.Context, r *http.Request) (interface{}, error) {
page, err := decodePageRequest(ctx, r)
if err != nil {
return nil, err
}
req := listDomainsReq{
token: apiutil.ExtractBearerToken(r),
page: page,
}
return req, nil
}
func decodeEnableDomainRequest(_ context.Context, r *http.Request) (interface{}, error) {
req := enableDomainReq{
token: apiutil.ExtractBearerToken(r),
domainID: chi.URLParam(r, "domainID"),
}
return req, nil
}
func decodeDisableDomainRequest(_ context.Context, r *http.Request) (interface{}, error) {
req := disableDomainReq{
token: apiutil.ExtractBearerToken(r),
domainID: chi.URLParam(r, "domainID"),
}
return req, nil
}
func decodeFreezeDomainRequest(_ context.Context, r *http.Request) (interface{}, error) {
req := freezeDomainReq{
token: apiutil.ExtractBearerToken(r),
domainID: chi.URLParam(r, "domainID"),
}
return req, nil
}
func decodeAssignUsersRequest(_ context.Context, r *http.Request) (interface{}, error) {
if !strings.Contains(r.Header.Get("Content-Type"), api.ContentType) {
return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType)
}
req := assignUsersReq{
token: apiutil.ExtractBearerToken(r),
domainID: chi.URLParam(r, "domainID"),
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity))
}
return req, nil
}
func decodeUnassignUserRequest(_ context.Context, r *http.Request) (interface{}, error) {
if !strings.Contains(r.Header.Get("Content-Type"), api.ContentType) {
return nil, errors.Wrap(apiutil.ErrValidation, apiutil.ErrUnsupportedContentType)
}
req := unassignUserReq{
token: apiutil.ExtractBearerToken(r),
domainID: chi.URLParam(r, "domainID"),
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, errors.Wrap(err, errors.ErrMalformedEntity))
}
return req, nil
}
func decodeListUserDomainsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
page, err := decodePageRequest(ctx, r)
if err != nil {
return nil, err
}
req := listUserDomainsReq{
token: apiutil.ExtractBearerToken(r),
userID: chi.URLParam(r, "userID"),
page: page,
}
return req, nil
}
func decodePageRequest(_ context.Context, r *http.Request) (page, error) {
s, err := apiutil.ReadStringQuery(r, api.StatusKey, api.DefClientStatus)
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
st, err := auth.ToStatus(s)
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
o, err := apiutil.ReadNumQuery[uint64](r, api.OffsetKey, api.DefOffset)
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
or, err := apiutil.ReadStringQuery(r, api.OrderKey, api.DefOrder)
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
dir, err := apiutil.ReadStringQuery(r, api.DirKey, api.DefDir)
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
l, err := apiutil.ReadNumQuery[uint64](r, api.LimitKey, api.DefLimit)
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
m, err := apiutil.ReadMetadataQuery(r, api.MetadataKey, nil)
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
n, err := apiutil.ReadStringQuery(r, api.NameKey, "")
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
t, err := apiutil.ReadStringQuery(r, api.TagKey, "")
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
p, err := apiutil.ReadStringQuery(r, api.PermissionKey, "")
if err != nil {
return page{}, errors.Wrap(apiutil.ErrValidation, err)
}
return page{
offset: o,
order: or,
dir: dir,
limit: l,
name: n,
metadata: m,
tag: t,
permission: p,
status: st,
}, nil
}
-225
View File
@@ -1,225 +0,0 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0
package domains
import (
"context"
"github.com/absmach/magistrala/auth"
"github.com/absmach/magistrala/pkg/apiutil"
"github.com/absmach/magistrala/pkg/errors"
"github.com/go-kit/kit/endpoint"
)
func createDomainEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(createDomainReq)
if err := req.validate(); err != nil {
return nil, err
}
d := auth.Domain{
Name: req.Name,
Metadata: req.Metadata,
Tags: req.Tags,
Alias: req.Alias,
}
domain, err := svc.CreateDomain(ctx, req.token, d)
if err != nil {
return nil, err
}
return createDomainRes{domain}, nil
}
}
func retrieveDomainEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(retrieveDomainRequest)
if err := req.validate(); err != nil {
return nil, err
}
domain, err := svc.RetrieveDomain(ctx, req.token, req.domainID)
if err != nil {
return nil, err
}
return retrieveDomainRes{domain}, nil
}
}
func retrieveDomainPermissionsEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(retrieveDomainPermissionsRequest)
if err := req.validate(); err != nil {
return nil, err
}
permissions, err := svc.RetrieveDomainPermissions(ctx, req.token, req.domainID)
if err != nil {
return nil, err
}
return retrieveDomainPermissionsRes{Permissions: permissions}, nil
}
}
func updateDomainEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(updateDomainReq)
if err := req.validate(); err != nil {
return nil, err
}
var metadata auth.Metadata
if req.Metadata != nil {
metadata = *req.Metadata
}
d := auth.DomainReq{
Name: req.Name,
Metadata: &metadata,
Tags: req.Tags,
Alias: req.Alias,
}
domain, err := svc.UpdateDomain(ctx, req.token, req.domainID, d)
if err != nil {
return nil, err
}
return updateDomainRes{domain}, nil
}
}
func listDomainsEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(listDomainsReq)
if err := req.validate(); err != nil {
return nil, errors.Wrap(apiutil.ErrValidation, err)
}
page := auth.Page{
Offset: req.offset,
Limit: req.limit,
Name: req.name,
Metadata: req.metadata,
Order: req.order,
Dir: req.dir,
Tag: req.tag,
Permission: req.permission,
Status: req.status,
}
dp, err := svc.ListDomains(ctx, req.token, page)
if err != nil {
return nil, err
}
return listDomainsRes{dp}, nil
}
}
func enableDomainEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(enableDomainReq)
if err := req.validate(); err != nil {
return nil, err
}
enable := auth.EnabledStatus
d := auth.DomainReq{
Status: &enable,
}
if _, err := svc.ChangeDomainStatus(ctx, req.token, req.domainID, d); err != nil {
return nil, err
}
return enableDomainRes{}, nil
}
}
func disableDomainEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(disableDomainReq)
if err := req.validate(); err != nil {
return nil, err
}
disable := auth.DisabledStatus
d := auth.DomainReq{
Status: &disable,
}
if _, err := svc.ChangeDomainStatus(ctx, req.token, req.domainID, d); err != nil {
return nil, err
}
return disableDomainRes{}, nil
}
}
func freezeDomainEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(freezeDomainReq)
if err := req.validate(); err != nil {
return nil, err
}
freeze := auth.FreezeStatus
d := auth.DomainReq{
Status: &freeze,
}
if _, err := svc.ChangeDomainStatus(ctx, req.token, req.domainID, d); err != nil {
return nil, err
}
return freezeDomainRes{}, nil
}
}
func assignDomainUsersEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(assignUsersReq)
if err := req.validate(); err != nil {
return nil, err
}
if err := svc.AssignUsers(ctx, req.token, req.domainID, req.UserIDs, req.Relation); err != nil {
return nil, err
}
return assignUsersRes{}, nil
}
}
func unassignDomainUserEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(unassignUserReq)
if err := req.validate(); err != nil {
return nil, err
}
if err := svc.UnassignUser(ctx, req.token, req.domainID, req.UserID); err != nil {
return nil, err
}
return unassignUsersRes{}, nil
}
}
func listUserDomainsEndpoint(svc auth.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(listUserDomainsReq)
if err := req.validate(); err != nil {
return nil, err
}
page := auth.Page{
Offset: req.offset,
Limit: req.limit,
Name: req.name,
Metadata: req.metadata,
Order: req.order,
Dir: req.dir,
Tag: req.tag,
Permission: req.permission,
Status: req.status,
}
dp, err := svc.ListUserDomains(ctx, req.token, req.userID, page)
if err != nil {
return nil, err
}
return listUserDomainsRes{dp}, nil
}
}
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